axonweb3 / axon

Axon is a Layer 2 framework of CKB with native cross-chain and interoperability.
https://axonweb3.io
MIT License
65 stars 39 forks source link

fix!: fix the implementation of Axon Tries #1580

Closed driftluo closed 9 months ago

driftluo commented 9 months ago

What this PR does / why we need it?

This PR add rlp encode for some key and value:

  1. All trie tree's key should hash wrapper
    • In the ETH global state, a path is always the keccak256 hash of an Ethereum address^1
    • The storage trie's position is calculated as the keccak256 hash of the address and the storage position, both left-padded with zeros to a length of 32 bytes^2
  2. Storage trie tree value is U256' rlp encode
  3. Modifications to related rpc methods
  4. eth_getProof need to provide proof of non-existence
  5. Add address into EthAccountProof struct

Test

now,there is a contract:

pragma solidity >=0.7.0 <0.8.20;

contract Storage {
    uint pos0;
    mapping(address => uint) pos1;
    function setStorage() public {
        pos0 = 1234;
        pos1[msg.sender] = 5678;
    }
}

Deploy it, contract address is 0x5fc8d32690cc91d4c39d9d3abcbd707, then query:

❯ curl -X POST -H 'Content-Type: application/json' --data '{"jsonrpc":"2.0", "method": "eth_getStorageAt", "params": ["0x5fc8d32690cc91d4c39d9d3abcbd707", "0x0", "latest"], "id": 1}' 127.0.0.1:8000                                                                                                              
{"jsonrpc":"2.0","result":"0x0000000000000000000000000000000000000000000000000000000000000000","id":1}

Call method setStorage via transaction, sender address is 0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266,then query:

❯ curl -X POST -H 'Content-Type: application/json' --data '{"jsonrpc":"2.0", "method": "eth_getStorageAt", "params": ["0x5fc8d32690cc91d4c39d9d3abcbd16989f875707", "0x0", "latest"], "id": 1}' 127.0.0.1:8000
{"jsonrpc":"2.0","result":"0x00000000000000000000000000000000000000000000000000000000000004d2","id":1}

Calculate the position of pos1:

keccak(
  decodeHex(
    "0x000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266" +
      "0000000000000000000000000000000000000000000000000000000000000001"
  )
)

result:0xa3c1274aadd82e4d12c8004c33fb244ca686dad4fcc8957fc5668588c11d9502

View the value of this location:

❯ curl -X POST -H 'Content-Type: application/json' --data '{"jsonrpc":"2.0", "method": "eth_getStorageAt", "params": ["0x5fc8d32690cc91d4c39d9d3abcbd16989f875
707", "0xa3c1274aadd82e4d12c8004c33fb244ca686dad4fcc8957fc5668588c11d9502", "latest"], "id": 1}' 127.0.0.1:8000                                               
{"jsonrpc":"2.0","result":"0x000000000000000000000000000000000000000000000000000000000000162e","id":1}

View the corresponding proof:

