diff --git a/data.md b/data.md index 6dce771c62..14bad739d1 100644 --- a/data.md +++ b/data.md @@ -1182,6 +1182,44 @@ Tree Root Helper Functions syntax MerkleTree ::= #storageRoot( Map ) [function] // ---------------------------------------------------- rule #storageRoot( STORAGE ) => MerkleUpdateMap( .MerkleTree, #intMap2StorageMap( STORAGE ) ) +``` + +### State Root + +```k + syntax Map ::= "#precompiledContracts" [function] + // ------------------------------------------------- + rule #precompiledContracts + => #parseByteStackRaw( Hex2Raw( #unparseData( 1, 20 ) ) ) |-> #emptyContractRLP + #parseByteStackRaw( Hex2Raw( #unparseData( 2, 20 ) ) ) |-> #emptyContractRLP + #parseByteStackRaw( Hex2Raw( #unparseData( 3, 20 ) ) ) |-> #emptyContractRLP + #parseByteStackRaw( Hex2Raw( #unparseData( 4, 20 ) ) ) |-> #emptyContractRLP + #parseByteStackRaw( Hex2Raw( #unparseData( 5, 20 ) ) ) |-> #emptyContractRLP + #parseByteStackRaw( Hex2Raw( #unparseData( 6, 20 ) ) ) |-> #emptyContractRLP + #parseByteStackRaw( Hex2Raw( #unparseData( 7, 20 ) ) ) |-> #emptyContractRLP + #parseByteStackRaw( Hex2Raw( #unparseData( 8, 20 ) ) ) |-> #emptyContractRLP + + syntax String ::= "#emptyContractRLP" [function] + // ------------------------------------------------ + rule #emptyContractRLP => #rlpEncodeLength( #rlpEncodeWord(0) + +String #rlpEncodeWord(0) + +String #rlpEncodeString( Hex2Raw( Keccak256("\x80") ) ) + +String #rlpEncodeString( Hex2Raw( Keccak256("") ) ) + , 192 + ) + + syntax AccountData ::= AcctData ( nonce: Int, balance: Int, store: Map, code: ByteArray ) + // ----------------------------------------------------------------------------------------- + + syntax String ::= #rlpEncodeFullAccount( AccountData ) [function] + // ---------------------------------------------------------------------- + rule #rlpEncodeFullAccount( AcctData( NONCE, BAL, STORAGE, CODE ) ) + => #rlpEncodeLength( #rlpEncodeWord(NONCE) + +String #rlpEncodeWord(BAL) + +String #rlpEncodeString( Hex2Raw( Keccak256( #rlpEncodeMerkleTree( #storageRoot( STORAGE ) ) ) ) ) + +String #rlpEncodeString( Hex2Raw( Keccak256( #asString( CODE ) ) ) ) + , 192 + ) endmodule ``` diff --git a/tests/web3/firefly_getStateRootAll.expected.json b/tests/web3/firefly_getStateRootAll.expected.json new file mode 100644 index 0000000000..66cfaf14ed --- /dev/null +++ b/tests/web3/firefly_getStateRootAll.expected.json @@ -0,0 +1 @@ +[{"jsonrpc":"2.0","id":1,"result":true},{"jsonrpc":"2.0","id":2,"result":{"stateRoot":"0x62da78953c804219d3f2e14c92337806cf0604b57060b528ec480c4f89fdbe4e"}}] diff --git a/tests/web3/firefly_getStateRootAll.in.json b/tests/web3/firefly_getStateRootAll.in.json new file mode 100644 index 0000000000..73b88d2599 --- /dev/null +++ b/tests/web3/firefly_getStateRootAll.in.json @@ -0,0 +1,17 @@ +[{ + "jsonrpc":"2.0", + "id":1, + "method":"firefly_addAccount", + "params":[{ + "key":"0xcdeac0dd5ec7c04072af48f2a4451e102a80ca5bb441a7b4d72c176cea61866e", + "nonce":"0x1", + "balance":"0x56bc75e2d63100000", + "code":"0x6080604052348015600f57600080fd5b5060868061001e6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c80636d4ce63c14602d575b600080fd5b6033604c565b6040805163ffffffff9092168252519081900360200190f35b602a9056fea265627a7a72315820c0bd34730815aaf15c03933af0d41b94653dfda48fd932e0bcd9c83bc61cd5fa64736f6c634300050b0032" + }] +}, +{ + "jsonrpc":"2.0", + "id":2, + "method":"firefly_getStateRoot", + "params":[] +}] diff --git a/tests/web3/firefly_getStateRootBalance.expected.json b/tests/web3/firefly_getStateRootBalance.expected.json new file mode 100644 index 0000000000..3753b1396e --- /dev/null +++ b/tests/web3/firefly_getStateRootBalance.expected.json @@ -0,0 +1 @@ +[{"jsonrpc":"2.0","id":1,"result":true},{"jsonrpc":"2.0","id":2,"result":{"stateRoot":"0x0e0fb05cc0c18ae82d7742186716ecf01555dc7736119aba5e9424123c56bc1c"}}] diff --git a/tests/web3/firefly_getStateRootBalance.in.json b/tests/web3/firefly_getStateRootBalance.in.json new file mode 100644 index 0000000000..e145e8ebc3 --- /dev/null +++ b/tests/web3/firefly_getStateRootBalance.in.json @@ -0,0 +1,15 @@ +[{ + "jsonrpc":"2.0", + "id":1, + "method":"firefly_addAccount", + "params":[{ + "key":"0xcdeac0dd5ec7c04072af48f2a4451e102a80ca5bb441a7b4d72c176cea61866e", + "balance":"0x56bc75e2d63100000" + }] +}, +{ + "jsonrpc":"2.0", + "id":2, + "method":"firefly_getStateRoot", + "params":[] +}] diff --git a/tests/web3/firefly_getStateRootCode.expected.json b/tests/web3/firefly_getStateRootCode.expected.json new file mode 100644 index 0000000000..7df65172a1 --- /dev/null +++ b/tests/web3/firefly_getStateRootCode.expected.json @@ -0,0 +1 @@ +[{"jsonrpc":"2.0","id":1,"result":true},{"jsonrpc":"2.0","id":2,"result":{"stateRoot":"0xf8b8aab7e98399674eb2f6cffe421220bed88b519cc17145724a453352df4343"}}] diff --git a/tests/web3/firefly_getStateRootCode.in.json b/tests/web3/firefly_getStateRootCode.in.json new file mode 100644 index 0000000000..f6e798ff21 --- /dev/null +++ b/tests/web3/firefly_getStateRootCode.in.json @@ -0,0 +1,15 @@ +[{ + "jsonrpc":"2.0", + "id":1, + "method":"firefly_addAccount", + "params":[{ + "key":"0xcdeac0dd5ec7c04072af48f2a4451e102a80ca5bb441a7b4d72c176cea61866e", + "code":"0x6080604052348015600f57600080fd5b5060868061001e6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c80636d4ce63c14602d575b600080fd5b6033604c565b6040805163ffffffff9092168252519081900360200190f35b602a9056fea265627a7a72315820c0bd34730815aaf15c03933af0d41b94653dfda48fd932e0bcd9c83bc61cd5fa64736f6c634300050b0032" + }] +}, +{ + "jsonrpc":"2.0", + "id":2, + "method":"firefly_getStateRoot", + "params":[] +}] diff --git a/tests/web3/firefly_getStateRootNonce.expected.json b/tests/web3/firefly_getStateRootNonce.expected.json new file mode 100644 index 0000000000..0082c1c8fe --- /dev/null +++ b/tests/web3/firefly_getStateRootNonce.expected.json @@ -0,0 +1 @@ +[{"jsonrpc":"2.0","id":1,"result":true},{"jsonrpc":"2.0","id":2,"result":{"stateRoot":"0xb62b878cd9003caa9f8e830bdf2ba6b68539dae38c4f51d7e5e5c7973b62a893"}}] diff --git a/tests/web3/firefly_getStateRootNonce.in.json b/tests/web3/firefly_getStateRootNonce.in.json new file mode 100644 index 0000000000..b81b3f944c --- /dev/null +++ b/tests/web3/firefly_getStateRootNonce.in.json @@ -0,0 +1,15 @@ +[{ + "jsonrpc":"2.0", + "id":1, + "method":"firefly_addAccount", + "params":[{ + "key":"0xcdeac0dd5ec7c04072af48f2a4451e102a80ca5bb441a7b4d72c176cea61866e", + "nonce":"0x1" + }] +}, +{ + "jsonrpc":"2.0", + "id":2, + "method":"firefly_getStateRoot", + "params":[] +}] diff --git a/web3.md b/web3.md index 9937492bb8..a0bbeb034f 100644 --- a/web3.md +++ b/web3.md @@ -317,6 +317,8 @@ WEB3 JSON RPC "eth_estimateGas" rule #runRPCCall => #firefly_getCoverageData ... "firefly_getCoverageData" + rule #runRPCCall => #firefly_getStateRoot ... + "firefly_getStateRoot" rule #runRPCCall => #sendResponse( "error": {"code": -32601, "message": "Method not found"} ) ... [owise] @@ -1198,5 +1200,45 @@ Collecting Coverage Data syntax Int ::= #computePercentage ( Int, Int ) [function] // --------------------------------------------------------- rule #computePercentage (EXECUTED, TOTAL) => (100 *Int EXECUTED) /Int TOTAL +``` + +Helper Funcs +------------ + +```k + syntax AccountData ::= #getAcctData( Account ) [function] + // --------------------------------------------------------- + rule [[ #getAcctData( ACCT ) => AcctData(NONCE, BAL, STORAGE, CODE) ]] + + ACCT + NONCE + BAL + STORAGE + CODE + ... + +``` + +State Root +---------- + +```k + syntax MerkleTree ::= "#stateRoot" [function] + // --------------------------------------------- + rule #stateRoot => MerkleUpdateMap( .MerkleTree, #precompiledContracts #activeAccounts ) + + syntax Map ::= "#activeAccounts" [function] + | #accountsMap( Set ) [function] + // --------------------------------------------- + rule [[ #activeAccounts => #accountsMap( ACCTS ) ]] + ACCTS + + rule #accountsMap( .Set ) => .Map + rule #accountsMap( SetItem( ACCT:Int ) S ) => #parseByteStack( #unparseData( ACCT, 20 ) ) |-> #rlpEncodeFullAccount( #getAcctData( ACCT ) ) #accountsMap( S ) + + syntax KItem ::= "#firefly_getStateRoot" + // ---------------------------------------- + rule #firefly_getStateRoot => #sendResponse("result": { "stateRoot" : "0x" +String Keccak256( #rlpEncodeMerkleTree( #stateRoot ) ) } ) ... + endmodule ```