Skip to content

Commit

Permalink
Merge pull request howardwu#260 from weikengchen/master
Browse files Browse the repository at this point in the history
Add `no_std` for most of the packages
  • Loading branch information
howardwu authored Jun 15, 2021
2 parents 1449dfe + 67922e1 commit 523a1ff
Show file tree
Hide file tree
Showing 79 changed files with 746 additions and 556 deletions.
618 changes: 351 additions & 267 deletions Cargo.lock

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ members = [ "bitcoin", "ethereum", "model", "monero", "zcash" ]
[badges]
travis-ci = { repository = "AleoHQ/wagyu", branch = "master" }

[features]
default = ["std"]
std = ["wagyu-model/std", "wagyu-bitcoin/std", "wagyu-ethereum/std", "wagyu-model/std", "wagyu-monero/std", "wagyu-zcash/std"]

[dependencies]
wagyu-bitcoin = { path = "./bitcoin", version = "0.6.3" }
wagyu-ethereum = { path = "./ethereum", version = "0.6.3" }
Expand Down
2 changes: 1 addition & 1 deletion bitcoin/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ tiny-keccak = { version = "1.4" }

[features]
default = ["std"]
std = ["wagyu-model/default"]
std = ["wagyu-model/std"]

[badges]
travis-ci = { repository = "AleoHQ/wagyu", branch = "master" }
23 changes: 16 additions & 7 deletions bitcoin/src/address.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ use crate::network::BitcoinNetwork;
use crate::private_key::BitcoinPrivateKey;
use crate::public_key::BitcoinPublicKey;
use crate::witness_program::WitnessProgram;
use wagyu_model::no_std::*;
use wagyu_model::{
crypto::{checksum, hash160},
Address, AddressError, PrivateKey,
};
use wagyu_model::no_std::*;

use base58::{FromBase58, ToBase58};
use bech32::{u5, Bech32, FromBase32, ToBase32};
Expand Down Expand Up @@ -35,7 +35,12 @@ impl<N: BitcoinNetwork> Address for BitcoinAddress<N> {
let public_key = private_key.to_public_key();
match format {
BitcoinFormat::P2PKH => Self::p2pkh(&public_key),
BitcoinFormat::P2WSH => return Err(AddressError::IncompatibleFormats(String::from("non-script"), String::from("p2wsh address"))),
BitcoinFormat::P2WSH => {
return Err(AddressError::IncompatibleFormats(
String::from("non-script"),
String::from("p2wsh address"),
))
}
BitcoinFormat::P2SH_P2WPKH => Self::p2sh_p2wpkh(&public_key),
BitcoinFormat::Bech32 => Self::bech32(&public_key),
}
Expand All @@ -45,7 +50,12 @@ impl<N: BitcoinNetwork> Address for BitcoinAddress<N> {
fn from_public_key(public_key: &Self::PublicKey, format: &Self::Format) -> Result<Self, AddressError> {
match format {
BitcoinFormat::P2PKH => Self::p2pkh(public_key),
BitcoinFormat::P2WSH => return Err(AddressError::IncompatibleFormats(String::from("non-script"), String::from("p2wsh address"))),
BitcoinFormat::P2WSH => {
return Err(AddressError::IncompatibleFormats(
String::from("non-script"),
String::from("p2wsh address"),
))
}
BitcoinFormat::P2SH_P2WPKH => Self::p2sh_p2wpkh(public_key),
BitcoinFormat::Bech32 => Self::bech32(public_key),
}
Expand Down Expand Up @@ -841,14 +851,14 @@ mod tests {
),
(
"210253be79afe84fd9342c1f52024379b6da6299ea98844aee23838e8e678a765f7cac",
"tb1qhmdep02f0jpjxs36ckyzjtfesknu8a8xmhnva7f3vw95t9g6q4ksaqhl9x"
)
"tb1qhmdep02f0jpjxs36ckyzjtfesknu8a8xmhnva7f3vw95t9g6q4ksaqhl9x",
),
];

#[test]
fn from_str() {
SCRIPTPAIRS.iter().for_each(|(script, address)| {
let script_hex= hex::decode(script).unwrap();
let script_hex = hex::decode(script).unwrap();
let new_address = BitcoinAddress::<N>::p2wsh(&script_hex).unwrap();
assert_eq!(new_address.to_string(), address.to_string());
assert_eq!(new_address.format, BitcoinFormat::P2WSH);
Expand All @@ -863,5 +873,4 @@ mod tests {
});
}
}

}
2 changes: 1 addition & 1 deletion bitcoin/src/amount.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use wagyu_model::{Amount, AmountError};
use wagyu_model::no_std::*;
use wagyu_model::{Amount, AmountError};