❯ curl -X POST -H 'Content-Type: application/json' --data '{"jsonrpc":"2.0", "method": "eth_getProof", "params": ["0x5fc8d32690cc91d4c39d9d3abcbd16989f875707", ["0x0"], "latest"], "id": 1}' 127.0.0.1:8000
{"jsonrpc":"2.0","result":{"address":"0x5fc8d32690cc91d4c39d9d3abcbd16989f875707","balance":"0x0","codeHash":"0x787756d22ec4d065cf6bc3a2f1ece014187a350f14c2e1ba1a9bf86fed13ecb8","nonce":"0x1","storageHash":"0x3fa9ba7eae02e5f813c5cbfe8fbfc1b092b839aba7f307437a27953c0c924e5a","accountProof":["0xf90171a0728b81d3d7b2d2916d0fbda57d0ad2ee7122bc1bbb404a5d92f5513744261594a0a8ccb5de3b83939d40bde215ad7dc9776e42b4779dc82c16cef5a959205ad760a0bdef77ce9b63248421050ccefdb264e9e452063864974c40cc9e2429420528388080a0cf7f989d0ff8a7db5fc792031274c4e8e7b5137a522cb05d2919a6501b2f3e618080a03ccf0957fcbd90862e8b842e4daa180bb1dbfe133884c434627c1f64c8a1c1f1a0c5de83b7cfccd28ce188387f8ab8d2fef2b04b1d094e6d68d105701df9c992cf80a007a82ae61d050840c440553d8abe7b7200523861897916daee51e4ea7eed7b07a072396dfed6bef972f62f50a17f351f92892997843029cf13c123fbc224345399a0393625ad6eea8c6d6f5e673bab3306b5d5a5d6847f919d992674426c6de85132a0ee3f1b9b3fd7af1d56f68bc9930bcab38d8289de381cfa62d3c8fb955be59166a001dce38716d73c8cc21d429f70ed630f24fca6d775dd71d642f2e27b7a4855f680","0xf851a00d12f22cd63417d6c9daba695405cb0056ad7fbe8c6285c022e8373b232b5652808080808080808080808080a03660984bf30000651b20f27cfb9b63f8f3aeac6a344d7bf9651afa9b7c182df8808080","0xf869a02061055ea920808012c78dfc3fd2714d5ce59f19b79b6147d59d69a3888a84f5b846f8440180a03fa9ba7eae02e5f813c5cbfe8fbfc1b092b839aba7f307437a27953c0c924e5aa0787756d22ec4d065cf6bc3a2f1ece014187a350f14c2e1ba1a9bf86fed13ecb8"],"storageProof":[{"key":"0x0","value":"0x4d2","proof":["0xf8518080a036bb5f2fd6f99b186600638644e2f0396989955e201672f7e81e8c8f466ed5b98080808080a03eb026c7929b6972ef185ca629c576981cf00687578a90a4c993dfe28063c3a48080808080808080","0xe5a0390decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563838204d2"]}]},"id":1}
❯ curl -X POST -H 'Content-Type: application/json' --data '{"jsonrpc":"2.0", "method": "eth_getProof", "params": ["0x5fc8d32690cc91d4c39d9d3abcbd16989f875707", ["0xa3c1274aadd82e4d12c8004c33fb244ca686dad4fcc8957fc5668588c11d9502"], "latest"], "id": 1}' 127.0.0.1:8000
{"jsonrpc":"2.0","result":{"address":"0x5fc8d32690cc91d4c39d9d3abcbd16989f875707","balance":"0x0","codeHash":"0x787756d22ec4d065cf6bc3a2f1ece014187a350f14c2e1
ba1a9bf86fed13ecb8","nonce":"0x1","storageHash":"0x3fa9ba7eae02e5f813c5cbfe8fbfc1b092b839aba7f307437a27953c0c924e5a","accountProof":["0xf90171a0728b81d3d7b2d2
916d0fbda57d0ad2ee7122bc1bbb404a5d92f5513744261594a0a8ccb5de3b83939d40bde215ad7dc9776e42b4779dc82c16cef5a959205ad760a0bdef77ce9b63248421050ccefdb264e9e4520638
64974c40cc9e2429420528388080a0cf7f989d0ff8a7db5fc792031274c4e8e7b5137a522cb05d2919a6501b2f3e618080a03ccf0957fcbd90862e8b842e4daa180bb1dbfe133884c434627c1f64c8
a1c1f1a0c5de83b7cfccd28ce188387f8ab8d2fef2b04b1d094e6d68d105701df9c992cf80a007a82ae61d050840c440553d8abe7b7200523861897916daee51e4ea7eed7b07a072396dfed6bef972
f62f50a17f351f92892997843029cf13c123fbc224345399a0a997b7b708f3844c061e50c77f00218a46b957240d3d1ab2a7c73328dcaf327aa0ee3f1b9b3fd7af1d56f68bc9930bcab38d8289de38
1cfa62d3c8fb955be59166a001dce38716d73c8cc21d429f70ed630f24fca6d775dd71d642f2e27b7a4855f680","0xf851a00d12f22cd63417d6c9daba695405cb0056ad7fbe8c6285c022e8373b2
32b5652808080808080808080808080a03660984bf30000651b20f27cfb9b63f8f3aeac6a344d7bf9651afa9b7c182df8808080","0xf869a02061055ea920808012c78dfc3fd2714d5ce59f19b79b
6147d59d69a3888a84f5b846f8440180a03fa9ba7eae02e5f813c5cbfe8fbfc1b092b839aba7f307437a27953c0c924e5aa0787756d22ec4d065cf6bc3a2f1ece014187a350f14c2e1ba1a9bf86fed
13ecb8"],"storageProof":[{"key":"0xa3c1274aadd82e4d12c8004c33fb244ca686dad4fcc8957fc5668588c11d9502","value":"0x162e","proof":["0xf8518080a036bb5f2fd6f99b1866
00638644e2f0396989955e201672f7e81e8c8f466ed5b98080808080a03eb026c7929b6972ef185ca629c576981cf00687578a90a4c993dfe28063c3a48080808080808080","0xe5a03b2a4240244
fa16f1700a049d06193952b863cf8f9f7995b98c5087db703ca9f8382162e"]}]},"id":1}

Test related code:

#[tokio::test]
async fn deploy_contract() {
    let wallet = MnemonicBuilder::<English>::default()
        .phrase("test test test test test test test test test test test junk")
        .build()
        .unwrap();
    let provider = Provider::<Http>::try_from("http://127.0.0.1:8000").unwrap();
    let client = SignerMiddleware::new(provider.clone(), wallet.clone());

    let abi = Contract::load(r#"[{"inputs":[],"name":"setStorage","outputs":[],"stateMutability":"nonpayable","type":"function"}]"#.as_bytes()).unwrap();
    let bytecode: ethers::types::Bytes = Hex::from_str("0x6080604052348015600f57600080fd5b5060bc8061001e6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c8063d3404b6d14602d575b600080fd5b60336035565b005b6104d260008190555061162e600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555056fea26469706673582212203031709c289be38bbf898048dbcca424c6fb9d0c0ffe3c2877c71b7b75e6174964736f6c63430008130033").unwrap().as_bytes().into();

    let factory = ContractFactory::new(abi, bytecode, Arc::new(client.clone()));

    let contract = factory.deploy(()).unwrap();

    let mut tx = contract.legacy().tx;

    let from = wallet.address();
    let nonce = provider.get_transaction_count(from, None).await.unwrap();
    tx.set_chain_id(0x41786f6e);
    tx.set_nonce(nonce);
    tx.set_gas_price(1);
    tx.set_gas(30000000);
    tx.set_from(from);

    let signature: Signature = wallet.sign_transaction(&tx).await.unwrap();

    let res = provider
        .send_raw_transaction(dbg!(tx.rlp_signed(&signature)))
        .await
        .unwrap()
        .await
        .unwrap()
        .expect("failed to send eth tx");

    println!("Incrementer.sol has been deployed to {:?}", res);
}

#[tokio::test]
async fn call_set() {
    let tx_data = super::test_abi::SetStorageCall.encode();
    send_eth_tx(
        "http://127.0.0.1:8000",
        tx_data,
        "0x5fc8d32690cc91d4c39d9d3abcbd16989f875707"
            .parse()
            .unwrap(),
    )
    .await
}

pub async fn send_eth_tx(axon_url: &str, data: Vec<u8>, to: Address) {
    let provider = Provider::<Http>::try_from(axon_url).unwrap();
    let wallet = MnemonicBuilder::<English>::default()
        .phrase("test test test test test test test test test test test junk")
        .build()
        .unwrap();
    let from: Address = dbg!(wallet.address());
    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(210000)
        .nonce(nonce);

    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");
}

#[test]
fn test_hash() {
    let key = "0x000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266".to_string()
        + "0000000000000000000000000000000000000000000000000000000000000001";
    let decode = Hex::from_str(&key).unwrap();
    let a = Hasher::digest(decode.as_bytes());
    dbg!(Hex::encode(a).as_string());
}

What is the impact of this PR?

Breaking Change

PR relation:

CI Settings
### **CI Usage** **Tip**: Check the CI you want to run below, and then comment `/run-ci`. **CI Switch** - [x] Web3 Compatible Tests - [x] OCT 1-5 And 12-15 - [x] OCT 6-10 - [x] OCT 11 - [x] OCT 16-19 - [x] v3 Core Tests ### **CI Description** | CI Name | Description | | ----------------------------------------- | ------------------------------------------------------------------------- | | *Web3 Compatible Test* | Test the Web3 compatibility of Axon | | *v3 Core Test* | Run the compatibility tests provided by Uniswap V3 | | *OCT 1-5 \| 6-10 \| 11 \| 12-15 \| 16-19* | Run the compatibility tests provided by OpenZeppelin |

References

Flouse commented 9 months ago

/run-ci

github-actions[bot] commented 9 months ago

CI tests run on commit:

CI test list: