-
Notifications
You must be signed in to change notification settings - Fork 382
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix bitcoin lockdrop audit issues (#194)
* Fix all tests * Fix lockdrop script compiler, using bitcoin library * Added tests for btc_utils * Style fixes
- Loading branch information
Showing
23 changed files
with
392 additions
and
665 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,57 +1,58 @@ | ||
use codec::Encode; | ||
use ripemd160::{Digest, Ripemd160}; | ||
use sp_core::{ecdsa, hashing::sha2_256}; | ||
//! Bitcoin locking helpers. | ||
pub const BTC_TESTNET: u8 = 0x6f; | ||
//pub const BTC_MAINNET: u8 = 0x00; | ||
use bitcoin::blockdata::script::Script; | ||
use bitcoin::network::constants::Network; | ||
use bitcoin::util::address::Address; | ||
use bitcoin::util::key::PublicKey; | ||
use bitcoin_script::bitcoin_script; | ||
use sp_core::ecdsa; | ||
|
||
/// Bitcoin RIPEMD160 hashing function. | ||
pub fn ripemd160(data: &[u8]) -> [u8; 20] { | ||
let mut hasher = Ripemd160::new(); | ||
hasher.input(data); | ||
let mut output = [0u8; 20]; | ||
output.copy_from_slice(&hasher.result()); | ||
output | ||
/// Encode block delay in BIP68 standard | ||
fn bip68_encode(blocks: u32) -> u32 { | ||
0x0000ffff & blocks | ||
} | ||
|
||
/// Compile BTC sequence lock script for givent public key and duration in blocks. | ||
pub fn lock_script(public: &ecdsa::Public, duration: u64) -> Vec<u8> { | ||
let blocks = duration / 600; | ||
let full_public = secp256k1::PublicKey::parse_slice(public.as_ref(), None) | ||
.expect("public key has correct length") | ||
.serialize(); | ||
blocks.using_encoded(|enc_blocks| { | ||
let mut output = vec![]; | ||
output.extend(vec![enc_blocks.len() as u8]); // Lock duration length | ||
output.extend(enc_blocks); // Lock duration in blocks | ||
output.extend(vec![0x27, 0x55]); // OP_CHECKSEQUENCEVERIFY OP_DROP | ||
output.extend(vec![full_public.len() as u8 - 1]); // Public key lenght | ||
output.extend(&full_public[1..]); // Public key | ||
output.extend(vec![0xAC]); // OP_CHECKSIG | ||
output | ||
}) | ||
pub fn lock_script(public: &ecdsa::Public, duration: u32) -> Script { | ||
let public_key = PublicKey::from_slice(public.as_ref()).unwrap(); | ||
let blocks = bip68_encode(duration) as i64; | ||
let script = bitcoin_script! { | ||
<blocks> | ||
OP_CSV | ||
OP_DROP | ||
<public_key> | ||
OP_CHECKSIG | ||
}; | ||
script.to_p2sh() | ||
} | ||
|
||
/// Get hash of binary BTC script. | ||
pub fn script_hash(script: &[u8]) -> [u8; 20] { | ||
ripemd160(&sha2_256(script)[..]) | ||
pub fn to_address(public: &ecdsa::Public) -> String { | ||
let public_key = PublicKey::from_slice(public.as_ref()).unwrap(); | ||
Address::p2pkh(&public_key, Network::Testnet).to_string() | ||
} | ||
|
||
/// Compile BTC pay-to-script-hash script for given script hash. | ||
pub fn p2sh(script_hash: &[u8; 20]) -> Vec<u8> { | ||
let mut output = vec![]; | ||
output.extend(vec![0xa9, 0x14]); // OP_HASH160 20 | ||
output.extend(script_hash); // <scriptHash> | ||
output.extend(vec![0x87]); // OP_EQUAL | ||
output | ||
} | ||
#[cfg(test)] | ||
mod tests { | ||
use super::*; | ||
use hex_literal::hex; | ||
use sp_core::crypto::Public; | ||
|
||
#[test] | ||
fn test_lock_scipt() { | ||
let public = ecdsa::Public::from_slice( | ||
&hex!["038ea27103fb646a2cea9eca9080737e0b23640caaaef2853416c9b286b353313e"][..], | ||
); | ||
let duration = 10; | ||
let script = lock_script(&public, duration); | ||
let address = Address::from_script(&script, Network::Testnet).unwrap(); | ||
assert_eq!(address.to_string(), "2MuJcWGWe8XkPc6h7pt6vQDyaTwDZxKJZ8p"); | ||
} | ||
|
||
/// Get Bitcoin addres for given ECDSA public key and network tag. | ||
/// Note: It works for `1`-prefixed addresses | ||
pub fn to_address(public_key: &ecdsa::Public, network: u8) -> String { | ||
let mut key_hash = vec![network]; | ||
key_hash.extend(&ripemd160(&sha2_256(public_key.as_ref())[..])[..]); | ||
let check_sum = sha2_256(&sha2_256(&key_hash)[..]); | ||
key_hash.extend(&check_sum[0..4]); | ||
bs58::encode(key_hash).into_string() | ||
#[test] | ||
fn test_to_address() { | ||
let public = ecdsa::Public::from_full( | ||
&hex!["0431e12c2db27f3b07fcc560cdbff90923bf9b5b03769103a44b38426f9469172f3eef59e4f01df729428161c33ec5b32763e2e5a0072551b7808ae9d89286b37b"][..] | ||
).unwrap(); | ||
assert_eq!(to_address(&public), "mzUQaN6vnYDYNNYJVpRz2ipxLcWsQg6b8z"); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
//! Lockdrop module CLI parameters. | ||
//! Lockdrop module CLI parameters. | ||
use structopt::StructOpt; | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.