Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix!: fix the implementation of Axon Tries #1580

Merged
merged 2 commits into from
Nov 27, 2023
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
110 changes: 66 additions & 44 deletions core/api/src/adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use protocol::types::{
Proposal, Receipt, SignedTransaction, TxResp, H160, H256, MAX_BLOCK_GAS_LIMIT, NIL_DATA,
RLP_NULL, U256,
};
use protocol::{async_trait, codec::ProtocolCodec, trie, ProtocolError, ProtocolResult};
use protocol::{async_trait, codec::ProtocolCodec, trie, ProtocolResult};

use core_executor::{
system_contract::metadata::MetadataHandle, AxonExecutor, AxonExecutorReadOnlyAdapter, MPTTrie,
Expand Down Expand Up @@ -239,10 +239,11 @@ where
let storage_mpt_tree = MPTTrie::from_root(account.storage_root, Arc::clone(&self.trie_db))?;

let hash: Hash = BigEndianHash::from_uint(&position);
storage_mpt_tree
let value: H256 = storage_mpt_tree
.get(hash.as_bytes())?
.map(Into::into)
.ok_or_else(|| APIError::Adapter("Can't find this position".to_string()).into())
.map(|v| BigEndianHash::from_uint(&U256::decode(v).unwrap()))
.unwrap_or(H256::zero());
Ok(Bytes::from(value.0.to_vec()))
}

async fn get_proof(
Expand All @@ -253,51 +254,72 @@ where
state_root: Hash,
) -> ProtocolResult<EthAccountProof> {
let state_mpt_tree = MPTTrie::from_root(state_root, Arc::clone(&self.trie_db))?;
let raw_account = state_mpt_tree
.get(address.as_bytes())?
.ok_or_else(|| APIError::Adapter("Can't find this address".to_string()))?;

let account = Account::decode(raw_account).unwrap();

let account_proof = state_mpt_tree
let account_proof: Vec<Hex> = state_mpt_tree
.get_proof(address.as_bytes())?
.into_iter()
.map(Hex::encode)
.collect();

let storage_mpt_tree = MPTTrie::from_root(account.storage_root, Arc::clone(&self.trie_db))?;

let mut storage_proofs = Vec::with_capacity(storage_position.len());

for h in storage_position {
let hash: Hash = BigEndianHash::from_uint(&h);
let proof = EthStorageProof {
key: hash,
value: storage_mpt_tree
.get(hash.as_bytes())?
.map(|v| H256::from_slice(&v))
.ok_or_else(|| {
Into::<ProtocolError>::into(APIError::Adapter(
"Can't find this position".to_string(),
))
})?,
proof: storage_mpt_tree
.get_proof(hash.as_bytes())?
.into_iter()
.map(Hex::encode)
.collect(),
};
storage_proofs.push(proof);
match state_mpt_tree.get(address.as_bytes())? {
driftluo marked this conversation as resolved.
Show resolved Hide resolved
Some(raw_account) => {
let account = Account::decode(raw_account).unwrap();

let storage_mpt_tree =
MPTTrie::from_root(account.storage_root, Arc::clone(&self.trie_db))?;

let mut storage_proofs = Vec::with_capacity(storage_position.len());

for h in storage_position {
let hash: Hash = BigEndianHash::from_uint(&h);
let storage_proof = storage_mpt_tree
.get_proof(hash.as_bytes())?
.into_iter()
.map(Hex::encode)
.collect();
let proof = match storage_mpt_tree.get(hash.as_bytes())? {
Some(v) => EthStorageProof {
key: h,
value: U256::decode(&v).unwrap(),
proof: storage_proof,
},
// key is not exist
None => EthStorageProof {
key: h,
value: U256::zero(),
proof: storage_proof,
},
};
storage_proofs.push(proof);
}
Ok(EthAccountProof {
address,
balance: account.balance,
code_hash: account.code_hash,
nonce: account.nonce,
storage_hash: account.storage_root,
account_proof,
storage_proof: storage_proofs,
})
}
None => {
// account is not exist
Ok(EthAccountProof {
address,
balance: U256::zero(),
code_hash: H256::zero(),
nonce: U256::zero(),
storage_hash: H256::zero(),
account_proof,
storage_proof: storage_position
.into_iter()
.map(|h| EthStorageProof {
key: h,
value: U256::zero(),
proof: Vec::new(),
})
.collect(),
})
}
}

Ok(EthAccountProof {
balance: account.balance,
code_hash: account.code_hash,
nonce: account.nonce,
storage_hash: account.storage_root,
account_proof,
storage_proof: storage_proofs,
})
}

async fn get_metadata_by_number(
Expand Down
20 changes: 19 additions & 1 deletion core/executor/src/adapter/backend/apply.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,25 @@ where
};

storage.into_iter().for_each(|(k, v)| {
let _ = storage_trie.insert(k.as_bytes().to_vec(), v.as_bytes().to_vec());
// https://github.com/ethereum/go-ethereum/blob/ad16f11f841ab3a5fdedc8ddfc602f0717a34dd0/core/state/state_object.go#L306-L311
// if value is zero, delete it's key
if v == H256::zero() {
storage_trie
.remove(k.as_bytes())
.expect("Failed to remove entry with zero value from storage trie");
} else {
storage_trie
.insert(
k.as_bytes().to_vec(),
// https://github.com/ethereum/go-ethereum/blob/ad16f11f841ab3a5fdedc8ddfc602f0717a34dd0/core/state/state_object.go#L314
// Trim left zeroes and then rlp
U256::from_big_endian(v.as_bytes())
.encode()
.unwrap()
.to_vec(),
)
.expect("trie tree insert fail");
}
});

let storage_root = storage_trie
Expand Down
8 changes: 6 additions & 2 deletions core/executor/src/adapter/backend/read_only.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ use evm::backend::Basic;
use protocol::traits::{Backend, Context, ExecutorReadOnlyAdapter, ReadOnlyStorage};
use protocol::trie::Trie as _;
use protocol::types::{
Account, Bytes, ExecutorContext, MerkleRoot, H160, H256, NIL_DATA, RLP_NULL, U256,
Account, BigEndianHash, Bytes, ExecutorContext, MerkleRoot, H160, H256, NIL_DATA, RLP_NULL,
U256,
};
use protocol::{codec::ProtocolCodec, trie, ProtocolResult};

Expand Down Expand Up @@ -172,7 +173,10 @@ where
} else {
MPTTrie::from_root(storage_root, Arc::clone(&self.db)).map(
|trie| match trie.get(index.as_bytes()) {
Ok(Some(res)) => H256::from_slice(res.as_ref()),
Ok(Some(res)) => {
let value = U256::decode(res).unwrap();
BigEndianHash::from_uint(&value)
}
_ => H256::default(),
},
)
Expand Down
15 changes: 8 additions & 7 deletions core/executor/src/adapter/trie/wrapped.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,34 @@ use std::sync::Arc;
use hasher::HasherKeccak;

use protocol::trie::{PatriciaTrie, Trie, TrieError, DB as TrieDB};
use protocol::types::MerkleRoot;
use protocol::types::{Hasher, MerkleRoot};
use protocol::ProtocolResult;

pub struct MPTTrie<DB: TrieDB>(PatriciaTrie<DB, HasherKeccak>);

impl<DB: TrieDB> Trie<DB, HasherKeccak> for MPTTrie<DB> {
fn get(&self, key: &[u8]) -> Result<Option<Vec<u8>>, TrieError> {
self.0.get(key)
self.0.get(&Hasher::digest(key).0)
}

fn contains(&self, key: &[u8]) -> Result<bool, TrieError> {
self.0.contains(key)
self.0.contains(&Hasher::digest(key).0)
}

fn insert(&mut self, key: Vec<u8>, value: Vec<u8>) -> Result<(), TrieError> {
self.0.insert(key, value)
self.0.insert(Hasher::digest(key).0.to_vec(), value)
}

fn remove(&mut self, key: &[u8]) -> Result<bool, TrieError> {
self.0.remove(key)
self.0.remove(&Hasher::digest(key).0)
}

fn root(&mut self) -> Result<Vec<u8>, TrieError> {
self.0.root()
}

fn get_proof(&self, key: &[u8]) -> Result<Vec<Vec<u8>>, TrieError> {
self.0.get_proof(key)
self.0.get_proof(&Hasher::digest(key).0)
}

fn verify_proof(
Expand All @@ -39,7 +39,8 @@ impl<DB: TrieDB> Trie<DB, HasherKeccak> for MPTTrie<DB> {
key: &[u8],
proof: Vec<Vec<u8>>,
) -> Result<Option<Vec<u8>>, TrieError> {
self.0.verify_proof(root_hash, key, proof)
self.0
.verify_proof(root_hash, &Hasher::digest(key).0, proof)
}
}

Expand Down
61 changes: 0 additions & 61 deletions core/executor/src/tests/system_script/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -250,64 +250,3 @@ fn test_set_ckb_related_info() {
assert_ne!(new_metadata_root, old_metadata_root);
});
}

