refactoring/reorganizing packages
This commit is contained in:
parent
efbb9042ac
commit
0acab0c3dd
@ -149,8 +149,6 @@ var (
|
|||||||
utils.EWASMInterpreterFlag,
|
utils.EWASMInterpreterFlag,
|
||||||
utils.EVMInterpreterFlag,
|
utils.EVMInterpreterFlag,
|
||||||
utils.StateDiffFlag,
|
utils.StateDiffFlag,
|
||||||
utils.StateDiffModeFlag,
|
|
||||||
utils.StateDiffPathFlag,
|
|
||||||
configFileFlag,
|
configFileFlag,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -266,8 +266,6 @@ var AppHelpFlagGroups = []flagGroup{
|
|||||||
Name: "STATE DIFF",
|
Name: "STATE DIFF",
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
utils.StateDiffFlag,
|
utils.StateDiffFlag,
|
||||||
utils.StateDiffModeFlag,
|
|
||||||
utils.StateDiffPathFlag,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -32,6 +32,8 @@ import (
|
|||||||
"text/template"
|
"text/template"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
cli "gopkg.in/urfave/cli.v1"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/accounts"
|
"github.com/ethereum/go-ethereum/accounts"
|
||||||
"github.com/ethereum/go-ethereum/accounts/keystore"
|
"github.com/ethereum/go-ethereum/accounts/keystore"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
@ -62,11 +64,10 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/p2p/netutil"
|
"github.com/ethereum/go-ethereum/p2p/netutil"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
whisper "github.com/ethereum/go-ethereum/whisper/whisperv6"
|
|
||||||
pcsclite "github.com/gballet/go-libpcsclite"
|
|
||||||
cli "gopkg.in/urfave/cli.v1"
|
|
||||||
"github.com/ethereum/go-ethereum/statediff/service"
|
|
||||||
"github.com/ethereum/go-ethereum/statediff"
|
"github.com/ethereum/go-ethereum/statediff"
|
||||||
|
whisper "github.com/ethereum/go-ethereum/whisper/whisperv6"
|
||||||
|
|
||||||
|
pcsclite "github.com/gballet/go-libpcsclite"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -762,18 +763,6 @@ var (
|
|||||||
Name: "statediff",
|
Name: "statediff",
|
||||||
Usage: "Enables the calculation of state diffs between each block, persists these state diffs the configured persistence mode.",
|
Usage: "Enables the calculation of state diffs between each block, persists these state diffs the configured persistence mode.",
|
||||||
}
|
}
|
||||||
|
|
||||||
StateDiffModeFlag = cli.StringFlag{
|
|
||||||
Name: "statediff.mode",
|
|
||||||
Usage: "Enables the user to determine which persistence mode they'd like to store the state diffs in.",
|
|
||||||
Value: "csv",
|
|
||||||
}
|
|
||||||
|
|
||||||
StateDiffPathFlag = cli.StringFlag{
|
|
||||||
Name: "statediff.path",
|
|
||||||
Usage: "Enables the user to determine where to persist the state diffs.",
|
|
||||||
Value: ".",
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// MakeDataDir retrieves the currently requested data directory, terminating
|
// MakeDataDir retrieves the currently requested data directory, terminating
|
||||||
@ -983,6 +972,9 @@ func setWS(ctx *cli.Context, cfg *node.Config) {
|
|||||||
if ctx.GlobalIsSet(WSApiFlag.Name) {
|
if ctx.GlobalIsSet(WSApiFlag.Name) {
|
||||||
cfg.WSModules = splitAndTrim(ctx.GlobalString(WSApiFlag.Name))
|
cfg.WSModules = splitAndTrim(ctx.GlobalString(WSApiFlag.Name))
|
||||||
}
|
}
|
||||||
|
if ctx.GlobalBool(StateDiffFlag.Name) {
|
||||||
|
cfg.WSModules = append(cfg.WSModules, "statediff")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// setIPC creates an IPC path configuration from the set command line flags,
|
// setIPC creates an IPC path configuration from the set command line flags,
|
||||||
@ -1629,29 +1621,14 @@ func RegisterGraphQLService(stack *node.Node, endpoint string, cors, vhosts []st
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RegisterStateDiffService configures and registers a service to stream state diff data over RPC
|
||||||
func RegisterStateDiffService(stack *node.Node, ctx *cli.Context) {
|
func RegisterStateDiffService(stack *node.Node, ctx *cli.Context) {
|
||||||
//based on the context, if path and mode are set, update the config here
|
|
||||||
//otherwise pass in an empty config
|
|
||||||
|
|
||||||
modeFlag := ctx.GlobalString(StateDiffModeFlag.Name)
|
|
||||||
mode, err := statediff.NewMode(modeFlag)
|
|
||||||
if err != nil {
|
|
||||||
Fatalf("Failed to register State Diff Service", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
path := ctx.GlobalString(StateDiffPathFlag.Name)
|
|
||||||
|
|
||||||
config := statediff.Config{
|
|
||||||
Mode: mode,
|
|
||||||
Path: path,
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
|
if err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
|
||||||
var ethServ *eth.Ethereum
|
var ethServ *eth.Ethereum
|
||||||
ctx.Service(ðServ)
|
ctx.Service(ðServ)
|
||||||
chainDb := ethServ.ChainDb()
|
chainDb := ethServ.ChainDb()
|
||||||
blockChain := ethServ.BlockChain()
|
blockChain := ethServ.BlockChain()
|
||||||
return service.NewStateDiffService(chainDb, blockChain, config)
|
return statediff.NewStateDiffService(chainDb, blockChain)
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
Fatalf("Failed to register State Diff Service", err)
|
Fatalf("Failed to register State Diff Service", err)
|
||||||
}
|
}
|
||||||
|
@ -1344,16 +1344,19 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.
|
|||||||
bc.triegc.Push(root, number)
|
bc.triegc.Push(root, number)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
if bc.cacheConfig.ProcessingStateDiffs {
|
if bc.cacheConfig.ProcessingStateDiffs {
|
||||||
if !bc.allowedRootToBeDereferenced(root.(common.Hash)) {
|
if !bc.allowedRootToBeDereferenced(root.(common.Hash)) {
|
||||||
bc.triegc.Push(root, number)
|
bc.triegc.Push(root, number)
|
||||||
break
|
break
|
||||||
} else {
|
} else {
|
||||||
|
log.Debug("Current root found in stateDiffsProcessed collection with a count of 2, okay to dereference",
|
||||||
|
"root", root.(common.Hash).Hex(),
|
||||||
|
"blockNumber", uint64(-number),
|
||||||
|
"size of stateDiffsProcessed", len(bc.stateDiffsProcessed))
|
||||||
delete(bc.stateDiffsProcessed, root.(common.Hash))
|
delete(bc.stateDiffsProcessed, root.(common.Hash))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
log.Debug("Dereferencing", "root", root.(common.Hash).Hex())
|
||||||
triedb.Dereference(root.(common.Hash))
|
triedb.Dereference(root.(common.Hash))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,93 +0,0 @@
|
|||||||
// Copyright 2015 The go-ethereum Authors
|
|
||||||
// This file is part of the go-ethereum library.
|
|
||||||
//
|
|
||||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// The go-ethereum library is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU Lesser General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Lesser General Public License
|
|
||||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
// Contains a batch of utility type declarations used by the tests. As the node
|
|
||||||
// operates on unique types, a lot of them are needed to check various features.
|
|
||||||
|
|
||||||
package statediff
|
|
||||||
|
|
||||||
import "fmt"
|
|
||||||
|
|
||||||
type Config struct {
|
|
||||||
Mode StateDiffMode // Mode for storing diffs
|
|
||||||
Path string // Path for storing diffs
|
|
||||||
}
|
|
||||||
|
|
||||||
type StateDiffMode int
|
|
||||||
|
|
||||||
const (
|
|
||||||
CSV StateDiffMode = iota
|
|
||||||
IPLD
|
|
||||||
LDB
|
|
||||||
SQL
|
|
||||||
)
|
|
||||||
|
|
||||||
func (mode StateDiffMode) IsValid() bool {
|
|
||||||
return mode >= IPLD && mode <= SQL
|
|
||||||
}
|
|
||||||
|
|
||||||
// String implements the stringer interface.
|
|
||||||
func (mode StateDiffMode) String() string {
|
|
||||||
switch mode {
|
|
||||||
case CSV:
|
|
||||||
return "csv"
|
|
||||||
case IPLD:
|
|
||||||
return "ipfs"
|
|
||||||
case LDB:
|
|
||||||
return "ldb"
|
|
||||||
case SQL:
|
|
||||||
return "sql"
|
|
||||||
default:
|
|
||||||
return "unknown"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewMode(mode string) (StateDiffMode, error) {
|
|
||||||
stateDiffMode := StateDiffMode(0)
|
|
||||||
err := stateDiffMode.UnmarshalText([]byte(mode))
|
|
||||||
return stateDiffMode, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (mode StateDiffMode) MarshalText() ([]byte, error) {
|
|
||||||
switch mode {
|
|
||||||
case CSV:
|
|
||||||
return []byte("ipfs"), nil
|
|
||||||
case IPLD:
|
|
||||||
return []byte("ipfs"), nil
|
|
||||||
case LDB:
|
|
||||||
return []byte("ldb"), nil
|
|
||||||
case SQL:
|
|
||||||
return []byte("sql"), nil
|
|
||||||
default:
|
|
||||||
return nil, fmt.Errorf("unknown state diff storage mode %d", mode)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (mode *StateDiffMode) UnmarshalText(text []byte) error {
|
|
||||||
switch string(text) {
|
|
||||||
case "csv":
|
|
||||||
*mode = CSV
|
|
||||||
case "ipfs":
|
|
||||||
*mode = IPLD
|
|
||||||
case "ldb":
|
|
||||||
*mode = LDB
|
|
||||||
case "sql":
|
|
||||||
*mode = SQL
|
|
||||||
default:
|
|
||||||
return fmt.Errorf(`unknown state diff storage mode %q, want "ipfs", "ldb" or "sql"`, text)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
@ -1,24 +0,0 @@
|
|||||||
package statediff_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/statediff"
|
|
||||||
"github.com/ethereum/go-ethereum/statediff/testhelpers"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestNewMode(t *testing.T) {
|
|
||||||
mode, err := statediff.NewMode("csv")
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf(testhelpers.ErrorFormatString, t.Name(), err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if mode != statediff.CSV {
|
|
||||||
t.Error()
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = statediff.NewMode("not a real mode")
|
|
||||||
if err == nil {
|
|
||||||
t.Error("Expected an error, and got nil.")
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,51 +0,0 @@
|
|||||||
// Copyright 2015 The go-ethereum Authors
|
|
||||||
// This file is part of the go-ethereum library.
|
|
||||||
//
|
|
||||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// The go-ethereum library is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU Lesser General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Lesser General Public License
|
|
||||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
// Contains a batch of utility type declarations used by the tests. As the node
|
|
||||||
// operates on unique types, a lot of them are needed to check various features.
|
|
||||||
|
|
||||||
package extractor
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
|
||||||
"github.com/ethereum/go-ethereum/statediff/builder"
|
|
||||||
"github.com/ethereum/go-ethereum/statediff/publisher"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Extractor interface {
|
|
||||||
ExtractStateDiff(parent, current types.Block) (string, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
type extractor struct {
|
|
||||||
Builder builder.Builder // Interface for building state diff objects from two blocks
|
|
||||||
Publisher publisher.Publisher // Interface for publishing state diff objects to a datastore (e.g. IPFS)
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewExtractor(builder builder.Builder, publisher publisher.Publisher) *extractor {
|
|
||||||
return &extractor{
|
|
||||||
Builder: builder,
|
|
||||||
Publisher: publisher,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *extractor) ExtractStateDiff(parent, current types.Block) (string, error) {
|
|
||||||
stateDiff, err := e.Builder.BuildStateDiff(parent.Root(), current.Root(), current.Number().Int64(), current.Hash())
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
return e.Publisher.PublishStateDiff(stateDiff)
|
|
||||||
}
|
|
@ -1,123 +0,0 @@
|
|||||||
package extractor_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"math/big"
|
|
||||||
"math/rand"
|
|
||||||
"reflect"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
|
||||||
b "github.com/ethereum/go-ethereum/statediff/builder"
|
|
||||||
e "github.com/ethereum/go-ethereum/statediff/extractor"
|
|
||||||
"github.com/ethereum/go-ethereum/statediff/testhelpers/mocks"
|
|
||||||
)
|
|
||||||
|
|
||||||
var publisher mocks.Publisher
|
|
||||||
var builder mocks.Builder
|
|
||||||
var currentBlockNumber *big.Int
|
|
||||||
var parentBlock, currentBlock *types.Block
|
|
||||||
var expectedStateDiff b.StateDiff
|
|
||||||
var extractor e.Extractor
|
|
||||||
var err error
|
|
||||||
|
|
||||||
func TestExtractor(t *testing.T) {
|
|
||||||
publisher = mocks.Publisher{}
|
|
||||||
builder = mocks.Builder{}
|
|
||||||
extractor = e.NewExtractor(&builder, &publisher)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
blockNumber := rand.Int63()
|
|
||||||
parentBlockNumber := big.NewInt(blockNumber - int64(1))
|
|
||||||
currentBlockNumber = big.NewInt(blockNumber)
|
|
||||||
parentBlock = types.NewBlock(&types.Header{Number: parentBlockNumber}, nil, nil, nil)
|
|
||||||
currentBlock = types.NewBlock(&types.Header{Number: currentBlockNumber}, nil, nil, nil)
|
|
||||||
|
|
||||||
expectedStateDiff = b.StateDiff{
|
|
||||||
BlockNumber: blockNumber,
|
|
||||||
BlockHash: currentBlock.Hash(),
|
|
||||||
CreatedAccounts: nil,
|
|
||||||
DeletedAccounts: nil,
|
|
||||||
UpdatedAccounts: nil,
|
|
||||||
}
|
|
||||||
|
|
||||||
testBuildStateDiffStruct(t)
|
|
||||||
testBuildStateDiffErrorHandling(t)
|
|
||||||
testPublishingStateDiff(t)
|
|
||||||
testPublisherErrorHandling(t)
|
|
||||||
}
|
|
||||||
|
|
||||||
func testBuildStateDiffStruct(t *testing.T) {
|
|
||||||
builder.SetStateDiffToBuild(&expectedStateDiff)
|
|
||||||
|
|
||||||
_, err = extractor.ExtractStateDiff(*parentBlock, *currentBlock)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !equals(builder.OldStateRoot, parentBlock.Root()) {
|
|
||||||
t.Error()
|
|
||||||
}
|
|
||||||
if !equals(builder.NewStateRoot, currentBlock.Root()) {
|
|
||||||
t.Error()
|
|
||||||
}
|
|
||||||
if !equals(builder.BlockNumber, currentBlockNumber.Int64()) {
|
|
||||||
t.Error()
|
|
||||||
}
|
|
||||||
if !equals(builder.BlockHash, currentBlock.Hash()) {
|
|
||||||
t.Error()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func testBuildStateDiffErrorHandling(t *testing.T) {
|
|
||||||
builder.SetBuilderError(mocks.Error)
|
|
||||||
|
|
||||||
_, err = extractor.ExtractStateDiff(*parentBlock, *currentBlock)
|
|
||||||
if err == nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !equals(err, mocks.Error) {
|
|
||||||
t.Error()
|
|
||||||
}
|
|
||||||
builder.SetBuilderError(nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
func testPublishingStateDiff(t *testing.T) {
|
|
||||||
builder.SetStateDiffToBuild(&expectedStateDiff)
|
|
||||||
|
|
||||||
_, err = extractor.ExtractStateDiff(*parentBlock, *currentBlock)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !equals(publisher.StateDiff, &expectedStateDiff) {
|
|
||||||
t.Error()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func testPublisherErrorHandling(t *testing.T) {
|
|
||||||
publisher.SetPublisherError(mocks.Error)
|
|
||||||
|
|
||||||
_, err = extractor.ExtractStateDiff(*parentBlock, *currentBlock)
|
|
||||||
if err == nil {
|
|
||||||
t.Error("Expected an error, but it didn't occur.")
|
|
||||||
}
|
|
||||||
if !equals(err, mocks.Error) {
|
|
||||||
t.Error()
|
|
||||||
}
|
|
||||||
|
|
||||||
publisher.SetPublisherError(nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
func equals(actual, expected interface{}) (success bool) {
|
|
||||||
if actualByteSlice, ok := actual.([]byte); ok {
|
|
||||||
if expectedByteSlice, ok := expected.([]byte); ok {
|
|
||||||
return bytes.Equal(actualByteSlice, expectedByteSlice)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return reflect.DeepEqual(actual, expected)
|
|
||||||
}
|
|
118
statediff/helpers.go
Normal file
118
statediff/helpers.go
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
// Copyright 2015 The go-ethereum Authors
|
||||||
|
// This file is part of the go-ethereum library.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public License
|
||||||
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
// Contains a batch of utility type declarations used by the tests. As the node
|
||||||
|
// operates on unique types, a lot of them are needed to check various features.
|
||||||
|
|
||||||
|
package statediff
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/trie"
|
||||||
|
)
|
||||||
|
|
||||||
|
func sortKeys(data AccountsMap) []string {
|
||||||
|
var keys []string
|
||||||
|
for key := range data {
|
||||||
|
keys = append(keys, key.Hex())
|
||||||
|
}
|
||||||
|
sort.Strings(keys)
|
||||||
|
|
||||||
|
return keys
|
||||||
|
}
|
||||||
|
|
||||||
|
// BytesToNiblePath
|
||||||
|
func bytesToNiblePath(path []byte) string {
|
||||||
|
if hasTerm(path) {
|
||||||
|
path = path[:len(path)-1]
|
||||||
|
}
|
||||||
|
nibblePath := ""
|
||||||
|
for i, v := range common.ToHex(path) {
|
||||||
|
if i%2 == 0 && i > 1 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
nibblePath = nibblePath + string(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nibblePath
|
||||||
|
}
|
||||||
|
|
||||||
|
func findIntersection(a, b []string) []string {
|
||||||
|
lenA := len(a)
|
||||||
|
lenB := len(b)
|
||||||
|
iOfA, iOfB := 0, 0
|
||||||
|
updates := make([]string, 0)
|
||||||
|
if iOfA >= lenA || iOfB >= lenB {
|
||||||
|
return updates
|
||||||
|
}
|
||||||
|
for {
|
||||||
|
switch strings.Compare(a[iOfA], b[iOfB]) {
|
||||||
|
// a[iOfA] < b[iOfB]
|
||||||
|
case -1:
|
||||||
|
iOfA++
|
||||||
|
if iOfA >= lenA {
|
||||||
|
return updates
|
||||||
|
}
|
||||||
|
// a[iOfA] == b[iOfB]
|
||||||
|
case 0:
|
||||||
|
updates = append(updates, a[iOfA])
|
||||||
|
iOfA++
|
||||||
|
iOfB++
|
||||||
|
if iOfA >= lenA || iOfB >= lenB {
|
||||||
|
return updates
|
||||||
|
}
|
||||||
|
// a[iOfA] > b[iOfB]
|
||||||
|
case 1:
|
||||||
|
iOfB++
|
||||||
|
if iOfB >= lenB {
|
||||||
|
return updates
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func pathToStr(it trie.NodeIterator) string {
|
||||||
|
return bytesToNiblePath(it.Path())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Duplicated from trie/encoding.go
|
||||||
|
func hexToKeyBytes(hex []byte) []byte {
|
||||||
|
if hasTerm(hex) {
|
||||||
|
hex = hex[:len(hex)-1]
|
||||||
|
}
|
||||||
|
if len(hex)&1 != 0 {
|
||||||
|
panic("can't convert hex key of odd length")
|
||||||
|
}
|
||||||
|
key := make([]byte, (len(hex)+1)/2)
|
||||||
|
decodeNibbles(hex, key)
|
||||||
|
|
||||||
|
return key
|
||||||
|
}
|
||||||
|
|
||||||
|
func decodeNibbles(nibbles []byte, bytes []byte) {
|
||||||
|
for bi, ni := 0, 0; ni < len(nibbles); bi, ni = bi+1, ni+2 {
|
||||||
|
bytes[bi] = nibbles[ni]<<4 | nibbles[ni+1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// hasTerm returns whether a hex key has the terminator flag.
|
||||||
|
func hasTerm(s []byte) bool {
|
||||||
|
return len(s) > 0 && s[len(s)-1] == 16
|
||||||
|
}
|
@ -1,130 +0,0 @@
|
|||||||
package publisher
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/csv"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"strconv"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
|
||||||
"github.com/ethereum/go-ethereum/statediff/builder"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
Headers = []string{
|
|
||||||
"blockNumber", "blockHash", "accountAction", "codeHash",
|
|
||||||
"nonceValue", "balanceValue", "contractRoot", "storageDiffPaths",
|
|
||||||
"accountLeafKey", "storageKey", "storageValue",
|
|
||||||
}
|
|
||||||
|
|
||||||
timeStampFormat = "20060102150405.00000"
|
|
||||||
deletedAccountAction = "deleted"
|
|
||||||
createdAccountAction = "created"
|
|
||||||
updatedAccountAction = "updated"
|
|
||||||
)
|
|
||||||
|
|
||||||
func createCSVFilePath(path, blockNumber string) string {
|
|
||||||
now := time.Now()
|
|
||||||
timeStamp := now.Format(timeStampFormat)
|
|
||||||
suffix := timeStamp + "-" + blockNumber
|
|
||||||
filePath := filepath.Join(path, suffix)
|
|
||||||
filePath = filePath + ".csv"
|
|
||||||
return filePath
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *publisher) publishStateDiffToCSV(sd builder.StateDiff) (string, error) {
|
|
||||||
filePath := createCSVFilePath(p.Config.Path, strconv.FormatInt(sd.BlockNumber, 10))
|
|
||||||
|
|
||||||
file, err := os.OpenFile(filePath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
defer file.Close()
|
|
||||||
|
|
||||||
writer := csv.NewWriter(file)
|
|
||||||
defer writer.Flush()
|
|
||||||
|
|
||||||
var data [][]string
|
|
||||||
data = append(data, Headers)
|
|
||||||
data = append(data, accumulateAccountRows(sd)...)
|
|
||||||
for _, value := range data {
|
|
||||||
err := writer.Write(value)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return filePath, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func accumulateAccountRows(sd builder.StateDiff) [][]string {
|
|
||||||
var accountRows [][]string
|
|
||||||
for accountAddr, accountDiff := range sd.CreatedAccounts {
|
|
||||||
formattedAccountData := formatAccountData(accountAddr, accountDiff, sd, createdAccountAction)
|
|
||||||
|
|
||||||
accountRows = append(accountRows, formattedAccountData...)
|
|
||||||
}
|
|
||||||
|
|
||||||
for accountAddr, accountDiff := range sd.UpdatedAccounts {
|
|
||||||
formattedAccountData := formatAccountData(accountAddr, accountDiff, sd, updatedAccountAction)
|
|
||||||
|
|
||||||
accountRows = append(accountRows, formattedAccountData...)
|
|
||||||
}
|
|
||||||
|
|
||||||
for accountAddr, accountDiff := range sd.DeletedAccounts {
|
|
||||||
formattedAccountData := formatAccountData(accountAddr, accountDiff, sd, deletedAccountAction)
|
|
||||||
|
|
||||||
accountRows = append(accountRows, formattedAccountData...)
|
|
||||||
}
|
|
||||||
|
|
||||||
return accountRows
|
|
||||||
}
|
|
||||||
|
|
||||||
func formatAccountData(accountAddr common.Hash, accountDiff builder.AccountDiff, sd builder.StateDiff, accountAction string) [][]string {
|
|
||||||
blockNumberString := strconv.FormatInt(sd.BlockNumber, 10)
|
|
||||||
blockHash := sd.BlockHash.String()
|
|
||||||
codeHash := accountDiff.CodeHash
|
|
||||||
nonce := strconv.FormatUint(*accountDiff.Nonce.Value, 10)
|
|
||||||
balance := accountDiff.Balance.Value.String()
|
|
||||||
newContractRoot := accountDiff.ContractRoot.Value
|
|
||||||
address := accountAddr.String()
|
|
||||||
var result [][]string
|
|
||||||
|
|
||||||
if len(accountDiff.Storage) > 0 {
|
|
||||||
for storagePath, storage := range accountDiff.Storage {
|
|
||||||
formattedAccountData := []string{
|
|
||||||
blockNumberString,
|
|
||||||
blockHash,
|
|
||||||
accountAction,
|
|
||||||
codeHash,
|
|
||||||
nonce,
|
|
||||||
balance,
|
|
||||||
*newContractRoot,
|
|
||||||
storagePath,
|
|
||||||
address,
|
|
||||||
*storage.Key,
|
|
||||||
*storage.Value,
|
|
||||||
}
|
|
||||||
|
|
||||||
result = append(result, formattedAccountData)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
formattedAccountData := []string{
|
|
||||||
blockNumberString,
|
|
||||||
blockHash,
|
|
||||||
accountAction,
|
|
||||||
codeHash,
|
|
||||||
nonce,
|
|
||||||
balance,
|
|
||||||
*newContractRoot,
|
|
||||||
"",
|
|
||||||
address,
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
}
|
|
||||||
result = append(result, formattedAccountData)
|
|
||||||
}
|
|
||||||
|
|
||||||
return result
|
|
||||||
}
|
|
@ -1,48 +0,0 @@
|
|||||||
// Copyright 2015 The go-ethereum Authors
|
|
||||||
// This file is part of the go-ethereum library.
|
|
||||||
//
|
|
||||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// The go-ethereum library is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU Lesser General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Lesser General Public License
|
|
||||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
// Contains a batch of utility type declarations used by the tests. As the node
|
|
||||||
// operates on unique types, a lot of them are needed to check various features.
|
|
||||||
|
|
||||||
package publisher
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/ethereum/go-ethereum/statediff"
|
|
||||||
"github.com/ethereum/go-ethereum/statediff/builder"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Publisher interface {
|
|
||||||
PublishStateDiff(sd *builder.StateDiff) (string, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
type publisher struct {
|
|
||||||
Config statediff.Config
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewPublisher(config statediff.Config) (*publisher, error) {
|
|
||||||
return &publisher{
|
|
||||||
Config: config,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *publisher) PublishStateDiff(sd *builder.StateDiff) (string, error) {
|
|
||||||
switch p.Config.Mode {
|
|
||||||
case statediff.CSV:
|
|
||||||
return p.publishStateDiffToCSV(*sd)
|
|
||||||
default:
|
|
||||||
return p.publishStateDiffToCSV(*sd)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,316 +0,0 @@
|
|||||||
package publisher_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/csv"
|
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"reflect"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/statediff"
|
|
||||||
"github.com/ethereum/go-ethereum/statediff/builder"
|
|
||||||
p "github.com/ethereum/go-ethereum/statediff/publisher"
|
|
||||||
"github.com/ethereum/go-ethereum/statediff/testhelpers"
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
tempDir = os.TempDir()
|
|
||||||
testFilePrefix = "test-statediff"
|
|
||||||
publisher p.Publisher
|
|
||||||
dir string
|
|
||||||
err error
|
|
||||||
)
|
|
||||||
|
|
||||||
var expectedCreatedAccountRow = []string{
|
|
||||||
strconv.FormatInt(testhelpers.BlockNumber, 10),
|
|
||||||
testhelpers.BlockHash,
|
|
||||||
"created",
|
|
||||||
testhelpers.CodeHash,
|
|
||||||
strconv.FormatUint(testhelpers.NewNonceValue, 10),
|
|
||||||
strconv.FormatInt(testhelpers.NewBalanceValue, 10),
|
|
||||||
testhelpers.ContractRoot,
|
|
||||||
testhelpers.StoragePath,
|
|
||||||
testhelpers.ContractLeafKey.Hex(),
|
|
||||||
"0000000000000000000000000000000000000000000000000000000000000001",
|
|
||||||
testhelpers.StorageValue,
|
|
||||||
}
|
|
||||||
|
|
||||||
var expectedCreatedAccountWithoutStorageUpdateRow = []string{
|
|
||||||
strconv.FormatInt(testhelpers.BlockNumber, 10),
|
|
||||||
testhelpers.BlockHash,
|
|
||||||
"created",
|
|
||||||
testhelpers.CodeHash,
|
|
||||||
strconv.FormatUint(testhelpers.NewNonceValue, 10),
|
|
||||||
strconv.FormatInt(testhelpers.NewBalanceValue, 10),
|
|
||||||
testhelpers.ContractRoot,
|
|
||||||
"",
|
|
||||||
testhelpers.AnotherContractLeafKey.Hex(),
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
}
|
|
||||||
|
|
||||||
var expectedUpdatedAccountRow = []string{
|
|
||||||
strconv.FormatInt(testhelpers.BlockNumber, 10),
|
|
||||||
testhelpers.BlockHash,
|
|
||||||
"updated",
|
|
||||||
testhelpers.CodeHash,
|
|
||||||
strconv.FormatUint(testhelpers.NewNonceValue, 10),
|
|
||||||
strconv.FormatInt(testhelpers.NewBalanceValue, 10),
|
|
||||||
testhelpers.ContractRoot,
|
|
||||||
testhelpers.StoragePath,
|
|
||||||
testhelpers.ContractLeafKey.Hex(),
|
|
||||||
"0000000000000000000000000000000000000000000000000000000000000001",
|
|
||||||
testhelpers.StorageValue,
|
|
||||||
}
|
|
||||||
|
|
||||||
var expectedDeletedAccountRow = []string{
|
|
||||||
strconv.FormatInt(testhelpers.BlockNumber, 10),
|
|
||||||
testhelpers.BlockHash,
|
|
||||||
"deleted",
|
|
||||||
testhelpers.CodeHash,
|
|
||||||
strconv.FormatUint(testhelpers.NewNonceValue, 10),
|
|
||||||
strconv.FormatInt(testhelpers.NewBalanceValue, 10),
|
|
||||||
testhelpers.ContractRoot,
|
|
||||||
testhelpers.StoragePath,
|
|
||||||
testhelpers.ContractLeafKey.Hex(),
|
|
||||||
"0000000000000000000000000000000000000000000000000000000000000001",
|
|
||||||
testhelpers.StorageValue,
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPublisher(t *testing.T) {
|
|
||||||
dir, err = ioutil.TempDir(tempDir, testFilePrefix)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
config := statediff.Config{
|
|
||||||
Path: dir,
|
|
||||||
Mode: statediff.CSV,
|
|
||||||
}
|
|
||||||
publisher, err = p.NewPublisher(config)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
type Test func(t *testing.T)
|
|
||||||
|
|
||||||
var tests = []Test{
|
|
||||||
testFileName,
|
|
||||||
testColumnHeaders,
|
|
||||||
testAccountDiffs,
|
|
||||||
testWhenNoDiff,
|
|
||||||
testDefaultPublisher,
|
|
||||||
testDefaultDirectory,
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, test := range tests {
|
|
||||||
test(t)
|
|
||||||
err := removeFilesFromDir(dir)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Error removing files from temp dir: %s", dir)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func removeFilesFromDir(dir string) error {
|
|
||||||
files, err := filepath.Glob(filepath.Join(dir, "*"))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, file := range files {
|
|
||||||
err = os.RemoveAll(file)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func testFileName(t *testing.T) {
|
|
||||||
fileName, err := publisher.PublishStateDiff(&testhelpers.TestStateDiff)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf(testhelpers.ErrorFormatString, t.Name(), err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !strings.HasPrefix(fileName, dir) {
|
|
||||||
t.Errorf(testhelpers.TestFailureFormatString, t.Name(), dir, fileName)
|
|
||||||
}
|
|
||||||
blockNumberWithFileExt := strconv.FormatInt(testhelpers.BlockNumber, 10) + ".csv"
|
|
||||||
if !strings.HasSuffix(fileName, blockNumberWithFileExt) {
|
|
||||||
t.Errorf(testhelpers.TestFailureFormatString, t.Name(), blockNumberWithFileExt, fileName)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func testColumnHeaders(t *testing.T) {
|
|
||||||
_, err = publisher.PublishStateDiff(&testhelpers.TestStateDiff)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf(testhelpers.ErrorFormatString, t.Name(), err)
|
|
||||||
}
|
|
||||||
|
|
||||||
file, err := getTestDiffFile(dir)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf(testhelpers.ErrorFormatString, t.Name(), err)
|
|
||||||
}
|
|
||||||
|
|
||||||
lines, err := csv.NewReader(file).ReadAll()
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf(testhelpers.ErrorFormatString, t.Name(), err)
|
|
||||||
}
|
|
||||||
if len(lines) < 1 {
|
|
||||||
t.Errorf(testhelpers.ErrorFormatString, t.Name(), err)
|
|
||||||
}
|
|
||||||
if !equals(lines[0], p.Headers) {
|
|
||||||
t.Error()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func testAccountDiffs(t *testing.T) {
|
|
||||||
// it persists the created, updated and deleted account diffs to a CSV file
|
|
||||||
_, err = publisher.PublishStateDiff(&testhelpers.TestStateDiff)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf(testhelpers.ErrorFormatString, t.Name(), err)
|
|
||||||
}
|
|
||||||
|
|
||||||
file, err := getTestDiffFile(dir)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf(testhelpers.ErrorFormatString, t.Name(), err)
|
|
||||||
}
|
|
||||||
|
|
||||||
lines, err := csv.NewReader(file).ReadAll()
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf(testhelpers.ErrorFormatString, t.Name(), err)
|
|
||||||
}
|
|
||||||
if len(lines) <= 3 {
|
|
||||||
t.Errorf(testhelpers.ErrorFormatString, t.Name(), err)
|
|
||||||
}
|
|
||||||
if !equals(lines[1], expectedCreatedAccountRow) {
|
|
||||||
t.Errorf(testhelpers.ErrorFormatString, t.Name(), err)
|
|
||||||
}
|
|
||||||
if !equals(lines[2], expectedCreatedAccountWithoutStorageUpdateRow) {
|
|
||||||
t.Errorf(testhelpers.ErrorFormatString, t.Name(), err)
|
|
||||||
}
|
|
||||||
if !equals(lines[3], expectedUpdatedAccountRow) {
|
|
||||||
t.Errorf(testhelpers.ErrorFormatString, t.Name(), err)
|
|
||||||
}
|
|
||||||
if !equals(lines[4], expectedDeletedAccountRow) {
|
|
||||||
t.Errorf(testhelpers.ErrorFormatString, t.Name(), err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func testWhenNoDiff(t *testing.T) {
|
|
||||||
//it creates an empty CSV when there is no diff
|
|
||||||
emptyDiff := builder.StateDiff{}
|
|
||||||
_, err = publisher.PublishStateDiff(&emptyDiff)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf(testhelpers.ErrorFormatString, t.Name(), err)
|
|
||||||
}
|
|
||||||
|
|
||||||
file, err := getTestDiffFile(dir)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf(testhelpers.ErrorFormatString, t.Name(), err)
|
|
||||||
}
|
|
||||||
|
|
||||||
lines, err := csv.NewReader(file).ReadAll()
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf(testhelpers.ErrorFormatString, t.Name(), err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !equals(len(lines), 1) {
|
|
||||||
t.Errorf(testhelpers.ErrorFormatString, t.Name(), err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func testDefaultPublisher(t *testing.T) {
|
|
||||||
//it defaults to publishing state diffs to a CSV file when no mode is configured
|
|
||||||
config := statediff.Config{Path: dir}
|
|
||||||
publisher, err = p.NewPublisher(config)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf(testhelpers.ErrorFormatString, t.Name(), err)
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = publisher.PublishStateDiff(&testhelpers.TestStateDiff)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf(testhelpers.ErrorFormatString, t.Name(), err)
|
|
||||||
}
|
|
||||||
|
|
||||||
file, err := getTestDiffFile(dir)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf(testhelpers.ErrorFormatString, t.Name(), err)
|
|
||||||
}
|
|
||||||
|
|
||||||
lines, err := csv.NewReader(file).ReadAll()
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf(testhelpers.ErrorFormatString, t.Name(), err)
|
|
||||||
}
|
|
||||||
if !equals(len(lines), 5) {
|
|
||||||
t.Errorf(testhelpers.ErrorFormatString, t.Name(), err)
|
|
||||||
}
|
|
||||||
if !equals(lines[0], p.Headers) {
|
|
||||||
t.Errorf(testhelpers.ErrorFormatString, t.Name(), err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func testDefaultDirectory(t *testing.T) {
|
|
||||||
//it defaults to publishing CSV files in the current directory when no path is configured
|
|
||||||
config := statediff.Config{}
|
|
||||||
publisher, err = p.NewPublisher(config)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf(testhelpers.ErrorFormatString, t.Name(), err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err := os.Chdir(dir)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf(testhelpers.ErrorFormatString, t.Name(), err)
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = publisher.PublishStateDiff(&testhelpers.TestStateDiff)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf(testhelpers.ErrorFormatString, t.Name(), err)
|
|
||||||
}
|
|
||||||
|
|
||||||
file, err := getTestDiffFile(dir)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf(testhelpers.ErrorFormatString, t.Name(), err)
|
|
||||||
}
|
|
||||||
|
|
||||||
lines, err := csv.NewReader(file).ReadAll()
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf(testhelpers.ErrorFormatString, t.Name(), err)
|
|
||||||
}
|
|
||||||
if !equals(len(lines), 5) {
|
|
||||||
t.Errorf(testhelpers.ErrorFormatString, t.Name(), err)
|
|
||||||
}
|
|
||||||
if !equals(lines[0], p.Headers) {
|
|
||||||
t.Errorf(testhelpers.ErrorFormatString, t.Name(), err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func getTestDiffFile(dir string) (*os.File, error) {
|
|
||||||
files, err := ioutil.ReadDir(dir)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if len(files) == 0 {
|
|
||||||
return nil, errors.New("There are 0 files.")
|
|
||||||
}
|
|
||||||
|
|
||||||
fileName := files[0].Name()
|
|
||||||
filePath := filepath.Join(dir, fileName)
|
|
||||||
|
|
||||||
return os.Open(filePath)
|
|
||||||
}
|
|
||||||
|
|
||||||
func equals(actual, expected interface{}) (success bool) {
|
|
||||||
if actualByteSlice, ok := actual.([]byte); ok {
|
|
||||||
if expectedByteSlice, ok := expected.([]byte); ok {
|
|
||||||
return bytes.Equal(actualByteSlice, expectedByteSlice)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return reflect.DeepEqual(actual, expected)
|
|
||||||
}
|
|
@ -1,4 +1,83 @@
|
|||||||
|
// Copyright 2015 The go-ethereum Authors
|
||||||
|
// This file is part of the go-ethereum library.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public License
|
||||||
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
package testhelpers
|
package testhelpers
|
||||||
|
|
||||||
var ErrorFormatString = "Error: %s, %+v"
|
import (
|
||||||
var TestFailureFormatString = "Test failed: %s\nexpected %+v, got %+v\n"
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/consensus/ethash"
|
||||||
|
"github.com/ethereum/go-ethereum/core"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
|
"github.com/ethereum/go-ethereum/params"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MakeChain creates a chain of n blocks starting at and including parent.
|
||||||
|
// the returned hash chain is ordered head->parent. In addition, every 3rd block
|
||||||
|
// contains a transaction and every 5th an uncle to allow testing correct block
|
||||||
|
// reassembly.
|
||||||
|
func MakeChain(n int, parent *types.Block) ([]common.Hash, map[common.Hash]*types.Block, *core.BlockChain) {
|
||||||
|
blocks, _ := core.GenerateChain(params.TestChainConfig, parent, ethash.NewFaker(), Testdb, n, testChainGen)
|
||||||
|
headers := make([]*types.Header, len(blocks))
|
||||||
|
for i, block := range blocks {
|
||||||
|
headers[i] = block.Header()
|
||||||
|
}
|
||||||
|
chain, _ := core.NewBlockChain(Testdb, nil, params.TestChainConfig, ethash.NewFaker(), vm.Config{}, nil)
|
||||||
|
|
||||||
|
hashes := make([]common.Hash, n+1)
|
||||||
|
hashes[len(hashes)-1] = parent.Hash()
|
||||||
|
blockm := make(map[common.Hash]*types.Block, n+1)
|
||||||
|
blockm[parent.Hash()] = parent
|
||||||
|
for i, b := range blocks {
|
||||||
|
hashes[len(hashes)-i-2] = b.Hash()
|
||||||
|
blockm[b.Hash()] = b
|
||||||
|
}
|
||||||
|
return hashes, blockm, chain
|
||||||
|
}
|
||||||
|
|
||||||
|
func testChainGen(i int, block *core.BlockGen) {
|
||||||
|
signer := types.HomesteadSigner{}
|
||||||
|
switch i {
|
||||||
|
case 0:
|
||||||
|
// In block 1, the test bank sends account #1 some ether.
|
||||||
|
tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(TestBankAddress), Account1Addr, big.NewInt(10000), params.TxGas, nil, nil), signer, TestBankKey)
|
||||||
|
block.AddTx(tx)
|
||||||
|
case 1:
|
||||||
|
// In block 2, the test bank sends some more ether to account #1.
|
||||||
|
// account1Addr passes it on to account #2.
|
||||||
|
// account1Addr creates a test contract.
|
||||||
|
tx1, _ := types.SignTx(types.NewTransaction(block.TxNonce(TestBankAddress), Account1Addr, big.NewInt(1000), params.TxGas, nil, nil), signer, TestBankKey)
|
||||||
|
nonce := block.TxNonce(Account1Addr)
|
||||||
|
tx2, _ := types.SignTx(types.NewTransaction(nonce, Account2Addr, big.NewInt(1000), params.TxGas, nil, nil), signer, Account1Key)
|
||||||
|
nonce++
|
||||||
|
tx3, _ := types.SignTx(types.NewContractCreation(nonce, big.NewInt(0), 1000000, big.NewInt(0), ContractCode), signer, Account1Key)
|
||||||
|
ContractAddr = crypto.CreateAddress(Account1Addr, nonce) //0xaE9BEa628c4Ce503DcFD7E305CaB4e29E7476592
|
||||||
|
block.AddTx(tx1)
|
||||||
|
block.AddTx(tx2)
|
||||||
|
block.AddTx(tx3)
|
||||||
|
case 2:
|
||||||
|
// Block 3 is empty but was mined by account #2.
|
||||||
|
block.SetCoinbase(Account2Addr)
|
||||||
|
//get function: 60cd2685
|
||||||
|
//put function: c16431b9
|
||||||
|
data := common.Hex2Bytes("C16431B900000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003")
|
||||||
|
tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(TestBankAddress), ContractAddr, big.NewInt(0), 100000, nil, data), signer, TestBankKey)
|
||||||
|
block.AddTx(tx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,3 +1,19 @@
|
|||||||
|
// Copyright 2015 The go-ethereum Authors
|
||||||
|
// This file is part of the go-ethereum library.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public License
|
||||||
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
package mocks
|
package mocks
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -11,6 +27,7 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/event"
|
"github.com/ethereum/go-ethereum/event"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// BlockChain is a mock blockchain for testing
|
||||||
type BlockChain struct {
|
type BlockChain struct {
|
||||||
ParentHashesLookedUp []common.Hash
|
ParentHashesLookedUp []common.Hash
|
||||||
parentBlocksToReturn []*types.Block
|
parentBlocksToReturn []*types.Block
|
||||||
@ -18,34 +35,39 @@ type BlockChain struct {
|
|||||||
ChainEvents []core.ChainEvent
|
ChainEvents []core.ChainEvent
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mc *BlockChain) AddToStateDiffProcessedCollection(hash common.Hash) {}
|
// AddToStateDiffProcessedCollection mock method
|
||||||
|
func (blockChain *BlockChain) AddToStateDiffProcessedCollection(hash common.Hash) {}
|
||||||
|
|
||||||
func (mc *BlockChain) SetParentBlocksToReturn(blocks []*types.Block) {
|
// SetParentBlocksToReturn mock method
|
||||||
mc.parentBlocksToReturn = blocks
|
func (blockChain *BlockChain) SetParentBlocksToReturn(blocks []*types.Block) {
|
||||||
|
blockChain.parentBlocksToReturn = blocks
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mc *BlockChain) GetBlockByHash(hash common.Hash) *types.Block {
|
// GetBlockByHash mock method
|
||||||
mc.ParentHashesLookedUp = append(mc.ParentHashesLookedUp, hash)
|
func (blockChain *BlockChain) GetBlockByHash(hash common.Hash) *types.Block {
|
||||||
|
blockChain.ParentHashesLookedUp = append(blockChain.ParentHashesLookedUp, hash)
|
||||||
|
|
||||||
var parentBlock *types.Block
|
var parentBlock *types.Block
|
||||||
if len(mc.parentBlocksToReturn) > 0 {
|
if len(blockChain.parentBlocksToReturn) > 0 {
|
||||||
parentBlock = mc.parentBlocksToReturn[mc.callCount]
|
parentBlock = blockChain.parentBlocksToReturn[blockChain.callCount]
|
||||||
}
|
}
|
||||||
|
|
||||||
mc.callCount++
|
blockChain.callCount++
|
||||||
return parentBlock
|
return parentBlock
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bc *BlockChain) SetChainEvents(chainEvents []core.ChainEvent) {
|
// SetChainEvents mock method
|
||||||
bc.ChainEvents = chainEvents
|
func (blockChain *BlockChain) SetChainEvents(chainEvents []core.ChainEvent) {
|
||||||
|
blockChain.ChainEvents = chainEvents
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bc *BlockChain) SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription {
|
// SubscribeChainEvent mock method
|
||||||
|
func (blockChain *BlockChain) SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription {
|
||||||
subErr := errors.New("Subscription Error")
|
subErr := errors.New("Subscription Error")
|
||||||
|
|
||||||
var eventCounter int
|
var eventCounter int
|
||||||
subscription := event.NewSubscription(func(quit <-chan struct{}) error {
|
subscription := event.NewSubscription(func(quit <-chan struct{}) error {
|
||||||
for _, chainEvent := range bc.ChainEvents {
|
for _, chainEvent := range blockChain.ChainEvents {
|
||||||
if eventCounter > 1 {
|
if eventCounter > 1 {
|
||||||
time.Sleep(250 * time.Millisecond)
|
time.Sleep(250 * time.Millisecond)
|
||||||
return subErr
|
return subErr
|
||||||
|
@ -1,20 +1,38 @@
|
|||||||
|
// Copyright 2015 The go-ethereum Authors
|
||||||
|
// This file is part of the go-ethereum library.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public License
|
||||||
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
package mocks
|
package mocks
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/statediff/builder"
|
"github.com/ethereum/go-ethereum/statediff"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Builder is a mock state diff builder
|
||||||
type Builder struct {
|
type Builder struct {
|
||||||
OldStateRoot common.Hash
|
OldStateRoot common.Hash
|
||||||
NewStateRoot common.Hash
|
NewStateRoot common.Hash
|
||||||
BlockNumber int64
|
BlockNumber int64
|
||||||
BlockHash common.Hash
|
BlockHash common.Hash
|
||||||
stateDiff *builder.StateDiff
|
stateDiff statediff.StateDiff
|
||||||
builderError error
|
builderError error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (builder *Builder) BuildStateDiff(oldStateRoot, newStateRoot common.Hash, blockNumber int64, blockHash common.Hash) (*builder.StateDiff, error) {
|
// BuildStateDiff mock method
|
||||||
|
func (builder *Builder) BuildStateDiff(oldStateRoot, newStateRoot common.Hash, blockNumber int64, blockHash common.Hash) (statediff.StateDiff, error) {
|
||||||
builder.OldStateRoot = oldStateRoot
|
builder.OldStateRoot = oldStateRoot
|
||||||
builder.NewStateRoot = newStateRoot
|
builder.NewStateRoot = newStateRoot
|
||||||
builder.BlockNumber = blockNumber
|
builder.BlockNumber = blockNumber
|
||||||
@ -23,10 +41,12 @@ func (builder *Builder) BuildStateDiff(oldStateRoot, newStateRoot common.Hash, b
|
|||||||
return builder.stateDiff, builder.builderError
|
return builder.stateDiff, builder.builderError
|
||||||
}
|
}
|
||||||
|
|
||||||
func (builder *Builder) SetStateDiffToBuild(stateDiff *builder.StateDiff) {
|
// SetStateDiffToBuild mock method
|
||||||
|
func (builder *Builder) SetStateDiffToBuild(stateDiff statediff.StateDiff) {
|
||||||
builder.stateDiff = stateDiff
|
builder.stateDiff = stateDiff
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetBuilderError mock method
|
||||||
func (builder *Builder) SetBuilderError(err error) {
|
func (builder *Builder) SetBuilderError(err error) {
|
||||||
builder.builderError = err
|
builder.builderError = err
|
||||||
}
|
}
|
||||||
|
@ -1,5 +0,0 @@
|
|||||||
package mocks
|
|
||||||
|
|
||||||
import "errors"
|
|
||||||
|
|
||||||
var Error = errors.New("mock error")
|
|
@ -1,20 +0,0 @@
|
|||||||
package mocks
|
|
||||||
|
|
||||||
import "github.com/ethereum/go-ethereum/core/types"
|
|
||||||
|
|
||||||
type Extractor struct {
|
|
||||||
ParentBlocks []types.Block
|
|
||||||
CurrentBlocks []types.Block
|
|
||||||
extractError error
|
|
||||||
}
|
|
||||||
|
|
||||||
func (me *Extractor) ExtractStateDiff(parent, current types.Block) (string, error) {
|
|
||||||
me.ParentBlocks = append(me.ParentBlocks, parent)
|
|
||||||
me.CurrentBlocks = append(me.CurrentBlocks, current)
|
|
||||||
|
|
||||||
return "", me.extractError
|
|
||||||
}
|
|
||||||
|
|
||||||
func (me *Extractor) SetExtractError(err error) {
|
|
||||||
me.extractError = err
|
|
||||||
}
|
|
@ -1,17 +1,36 @@
|
|||||||
|
// Copyright 2015 The go-ethereum Authors
|
||||||
|
// This file is part of the go-ethereum library.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public License
|
||||||
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
package mocks
|
package mocks
|
||||||
|
|
||||||
import "github.com/ethereum/go-ethereum/statediff/builder"
|
import "github.com/ethereum/go-ethereum/statediff"
|
||||||
|
|
||||||
|
// Publisher mock
|
||||||
type Publisher struct {
|
type Publisher struct {
|
||||||
StateDiff *builder.StateDiff
|
StateDiff *statediff.StateDiff
|
||||||
publisherError error
|
publisherError error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (publisher *Publisher) PublishStateDiff(sd *builder.StateDiff) (string, error) {
|
// PublishStateDiff mock method
|
||||||
|
func (publisher *Publisher) PublishStateDiff(sd *statediff.StateDiff) (string, error) {
|
||||||
publisher.StateDiff = sd
|
publisher.StateDiff = sd
|
||||||
return "", publisher.publisherError
|
return "", publisher.publisherError
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetPublisherError mock method
|
||||||
func (publisher *Publisher) SetPublisherError(err error) {
|
func (publisher *Publisher) SetPublisherError(err error) {
|
||||||
publisher.publisherError = err
|
publisher.publisherError = err
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,19 @@
|
|||||||
|
// Copyright 2015 The go-ethereum Authors
|
||||||
|
// This file is part of the go-ethereum library.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public License
|
||||||
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
package testhelpers
|
package testhelpers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -5,71 +21,94 @@ import (
|
|||||||
"math/rand"
|
"math/rand"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/core"
|
||||||
|
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||||
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/statediff/builder"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
|
"github.com/ethereum/go-ethereum/statediff"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// AddressToLeafKey hashes an returns an address
|
||||||
func AddressToLeafKey(address common.Address) common.Hash {
|
func AddressToLeafKey(address common.Address) common.Hash {
|
||||||
return common.BytesToHash(crypto.Keccak256(address[:]))
|
return common.BytesToHash(crypto.Keccak256(address[:]))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test variables
|
||||||
var (
|
var (
|
||||||
BlockNumber = rand.Int63()
|
BlockNumber = rand.Int63()
|
||||||
BlockHash = "0xfa40fbe2d98d98b3363a778d52f2bcd29d6790b9b3f3cab2b167fd12d3550f73"
|
BlockHash = "0xfa40fbe2d98d98b3363a778d52f2bcd29d6790b9b3f3cab2b167fd12d3550f73"
|
||||||
CodeHash = "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"
|
CodeHash = common.Hex2Bytes("0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470")
|
||||||
NewNonceValue = rand.Uint64()
|
NewNonceValue = rand.Uint64()
|
||||||
NewBalanceValue = rand.Int63()
|
NewBalanceValue = rand.Int63()
|
||||||
ContractRoot = "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"
|
ContractRoot = common.HexToHash("0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")
|
||||||
StoragePath = "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"
|
StoragePath = common.HexToHash("0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470").Bytes()
|
||||||
StorageKey = "0000000000000000000000000000000000000000000000000000000000000001"
|
StorageKey = common.HexToHash("0000000000000000000000000000000000000000000000000000000000000001").Bytes()
|
||||||
StorageValue = "0x03"
|
StorageValue = common.Hex2Bytes("0x03")
|
||||||
storage = map[string]builder.DiffStorage{StoragePath: {
|
storage = []statediff.StorageDiff{{
|
||||||
Key: &StorageKey,
|
Key: StorageKey,
|
||||||
Value: &StorageValue,
|
Value: StorageValue,
|
||||||
|
Path: StoragePath,
|
||||||
|
Proof: [][]byte{},
|
||||||
}}
|
}}
|
||||||
emptyStorage = map[string]builder.DiffStorage{}
|
emptyStorage = make([]statediff.StorageDiff, 0)
|
||||||
address = common.HexToAddress("0xaE9BEa628c4Ce503DcFD7E305CaB4e29E7476592")
|
address = common.HexToAddress("0xaE9BEa628c4Ce503DcFD7E305CaB4e29E7476592")
|
||||||
ContractLeafKey = AddressToLeafKey(address)
|
ContractLeafKey = AddressToLeafKey(address)
|
||||||
anotherAddress = common.HexToAddress("0xaE9BEa628c4Ce503DcFD7E305CaB4e29E7476593")
|
anotherAddress = common.HexToAddress("0xaE9BEa628c4Ce503DcFD7E305CaB4e29E7476593")
|
||||||
AnotherContractLeafKey = AddressToLeafKey(anotherAddress)
|
AnotherContractLeafKey = AddressToLeafKey(anotherAddress)
|
||||||
CreatedAccountDiffs = builder.AccountDiffsMap{
|
testAccount = state.Account{
|
||||||
ContractLeafKey: {
|
Nonce: NewNonceValue,
|
||||||
Nonce: builder.DiffUint64{Value: &NewNonceValue},
|
Balance: big.NewInt(NewBalanceValue),
|
||||||
Balance: builder.DiffBigInt{Value: big.NewInt(NewBalanceValue)},
|
Root: ContractRoot,
|
||||||
ContractRoot: builder.DiffString{Value: &ContractRoot},
|
|
||||||
CodeHash: CodeHash,
|
CodeHash: CodeHash,
|
||||||
|
}
|
||||||
|
valueBytes, _ = rlp.EncodeToBytes(testAccount)
|
||||||
|
CreatedAccountDiffs = statediff.AccountDiffsMap{
|
||||||
|
ContractLeafKey: {
|
||||||
|
Key: ContractLeafKey.Bytes(),
|
||||||
|
Value: valueBytes,
|
||||||
Storage: storage,
|
Storage: storage,
|
||||||
},
|
},
|
||||||
AnotherContractLeafKey: {
|
AnotherContractLeafKey: {
|
||||||
Nonce: builder.DiffUint64{Value: &NewNonceValue},
|
Key: AnotherContractLeafKey.Bytes(),
|
||||||
Balance: builder.DiffBigInt{Value: big.NewInt(NewBalanceValue)},
|
Value: valueBytes,
|
||||||
CodeHash: CodeHash,
|
|
||||||
ContractRoot: builder.DiffString{Value: &ContractRoot},
|
|
||||||
Storage: emptyStorage,
|
Storage: emptyStorage,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdatedAccountDiffs = builder.AccountDiffsMap{ContractLeafKey: {
|
UpdatedAccountDiffs = statediff.AccountDiffsMap{ContractLeafKey: {
|
||||||
Nonce: builder.DiffUint64{Value: &NewNonceValue},
|
Key: ContractLeafKey.Bytes(),
|
||||||
Balance: builder.DiffBigInt{Value: big.NewInt(NewBalanceValue)},
|
Value: valueBytes,
|
||||||
CodeHash: CodeHash,
|
|
||||||
ContractRoot: builder.DiffString{Value: &ContractRoot},
|
|
||||||
Storage: storage,
|
Storage: storage,
|
||||||
}}
|
}}
|
||||||
|
|
||||||
DeletedAccountDiffs = builder.AccountDiffsMap{ContractLeafKey: {
|
DeletedAccountDiffs = statediff.AccountDiffsMap{ContractLeafKey: {
|
||||||
Nonce: builder.DiffUint64{Value: &NewNonceValue},
|
Key: ContractLeafKey.Bytes(),
|
||||||
Balance: builder.DiffBigInt{Value: big.NewInt(NewBalanceValue)},
|
Value: valueBytes,
|
||||||
ContractRoot: builder.DiffString{Value: &ContractRoot},
|
|
||||||
CodeHash: CodeHash,
|
|
||||||
Storage: storage,
|
Storage: storage,
|
||||||
}}
|
}}
|
||||||
|
|
||||||
TestStateDiff = builder.StateDiff{
|
TestStateDiff = statediff.StateDiff{
|
||||||
BlockNumber: BlockNumber,
|
BlockNumber: BlockNumber,
|
||||||
BlockHash: common.HexToHash(BlockHash),
|
BlockHash: common.HexToHash(BlockHash),
|
||||||
CreatedAccounts: CreatedAccountDiffs,
|
CreatedAccounts: CreatedAccountDiffs,
|
||||||
DeletedAccounts: DeletedAccountDiffs,
|
DeletedAccounts: DeletedAccountDiffs,
|
||||||
UpdatedAccounts: UpdatedAccountDiffs,
|
UpdatedAccounts: UpdatedAccountDiffs,
|
||||||
}
|
}
|
||||||
|
Testdb = rawdb.NewMemoryDatabase()
|
||||||
|
|
||||||
|
TestBankKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
||||||
|
TestBankAddress = crypto.PubkeyToAddress(TestBankKey.PublicKey) //0x71562b71999873DB5b286dF957af199Ec94617F7
|
||||||
|
BankLeafKey = AddressToLeafKey(TestBankAddress)
|
||||||
|
TestBankFunds = big.NewInt(100000000)
|
||||||
|
Genesis = core.GenesisBlockForTesting(Testdb, TestBankAddress, TestBankFunds)
|
||||||
|
|
||||||
|
Account1Key, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
|
||||||
|
Account2Key, _ = crypto.HexToECDSA("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee")
|
||||||
|
Account1Addr = crypto.PubkeyToAddress(Account1Key.PublicKey) //0x703c4b2bD70c169f5717101CaeE543299Fc946C7
|
||||||
|
Account2Addr = crypto.PubkeyToAddress(Account2Key.PublicKey) //0x0D3ab14BBaD3D99F4203bd7a11aCB94882050E7e
|
||||||
|
Account1LeafKey = AddressToLeafKey(Account1Addr)
|
||||||
|
Account2LeafKey = AddressToLeafKey(Account2Addr)
|
||||||
|
ContractCode = common.Hex2Bytes("608060405234801561001057600080fd5b50602060405190810160405280600160ff16815250600090600161003592919061003b565b506100a5565b826064810192821561006f579160200282015b8281111561006e578251829060ff1690559160200191906001019061004e565b5b50905061007c9190610080565b5090565b6100a291905b8082111561009e576000816000905550600101610086565b5090565b90565b610124806100b46000396000f3fe6080604052348015600f57600080fd5b5060043610604f576000357c01000000000000000000000000000000000000000000000000000000009004806360cd2685146054578063c16431b9146093575b600080fd5b607d60048036036020811015606857600080fd5b810190808035906020019092919050505060c8565b6040518082815260200191505060405180910390f35b60c66004803603604081101560a757600080fd5b81019080803590602001909291908035906020019092919050505060e0565b005b6000808260648110151560d757fe5b01549050919050565b8060008360648110151560ef57fe5b0181905550505056fea165627a7a7230582064e918c3140a117bf3aa65865a9b9e83fae21ad1720506e7933b2a9f54bb40260029")
|
||||||
|
ContractAddr common.Address
|
||||||
)
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user