inject the network ID into the hash chain and the arguments hash
Signed-off-by: Uncle Stinky <uncle.stinky@ghostchain.io>
This commit is contained in:
parent
cc45fb5f9c
commit
414604f296
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "ghost-weaver"
|
name = "ghost-weaver"
|
||||||
version = "0.0.8"
|
version = "0.0.9"
|
||||||
description = "Weaving a secure cryptographic tapestry across different external chains."
|
description = "Weaving a secure cryptographic tapestry across different external chains."
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
authors.workspace = true
|
authors.workspace = true
|
||||||
|
|||||||
@ -8,7 +8,8 @@ use sp_std::vec;
|
|||||||
use ghost_helpers::networks::NetworkDataBuilder;
|
use ghost_helpers::networks::NetworkDataBuilder;
|
||||||
|
|
||||||
fn prepare_pallet<T: Config>(
|
fn prepare_pallet<T: Config>(
|
||||||
authorities_len: u32
|
authorities_len: u32,
|
||||||
|
maybe_network_id: Option<u64>,
|
||||||
) -> (NetworkIdOf<T>, T::AuthorityId, AuthIndex) {
|
) -> (NetworkIdOf<T>, T::AuthorityId, AuthIndex) {
|
||||||
let authority = T::AuthorityId::generate_pair(None);
|
let authority = T::AuthorityId::generate_pair(None);
|
||||||
let authorities = vec![authority.clone(); authorities_len as usize];
|
let authorities = vec![authority.clone(); authorities_len as usize];
|
||||||
@ -18,7 +19,9 @@ fn prepare_pallet<T: Config>(
|
|||||||
|
|
||||||
Authorities::<T>::put(bounded_authorities);
|
Authorities::<T>::put(bounded_authorities);
|
||||||
|
|
||||||
let network_id = NetworkIdOf::<T>::default();
|
let network_id_u64 = maybe_network_id.unwrap_or_default();
|
||||||
|
let network_id: NetworkIdOf<T> = network_id_u64.unique_saturated_into();
|
||||||
|
|
||||||
let network_data = NetworkDataBuilder::default()
|
let network_data = NetworkDataBuilder::default()
|
||||||
.with_network_type(NetworkType::Utxo)
|
.with_network_type(NetworkType::Utxo)
|
||||||
.with_gatekeeper(
|
.with_gatekeeper(
|
||||||
@ -42,7 +45,7 @@ mod benchmarks {
|
|||||||
fn extend_warp(
|
fn extend_warp(
|
||||||
a: Linear<1, { T::MaxAuthorities::get() as u32 }>,
|
a: Linear<1, { T::MaxAuthorities::get() as u32 }>,
|
||||||
) -> Result<(), BenchmarkError> {
|
) -> Result<(), BenchmarkError> {
|
||||||
let (network_id, authority, authority_index) = prepare_pallet::<T>(a);
|
let (network_id, authority, authority_index) = prepare_pallet::<T>(a, None);
|
||||||
|
|
||||||
TapestryDrafts::<T>::remove(&network_id);
|
TapestryDrafts::<T>::remove(&network_id);
|
||||||
|
|
||||||
@ -73,7 +76,7 @@ mod benchmarks {
|
|||||||
let next_session = weaving_session + 1;
|
let next_session = weaving_session + 1;
|
||||||
let root_hash = H256::repeat_byte(0x69);
|
let root_hash = H256::repeat_byte(0x69);
|
||||||
|
|
||||||
let (network_id, authority, authority_index) = prepare_pallet::<T>(a);
|
let (network_id, authority, authority_index) = prepare_pallet::<T>(a, None);
|
||||||
|
|
||||||
let tapestry_key = (network_id, weaving_session, next_session, root_hash);
|
let tapestry_key = (network_id, weaving_session, next_session, root_hash);
|
||||||
TapestryStrands::<T>::mutate(&tapestry_key, |tapestry| {
|
TapestryStrands::<T>::mutate(&tapestry_key, |tapestry| {
|
||||||
@ -139,7 +142,7 @@ mod benchmarks {
|
|||||||
) -> Result<(), BenchmarkError> {
|
) -> Result<(), BenchmarkError> {
|
||||||
let session = 69;
|
let session = 69;
|
||||||
let max_history_depth = a as usize;
|
let max_history_depth = a as usize;
|
||||||
let (network_id, _, _) = prepare_pallet::<T>(1);
|
let (network_id, _, _) = prepare_pallet::<T>(1, None);
|
||||||
|
|
||||||
// Real world tx at block #481838
|
// Real world tx at block #481838
|
||||||
// Block https://blockstream.info/block/0000000000000000011bdccb39e19e942a60edffdccd9779653c5b46b337904a
|
// Block https://blockstream.info/block/0000000000000000011bdccb39e19e942a60edffdccd9779653c5b46b337904a
|
||||||
@ -316,7 +319,7 @@ mod benchmarks {
|
|||||||
);
|
);
|
||||||
|
|
||||||
let thread_proof = ThreadProof::UtxoThreadProof(utxo_thread_proof);
|
let thread_proof = ThreadProof::UtxoThreadProof(utxo_thread_proof);
|
||||||
let pulled_thread_key = thread_proof.get_unique_key(session);
|
let pulled_thread_key = thread_proof.get_unique_key(session, network_id);
|
||||||
|
|
||||||
assert!(!PulledThreads::<T>::contains_key(&pulled_thread_key));
|
assert!(!PulledThreads::<T>::contains_key(&pulled_thread_key));
|
||||||
|
|
||||||
@ -330,14 +333,15 @@ mod benchmarks {
|
|||||||
|
|
||||||
#[benchmark]
|
#[benchmark]
|
||||||
fn pull_evm_thread() -> Result<(), BenchmarkError> {
|
fn pull_evm_thread() -> Result<(), BenchmarkError> {
|
||||||
let session = 69;
|
let session = 0;
|
||||||
let (network_id, _, _) = prepare_pallet::<T>(1);
|
let sepolia_network_id = 11155111;
|
||||||
|
let (network_id, _, _) = prepare_pallet::<T>(1, Some(sepolia_network_id));
|
||||||
|
|
||||||
// https://sepolia.etherscan.io/address/0x81acdf2da6b50d806c96aecd9a498a5359e373c0#readContract
|
// https://sepolia.etherscan.io/address/0x7fec11e652f4d54e8cf11c4b52c360380332f2bd#readContract
|
||||||
// getRoot: session 0, atBlock 11660400
|
// getRoot: session 0, atBlock 11716130
|
||||||
|
|
||||||
let root_string =
|
let root_string =
|
||||||
hex::decode("28d1e6b476b03a464f74d531d532572db29d6b57349e4f17f84e92843f6c4ee7")
|
hex::decode("07f4a5ba4750d9ddfc080429287cbcbde7464aa2f8ae13feaade0dcb45ca6129")
|
||||||
.expect("EVM Root hex should be valid");
|
.expect("EVM Root hex should be valid");
|
||||||
let expected_root = H256::from_slice(&root_string);
|
let expected_root = H256::from_slice(&root_string);
|
||||||
LoomStates::<T>::insert(&network_id, &session, expected_root);
|
LoomStates::<T>::insert(&network_id, &session, expected_root);
|
||||||
@ -352,8 +356,8 @@ mod benchmarks {
|
|||||||
let transfer_amount: BalanceOf<T> = 420u64.unique_saturated_into();
|
let transfer_amount: BalanceOf<T> = 420u64.unique_saturated_into();
|
||||||
|
|
||||||
let proof = vec![
|
let proof = vec![
|
||||||
H256::from_slice(&hex::decode("c5354289f0397c916949373043eb1d5ea99447f67fe014324d96c58ef02a2d11").expect("Proof should be valid")),
|
H256::from_slice(&hex::decode("7d831a4be9e37572687117870c3f96669a66bf07971e4fd705a36a0a4d6365b0").expect("Proof should be valid")),
|
||||||
H256::from_slice(&hex::decode("da1fbdfefa1e9aedfedcfc48fb17cb0e731529f7a3695114e0a9caa1989dd420").expect("Proof should be valid")),
|
H256::from_slice(&hex::decode("9f00b99751b7ccea1903949210408edb3ce50343985708c36a0b1d44e0a7628c").expect("Proof should be valid")),
|
||||||
H256::from_slice(&hex::decode("1c792b14bf66f82af36f00f5fba7014fa0c1e2ff3c7c273bfe523c1acf67dc3f").expect("Proof should be valid")),
|
H256::from_slice(&hex::decode("1c792b14bf66f82af36f00f5fba7014fa0c1e2ff3c7c273bfe523c1acf67dc3f").expect("Proof should be valid")),
|
||||||
H256::from_slice(&hex::decode("5fa080a686a5a0d05c3d4822fd54d632dc9cc04b1616046eba2ce499eb9af79f").expect("Proof should be valid")),
|
H256::from_slice(&hex::decode("5fa080a686a5a0d05c3d4822fd54d632dc9cc04b1616046eba2ce499eb9af79f").expect("Proof should be valid")),
|
||||||
H256::from_slice(&hex::decode("5eb949690a0404abf4cebafc7cfffa382191b7dd9e7df778581e6fb78efab35f").expect("Proof should be valid")),
|
H256::from_slice(&hex::decode("5eb949690a0404abf4cebafc7cfffa382191b7dd9e7df778581e6fb78efab35f").expect("Proof should be valid")),
|
||||||
@ -362,14 +366,14 @@ mod benchmarks {
|
|||||||
H256::from_slice(&hex::decode("de9c446fab46a8d27db1e3100f275a777d385b44e3cbc045cabac9da36cae040").expect("Proof should be valid")),
|
H256::from_slice(&hex::decode("de9c446fab46a8d27db1e3100f275a777d385b44e3cbc045cabac9da36cae040").expect("Proof should be valid")),
|
||||||
];
|
];
|
||||||
let slots = vec![H256::from_slice(
|
let slots = vec![H256::from_slice(
|
||||||
&hex::decode("2e474dabf492786b3505d7b7cf0bf07c9dbce92c91982fa7344c77e24fd4310d")
|
&hex::decode("f6182b8c276793f53d1820ad0405665177516e46e40af45e0dfea73c39a2306e")
|
||||||
.expect("Slot should be valid hex"),
|
.expect("Slot should be valid hex"),
|
||||||
)];
|
)];
|
||||||
|
|
||||||
let evm_thread_proof = EvmThreadProof::new(0, 1, receiver_account, transfer_amount, proof, slots);
|
let evm_thread_proof = EvmThreadProof::new(0, 1, receiver_account, transfer_amount, proof, slots);
|
||||||
|
|
||||||
let thread_proof = ThreadProof::EvmThreadProof(evm_thread_proof);
|
let thread_proof = ThreadProof::EvmThreadProof(evm_thread_proof);
|
||||||
let pulled_thread_key = thread_proof.get_unique_key(session);
|
let pulled_thread_key = thread_proof.get_unique_key(session, network_id);
|
||||||
|
|
||||||
assert!(!PulledThreads::<T>::contains_key(&pulled_thread_key));
|
assert!(!PulledThreads::<T>::contains_key(&pulled_thread_key));
|
||||||
|
|
||||||
|
|||||||
@ -439,7 +439,7 @@ pub mod pallet {
|
|||||||
.ok_or(Error::<T>::NonExistentNetworkId)?;
|
.ok_or(Error::<T>::NonExistentNetworkId)?;
|
||||||
|
|
||||||
let root_hash = LoomStates::<T>::get(&network_id, &session);
|
let root_hash = LoomStates::<T>::get(&network_id, &session);
|
||||||
let pulled_thread_key = thread_proof.get_unique_key(session);
|
let pulled_thread_key = thread_proof.get_unique_key(session, network_id);
|
||||||
|
|
||||||
ensure!(
|
ensure!(
|
||||||
!PulledThreads::<T>::contains_key(&pulled_thread_key),
|
!PulledThreads::<T>::contains_key(&pulled_thread_key),
|
||||||
@ -447,7 +447,7 @@ pub mod pallet {
|
|||||||
);
|
);
|
||||||
|
|
||||||
let (receiver_account, amount) = thread_proof
|
let (receiver_account, amount) = thread_proof
|
||||||
.verify_thread_proof(root_hash, &network_data.gatekeeper)
|
.verify_thread_proof(root_hash, network_id, &network_data.gatekeeper)
|
||||||
.ok_or(Error::<T>::InvalidMerkleProof)?;
|
.ok_or(Error::<T>::InvalidMerkleProof)?;
|
||||||
|
|
||||||
let receiver_bytes: &[u8; 32] = receiver_account.as_ref();
|
let receiver_bytes: &[u8; 32] = receiver_account.as_ref();
|
||||||
|
|||||||
@ -560,7 +560,7 @@ fn offchain_worker_should_fetch_hash_and_submit_unsigned_tx() {
|
|||||||
fn should_successfully_pull_evm_thread_and_mint_currency() {
|
fn should_successfully_pull_evm_thread_and_mint_currency() {
|
||||||
let pair = AuthorityPair::from_string("//Alice", None).expect("Should be valid seed");
|
let pair = AuthorityPair::from_string("//Alice", None).expect("Should be valid seed");
|
||||||
|
|
||||||
let network_id = 1;
|
let network_id = 11155111;
|
||||||
let network_data = NetworkDataBuilder::default()
|
let network_data = NetworkDataBuilder::default()
|
||||||
.with_network_type(NetworkType::Evm)
|
.with_network_type(NetworkType::Evm)
|
||||||
.build();
|
.build();
|
||||||
@ -568,204 +568,78 @@ fn should_successfully_pull_evm_thread_and_mint_currency() {
|
|||||||
let authorities = vec![pair.clone()];
|
let authorities = vec![pair.clone()];
|
||||||
let networks = vec![(network_id, network_data, Default::default())];
|
let networks = vec![(network_id, network_data, Default::default())];
|
||||||
|
|
||||||
// Contract address: 0x9a52C28dA655b69d8ddc430d6ebD04630BA0e845
|
// Contract address: 0x7fec11e652f4d54e8cf11c4b52c360380332f2bd
|
||||||
//
|
//
|
||||||
// three inserts
|
// three inserts
|
||||||
// 69 sfJ9hc4A7r578XM35nd48B3FWcd33XjpVnAbGC5tvtwthMWdU - 0xc477f0a42fdd861485bd854c7a5851614ea163bd295f7844e1c5493d662fdc4e
|
// 69 sfJ9hc4A7r578XM35nd48B3FWcd33XjpVnAbGC5tvtwthMWdU - 0xc477f0a42fdd861485bd854c7a5851614ea163bd295f7844e1c5493d662fdc4e
|
||||||
// 420 sfDxNicCEPts6CVttVMPCs2eoymDpQahu1GUVyGPWu6dhwADJ - 0x0ae3ba32f8555fe3031461e2cb6feeadb67029ef7490b982824fc90751a4cb3e
|
// 420 sfDxNicCEPts6CVttVMPCs2eoymDpQahu1GUVyGPWu6dhwADJ - 0x0ae3ba32f8555fe3031461e2cb6feeadb67029ef7490b982824fc90751a4cb3e
|
||||||
// 1337 sfH6zJ63fcxrFAZ1RmiHbxgy2t3sEufY26WdsBSS359AzJd4w - 0x962a2794f66c89e55d9b9692ce59f67345b99f6fddb51d90462c7eca8b5a7e1b
|
// 1337 sfH6zJ63fcxrFAZ1RmiHbxgy2t3sEufY26WdsBSS359AzJd4w - 0x962a2794f66c89e55d9b9692ce59f67345b99f6fddb51d90462c7eca8b5a7e1b
|
||||||
|
|
||||||
// https://sepolia.etherscan.io/address/0x81acdf2da6b50d806c96aecd9a498a5359e373c0#readContract
|
// https://sepolia.etherscan.io/address/0x7fec11e652f4d54e8cf11c4b52c360380332f2bd#readContract
|
||||||
// getRoot: atBlock 11660400, globalIndexes from 0 to 2
|
// getRoot: atBlock 11716130, globalIndexes from 0 to 2
|
||||||
let inserts = vec![
|
let inserts = vec![
|
||||||
(
|
(
|
||||||
0,
|
0,
|
||||||
hex::decode("c477f0a42fdd861485bd854c7a5851614ea163bd295f7844e1c5493d662fdc4e")
|
hex::decode("c477f0a42fdd861485bd854c7a5851614ea163bd295f7844e1c5493d662fdc4e").expect("Bytes32 from EVM should be valid"),
|
||||||
.expect("Bytes32 from EVM should be valid"),
|
|
||||||
69u64,
|
69u64,
|
||||||
vec![
|
vec![
|
||||||
H256::from_slice(
|
H256::from_slice(&hex::decode("2d931b11b1652669a04e7b5b50418f5e1e2fabb6791dabc9a196e719ad5cf9c6").expect("Proof should be valid")),
|
||||||
&hex::decode(
|
H256::from_slice(&hex::decode("9f00b99751b7ccea1903949210408edb3ce50343985708c36a0b1d44e0a7628c").expect("Proof should be valid")),
|
||||||
"675a2e7b05b8b3932cd0faf88f1bc29767b7462667f56d051b8d5325bda0ee73",
|
H256::from_slice(&hex::decode("1c792b14bf66f82af36f00f5fba7014fa0c1e2ff3c7c273bfe523c1acf67dc3f").expect("Proof should be valid")),
|
||||||
)
|
H256::from_slice(&hex::decode("5fa080a686a5a0d05c3d4822fd54d632dc9cc04b1616046eba2ce499eb9af79f").expect("Proof should be valid")),
|
||||||
.expect("Proof should be valid"),
|
H256::from_slice(&hex::decode("5eb949690a0404abf4cebafc7cfffa382191b7dd9e7df778581e6fb78efab35f").expect("Proof should be valid")),
|
||||||
),
|
H256::from_slice(&hex::decode("d364c9d5dadad4569b6dd47f7feabafa3571f842434425548335ac6e690dd071").expect("Proof should be valid")),
|
||||||
H256::from_slice(
|
H256::from_slice(&hex::decode("68d8bc5b77979c1a6702334f529f5783f79e942fd2cd03f6e55ac2cf496e849f").expect("Proof should be valid")),
|
||||||
&hex::decode(
|
H256::from_slice(&hex::decode("de9c446fab46a8d27db1e3100f275a777d385b44e3cbc045cabac9da36cae040").expect("Proof should be valid")),
|
||||||
"da1fbdfefa1e9aedfedcfc48fb17cb0e731529f7a3695114e0a9caa1989dd420",
|
|
||||||
)
|
|
||||||
.expect("Proof should be valid"),
|
|
||||||
),
|
|
||||||
H256::from_slice(
|
|
||||||
&hex::decode(
|
|
||||||
"1c792b14bf66f82af36f00f5fba7014fa0c1e2ff3c7c273bfe523c1acf67dc3f",
|
|
||||||
)
|
|
||||||
.expect("Proof should be valid"),
|
|
||||||
),
|
|
||||||
H256::from_slice(
|
|
||||||
&hex::decode(
|
|
||||||
"5fa080a686a5a0d05c3d4822fd54d632dc9cc04b1616046eba2ce499eb9af79f",
|
|
||||||
)
|
|
||||||
.expect("Proof should be valid"),
|
|
||||||
),
|
|
||||||
H256::from_slice(
|
|
||||||
&hex::decode(
|
|
||||||
"5eb949690a0404abf4cebafc7cfffa382191b7dd9e7df778581e6fb78efab35f",
|
|
||||||
)
|
|
||||||
.expect("Proof should be valid"),
|
|
||||||
),
|
|
||||||
H256::from_slice(
|
|
||||||
&hex::decode(
|
|
||||||
"d364c9d5dadad4569b6dd47f7feabafa3571f842434425548335ac6e690dd071",
|
|
||||||
)
|
|
||||||
.expect("Proof should be valid"),
|
|
||||||
),
|
|
||||||
H256::from_slice(
|
|
||||||
&hex::decode(
|
|
||||||
"68d8bc5b77979c1a6702334f529f5783f79e942fd2cd03f6e55ac2cf496e849f",
|
|
||||||
)
|
|
||||||
.expect("Proof should be valid"),
|
|
||||||
),
|
|
||||||
H256::from_slice(
|
|
||||||
&hex::decode(
|
|
||||||
"de9c446fab46a8d27db1e3100f275a777d385b44e3cbc045cabac9da36cae040",
|
|
||||||
)
|
|
||||||
.expect("Proof should be valid"),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
vec![H256::from_slice(
|
vec![H256::from_slice(
|
||||||
&hex::decode("350a78f78c810898b7c60ddba671543bfbe683ffb0ac393df0e132f607b5f738")
|
&hex::decode("f494b2065ca61f2af007a3dd5f1f3d228a3ad09f4f7b7c5ef3eeb3aee6718ee2").expect("Slot should be valid hex"),
|
||||||
.expect("Slot should be valid hex"),
|
|
||||||
)],
|
)],
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
1,
|
1,
|
||||||
hex::decode("0ae3ba32f8555fe3031461e2cb6feeadb67029ef7490b982824fc90751a4cb3e")
|
hex::decode("0ae3ba32f8555fe3031461e2cb6feeadb67029ef7490b982824fc90751a4cb3e").expect("Bytes32 from EVM should be valid"),
|
||||||
.expect("Bytes32 from EVM should be valid"),
|
|
||||||
420u64,
|
420u64,
|
||||||
vec![
|
vec![
|
||||||
H256::from_slice(
|
H256::from_slice(&hex::decode("7d831a4be9e37572687117870c3f96669a66bf07971e4fd705a36a0a4d6365b0").expect("Proof should be valid")),
|
||||||
&hex::decode(
|
H256::from_slice(&hex::decode("9f00b99751b7ccea1903949210408edb3ce50343985708c36a0b1d44e0a7628c").expect("Proof should be valid")),
|
||||||
"c5354289f0397c916949373043eb1d5ea99447f67fe014324d96c58ef02a2d11",
|
H256::from_slice(&hex::decode("1c792b14bf66f82af36f00f5fba7014fa0c1e2ff3c7c273bfe523c1acf67dc3f").expect("Proof should be valid")),
|
||||||
)
|
H256::from_slice(&hex::decode("5fa080a686a5a0d05c3d4822fd54d632dc9cc04b1616046eba2ce499eb9af79f").expect("Proof should be valid")),
|
||||||
.expect("Proof should be valid"),
|
H256::from_slice(&hex::decode("5eb949690a0404abf4cebafc7cfffa382191b7dd9e7df778581e6fb78efab35f").expect("Proof should be valid")),
|
||||||
),
|
H256::from_slice(&hex::decode("d364c9d5dadad4569b6dd47f7feabafa3571f842434425548335ac6e690dd071").expect("Proof should be valid")),
|
||||||
H256::from_slice(
|
H256::from_slice(&hex::decode("68d8bc5b77979c1a6702334f529f5783f79e942fd2cd03f6e55ac2cf496e849f").expect("Proof should be valid")),
|
||||||
&hex::decode(
|
H256::from_slice(&hex::decode("de9c446fab46a8d27db1e3100f275a777d385b44e3cbc045cabac9da36cae040").expect("Proof should be valid")),
|
||||||
"da1fbdfefa1e9aedfedcfc48fb17cb0e731529f7a3695114e0a9caa1989dd420",
|
|
||||||
)
|
|
||||||
.expect("Proof should be valid"),
|
|
||||||
),
|
|
||||||
H256::from_slice(
|
|
||||||
&hex::decode(
|
|
||||||
"1c792b14bf66f82af36f00f5fba7014fa0c1e2ff3c7c273bfe523c1acf67dc3f",
|
|
||||||
)
|
|
||||||
.expect("Proof should be valid"),
|
|
||||||
),
|
|
||||||
H256::from_slice(
|
|
||||||
&hex::decode(
|
|
||||||
"5fa080a686a5a0d05c3d4822fd54d632dc9cc04b1616046eba2ce499eb9af79f",
|
|
||||||
)
|
|
||||||
.expect("Proof should be valid"),
|
|
||||||
),
|
|
||||||
H256::from_slice(
|
|
||||||
&hex::decode(
|
|
||||||
"5eb949690a0404abf4cebafc7cfffa382191b7dd9e7df778581e6fb78efab35f",
|
|
||||||
)
|
|
||||||
.expect("Proof should be valid"),
|
|
||||||
),
|
|
||||||
H256::from_slice(
|
|
||||||
&hex::decode(
|
|
||||||
"d364c9d5dadad4569b6dd47f7feabafa3571f842434425548335ac6e690dd071",
|
|
||||||
)
|
|
||||||
.expect("Proof should be valid"),
|
|
||||||
),
|
|
||||||
H256::from_slice(
|
|
||||||
&hex::decode(
|
|
||||||
"68d8bc5b77979c1a6702334f529f5783f79e942fd2cd03f6e55ac2cf496e849f",
|
|
||||||
)
|
|
||||||
.expect("Proof should be valid"),
|
|
||||||
),
|
|
||||||
H256::from_slice(
|
|
||||||
&hex::decode(
|
|
||||||
"de9c446fab46a8d27db1e3100f275a777d385b44e3cbc045cabac9da36cae040",
|
|
||||||
)
|
|
||||||
.expect("Proof should be valid"),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
vec![H256::from_slice(
|
vec![H256::from_slice(
|
||||||
&hex::decode("2e474dabf492786b3505d7b7cf0bf07c9dbce92c91982fa7344c77e24fd4310d")
|
&hex::decode("f6182b8c276793f53d1820ad0405665177516e46e40af45e0dfea73c39a2306e").expect("Slot should be valid hex"),
|
||||||
.expect("Slot should be valid hex"),
|
|
||||||
)],
|
)],
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
2,
|
2,
|
||||||
hex::decode("962a2794f66c89e55d9b9692ce59f67345b99f6fddb51d90462c7eca8b5a7e1b")
|
hex::decode("962a2794f66c89e55d9b9692ce59f67345b99f6fddb51d90462c7eca8b5a7e1b").expect("Bytes32 from EVM should be valid"),
|
||||||
.expect("Bytes32 from EVM should be valid"),
|
|
||||||
1337u64,
|
1337u64,
|
||||||
vec![
|
vec![
|
||||||
H256::from_slice(
|
H256::from_slice(&hex::decode("f39a869f62e75cf5f0bf914688a6b289caf2049435d8e68c5c5e6d05e44913f3").expect("Proof should be valid")),
|
||||||
&hex::decode(
|
H256::from_slice(&hex::decode("385de173dc8295d4153b2de3bd705dd96556c8c316a996b3e56adce0970ffa36").expect("Proof should be valid")),
|
||||||
"f39a869f62e75cf5f0bf914688a6b289caf2049435d8e68c5c5e6d05e44913f3",
|
H256::from_slice(&hex::decode("1c792b14bf66f82af36f00f5fba7014fa0c1e2ff3c7c273bfe523c1acf67dc3f").expect("Proof should be valid")),
|
||||||
)
|
H256::from_slice(&hex::decode("5fa080a686a5a0d05c3d4822fd54d632dc9cc04b1616046eba2ce499eb9af79f").expect("Proof should be valid")),
|
||||||
.expect("Proof should be valid"),
|
H256::from_slice(&hex::decode("5eb949690a0404abf4cebafc7cfffa382191b7dd9e7df778581e6fb78efab35f").expect("Proof should be valid")),
|
||||||
),
|
H256::from_slice(&hex::decode("d364c9d5dadad4569b6dd47f7feabafa3571f842434425548335ac6e690dd071").expect("Proof should be valid")),
|
||||||
H256::from_slice(
|
H256::from_slice(&hex::decode("68d8bc5b77979c1a6702334f529f5783f79e942fd2cd03f6e55ac2cf496e849f").expect("Proof should be valid")),
|
||||||
&hex::decode(
|
H256::from_slice(&hex::decode("de9c446fab46a8d27db1e3100f275a777d385b44e3cbc045cabac9da36cae040").expect("Proof should be valid")),
|
||||||
"e0090094ce1d7af8a81ba78bef4b137c1ab32d20d5487224a9f8df95b516c1e4",
|
|
||||||
)
|
|
||||||
.expect("Proof should be valid"),
|
|
||||||
),
|
|
||||||
H256::from_slice(
|
|
||||||
&hex::decode(
|
|
||||||
"1c792b14bf66f82af36f00f5fba7014fa0c1e2ff3c7c273bfe523c1acf67dc3f",
|
|
||||||
)
|
|
||||||
.expect("Proof should be valid"),
|
|
||||||
),
|
|
||||||
H256::from_slice(
|
|
||||||
&hex::decode(
|
|
||||||
"5fa080a686a5a0d05c3d4822fd54d632dc9cc04b1616046eba2ce499eb9af79f",
|
|
||||||
)
|
|
||||||
.expect("Proof should be valid"),
|
|
||||||
),
|
|
||||||
H256::from_slice(
|
|
||||||
&hex::decode(
|
|
||||||
"5eb949690a0404abf4cebafc7cfffa382191b7dd9e7df778581e6fb78efab35f",
|
|
||||||
)
|
|
||||||
.expect("Proof should be valid"),
|
|
||||||
),
|
|
||||||
H256::from_slice(
|
|
||||||
&hex::decode(
|
|
||||||
"d364c9d5dadad4569b6dd47f7feabafa3571f842434425548335ac6e690dd071",
|
|
||||||
)
|
|
||||||
.expect("Proof should be valid"),
|
|
||||||
),
|
|
||||||
H256::from_slice(
|
|
||||||
&hex::decode(
|
|
||||||
"68d8bc5b77979c1a6702334f529f5783f79e942fd2cd03f6e55ac2cf496e849f",
|
|
||||||
)
|
|
||||||
.expect("Proof should be valid"),
|
|
||||||
),
|
|
||||||
H256::from_slice(
|
|
||||||
&hex::decode(
|
|
||||||
"de9c446fab46a8d27db1e3100f275a777d385b44e3cbc045cabac9da36cae040",
|
|
||||||
)
|
|
||||||
.expect("Proof should be valid"),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
vec![H256::from_slice(
|
vec![H256::from_slice(
|
||||||
&hex::decode("bde870fce92d701a7a5d6f63003e1cd2cb61c3266fc1be256844b8ca61d9c9ab")
|
&hex::decode("2f52c7d2d3f4167c436f3b6cc0a7d944a45846ba87f74998100b83122d5eb0ad").expect("Slot should be valid hex"),
|
||||||
.expect("Slot should be valid hex"),
|
|
||||||
)],
|
)],
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
|
|
||||||
new_test_ext(authorities, networks).execute_with(|| {
|
new_test_ext(authorities, networks).execute_with(|| {
|
||||||
// https://sepolia.etherscan.io/address/0x81acdf2da6b50d806c96aecd9a498a5359e373c0#readContract
|
// https://sepolia.etherscan.io/address/0x7fec11e652f4d54e8cf11c4b52c360380332f2bd#readContract
|
||||||
// getRoot: session 0, atBlock 11660400
|
// getRoot: session 0, atBlock 11716130
|
||||||
let session = 0;
|
let session = 0;
|
||||||
let root_string =
|
let root_string =
|
||||||
hex::decode("28d1e6b476b03a464f74d531d532572db29d6b57349e4f17f84e92843f6c4ee7")
|
hex::decode("07f4a5ba4750d9ddfc080429287cbcbde7464aa2f8ae13feaade0dcb45ca6129")
|
||||||
.expect("Root hex should be valid");
|
.expect("Root hex should be valid");
|
||||||
let expected_root = H256::from_slice(&root_string);
|
let expected_root = H256::from_slice(&root_string);
|
||||||
LoomStates::<TestRuntime>::insert(&network_id, &session, expected_root);
|
LoomStates::<TestRuntime>::insert(&network_id, &session, expected_root);
|
||||||
@ -795,7 +669,7 @@ fn should_successfully_pull_evm_thread_and_mint_currency() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
let thread_info = ThreadProof::EvmThreadProof(evm_thread_proof);
|
let thread_info = ThreadProof::EvmThreadProof(evm_thread_proof);
|
||||||
let pulled_thread_key = thread_info.get_unique_key(session);
|
let pulled_thread_key = thread_info.get_unique_key(session, network_id);
|
||||||
|
|
||||||
assert_eq!(Balances::free_balance(&receiver_account), 0);
|
assert_eq!(Balances::free_balance(&receiver_account), 0);
|
||||||
assert!(!PulledThreads::<TestRuntime>::contains_key(
|
assert!(!PulledThreads::<TestRuntime>::contains_key(
|
||||||
@ -806,8 +680,7 @@ fn should_successfully_pull_evm_thread_and_mint_currency() {
|
|||||||
network_id,
|
network_id,
|
||||||
session,
|
session,
|
||||||
thread_info
|
thread_info
|
||||||
)
|
).is_ok());
|
||||||
.is_ok());
|
|
||||||
|
|
||||||
assert!(PulledThreads::<TestRuntime>::contains_key(
|
assert!(PulledThreads::<TestRuntime>::contains_key(
|
||||||
&pulled_thread_key
|
&pulled_thread_key
|
||||||
@ -887,7 +760,7 @@ fn should_successfully_pull_utxo_thread_and_mint_currency() {
|
|||||||
|
|
||||||
let utxo_thread_proof = UtxoThreadProof::new(payload.0, payload.1, payload.2);
|
let utxo_thread_proof = UtxoThreadProof::new(payload.0, payload.1, payload.2);
|
||||||
let thread_info = ThreadProof::UtxoThreadProof(utxo_thread_proof);
|
let thread_info = ThreadProof::UtxoThreadProof(utxo_thread_proof);
|
||||||
let pulled_thread_key = thread_info.get_unique_key(session);
|
let pulled_thread_key = thread_info.get_unique_key(session, network_id);
|
||||||
|
|
||||||
assert_eq!(Balances::free_balance(&receiver_account), 0);
|
assert_eq!(Balances::free_balance(&receiver_account), 0);
|
||||||
assert!(!PulledThreads::<TestRuntime>::contains_key(
|
assert!(!PulledThreads::<TestRuntime>::contains_key(
|
||||||
|
|||||||
@ -288,31 +288,40 @@ where
|
|||||||
Balance: Copy + Clone + Eq + PartialEq + UniqueSaturatedInto<u128>,
|
Balance: Copy + Clone + Eq + PartialEq + UniqueSaturatedInto<u128>,
|
||||||
u64: UniqueSaturatedInto<Balance>,
|
u64: UniqueSaturatedInto<Balance>,
|
||||||
{
|
{
|
||||||
pub fn is_evm_proof_correct(&self) -> bool {
|
pub fn verify_thread_proof<NetworkId>(
|
||||||
|
&self,
|
||||||
|
root_hash: H256,
|
||||||
|
network_id: NetworkId,
|
||||||
|
gatekeeper: &[u8]
|
||||||
|
) -> Option<(AccountId32, Balance)>
|
||||||
|
where
|
||||||
|
NetworkId: Copy + Clone + Eq + PartialEq + UniqueSaturatedInto<u64>,
|
||||||
|
{
|
||||||
match self {
|
match self {
|
||||||
Self::EvmThreadProof(_) => true,
|
Self::UtxoThreadProof(utxo_thread) => {
|
||||||
Self::UtxoThreadProof(_) => false,
|
utxo_thread.verify_thread_proof(root_hash, gatekeeper)
|
||||||
|
},
|
||||||
|
Self::EvmThreadProof(evm_thread) => {
|
||||||
|
evm_thread.verify_thread_proof(root_hash, network_id)
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_utxo_proof_correct(&self) -> bool {
|
pub fn get_unique_key<NetworkId>(
|
||||||
|
&self,
|
||||||
|
session: WeavingSession,
|
||||||
|
network_id: NetworkId,
|
||||||
|
) -> H256
|
||||||
|
where
|
||||||
|
NetworkId: Copy + Clone + Eq + PartialEq + UniqueSaturatedInto<u64>,
|
||||||
|
{
|
||||||
match self {
|
match self {
|
||||||
Self::UtxoThreadProof(_) => true,
|
Self::EvmThreadProof(thread_info) => {
|
||||||
Self::EvmThreadProof(_) => false,
|
thread_info.get_unique_key(session, network_id)
|
||||||
}
|
},
|
||||||
}
|
Self::UtxoThreadProof(utxo_thread) => {
|
||||||
|
utxo_thread.get_unique_key(network_id)
|
||||||
pub fn verify_thread_proof(&self, root_hash: H256, gatekeeper: &[u8]) -> Option<(AccountId32, Balance)> {
|
},
|
||||||
match self {
|
|
||||||
Self::UtxoThreadProof(utxo_thread) => utxo_thread.verify_thread_proof(root_hash, gatekeeper),
|
|
||||||
Self::EvmThreadProof(evm_thread) => evm_thread.verify_thread_proof(root_hash),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_unique_key(&self, session: WeavingSession) -> H256 {
|
|
||||||
match self {
|
|
||||||
Self::EvmThreadProof(thread_info) => thread_info.get_unique_key(session),
|
|
||||||
Self::UtxoThreadProof(utxo_thread) => utxo_thread.get_unique_key(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -331,11 +340,18 @@ impl<Balance> EvmThreadProof<Balance>
|
|||||||
where
|
where
|
||||||
Balance: Copy + Clone + Eq + PartialEq + UniqueSaturatedInto<u128>,
|
Balance: Copy + Clone + Eq + PartialEq + UniqueSaturatedInto<u128>,
|
||||||
{
|
{
|
||||||
pub fn verify_thread_proof(&self, root_hash: H256) -> Option<(AccountId32, Balance)> {
|
pub fn verify_thread_proof<NetworkId>(
|
||||||
|
&self,
|
||||||
|
root_hash: H256,
|
||||||
|
network_id: NetworkId,
|
||||||
|
) -> Option<(AccountId32, Balance)>
|
||||||
|
where
|
||||||
|
NetworkId: Copy + Clone + Eq + PartialEq + UniqueSaturatedInto<u64>,
|
||||||
|
{
|
||||||
if EVM_MERKLE_DEPTH as usize != self.proof.len() { return None; }
|
if EVM_MERKLE_DEPTH as usize != self.proof.len() { return None; }
|
||||||
|
|
||||||
let proof_valid = verify_tree_proof::<SubstrateKeccakHasher, _>(
|
let proof_valid = verify_tree_proof::<SubstrateKeccakHasher, _>(
|
||||||
&self.get_preimage_slice().to_fixed_bytes(),
|
&self.get_preimage_slice(network_id).to_fixed_bytes(),
|
||||||
self.proof.as_ref(),
|
self.proof.as_ref(),
|
||||||
root_hash,
|
root_hash,
|
||||||
self.proof_index,
|
self.proof_index,
|
||||||
@ -346,8 +362,17 @@ where
|
|||||||
Some((self.receiver.clone(), self.amount))
|
Some((self.receiver.clone(), self.amount))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_preimage_slice(&self) -> H256 {
|
fn get_preimage_slice<NetworkId>(&self, network_id: NetworkId) -> H256
|
||||||
|
where
|
||||||
|
NetworkId: Copy + Clone + Eq + PartialEq + UniqueSaturatedInto<u64>,
|
||||||
|
{
|
||||||
let slot_index_usize: usize = self.slot_index.unique_saturated_into();
|
let slot_index_usize: usize = self.slot_index.unique_saturated_into();
|
||||||
|
let slot_index_out_of_range = slot_index_usize >= self.slots.len();
|
||||||
|
let too_many_slots_given = (EVM_VALUES_DEPTH as usize) < self.slots.len();
|
||||||
|
|
||||||
|
if slot_index_out_of_range || too_many_slots_given {
|
||||||
|
return SubstrateKeccakHasher::empty();
|
||||||
|
}
|
||||||
|
|
||||||
(slot_index_usize < self.slots.len())
|
(slot_index_usize < self.slots.len())
|
||||||
.then(|| {
|
.then(|| {
|
||||||
@ -356,7 +381,7 @@ where
|
|||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(index, &preimage)| {
|
.map(|(index, &preimage)| {
|
||||||
if index == slot_index_usize {
|
if index == slot_index_usize {
|
||||||
self.compute_arguments_hash()
|
self.compute_arguments_hash(network_id)
|
||||||
} else {
|
} else {
|
||||||
preimage
|
preimage
|
||||||
}
|
}
|
||||||
@ -367,20 +392,55 @@ where
|
|||||||
.unwrap_or(SubstrateKeccakHasher::empty())
|
.unwrap_or(SubstrateKeccakHasher::empty())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_unique_key(&self, session: WeavingSession) -> H256 {
|
pub fn get_unique_key<NetworkId>(
|
||||||
let session_bytes = (session as u64).to_be_bytes();
|
&self,
|
||||||
let slot_bytes = (self.slot_index as u64).to_be_bytes();
|
session: WeavingSession,
|
||||||
let proof_bytes = (self.proof_index as u64).to_be_bytes();
|
network_id: NetworkId,
|
||||||
|
) -> H256
|
||||||
let mut h1 = [0u8; 32]; h1[24..32].copy_from_slice(&session_bytes);
|
where
|
||||||
let mut h2 = [0u8; 32]; h2[24..32].copy_from_slice(&slot_bytes);
|
NetworkId: Copy + Clone + Eq + PartialEq + UniqueSaturatedInto<u64>,
|
||||||
let mut h3 = [0u8; 32]; h3[24..32].copy_from_slice(&proof_bytes);
|
{
|
||||||
|
let metadata: [H256; 4] = [
|
||||||
let metadata: [H256; 3] = [H256::from(h1), H256::from(h2), H256::from(h3)];
|
H256::from_low_u64_be(session as u64),
|
||||||
|
H256::from_low_u64_be(self.slot_index.unique_saturated_into()),
|
||||||
|
H256::from_low_u64_be(self.proof_index.unique_saturated_into()),
|
||||||
|
H256::from_low_u64_be(network_id.unique_saturated_into()),
|
||||||
|
];
|
||||||
|
|
||||||
sequential_hash::<SubstrateBlake2Hasher, _>(metadata)
|
sequential_hash::<SubstrateBlake2Hasher, _>(metadata)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn compute_arguments_hash<NetworkId>(&self, network_id: NetworkId) -> H256
|
||||||
|
where
|
||||||
|
NetworkId: Copy + Clone + Eq + PartialEq + UniqueSaturatedInto<u64>,
|
||||||
|
{
|
||||||
|
let amount_u128: u128 = self.amount.unique_saturated_into();
|
||||||
|
let slot_index_u64: u64 = self.slot_index.unique_saturated_into();
|
||||||
|
let network_id_u64: u64 = network_id.unique_saturated_into();
|
||||||
|
|
||||||
|
let amount_u256 = U256::from(amount_u128);
|
||||||
|
let slot_index_u256 = U256::from(slot_index_u64);
|
||||||
|
let network_id_u256 = U256::from(network_id_u64);
|
||||||
|
|
||||||
|
let mut padded_amount = [0u8; 32];
|
||||||
|
amount_u256.to_big_endian(&mut padded_amount);
|
||||||
|
|
||||||
|
let mut padded_slot_index = [0u8; 32];
|
||||||
|
slot_index_u256.to_big_endian(&mut padded_slot_index);
|
||||||
|
|
||||||
|
let mut padded_network_id = [0u8; 32];
|
||||||
|
network_id_u256.to_big_endian(&mut padded_network_id);
|
||||||
|
|
||||||
|
let inputs: [&[u8]; 4] = [
|
||||||
|
padded_amount.as_ref(),
|
||||||
|
self.receiver.as_ref(),
|
||||||
|
padded_slot_index.as_ref(),
|
||||||
|
padded_network_id.as_ref(),
|
||||||
|
];
|
||||||
|
|
||||||
|
sequential_hash::<SubstrateKeccakHasher, _>(inputs)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn new(
|
pub fn new(
|
||||||
slot_index: ThreadId,
|
slot_index: ThreadId,
|
||||||
proof_index: ThreadId,
|
proof_index: ThreadId,
|
||||||
@ -404,27 +464,6 @@ where
|
|||||||
slots,
|
slots,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compute_arguments_hash(&self) -> H256 {
|
|
||||||
let amount_u128: u128 = self.amount.unique_saturated_into();
|
|
||||||
let amount_u256 = U256::from(amount_u128);
|
|
||||||
|
|
||||||
let slot_index_u64: u64 = self.slot_index.unique_saturated_into();
|
|
||||||
let slot_index_u256 = U256::from(slot_index_u64);
|
|
||||||
|
|
||||||
let mut padded_amount = [0u8; 32];
|
|
||||||
amount_u256.to_big_endian(&mut padded_amount);
|
|
||||||
|
|
||||||
let mut padded_slot_index = [0u8; 32];
|
|
||||||
slot_index_u256.to_big_endian(&mut padded_slot_index);
|
|
||||||
|
|
||||||
let inputs: [&[u8]; 3] = [
|
|
||||||
padded_amount.as_ref(),
|
|
||||||
self.receiver.as_ref(),
|
|
||||||
padded_slot_index.as_ref(),
|
|
||||||
];
|
|
||||||
sequential_hash::<SubstrateKeccakHasher, _>(inputs)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo, MaxEncodedLen)]
|
#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo, MaxEncodedLen)]
|
||||||
@ -447,7 +486,7 @@ impl UtxoThreadProof {
|
|||||||
root_hash: H256,
|
root_hash: H256,
|
||||||
gatekeeper_ref: &[u8],
|
gatekeeper_ref: &[u8],
|
||||||
) -> Option<(AccountId32, Balance)>
|
) -> Option<(AccountId32, Balance)>
|
||||||
where
|
where
|
||||||
Balance: Copy + Clone + Eq + PartialEq + UniqueSaturatedInto<u128>,
|
Balance: Copy + Clone + Eq + PartialEq + UniqueSaturatedInto<u128>,
|
||||||
u64: UniqueSaturatedInto<Balance>,
|
u64: UniqueSaturatedInto<Balance>,
|
||||||
{
|
{
|
||||||
@ -488,10 +527,17 @@ impl UtxoThreadProof {
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_unique_key(&self) -> H256 {
|
pub fn get_unique_key<NetworkId>(&self, network_id: NetworkId) -> H256
|
||||||
|
where
|
||||||
|
NetworkId: Copy + Clone + Eq + PartialEq + UniqueSaturatedInto<u64>,
|
||||||
|
{
|
||||||
|
let network_id_u64: u64 = network_id.unique_saturated_into();
|
||||||
|
let network_id_bytes = network_id_u64.to_be_bytes();
|
||||||
|
|
||||||
let metadata: &[&[u8]] = &[
|
let metadata: &[&[u8]] = &[
|
||||||
self.gettxproof_bytes.as_ref(),
|
self.gettxproof_bytes.as_ref(),
|
||||||
self.getrawtransaction_bytes.as_ref(),
|
self.getrawtransaction_bytes.as_ref(),
|
||||||
|
network_id_bytes.as_ref(),
|
||||||
];
|
];
|
||||||
|
|
||||||
sequential_hash::<SubstrateBlake2Hasher, _>(metadata)
|
sequential_hash::<SubstrateBlake2Hasher, _>(metadata)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user