Skip to content

Commit

Permalink
Merge branch 'dev' into 'master'
Browse files Browse the repository at this point in the history
v0.1.1: Updates to BTC-Relay

See merge request interlay/btc-parachain!116
  • Loading branch information
nud3l committed May 27, 2020
2 parents d895a3f + 1448891 commit 8625b40
Show file tree
Hide file tree
Showing 20 changed files with 272 additions and 112 deletions.
6 changes: 3 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
<h2 align="center">BTC-Parachain</h2>

<p align="center">
A trust-minimized bridge from Bitcoin to Polkador
A trust-minimized bridge from Bitcoin to Polkadot.
<br />
<a href="https://interlay.gitlab.io/polkabtc-spec/"><strong>Explore the specification »</strong></a>
<br />
Expand Down
9 changes: 3 additions & 6 deletions crates/bitcoin/src/formatter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -202,14 +202,11 @@ impl Formattable<bool> for U256 {
let mantissa = if exponent > 3 {
self / U256::from(256).pow(U256::from(exponent) - 3)
} else {
self.clone()
*self
};
let mut mantissa_bytes: [u8; 32] = Default::default();
mantissa.to_little_endian(&mut mantissa_bytes);
for i in 0..=2 {
// only three first bytes should be set because of the division
bytes[i] = mantissa_bytes[i];
}
bytes[..2 + 1].clone_from_slice(&mantissa_bytes[..2 + 1]);
Vec::from(&bytes[..])
}
}
Expand Down Expand Up @@ -273,7 +270,7 @@ impl Formatter {
Formatter { bytes: Vec::new() }
}

fn output(&mut self, bytes: &Vec<u8>) {
fn output(&mut self, bytes: &[u8]) {
self.bytes.extend(bytes);
}

Expand Down
2 changes: 1 addition & 1 deletion crates/bitcoin/src/merkle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ impl MerkleProof {
// TODO: This seems to be exactly the same logic as compute_merkle_root in impl BlockBuilder. Extract this as a helper and reuse the logic.
fn compute_hash(&self, height: u32, pos: u32, tx_ids: &[H256Le]) -> H256Le {
if height == 0 {
return tx_ids[pos as usize];
tx_ids[pos as usize]
} else {
let left = self.compute_hash(height - 1, pos * 2, tx_ids);
let right = if pos * 2 + 1 < self.compute_tree_width(height - 1) {
Expand Down
2 changes: 1 addition & 1 deletion crates/bitcoin/src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ pub fn parse_block_header(raw_header: &RawBlockHeader) -> Result<BlockHeader, Er
let block_header = BlockHeader {
merkle_root,
target,
timestamp: timestamp,
timestamp,
version,
nonce,
hash_prev_block,
Expand Down
64 changes: 49 additions & 15 deletions crates/bitcoin/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ impl From<[u8; 20]> for Address {

impl From<Address> for [u8; 20] {
fn from(address: Address) -> [u8; 20] {
address.0.clone()
address.0
}
}

Expand Down Expand Up @@ -312,9 +312,15 @@ pub struct Script {
pub(crate) bytes: Vec<u8>,
}

impl Default for Script {
fn default() -> Self {
Script { bytes: vec![] }
}
}

impl Script {
pub fn new() -> Script {
Script { bytes: vec![] }
Self::default()
}

pub fn height(height: u32) -> Script {
Expand Down Expand Up @@ -380,11 +386,15 @@ impl Script {
pub fn len(&self) -> usize {
self.bytes.len()
}

pub fn is_empty(&self) -> bool {
self.len() == 0
}
}

impl From<Vec<u8>> for Script {
fn from(bytes: Vec<u8>) -> Script {
Script { bytes: bytes }
Script { bytes }
}
}

Expand All @@ -393,7 +403,7 @@ impl TryFrom<&str> for Script {

fn try_from(hex_string: &str) -> Result<Script, Self::Error> {
let bytes = hex::decode(hex_string).map_err(|_e| Error::RuntimeError)?;
Ok(Script { bytes: bytes })
Ok(Script { bytes })
}
}

Expand All @@ -407,21 +417,21 @@ pub struct TransactionOutput {
impl TransactionOutput {
pub fn p2pkh(value: i64, address: &Address) -> TransactionOutput {
TransactionOutput {
value: value,
value,
script: Script::p2pkh(address),
}
}

pub fn p2sh(value: i64, address: &Address) -> TransactionOutput {
TransactionOutput {
value: value,
value,
script: Script::p2sh(address),
}
}

pub fn op_return(value: i64, return_content: &[u8]) -> TransactionOutput {
TransactionOutput {
value: value,
value,
script: Script::op_return(return_content),
}
}
Expand Down Expand Up @@ -522,12 +532,18 @@ pub struct BlockBuilder {
block: Block,
}

impl BlockBuilder {
pub fn new() -> BlockBuilder {
impl Default for BlockBuilder {
fn default() -> Self {
BlockBuilder {
block: Default::default(),
}
}
}

impl BlockBuilder {
pub fn new() -> BlockBuilder {
Self::default()
}

pub fn with_timestamp(&mut self, timestamp: u32) -> &mut Self {
self.block.header.timestamp = timestamp;
Expand All @@ -545,6 +561,12 @@ impl BlockBuilder {
}

pub fn mine(&mut self, target: U256) -> Block {
// NOTE: this function is used only for testing
// so we panic instead of returning a Result
// as this is a problem on the caller side
if self.block.transactions.is_empty() {
panic!("trying to mine a block without a coinbase");
}
self.block.header.target = target;
self.block.header.merkle_root = self.compute_merkle_root();
let mut nonce: u32 = 0;
Expand Down Expand Up @@ -622,12 +644,12 @@ pub struct BlockChain {
impl BlockChain {
// Checks if there is a NO_DATA block in the BlockChain
pub fn is_no_data(&self) -> bool {
self.no_data.len() > 0
!self.no_data.is_empty()
}

// Checks if there is an INVALID block in the BlockChain
pub fn is_invalid(&self) -> bool {
self.invalid.len() > 0
!self.invalid.is_empty()
}
}

Expand Down Expand Up @@ -765,8 +787,8 @@ pub struct TransactionBuilder {
transaction: Transaction,
}

impl TransactionBuilder {
pub fn new() -> TransactionBuilder {
impl Default for TransactionBuilder {
fn default() -> Self {
TransactionBuilder {
transaction: Transaction {
version: 2,
Expand All @@ -777,6 +799,12 @@ impl TransactionBuilder {
},
}
}
}

impl TransactionBuilder {
pub fn new() -> TransactionBuilder {
Self::default()
}

pub fn with_version(&mut self, version: i32) -> &mut Self {
self.transaction.version = version;
Expand Down Expand Up @@ -814,8 +842,8 @@ pub struct TransactionInputBuilder {
trasaction_input: TransactionInput,
}

impl TransactionInputBuilder {
pub fn new() -> TransactionInputBuilder {
impl Default for TransactionInputBuilder {
fn default() -> Self {
TransactionInputBuilder {
trasaction_input: TransactionInput {
previous_hash: H256Le::zero(),
Expand All @@ -828,6 +856,12 @@ impl TransactionInputBuilder {
},
}
}
}

impl TransactionInputBuilder {
pub fn new() -> TransactionInputBuilder {
Self::default()
}

pub fn with_previous_hash(&mut self, previous_hash: H256Le) -> &mut Self {
self.trasaction_input.previous_hash = previous_hash;
Expand Down
6 changes: 3 additions & 3 deletions crates/bitcoin/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ pub fn log2(value: u64) -> u8 {
let mut current = value - 1;
let mut result: u8 = 0;
while current > 0 {
current = current >> 1;
current >>= 1;
result += 1;
}
result
Expand All @@ -76,10 +76,10 @@ pub fn log2(value: u64) -> u8 {
/// assert_eq!(bitcoin::utils::log256(&65537u32.into()), 3);
/// ```
pub fn log256(value: &U256) -> u8 {
let mut current = (value - 1).clone();
let mut current = value - 1;
let mut result: u8 = 0;
while current > 0.into() {
current = current >> 8;
current >>= 8;
result += 1;
}
result
Expand Down
2 changes: 1 addition & 1 deletion crates/btc-relay/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "btc-relay"
version = "0.0.1"
version = "0.1.0"
authors = ["Interlay Ltd"]
edition = "2018"

Expand Down
50 changes: 27 additions & 23 deletions crates/btc-relay/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ decl_storage! {
BlockHeaders: map hasher(blake2_128_concat) H256Le => RichBlockHeader;

/// Sorted mapping of BlockChain elements with reference to ChainsIndex
Chains: map hasher(blake2_128_concat) u32 => u32;
Chains: map hasher(blake2_128_concat) u32 => Option<u32>;

/// Store the index for each tracked blockchain
ChainsIndex: map hasher(blake2_128_concat) u32 => Option<BlockChain>;
Expand Down Expand Up @@ -399,18 +399,9 @@ impl<T: Trait> Module<T> {
) -> Result<(), Error> {
Self::transaction_verification_allowed(block_height)?;

//let main_chain = Self::get_block_chain_from_id(MAIN_CHAIN_ID);
let best_block_height = Self::get_best_block_height();

let next_best_fork_id = Self::get_chain_id_from_position(1);
let next_best_fork_chain = Self::get_block_chain_from_id(next_best_fork_id)?;
let next_best_fork_height = next_best_fork_chain.max_height;

// fail if there is an ongoing fork
ensure!(
best_block_height >= next_best_fork_height + Self::confirmations(),
Error::OngoingFork
);
Self::ensure_no_ongoing_fork(best_block_height)?;

// This call fails if not enough confirmations
Self::check_confirmations(best_block_height, confirmations, block_height, insecure)?;
Expand Down Expand Up @@ -471,8 +462,8 @@ impl<T: Trait> Module<T> {
// ********************************

/// Get chain id from position (sorted by max block height)
fn get_chain_id_from_position(position: u32) -> u32 {
<Chains>::get(position)
fn get_chain_id_from_position(position: u32) -> Result<u32, Error> {
<Chains>::get(position).ok_or(Error::InvalidChainID)
}
/// Get the position of the fork in Chains
fn get_chain_position_from_chain_id(chain_id: u32) -> Result<u32, Error> {
Expand All @@ -483,16 +474,7 @@ impl<T: Trait> Module<T> {
}
Err(Error::ForkIdNotFound)
}
// match <Chains>::enumerate()
// .position(|(_k, v)| v == chain_id)
// {
// Some(pos) => return Ok(pos as u32),
// None => return Err(Error::ForkIdNotFound),
// };
//}
/// Get a blockchain from the id
// TODO: the return of this element can an empty element when it was deleted
// Function should be changed to return a Result or Option
fn get_block_chain_from_id(chain_id: u32) -> Result<BlockChain, Error> {
<ChainsIndex>::get(chain_id).ok_or(Error::InvalidChainID)
}
Expand Down Expand Up @@ -660,6 +642,7 @@ impl<T: Trait> Module<T> {
Self::insert_block_hash(blockchain.chain_id, block_height, *block_hash);

blockchain.max_height = block_height;
Self::set_block_chain_from_id(blockchain.chain_id, &blockchain);

Ok(blockchain)
}
Expand Down Expand Up @@ -903,7 +886,7 @@ impl<T: Trait> Module<T> {
// get the previous position
let prev_position = current_position - 1;
// get the blockchain id
let prev_blockchain_id = Self::get_chain_id_from_position(prev_position);
let prev_blockchain_id = Self::get_chain_id_from_position(prev_position)?;
// get the previous blockchain height
let prev_height = Self::get_block_chain_from_id(prev_blockchain_id)?.max_height;
// swap elements if block height is greater
Expand Down Expand Up @@ -1138,6 +1121,27 @@ impl<T: Trait> Module<T> {
}
Ok(())
}

fn ensure_no_ongoing_fork(best_block_height: u32) -> UnitResult {
// check if there is a next best fork
match Self::get_chain_id_from_position(1) {
// if yes, check that the main chain is at least Self::confirmations() ahead
Ok(id) => {
let next_best_fork_height = Self::get_block_chain_from_id(id)?.max_height;

debug::print!("Best block height: {}", best_block_height);
debug::print!("Next best fork height: {}", next_best_fork_height);
// fail if there is an ongoing fork
ensure!(
best_block_height >= next_best_fork_height + Self::confirmations(),
Error::OngoingFork
);
}
// else, do nothing if there is no fork
Err(_) => {}
}
Ok(())
}
}

decl_event! {
Expand Down
Loading

0 comments on commit 8625b40

Please sign in to comment.