Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions Cargo.lock

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

133 changes: 132 additions & 1 deletion common/src/address/dehexify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.

use crypto::vrf::VRFPublicKey;
use serialization::json_encoded::JsonEncoded;

use crate::chain::{tokens::TokenId, ChainConfig, DelegationId, Destination, PoolId};
use crate::chain::{tokens::TokenId, ChainConfig, DelegationId, Destination, OrderId, PoolId};

use super::hexified::HexifiedAddress;

Expand All @@ -25,6 +26,8 @@ pub fn dehexify_all_addresses(conf: &ChainConfig, input: &str) -> String {
let result = HexifiedAddress::<PoolId>::replace_with_address(conf, &result).to_string();
let result = HexifiedAddress::<DelegationId>::replace_with_address(conf, &result).to_string();
let result = HexifiedAddress::<TokenId>::replace_with_address(conf, &result).to_string();
let result = HexifiedAddress::<OrderId>::replace_with_address(conf, &result).to_string();
let result = HexifiedAddress::<VRFPublicKey>::replace_with_address(conf, &result).to_string();

result
}
Expand All @@ -39,3 +42,131 @@ pub fn to_dehexified_json<T: serde::Serialize>(
}

// TODO: add tests that create blocks, and ensure the replacement in json works properly.
#[cfg(test)]
mod tests {
use rstest::rstest;
use strum::{EnumCount, EnumDiscriminants, EnumIter, IntoEnumIterator};

use crypto::{
key::{KeyKind, PrivateKey},
vrf::{VRFKeyKind, VRFPrivateKey, VRFPublicKey},
};
use test_utils::random::{gen_random_alnum_string, make_seedable_rng, Seed};

use crate::{
address::{hexified::HexifiedAddress, pubkeyhash::PublicKeyHash, Address},
chain::{
config::create_regtest, tokens::TokenId, DelegationId, Destination, DestinationTag,
OrderId, PoolId,
},
primitives::H256,
};

#[derive(PartialEq, Eq, PartialOrd, Ord, EnumCount, EnumDiscriminants)]
#[strum_discriminants(name(HexifiableTag), derive(EnumIter))]
enum Hexifiable {
Destination(Destination),
PoolId(PoolId),
DelegationId(DelegationId),
TokenId(TokenId),
OrderId(OrderId),
VRFPublicKey(VRFPublicKey),
}

#[rstest]
#[trace]
#[case(Seed::from_entropy())]
fn many_random_instances(#[case] seed: Seed) {
use crate::address::dehexify::dehexify_all_addresses;
use randomness::seq::IteratorRandom;

let mut rng = make_seedable_rng(seed);
let chain_config = create_regtest();

let strings = (0..100)
.map(|_| gen_random_alnum_string(&mut rng, 0, 50))
.collect::<Vec<String>>();

let keys = (0..strings.len())
.map(|_| match HexifiableTag::iter().choose(&mut rng).unwrap() {
HexifiableTag::Destination => {
let dest = match DestinationTag::iter().choose(&mut rng).unwrap() {
DestinationTag::AnyoneCanSpend => Destination::AnyoneCanSpend,
DestinationTag::PublicKey => {
let (_private_key, public_key) =
PrivateKey::new_from_rng(&mut rng, KeyKind::Secp256k1Schnorr);
Destination::PublicKey(public_key)
}
DestinationTag::PublicKeyHash => {
let (_private_key, public_key) =
PrivateKey::new_from_rng(&mut rng, KeyKind::Secp256k1Schnorr);
Destination::PublicKeyHash(PublicKeyHash::from(&public_key))
}
DestinationTag::ScriptHash => Destination::ScriptHash(
crate::primitives::Id::new(H256::random_using(&mut rng)),
),
DestinationTag::ClassicMultisig => {
let (_private_key, public_key) =
PrivateKey::new_from_rng(&mut rng, KeyKind::Secp256k1Schnorr);
Destination::ClassicMultisig(PublicKeyHash::from(&public_key))
}
};
Hexifiable::Destination(dest)
}
HexifiableTag::PoolId => Hexifiable::PoolId(PoolId::random_using(&mut rng)),
HexifiableTag::DelegationId => {
Hexifiable::DelegationId(DelegationId::random_using(&mut rng))
}
HexifiableTag::TokenId => Hexifiable::TokenId(TokenId::random_using(&mut rng)),
HexifiableTag::OrderId => Hexifiable::OrderId(OrderId::random_using(&mut rng)),
HexifiableTag::VRFPublicKey => Hexifiable::VRFPublicKey(
VRFPrivateKey::new_from_rng(&mut rng, VRFKeyKind::Schnorrkel).1,
),
})
.collect::<Vec<_>>();

let final_str = strings
.iter()
.zip(keys.iter())
.map(|(s, k)| {
let hexified = match k {
Hexifiable::Destination(d) => HexifiedAddress::new(d).to_string(),
Hexifiable::PoolId(d) => HexifiedAddress::new(d).to_string(),
Hexifiable::DelegationId(d) => HexifiedAddress::new(d).to_string(),
Hexifiable::TokenId(d) => HexifiedAddress::new(d).to_string(),
Hexifiable::OrderId(d) => HexifiedAddress::new(d).to_string(),
Hexifiable::VRFPublicKey(d) => HexifiedAddress::new(d).to_string(),
};
s.clone() + &hexified
})
.collect::<Vec<_>>()
.join("");

let to_test = dehexify_all_addresses(&chain_config, &final_str);

let expected = strings
.iter()
.zip(keys.into_iter())
.map(|(s, k)| {
let address_str = match k {
Hexifiable::Destination(d) => {
Address::new(&chain_config, d).unwrap().to_string()
}
Hexifiable::PoolId(d) => Address::new(&chain_config, d).unwrap().to_string(),
Hexifiable::DelegationId(d) => {
Address::new(&chain_config, d).unwrap().to_string()
}
Hexifiable::TokenId(d) => Address::new(&chain_config, d).unwrap().to_string(),
Hexifiable::OrderId(d) => Address::new(&chain_config, d).unwrap().to_string(),
Hexifiable::VRFPublicKey(d) => {
Address::new(&chain_config, d).unwrap().to_string()
}
};
s.clone() + &address_str
})
.collect::<Vec<_>>()
.join("");

assert_eq!(to_test, expected);
}
}
13 changes: 12 additions & 1 deletion common/src/chain/transaction/signature/inputsig/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,18 @@ use standard_signature::StandardInputSignature;