// #[tokio::test]
// async fn update_consensus_config() {
// let config:
// crate::system_contract::metadata::metadata_abi::ConsensusConfig =
// ConsensusConfig { gas_limit: 0x3e7fffffc18,
// interval: 0xbb8,
// propose_ratio: 0xf,
// prevote_ratio: 0xa,
// precommit_ratio: 0xa,
// brake_ratio: 0xa,
// tx_num_limit: 0x4e20,
// max_tx_size: 0x186a0000,
// max_contract_limit: 0x8000u64,
// }
// .into();

// let tx_data =
// crate::system_contract::metadata::metadata_abi::UpdateConsensusConfigCall { config }
// .encode();

// send_eth_tx("http://127.0.0.1:8000", tx_data, METADATA_CONTRACT_ADDRESS).await
// }
// use ethers::prelude::*;
// use ethers::signers::{LocalWallet, Signer};
// use ethers::types::transaction::eip2718::TypedTransaction::Legacy;
// use ethers::types::{Address, TransactionRequest};

// const ADDRESS: &str = "0x8ab0CF264DF99D83525e9E11c7e4db01558AE1b1";
// const PRIVATE_KEY: &str =
// "37aa0f893d05914a4def0460c0a984d3611546cfb26924d7a7ca6e0db9950a2d"; pub async
// fn send_eth_tx(axon_url: &str, data: Vec<u8>, to: Address) { let provider
// = Provider::<Http>::try_from(axon_url).unwrap();

// let from: Address = ADDRESS.parse().unwrap();
// let nonce = provider.get_transaction_count(from, None).await.unwrap();

// let transaction_request = TransactionRequest::new()
// .chain_id(0x41786f6e)
// .to(to)
// .data(data)
// .from(from)
// .gas_price(1)
// .gas(21000)
// .nonce(nonce);

// let wallet = LocalWallet::from_str(PRIVATE_KEY).expect(
// "failed to create
// wallet",
// );
// let tx = Legacy(transaction_request);
// let signature: Signature = wallet.sign_transaction(&tx).await.unwrap();

// provider
// .send_raw_transaction(tx.rlp_signed(&signature))
// .await
// .unwrap()
// .await
// .unwrap()
// .expect("failed to send eth tx");
// }
Loading
Loading