Skip to content

Commit

Permalink
feat: add method to return proof
Browse files Browse the repository at this point in the history
  • Loading branch information
kstdl committed Oct 31, 2023
1 parent 333915d commit 6b1316f
Show file tree
Hide file tree
Showing 4 changed files with 209 additions and 34 deletions.
61 changes: 61 additions & 0 deletions taraxa/C/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@ package main
//#include <rocksdb/c.h>
import "C"
import (
"fmt"
"math/big"
"sync"
"unsafe"

"github.com/Taraxa-project/taraxa-evm/taraxa/state/chain_config"
"github.com/Taraxa-project/taraxa-evm/taraxa/state/rewards_stats"
"github.com/Taraxa-project/taraxa-evm/taraxa/state/state_db"
"github.com/holiman/uint256"

"github.com/Taraxa-project/taraxa-evm/taraxa/state/state_db_rocksdb"
Expand Down Expand Up @@ -409,6 +411,65 @@ func taraxa_evm_state_api_validators_stakes(
enc_rlp(&ret, cb)
}

//export taraxa_evm_state_api_get_proof
func taraxa_evm_state_api_get_proof(
ptr C.taraxa_evm_state_API_ptr,
params_enc C.taraxa_evm_Bytes,
cb C.taraxa_evm_BytesCallback,
cb_err C.taraxa_evm_BytesCallback,
) {
defer handle_err(cb_err)
var params struct {
BlkNum types.BlockNum
Addr common.Address
StateRoot common.Hash
Keys []common.Hash
}
dec_rlp(params_enc, &params)

type StorageProof struct {
Key common.Hash
Value []byte
Proof [][]byte
}
var ret struct {
Balance big.Int
CodeHash common.Hash
Nonce big.Int
StorageHash common.Hash
AccountProof [][]byte
StorageProof []StorageProof
}

blk_state := state_API_instances[ptr].ReadBlock(params.BlkNum)
blk_state.GetAccount(&params.Addr, func(acc state_db.Account) {
ret.Balance = *acc.Balance
ret.CodeHash = *acc.CodeHash
ret.Nonce = *acc.Nonce
ret.StorageHash = *acc.StorageRootHash
})
var err error
ret.AccountProof, err = blk_state.GetStorageProof(&params.StateRoot, &params.Addr)
if err != nil {
fmt.Println("GetStorageProof error:", err)
}
for _, key := range params.Keys {
var proof StorageProof
proof.Key = key
proof.Proof, err = blk_state.GetProof(&params.Addr, &key)
if err != nil {
fmt.Println("GetProof error:", err)
}
blk_state.GetAccountStorage(&params.Addr, &key, func(bytes []byte) {
proof.Value = bytes
})

ret.StorageProof = append(ret.StorageProof, proof)
}

enc_rlp(&ret, cb)
}

type state_API_ptr = byte

const state_API_max_instances = ^state_API_ptr(0)
Expand Down
122 changes: 120 additions & 2 deletions taraxa/state/contracts/tests/dpos/trie_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ func TestTrieVal(t *testing.T) {

fmt.Println()
fmt.Println()
storage_proof := state.ProveAccountStorage(&root, test.ContractAddr)
storage_proof, _ := state.GetStorageProof(&root, test.ContractAddr)

for i, r := range storage_proof {
fmt.Println("proof", i, common.Bytes2Hex(r))
Expand All @@ -269,7 +269,7 @@ func TestTrieVal(t *testing.T) {
fmt.Println()
fmt.Println()
h := common.HexToHash("0x7673bcbb3401a7cbae68f81d40eea2cf35afdaf7ecd016ebf3f02857fcc1260a")
res := state.Prove(test.ContractAddr, &h)
res, _ := state.GetProof(test.ContractAddr, &h)
for i, r := range res {
fmt.Println("proof", i, common.Bytes2Hex(r))
}
Expand All @@ -287,3 +287,121 @@ func TestTrieVal(t *testing.T) {
// rlp node f8f18080a0be6aba9ac1c6352f17e80656c7f0b3953ec8ce0e1f2cfb05ef769bfc37d1d77580a0b7b49995dce6c474becec567a6c96c93da7e0990598ac4dc1affbcd3ad452453a010c7db9de7b9d84c39923dbd3949bce63056bfc5e6f0e8b9c4cab3463b6b878180a09e9e038f1f2f81d0bb0e1f416f50de622e9fcecadb4197c5c2bdce5088c7aa2380a05e1ea58069877ad278bf8365b9e3f5448a10f437314d1d2068d84d927b58c747a0ef4ffe20ccabaf1f61203f68e1d6e00cd25a4f54a782609104630224c2eafc7680a0fb21b3c21a8b1068229c1e1380f327c83bffd17a6036c867839c6eb6552248b880808080
// hash 731f155159fc21ab77a156b7735406bd2510206021b4f3137637cd0c32a80721
}

type StorageProof struct {
Key common.Hash
Value []byte
Proof [][]byte
}

func (u StorageProof) MarshalJSON() ([]byte, error) {
return json.Marshal(struct {
Key string `json:"key"`
Value string `json:"value"`
Proof []string `json:"proof"`
}{
Key: u.Key.Hex(),
Value: common.Bytes2Hex(u.Value),
Proof: func() (ret []string) {
for _, p := range u.Proof {
ret = append(ret, common.Bytes2Hex(p))
}
return
}(),
})
}

type FullProof struct {
Balance big.Int
CodeHash common.Hash
Nonce big.Int
StorageHash common.Hash
AccountProof [][]byte
StorageProof []StorageProof
}

func (u FullProof) MarshalJSON() ([]byte, error) {
return json.Marshal(struct {
Balance string `json:"balance"`
CodeHash string `json:"codeHash"`
Nonce string `json:"nonce"`
StorageHash string `json:"storageHash"`
AccountProof []string `json:"accountProof"`
StorageProof []StorageProof `json:"storageProof"`
}{
Balance: u.Balance.String(),
CodeHash: u.CodeHash.Hex(),
Nonce: u.Nonce.String(),
StorageHash: u.StorageHash.Hex(),
AccountProof: func() (ret []string) {
for _, p := range u.AccountProof {
ret = append(ret, common.Bytes2Hex(p))
}
return
}(),
StorageProof: u.StorageProof,
})
}

func GetProof(blk_state state_db.ExtendedReader, address common.Address, state_root common.Hash, keys []common.Hash) (ret FullProof) {
blk_state.GetAccount(&address, func(acc state_db.Account) {
ret.Balance = *acc.Balance
ret.CodeHash = *acc.CodeHash
ret.Nonce = *acc.Nonce
ret.StorageHash = *acc.StorageRootHash
})
var err error
ret.AccountProof, err = blk_state.GetStorageProof(&state_root, &address)
if err != nil {
fmt.Println("GetStorageProof error:", err)
}
for _, key := range keys {
var proof StorageProof
proof.Key = key
proof.Proof, err = blk_state.GetProof(&address, &key)
if err != nil {
fmt.Println("GetProof error:", err)
}
blk_state.GetAccountStorage(&address, &key, func(bytes []byte) {
proof.Value = bytes
})

ret.StorageProof = append(ret.StorageProof, proof)
}
return
}

func TestGetProof(t *testing.T) {
_, test := init_contract_test(t, CopyDefaultChainConfig())
defer test.end()

root, _ := test.AdvanceBlock(nil, nil)
fmt.Println("state root", root.Hex())
fmt.Println("test contract addr", test.ContractAddr.Hex())

// for i := 100; i < 230; i++ {
// code := test.pack("set", big.NewInt(int64(i)), big.NewInt(int64(i+100)))
// // fmt.Println(common.Bytes2Hex(code))
// test.Execute(test.Sender, BigZero, code)
// }
// test.AdvanceBlock(nil, nil, nil)

state := state_db.ExtendedReader{Reader: test.statedb.GetBlockState(test.blk_n)}
// state.GetProof()
keys := []common.Hash{
common.HexToHash("0x7673bcbb3401a7cbae68f81d40eea2cf35afdaf7ecd016ebf3f02857fcc1260a"), // 100
common.HexToHash("0x0bb0d0c2a399402027fb0eaada47a2c630983f3dd97f193c64f3e30465d04ec3"), // 101
common.HexToHash("0x7ec3c2f200843fc90126ba954586fc6de68c1a3d419d6f0667702fd695602f05"), // 150
common.HexToHash("0x46a4a9204e2252337cfce182401bbabede11720ab2d2e2330f66de6cfcb0b379"), // 170
common.HexToHash("0xd83db53d400092e1cd810411bbe8320db49f103fdcd91dec3d07ef7ac3dacd1e"), // 181
common.HexToHash("0xef407a61ad059ad1a9edcba0919f1209387c016d49079cb4d982b420eb78a186"), // 221
}
p := GetProof(state, *test.ContractAddr, root, keys)
fmt.Println()
fmt.Println()
fmt.Println()
pj, _ := json.Marshal(p)
fmt.Println(string(pj))
fmt.Println("state root", root.Hex())

}
58 changes: 27 additions & 31 deletions taraxa/state/state_db/block_reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,44 +8,44 @@ import (

type ExtendedReader struct{ Reader }

func (self ExtendedReader) GetCode(hash *common.Hash) (ret []byte) {
self.Get(COL_code, hash, func(bytes []byte) {
func (er ExtendedReader) GetCode(hash *common.Hash) (ret []byte) {
er.Get(COL_code, hash, func(bytes []byte) {
ret = common.CopyBytes(bytes)
})
return
}

func (self ExtendedReader) GetAccountStorage(addr *common.Address, key *common.Hash, cb func([]byte)) {
AccountTrieInputAdapter{addr, self}.GetValue(keccak256.Hash(key[:]), cb)
func (er ExtendedReader) GetAccountStorage(addr *common.Address, key *common.Hash, cb func([]byte)) {
AccountTrieInputAdapter{addr, er}.GetValue(keccak256.Hash(key[:]), cb)
}

func (self ExtendedReader) GetAccount(addr *common.Address, cb func(Account)) {
self.GetRawAccount(addr, func(v []byte) {
func (er ExtendedReader) GetAccount(addr *common.Address, cb func(Account)) {
er.GetRawAccount(addr, func(v []byte) {
cb(DecodeAccountFromTrie(v))
})
}

func (self ExtendedReader) GetRawAccount(addr *common.Address, cb func([]byte)) {
MainTrieInputAdapter{self}.GetValue(keccak256.Hash(addr[:]), cb)
func (er ExtendedReader) GetRawAccount(addr *common.Address, cb func([]byte)) {
MainTrieInputAdapter{er}.GetValue(keccak256.Hash(addr[:]), cb)
}

func (self ExtendedReader) GetCodeByAddress(addr *common.Address) (ret []byte) {
self.GetRawAccount(addr, func(acc []byte) {
func (er ExtendedReader) GetCodeByAddress(addr *common.Address) (ret []byte) {
er.GetRawAccount(addr, func(acc []byte) {
if code_hash := CodeHash(acc); code_hash != nil {
ret = self.GetCode(code_hash)
ret = er.GetCode(code_hash)
}
})
return
}

func (self ExtendedReader) ForEachStorage(addr *common.Address, f func(*common.Hash, []byte)) {
self.GetRawAccount(addr, func(acc []byte) {
func (er ExtendedReader) ForEachStorage(addr *common.Address, f func(*common.Hash, []byte)) {
er.GetRawAccount(addr, func(acc []byte) {
storage_root := StorageRoot(acc)
if storage_root == nil {
return
}
trie.Reader{Schema: AccountTrieSchema{}}.ForEach(
AccountTrieInputAdapter{addr, self},
AccountTrieInputAdapter{addr, er},
storage_root,
true,
func(hash *common.Hash, val trie.Value) {
Expand All @@ -55,51 +55,47 @@ func (self ExtendedReader) ForEachStorage(addr *common.Address, f func(*common.H
})
}

func (self ExtendedReader) Prove(addr *common.Address, key *common.Hash) [][]byte {
res := make([][]byte, 0)
self.GetRawAccount(addr, func(acc []byte) {
func (er ExtendedReader) GetProof(addr *common.Address, key *common.Hash) (res [][]byte, err error) {
er.GetRawAccount(addr, func(acc []byte) {
storage_root := StorageRoot(acc)
if storage_root == nil {
return
}
res, _ = trie.Reader{Schema: AccountTrieSchema{}}.Prove(
AccountTrieInputAdapter{addr, self},
res, err = trie.Reader{Schema: AccountTrieSchema{}}.Prove(
AccountTrieInputAdapter{addr, er},
storage_root,
keccak256.Hash(key.Bytes()).Bytes())
})
return res
return
}

func (self ExtendedReader) ProveAccountStorage(storage_root *common.Hash, addr *common.Address) [][]byte {
res := make([][]byte, 0)
func (er ExtendedReader) GetStorageProof(storage_root *common.Hash, addr *common.Address) (res [][]byte, err error) {
if storage_root == nil {
return res
return
}
res, _ = trie.Reader{Schema: MainTrieSchema{}}.Prove(
MainTrieInputAdapter{self},
return trie.Reader{Schema: MainTrieSchema{}}.Prove(
MainTrieInputAdapter{er},
storage_root,
keccak256.Hash(addr[:]).Bytes())

return res
}

func (self ExtendedReader) ForEachAccountNodeHashByRoot(storage_root *common.Hash, f func(*common.Hash, []byte)) {
func (er ExtendedReader) ForEachAccountNodeHashByRoot(storage_root *common.Hash, f func(*common.Hash, []byte)) {
if storage_root == nil {
return
}
no_addr := common.Address{}
trie.Reader{Schema: AccountTrieSchema{}}.ForEachNodeHash(
AccountTrieInputAdapter{&no_addr, self},
AccountTrieInputAdapter{&no_addr, er},
storage_root,
f)
}

func (self ExtendedReader) ForEachMainNodeHashByRoot(storage_root *common.Hash, f func(*common.Hash, []byte)) {
func (er ExtendedReader) ForEachMainNodeHashByRoot(storage_root *common.Hash, f func(*common.Hash, []byte)) {
if storage_root == nil {
return
}
trie.Reader{Schema: MainTrieSchema{}}.ForEachNodeHash(
MainTrieInputAdapter{self},
MainTrieInputAdapter{er},
storage_root,
f)
}
2 changes: 1 addition & 1 deletion taraxa/state/state_db_rocksdb/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,7 @@ func (self *DB) GetDPOSConfigChanges() map[uint64][]byte {
it := self.db.NewIteratorCF(&ro, self.cf_handles[col_config_changes])
defer it.Close()
it.SeekToFirst()
for it = it; it.Valid(); it.Next() {
for ; it.Valid(); it.Next() {
key := big.NewInt(0).SetBytes(it.Key().Data()).Uint64()
// make a copy of bytes
res[key] = append([]byte(nil), it.Value().Data()...)
Expand Down

0 comments on commit 6b1316f

Please sign in to comment.