use super::{DestinationSigError, Signable};

#[derive(Debug, Encode, Decode, Clone, Eq, PartialEq, Ord, PartialOrd, EnumDiscriminants)]
#[derive(
Debug,
Encode,
Decode,
Clone,
Eq,
PartialEq,
Ord,
PartialOrd,
EnumDiscriminants,
serde::Serialize,
)]
#[strum_discriminants(name(InputWitnessTag))]
pub enum InputWitness {
#[codec(index = 0)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ use super::{
},
};

#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, serde::Serialize)]
pub struct StandardInputSignature {
sighash_type: SigHashType,
raw_signature: Vec<u8>,
Expand Down
2 changes: 1 addition & 1 deletion common/src/chain/transaction/signed_transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ use crate::{
use serialization::{Decode, Encode};
use utils::ensure;

#[derive(Debug, Clone, PartialEq, Eq, Encode)]
#[derive(Debug, Clone, PartialEq, Eq, Encode, serde::Serialize)]
pub struct SignedTransaction {
transaction: Transaction,
signatures: Vec<InputWitness>,
Expand Down
6 changes: 5 additions & 1 deletion wasm-wrappers/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@ serialization = { path = "../serialization" }
tx-verifier = { path = "../chainstate/tx-verifier" }
utils = { path = "../utils" }

bip39 = { workspace = true, default-features = false, features = ["std", "zeroize"] }
bip39 = { workspace = true, default-features = false, features = [
"std",
"zeroize",
] }
fixed-hash.workspace = true
itertools.workspace = true
serde.workspace = true
Expand All @@ -33,6 +36,7 @@ tsify = "0.5"
wasm-bindgen = "0.2"
# web-sys provides `console::log` and is useful during debugging.
web-sys = { version = "0.3", features = ["console"] }
serde-wasm-bindgen = "0.6"

[dev-dependencies]
hex.workspace = true
Expand Down
4 changes: 4 additions & 0 deletions wasm-wrappers/WASM-API.md
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,10 @@ ScriptHash and ClassicMultisig destinations are not supported.
Given inputs as bytes, outputs as bytes, and flags settings, this function returns
the transaction that contains them all, as bytes.

### Function: `decode_signed_transaction_to_js`

Decodes a signed transaction from its binary encoding into a JavaScript object.

### Function: `encode_witness_no_signature`

Encode an input witness of the variant that contains no signature.
Expand Down
Loading
Loading