Skip to content

Commit

Permalink
Merge pull request ethereum#172 from getamis/rlp-encode-dirty-dump
Browse files Browse the repository at this point in the history
core/state, core/rawdb: implement RLP encoder/decoder for DirtyDump
  • Loading branch information
markya0616 authored Jun 15, 2018
2 parents 29d1b68 + 4b59810 commit eeed4ff
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 7 deletions.
5 changes: 2 additions & 3 deletions core/rawdb/accessors_chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ package rawdb
import (
"bytes"
"encoding/binary"
"encoding/json"
"math/big"

"github.com/ethereum/go-ethereum/common"
Expand Down Expand Up @@ -60,7 +59,7 @@ func ReadDirtyDump(db DatabaseReader, root common.Hash) (*state.DirtyDump, error
return nil, err
}
result := &state.DirtyDump{}
err = json.Unmarshal(data, result)
err = rlp.DecodeBytes(data, result)
if err != nil {
return nil, err
}
Expand All @@ -69,7 +68,7 @@ func ReadDirtyDump(db DatabaseReader, root common.Hash) (*state.DirtyDump, error

// WriteDirtyDump stores the dirty dump for the given block
func WriteDirtyDump(db DatabaseWriter, hash common.Hash, dump *state.DirtyDump) error {
data, err := json.MarshalIndent(dump, "", " ")
data, err := rlp.EncodeToBytes(dump)
if err != nil {
return err
}
Expand Down
70 changes: 66 additions & 4 deletions core/state/dump.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package state
import (
"encoding/json"
"fmt"
"io"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/rlp"
Expand Down Expand Up @@ -85,6 +86,13 @@ type DirtyDump struct {
Accounts map[string]DirtyDumpAccount `json:"accounts"`
}

func newDirtyDump(trie Trie) *DirtyDump {
return &DirtyDump{
Root: fmt.Sprintf("%x", trie.Hash()),
Accounts: make(map[string]DirtyDumpAccount),
}
}

func (d *DirtyDump) Copy() *DirtyDump {
cpy := &DirtyDump{
Root: d.Root,
Expand All @@ -103,11 +111,49 @@ func (d *DirtyDump) Copy() *DirtyDump {
return cpy
}

func newDirtyDump(trie Trie) *DirtyDump {
return &DirtyDump{
Root: fmt.Sprintf("%x", trie.Hash()),
Accounts: make(map[string]DirtyDumpAccount),
// EncodeRLP implements rlp.Encoder.
func (d *DirtyDump) EncodeRLP(w io.Writer) error {
dirtyDumpRLP := dirtyDumpRLP{
Root: d.Root,
Accounts: make([]dirtyDumpAccountRLP, 0),
}
for account, dirtyDumpAccount := range d.Accounts {
accountRLP := dirtyDumpAccountRLP{
Account: account,
Balance: dirtyDumpAccount.Balance,
}
if len(dirtyDumpAccount.Storage) > 0 {
accountRLP.Storage = make([]dirtyStorageRLP, 0)
for key, val := range dirtyDumpAccount.Storage {
accountRLP.Storage = append(accountRLP.Storage, dirtyStorageRLP{Key: key, Value: val})
}
}
dirtyDumpRLP.Accounts = append(dirtyDumpRLP.Accounts, accountRLP)
}
return rlp.Encode(w, &dirtyDumpRLP)
}

// DecodeRLP implements rlp.Decoder.
func (d *DirtyDump) DecodeRLP(s *rlp.Stream) error {
var dec dirtyDumpRLP
if err := s.Decode(&dec); err != nil {
return err
}
d.Root = dec.Root
d.Accounts = make(map[string]DirtyDumpAccount)
for _, accountRLP := range dec.Accounts {
account := DirtyDumpAccount{
Balance: accountRLP.Balance,
}
if len(accountRLP.Storage) > 0 {
account.Storage = make(map[string]string)
for _, storageRLP := range accountRLP.Storage {
account.Storage[storageRLP.Key] = storageRLP.Value
}
}
d.Accounts[accountRLP.Account] = account
}
return nil
}

// DirtyDumpAccount records the changed balance and storage for an account.
Expand Down Expand Up @@ -167,3 +213,19 @@ func calcDirties(dirtyEntry []journalEntry) map[common.Address]*dirtyDiff {
}
return dirties
}

type dirtyDumpRLP struct {
Root string
Accounts []dirtyDumpAccountRLP
}

type dirtyDumpAccountRLP struct {
Account string
Balance string
Storage []dirtyStorageRLP
}

type dirtyStorageRLP struct {
Key string
Value string
}
36 changes: 36 additions & 0 deletions core/state/dump_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/rlp"
)

// Tests that an empty state is not scheduled for syncing.
Expand Down Expand Up @@ -217,3 +218,38 @@ func TestDumpDirtyCopy(t *testing.T) {
}
}
}

func TestRLPEncodeAndDecodeDumpDirty(t *testing.T) {
hash := common.HexToHash("01")
dump := &DirtyDump{
Root: common.Bytes2Hex(hash.Bytes()),
Accounts: map[string]DirtyDumpAccount{
"addr1": {
Balance: "100",
},
"addr2": {
Storage: map[string]string{
"addr2key1": "addr2value1",
},
},
"addr3": {
Balance: "300",
Storage: map[string]string{
"addr3key1": "addr3value1",
},
},
},
}
bytes, err := rlp.EncodeToBytes(dump)
if err != nil {
t.Errorf("unexpected error on rlp encode %v", err)
}

got := &DirtyDump{}
if err := rlp.DecodeBytes(bytes, got); err != nil {
t.Errorf("unexpected error on rlp decode %v", err)
}
if !reflect.DeepEqual(dump, got) {
t.Errorf("DirtyDump not equal between rlp encode/decode GOT %v WANT %v", got, dump)
}
}

0 comments on commit eeed4ff

Please sign in to comment.