From a04deb6b058504e7855990eb20bb30ce25ae1a86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ecl=C3=A9sio=20Junior?= Date: Tue, 5 Oct 2021 09:28:02 -0400 Subject: [PATCH] feat(rpc): Implement `childstate_getStorageSize` RPC call (#1810) * feat: implement childstate_getKeys * chore: finish unit tests * chore: add childstate to http.go module init * chore: address lint warns * chore: addressing test issues * chore: address deepsource complaints * feat: implement childstate_getStorageHash * feat: implement childstate_getStorageSize * chore: check nil before return len * chore: fix export comment * chore: transform common.Hash prop into pointer * chore: fix unit test --- dot/rpc/modules/childstate.go | 34 +++++++++++++++ dot/rpc/modules/childstate_test.go | 66 +++++++++++++++++++++++++++++- 2 files changed, 99 insertions(+), 1 deletion(-) diff --git a/dot/rpc/modules/childstate.go b/dot/rpc/modules/childstate.go index 361afe1fea..cc454f4977 100644 --- a/dot/rpc/modules/childstate.go +++ b/dot/rpc/modules/childstate.go @@ -36,6 +36,13 @@ type GetStorageHash struct { Hash *common.Hash } +// GetChildStorageRequest the request to get the entry child storage hash +type GetChildStorageRequest struct { + KeyChild []byte + EntryKey []byte + Hash *common.Hash +} + // ChildStateModule is the module responsible to implement all the childstate RPC calls type ChildStateModule struct { storageAPI StorageAPI @@ -80,6 +87,33 @@ func (cs *ChildStateModule) GetKeys(_ *http.Request, req *GetKeysRequest, res *[ return nil } +// GetStorageSize returns the size of a child storage entry. +func (cs *ChildStateModule) GetStorageSize(_ *http.Request, req *GetChildStorageRequest, res *uint64) error { + var hash common.Hash + + if req.Hash == nil { + hash = cs.blockAPI.BestBlockHash() + } else { + hash = *req.Hash + } + + stateRoot, err := cs.storageAPI.GetStateRootFromBlock(&hash) + if err != nil { + return err + } + + item, err := cs.storageAPI.GetStorageFromChild(stateRoot, req.KeyChild, req.EntryKey) + if err != nil { + return err + } + + if item != nil { + *res = uint64(len(item)) + } + + return nil +} + // GetStorageHash returns the hash of a child storage entry func (cs *ChildStateModule) GetStorageHash(_ *http.Request, req *GetStorageHash, res *string) error { var hash common.Hash diff --git a/dot/rpc/modules/childstate_test.go b/dot/rpc/modules/childstate_test.go index c46081698f..05f868661f 100644 --- a/dot/rpc/modules/childstate_test.go +++ b/dot/rpc/modules/childstate_test.go @@ -22,7 +22,6 @@ import ( "testing" "github.com/ChainSafe/chaindb" - "github.com/ChainSafe/gossamer/dot/types" "github.com/ChainSafe/gossamer/lib/common" "github.com/ChainSafe/gossamer/lib/trie" @@ -70,6 +69,71 @@ func TestChildStateGetKeys(t *testing.T) { } } +func TestChildStateGetStorageSize(t *testing.T) { + mod, blockHash := setupChildStateStorage(t) + invalidHash := common.BytesToHash([]byte("invalid block hash")) + + tests := []struct { + expect uint64 + err error + hash *common.Hash + keyChild []byte + entry []byte + }{ + { + err: nil, + expect: uint64(len([]byte(":child_first_value"))), + hash: nil, + entry: []byte(":child_first"), + keyChild: []byte(":child_storage_key"), + }, + { + err: nil, + expect: uint64(len([]byte(":child_second_value"))), + hash: &blockHash, + entry: []byte(":child_second"), + keyChild: []byte(":child_storage_key"), + }, + { + err: nil, + expect: 0, + hash: nil, + entry: []byte(":not_found_so_size_0"), + keyChild: []byte(":child_storage_key"), + }, + { + err: fmt.Errorf("child trie does not exist at key %s%s", trie.ChildStorageKeyPrefix, []byte(":not_exist")), + hash: &blockHash, + entry: []byte(":child_second"), + keyChild: []byte(":not_exist"), + }, + { + err: chaindb.ErrKeyNotFound, + hash: &invalidHash, + }, + } + + for _, test := range tests { + var req GetChildStorageRequest + var res uint64 + + req.Hash = test.hash + req.EntryKey = test.entry + req.KeyChild = test.keyChild + + err := mod.GetStorageSize(nil, &req, &res) + + if test.err != nil { + require.Error(t, err) + require.Equal(t, err, test.err) + } else { + require.NoError(t, err) + } + + require.Equal(t, test.expect, res) + } +} + func TestGetStorageHash(t *testing.T) { mod, blockHash := setupChildStateStorage(t) invalidBlockHash := common.BytesToHash([]byte("invalid block hash"))