use core::fmt;
use serde::Serialize;
Expand Down
6 changes: 2 additions & 4 deletions bitcoin/src/extended_private_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,8 @@ impl<N: BitcoinNetwork> ExtendedPrivateKey for BitcoinExtendedPrivateKey<N> {
let mut extended_private_key = self.clone();

for index in path.to_vec()?.into_iter() {
let public_key = &PublicKey::from_secret_key(
&extended_private_key.private_key.to_secp256k1_secret_key(),
)
.serialize_compressed()[..];
let public_key = &PublicKey::from_secret_key(&extended_private_key.private_key.to_secp256k1_secret_key())
.serialize_compressed()[..];

let mut mac = HmacSha512::new_varkey(&extended_private_key.chain_code)?;
match index {
Expand Down
10 changes: 2 additions & 8 deletions bitcoin/src/extended_public_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,10 +208,7 @@ mod tests {
let extended_private_key = BitcoinExtendedPrivateKey::<N>::from_str(extended_private_key).unwrap();
let extended_public_key = BitcoinExtendedPublicKey::<N>::from_extended_private_key(&extended_private_key);
assert_eq!(expected_extended_public_key, extended_public_key.to_string());
assert_eq!(
expected_public_key,
extended_public_key.public_key.to_string()
);
assert_eq!(expected_public_key, extended_public_key.public_key.to_string());
assert_eq!(expected_child_index, u32::from(extended_public_key.child_index));
assert_eq!(expected_chain_code, hex::encode(extended_public_key.chain_code));
assert_eq!(
Expand Down Expand Up @@ -263,10 +260,7 @@ mod tests {
extended_public_key: &str,
) {
let extended_public_key = BitcoinExtendedPublicKey::<N>::from_str(&extended_public_key).unwrap();
assert_eq!(
expected_public_key,
extended_public_key.public_key.to_string()
);
assert_eq!(expected_public_key, extended_public_key.public_key.to_string());
assert_eq!(expected_child_index, u32::from(extended_public_key.child_index));
assert_eq!(expected_chain_code, hex::encode(extended_public_key.chain_code));
assert_eq!(
Expand Down
2 changes: 1 addition & 1 deletion bitcoin/src/format.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::network::BitcoinNetwork;
use wagyu_model::{AddressError, ExtendedPrivateKeyError, ExtendedPublicKeyError, Format};
use wagyu_model::no_std::*;
use wagyu_model::{AddressError, ExtendedPrivateKeyError, ExtendedPublicKeyError, Format};

use core::fmt;
use serde::Serialize;
Expand Down
2 changes: 1 addition & 1 deletion bitcoin/src/mnemonic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ use crate::network::BitcoinNetwork;
use crate::private_key::BitcoinPrivateKey;
use crate::public_key::BitcoinPublicKey;
use crate::wordlist::BitcoinWordlist;
use wagyu_model::{ExtendedPrivateKey, Mnemonic, MnemonicCount, MnemonicError, MnemonicExtended};
use wagyu_model::no_std::*;
use wagyu_model::{ExtendedPrivateKey, Mnemonic, MnemonicCount, MnemonicError, MnemonicExtended};

use bitvec::prelude::*;
use core::{fmt, marker::PhantomData, ops::Div, str, str::FromStr};
Expand Down
2 changes: 1 addition & 1 deletion bitcoin/src/network/mainnet.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use crate::format::BitcoinFormat;
use crate::network::BitcoinNetwork;
use wagyu_model::no_std::*;
use wagyu_model::{
AddressError, ChildIndex, ExtendedPrivateKeyError, ExtendedPublicKeyError, Network, NetworkError, PrivateKeyError,
};
use wagyu_model::no_std::*;

use core::{fmt, str::FromStr};
use serde::Serialize;
Expand Down
2 changes: 1 addition & 1 deletion bitcoin/src/network/mod.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use crate::format::BitcoinFormat;
use wagyu_model::no_std::*;
use wagyu_model::{
AddressError, ChildIndex, ExtendedPrivateKeyError, ExtendedPublicKeyError, Network, PrivateKeyError,
};
use wagyu_model::no_std::*;

pub mod mainnet;
pub use self::mainnet::*;
Expand Down
2 changes: 1 addition & 1 deletion bitcoin/src/network/testnet.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use crate::format::BitcoinFormat;
use crate::network::BitcoinNetwork;
use wagyu_model::no_std::*;
use wagyu_model::{
AddressError, ChildIndex, ExtendedPrivateKeyError, ExtendedPublicKeyError, Network, NetworkError, PrivateKeyError,
};
use wagyu_model::no_std::*;

use core::{fmt, str::FromStr};
use serde::Serialize;
Expand Down
83 changes: 48 additions & 35 deletions bitcoin/src/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ use crate::network::BitcoinNetwork;
use crate::private_key::BitcoinPrivateKey;
use crate::public_key::BitcoinPublicKey;
use crate::witness_program::WitnessProgram;
use wagyu_model::no_std::{io::Read, *};
use wagyu_model::{PrivateKey, Transaction, TransactionError, TransactionId};
use wagyu_model::no_std::{*, io::Read};

use base58::FromBase58;
use bech32::{Bech32, FromBase32};
Expand Down Expand Up @@ -313,7 +313,7 @@ pub struct BitcoinTransactionInput<N: BitcoinNetwork> {
/// Provide more flexibility for multiple signatures (for P2WSH)
pub additional_witness: Option<(Vec<u8>, bool)>,
/// Option for additional witness stack script args
pub witness_script_data: Option<Vec<u8>>
pub witness_script_data: Option<Vec<u8>>,
}

impl<N: BitcoinNetwork> BitcoinTransactionInput<N> {
Expand Down Expand Up @@ -400,7 +400,7 @@ impl<N: BitcoinNetwork> BitcoinTransactionInput<N> {
witnesses: vec![],
is_signed: script_sig.len() > 0,
additional_witness: None,
witness_script_data: None
witness_script_data: None,
})
}

Expand Down Expand Up @@ -618,8 +618,8 @@ impl<N: BitcoinNetwork> Transaction for BitcoinTransaction<N> {
};
let c_address = BitcoinAddress::<N>::p2wsh(&input_script)?;
address == &c_address
},
_ => address == &private_key.to_address(&address.format())?
}
_ => address == &private_key.to_address(&address.format())?,
};

if address_is_valid && !transaction.parameters.inputs[vin].is_signed {
Expand All @@ -632,19 +632,17 @@ impl<N: BitcoinNetwork> Transaction for BitcoinTransaction<N> {

// Signature
let (signature, _) = secp256k1::sign(
&secp256k1::Message::parse_slice(&transaction_hash)?,
&private_key.to_secp256k1_secret_key(),
);
&secp256k1::Message::parse_slice(&transaction_hash)?,
&private_key.to_secp256k1_secret_key(),
);
let mut signature = signature.serialize_der().as_ref().to_vec();
signature.push((input.sighash_code as u32).to_le_bytes()[0]);
let signature = [variable_length_integer(signature.len() as u64)?, signature].concat();

// Public key
let public_key = private_key.to_public_key();
let public_key_bytes = match (&address.format(), public_key.is_compressed()) {
(BitcoinFormat::P2PKH, false) => {
public_key.to_secp256k1_public_key().serialize().to_vec()
}
(BitcoinFormat::P2PKH, false) => public_key.to_secp256k1_public_key().serialize().to_vec(),
_ => public_key.to_secp256k1_public_key().serialize_compressed().to_vec(),
};
let public_key = [vec![public_key_bytes.len() as u8], public_key_bytes].concat();
Expand All @@ -660,29 +658,36 @@ impl<N: BitcoinNetwork> Transaction for BitcoinTransaction<N> {
None => return Err(TransactionError::InvalidInputs("P2WSH".into())),
};

let ser_input_script = [variable_length_integer(input_script.len() as u64)?, input_script].concat();
let ser_input_script =
[variable_length_integer(input_script.len() as u64)?, input_script].concat();
transaction.parameters.segwit_flag = true;
transaction.parameters.inputs[vin].script_sig = vec![];
// TODO: (jaakinyele) Generalize to a vec of additional witnesses
let (other_signature, is_other_sig_first) = match transaction.parameters.inputs[vin].additional_witness.clone() {
Some(n) => (n.0, n.1),
None => return Err(TransactionError::InvalidInputs("P2WSH: missing additional witness input to complete multi-sig".into())),
};
let (other_signature, is_other_sig_first) =
match transaction.parameters.inputs[vin].additional_witness.clone() {
Some(n) => (n.0, n.1),
None => {
return Err(TransactionError::InvalidInputs(
"P2WSH: missing additional witness input to complete multi-sig".into(),
))
}
};
// Determine whether to append or prepend other signature(s)
let mut witness_field = match is_other_sig_first {
true => vec![other_signature, signature.clone()],
false => vec![signature.clone(), other_signature]
false => vec![signature.clone(), other_signature],
};
// Append witness stack script args (before witness script)
if transaction.parameters.inputs[vin].witness_script_data.is_some() {
let witness_script_data = transaction.parameters.inputs[vin].witness_script_data.clone().unwrap();
let witness_script_data = [vec![witness_script_data.len() as u8], witness_script_data].concat();
let witness_script_data =
transaction.parameters.inputs[vin].witness_script_data.clone().unwrap();
let witness_script_data =
[vec![witness_script_data.len() as u8], witness_script_data].concat();
witness_field.append(&mut vec![witness_script_data]);
}
// Append the witness script last
witness_field.append(&mut vec![ser_input_script.clone()]);
transaction.parameters.inputs[vin].witnesses
.append(&mut witness_field);
transaction.parameters.inputs[vin].witnesses.append(&mut witness_field);
transaction.parameters.inputs[vin].is_signed = true;
}
BitcoinFormat::P2SH_P2WPKH => {
Expand Down Expand Up @@ -946,27 +951,30 @@ mod tests {
inputs: Vec<Input>,
outputs: Vec<Output>,
expected_signed_transaction: &str,
expected_transaction_id: &str
expected_transaction_id: &str,
) {
let mut input_vec = vec![];
for input in &inputs {
let private_key = BitcoinPrivateKey::from_str(input.private_key).unwrap();
let private_key = BitcoinPrivateKey::from_str(input.private_key).unwrap();
let transaction_id = hex::decode(input.transaction_id).unwrap();
let redeem_script = match (input.redeem_script, input.address_format.clone()) {
(Some(script), BitcoinFormat::P2WSH) => Some(hex::decode(script).unwrap()),
(Some(script), _) => Some(hex::decode(script).unwrap()),
(None, BitcoinFormat::P2SH_P2WPKH) => {
let mut redeem_script = vec![0x00, 0x14];
redeem_script.extend(&hash160(
&private_key.to_public_key().to_secp256k1_public_key().serialize_compressed(),
&private_key
.to_public_key()
.to_secp256k1_public_key()
.serialize_compressed(),
));
Some(redeem_script)
}
(None, _) => None,
};
};
let address = match &input.address_format {
BitcoinFormat::P2WSH => BitcoinAddress::<N>::p2wsh(redeem_script.as_ref().unwrap()).unwrap(),
_ => private_key.to_address(&input.address_format).unwrap()
_ => private_key.to_address(&input.address_format).unwrap(),
};
let script_pub_key = input.script_pub_key.map(|script| hex::decode(script).unwrap());
let sequence = input.sequence.map(|seq| seq.to_vec());
Expand Down Expand Up @@ -994,13 +1002,13 @@ mod tests {
let address = BitcoinAddress::<N>::from_str(output.address);
if address.is_ok() {
output_vec.push(BitcoinTransactionOutput::new(&address.unwrap(), output.amount).unwrap());
} else {
} else {
let tx_output = BitcoinTransactionOutput {
amount: output.amount,
script_pub_key: hex::decode(output.address).unwrap()
script_pub_key: hex::decode(output.address).unwrap(),
};
output_vec.push(tx_output);
}
}
}

let transaction_parameters = BitcoinTransactionParameters::<N> {
Expand All @@ -1020,14 +1028,14 @@ mod tests {
.unwrap();
}

let signed_transaction_without_witness = hex::encode(&transaction.to_transaction_bytes_without_witness().unwrap());
let signed_transaction_without_witness =
hex::encode(&transaction.to_transaction_bytes_without_witness().unwrap());
let transaction_id = hex::encode(&transaction.to_transaction_id().unwrap().txid);

assert_eq!(expected_signed_transaction, &signed_transaction_without_witness);
assert_eq!(expected_transaction_id, &transaction_id);
}


fn test_transaction<N: BitcoinNetwork>(
version: u32,
lock_time: u32,
Expand All @@ -1046,7 +1054,10 @@ mod tests {
(None, BitcoinFormat::P2SH_P2WPKH) => {
let mut redeem_script = vec![0x00, 0x14];
redeem_script.extend(&hash160(
&private_key.to_public_key().to_secp256k1_public_key().serialize_compressed(),
&private_key
.to_public_key()
.to_secp256k1_public_key()
.serialize_compressed(),
));
Some(redeem_script)
}
Expand Down Expand Up @@ -1117,7 +1128,10 @@ mod tests {
(None, BitcoinFormat::P2SH_P2WPKH) => {
let mut redeem_script = vec![0x00, 0x14];
redeem_script.extend(&hash160(
&private_key.to_public_key().to_secp256k1_public_key().serialize_compressed(),
&private_key
.to_public_key()
.to_secp256k1_public_key()
.serialize_compressed(),
));
Some(redeem_script)
}
Expand Down Expand Up @@ -1866,7 +1880,7 @@ mod tests {
// Not including witness for now
expected_signed_transaction: "0200000001fa6a6160f798cba0c5cac5b9d2ba91d177fa8589875ba8ae7e46864c4e42957c37000000171600143d295b6276ff8e4579f3350873db3e839e230f41ffffffff0180841e0000000000220020c015c4a6be010e21657068fc2e6a9d02b27ebe4d490a25846f7237f104d1a3cd00000000",
expected_transaction_id: "d7f70088081d8c3bf45040f11789ee53868b4b00f900c86d32702f3497dec879",
},
},
TransactionTestCase { // Transaction 2 -> P2WSH to Bech32(P2WPKH) and itself
version: 2,
lock_time: 0,
Expand Down Expand Up @@ -1923,7 +1937,6 @@ mod tests {
);
});
}

}

mod test_helper_functions {
Expand Down
Loading

0 comments on commit 523a1ff

Please sign in to comment.