mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-19 18:32:23 +00:00
Merge branch 'ethereum:master' into patch/typo
This commit is contained in:
commit
8fd6d5bf7e
45 changed files with 560 additions and 424 deletions
1
.github/workflows/go.yml
vendored
1
.github/workflows/go.yml
vendored
|
|
@ -16,6 +16,7 @@ jobs:
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: 1.21.4
|
go-version: 1.21.4
|
||||||
|
cache: false
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
run: go test -short ./...
|
run: go test -short ./...
|
||||||
env:
|
env:
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ linters:
|
||||||
- durationcheck
|
- durationcheck
|
||||||
- exportloopref
|
- exportloopref
|
||||||
- whitespace
|
- whitespace
|
||||||
|
- revive # only certain checks enabled
|
||||||
|
|
||||||
### linters we tried and will not be using:
|
### linters we tried and will not be using:
|
||||||
###
|
###
|
||||||
|
|
@ -38,6 +39,15 @@ linters:
|
||||||
linters-settings:
|
linters-settings:
|
||||||
gofmt:
|
gofmt:
|
||||||
simplify: true
|
simplify: true
|
||||||
|
revive:
|
||||||
|
enable-all-rules: false
|
||||||
|
# here we enable specific useful rules
|
||||||
|
# see https://golangci-lint.run/usage/linters/#revive for supported rules
|
||||||
|
rules:
|
||||||
|
- name: receiver-naming
|
||||||
|
severity: warning
|
||||||
|
disabled: false
|
||||||
|
exclude: [""]
|
||||||
|
|
||||||
issues:
|
issues:
|
||||||
exclude-files:
|
exclude-files:
|
||||||
|
|
@ -47,6 +57,9 @@ issues:
|
||||||
linters:
|
linters:
|
||||||
- deadcode
|
- deadcode
|
||||||
- staticcheck
|
- staticcheck
|
||||||
|
- path: crypto/bn256/
|
||||||
|
linters:
|
||||||
|
- revive
|
||||||
- path: internal/build/pgp.go
|
- path: internal/build/pgp.go
|
||||||
text: 'SA1019: "golang.org/x/crypto/openpgp" is deprecated: this package is unmaintained except for security fixes.'
|
text: 'SA1019: "golang.org/x/crypto/openpgp" is deprecated: this package is unmaintained except for security fixes.'
|
||||||
- path: core/vm/contracts.go
|
- path: core/vm/contracts.go
|
||||||
|
|
|
||||||
|
|
@ -64,6 +64,9 @@ type Type struct {
|
||||||
var (
|
var (
|
||||||
// typeRegex parses the abi sub types
|
// typeRegex parses the abi sub types
|
||||||
typeRegex = regexp.MustCompile("([a-zA-Z]+)(([0-9]+)(x([0-9]+))?)?")
|
typeRegex = regexp.MustCompile("([a-zA-Z]+)(([0-9]+)(x([0-9]+))?)?")
|
||||||
|
|
||||||
|
// sliceSizeRegex grab the slice size
|
||||||
|
sliceSizeRegex = regexp.MustCompile("[0-9]+")
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewType creates a new reflection type of abi type given in t.
|
// NewType creates a new reflection type of abi type given in t.
|
||||||
|
|
@ -91,8 +94,7 @@ func NewType(t string, internalType string, components []ArgumentMarshaling) (ty
|
||||||
// grab the last cell and create a type from there
|
// grab the last cell and create a type from there
|
||||||
sliced := t[i:]
|
sliced := t[i:]
|
||||||
// grab the slice size with regexp
|
// grab the slice size with regexp
|
||||||
re := regexp.MustCompile("[0-9]+")
|
intz := sliceSizeRegex.FindAllString(sliced, -1)
|
||||||
intz := re.FindAllString(sliced, -1)
|
|
||||||
|
|
||||||
if len(intz) == 0 {
|
if len(intz) == 0 {
|
||||||
// is a slice
|
// is a slice
|
||||||
|
|
|
||||||
|
|
@ -73,6 +73,14 @@ var (
|
||||||
DerivationSignatureHash = sha256.Sum256(common.Hash{}.Bytes())
|
DerivationSignatureHash = sha256.Sum256(common.Hash{}.Bytes())
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// PinRegexp is the regular expression used to validate PIN codes.
|
||||||
|
pinRegexp = regexp.MustCompile(`^[0-9]{6,}$`)
|
||||||
|
|
||||||
|
// PukRegexp is the regular expression used to validate PUK codes.
|
||||||
|
pukRegexp = regexp.MustCompile(`^[0-9]{12,}$`)
|
||||||
|
)
|
||||||
|
|
||||||
// List of APDU command-related constants
|
// List of APDU command-related constants
|
||||||
const (
|
const (
|
||||||
claISO7816 = 0
|
claISO7816 = 0
|
||||||
|
|
@ -380,7 +388,7 @@ func (w *Wallet) Open(passphrase string) error {
|
||||||
case passphrase == "":
|
case passphrase == "":
|
||||||
return ErrPINUnblockNeeded
|
return ErrPINUnblockNeeded
|
||||||
case status.PinRetryCount > 0:
|
case status.PinRetryCount > 0:
|
||||||
if !regexp.MustCompile(`^[0-9]{6,}$`).MatchString(passphrase) {
|
if !pinRegexp.MatchString(passphrase) {
|
||||||
w.log.Error("PIN needs to be at least 6 digits")
|
w.log.Error("PIN needs to be at least 6 digits")
|
||||||
return ErrPINNeeded
|
return ErrPINNeeded
|
||||||
}
|
}
|
||||||
|
|
@ -388,7 +396,7 @@ func (w *Wallet) Open(passphrase string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
if !regexp.MustCompile(`^[0-9]{12,}$`).MatchString(passphrase) {
|
if !pukRegexp.MatchString(passphrase) {
|
||||||
w.log.Error("PUK needs to be at least 12 digits")
|
w.log.Error("PUK needs to be at least 12 digits")
|
||||||
return ErrPINUnblockNeeded
|
return ErrPINUnblockNeeded
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -494,9 +494,6 @@ func (api *BeaconLightApi) StartHeadListener(listener HeadEventListener) func()
|
||||||
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
|
||||||
stream.Close()
|
|
||||||
|
|
||||||
case event, ok := <-stream.Events:
|
case event, ok := <-stream.Events:
|
||||||
if !ok {
|
if !ok {
|
||||||
log.Trace("Event stream closed")
|
log.Trace("Event stream closed")
|
||||||
|
|
|
||||||
|
|
@ -186,11 +186,15 @@ func (s *serverWithTimeout) eventCallback(event Event) {
|
||||||
// call will just do nothing
|
// call will just do nothing
|
||||||
timer.Stop()
|
timer.Stop()
|
||||||
delete(s.timeouts, id)
|
delete(s.timeouts, id)
|
||||||
|
if s.childEventCb != nil {
|
||||||
s.childEventCb(event)
|
s.childEventCb(event)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
|
if s.childEventCb != nil {
|
||||||
s.childEventCb(event)
|
s.childEventCb(event)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// startTimeout starts a timeout timer for the given request.
|
// startTimeout starts a timeout timer for the given request.
|
||||||
|
|
@ -211,25 +215,27 @@ func (s *serverWithTimeout) startTimeout(reqData RequestResponse) {
|
||||||
delete(s.timeouts, id)
|
delete(s.timeouts, id)
|
||||||
childEventCb := s.childEventCb
|
childEventCb := s.childEventCb
|
||||||
s.lock.Unlock()
|
s.lock.Unlock()
|
||||||
|
if childEventCb != nil {
|
||||||
childEventCb(Event{Type: EvFail, Data: reqData})
|
childEventCb(Event{Type: EvFail, Data: reqData})
|
||||||
|
}
|
||||||
})
|
})
|
||||||
childEventCb := s.childEventCb
|
childEventCb := s.childEventCb
|
||||||
s.lock.Unlock()
|
s.lock.Unlock()
|
||||||
|
if childEventCb != nil {
|
||||||
childEventCb(Event{Type: EvTimeout, Data: reqData})
|
childEventCb(Event{Type: EvTimeout, Data: reqData})
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// unsubscribe stops all goroutines associated with the server.
|
// unsubscribe stops all goroutines associated with the server.
|
||||||
func (s *serverWithTimeout) unsubscribe() {
|
func (s *serverWithTimeout) unsubscribe() {
|
||||||
s.lock.Lock()
|
s.lock.Lock()
|
||||||
defer s.lock.Unlock()
|
|
||||||
|
|
||||||
for _, timer := range s.timeouts {
|
for _, timer := range s.timeouts {
|
||||||
if timer != nil {
|
if timer != nil {
|
||||||
timer.Stop()
|
timer.Stop()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
s.childEventCb = nil
|
s.lock.Unlock()
|
||||||
s.parent.Unsubscribe()
|
s.parent.Unsubscribe()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -328,10 +334,10 @@ func (s *serverWithLimits) eventCallback(event Event) {
|
||||||
}
|
}
|
||||||
childEventCb := s.childEventCb
|
childEventCb := s.childEventCb
|
||||||
s.lock.Unlock()
|
s.lock.Unlock()
|
||||||
if passEvent {
|
if passEvent && childEventCb != nil {
|
||||||
childEventCb(event)
|
childEventCb(event)
|
||||||
}
|
}
|
||||||
if sendCanRequestAgain {
|
if sendCanRequestAgain && childEventCb != nil {
|
||||||
childEventCb(Event{Type: EvCanRequestAgain})
|
childEventCb(Event{Type: EvCanRequestAgain})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -347,13 +353,12 @@ func (s *serverWithLimits) sendRequest(request Request) (reqId ID) {
|
||||||
// unsubscribe stops all goroutines associated with the server.
|
// unsubscribe stops all goroutines associated with the server.
|
||||||
func (s *serverWithLimits) unsubscribe() {
|
func (s *serverWithLimits) unsubscribe() {
|
||||||
s.lock.Lock()
|
s.lock.Lock()
|
||||||
defer s.lock.Unlock()
|
|
||||||
|
|
||||||
if s.delayTimer != nil {
|
if s.delayTimer != nil {
|
||||||
s.delayTimer.Stop()
|
s.delayTimer.Stop()
|
||||||
s.delayTimer = nil
|
s.delayTimer = nil
|
||||||
}
|
}
|
||||||
s.childEventCb = nil
|
s.childEventCb = nil
|
||||||
|
s.lock.Unlock()
|
||||||
s.serverWithTimeout.unsubscribe()
|
s.serverWithTimeout.unsubscribe()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -383,7 +388,7 @@ func (s *serverWithLimits) canRequestNow() bool {
|
||||||
}
|
}
|
||||||
childEventCb := s.childEventCb
|
childEventCb := s.childEventCb
|
||||||
s.lock.Unlock()
|
s.lock.Unlock()
|
||||||
if sendCanRequestAgain {
|
if sendCanRequestAgain && childEventCb != nil {
|
||||||
childEventCb(Event{Type: EvCanRequestAgain})
|
childEventCb(Event{Type: EvCanRequestAgain})
|
||||||
}
|
}
|
||||||
return canRequest
|
return canRequest
|
||||||
|
|
@ -415,7 +420,7 @@ func (s *serverWithLimits) delay(delay time.Duration) {
|
||||||
}
|
}
|
||||||
childEventCb := s.childEventCb
|
childEventCb := s.childEventCb
|
||||||
s.lock.Unlock()
|
s.lock.Unlock()
|
||||||
if sendCanRequestAgain {
|
if sendCanRequestAgain && childEventCb != nil {
|
||||||
childEventCb(Event{Type: EvCanRequestAgain})
|
childEventCb(Event{Type: EvCanRequestAgain})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,7 @@ func TestServerEvents(t *testing.T) {
|
||||||
expEvent(EvFail)
|
expEvent(EvFail)
|
||||||
rs.eventCb(Event{Type: EvResponse, Data: RequestResponse{ID: 1, Request: testRequest, Response: testResponse}})
|
rs.eventCb(Event{Type: EvResponse, Data: RequestResponse{ID: 1, Request: testRequest, Response: testResponse}})
|
||||||
expEvent(nil)
|
expEvent(nil)
|
||||||
|
srv.unsubscribe()
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestServerParallel(t *testing.T) {
|
func TestServerParallel(t *testing.T) {
|
||||||
|
|
@ -129,9 +130,7 @@ func TestServerEventRateLimit(t *testing.T) {
|
||||||
srv := NewServer(rs, clock)
|
srv := NewServer(rs, clock)
|
||||||
var eventCount int
|
var eventCount int
|
||||||
srv.subscribe(func(event Event) {
|
srv.subscribe(func(event Event) {
|
||||||
if !event.IsRequestEvent() {
|
|
||||||
eventCount++
|
eventCount++
|
||||||
}
|
|
||||||
})
|
})
|
||||||
expEvents := func(send, expAllowed int) {
|
expEvents := func(send, expAllowed int) {
|
||||||
eventCount = 0
|
eventCount = 0
|
||||||
|
|
@ -147,6 +146,30 @@ func TestServerEventRateLimit(t *testing.T) {
|
||||||
expEvents(5, 1)
|
expEvents(5, 1)
|
||||||
clock.Run(maxServerEventRate * maxServerEventBuffer * 2)
|
clock.Run(maxServerEventRate * maxServerEventBuffer * 2)
|
||||||
expEvents(maxServerEventBuffer+5, maxServerEventBuffer)
|
expEvents(maxServerEventBuffer+5, maxServerEventBuffer)
|
||||||
|
srv.unsubscribe()
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestServerUnsubscribe(t *testing.T) {
|
||||||
|
rs := &testRequestServer{}
|
||||||
|
clock := &mclock.Simulated{}
|
||||||
|
srv := NewServer(rs, clock)
|
||||||
|
var eventCount int
|
||||||
|
srv.subscribe(func(event Event) {
|
||||||
|
eventCount++
|
||||||
|
})
|
||||||
|
eventCb := rs.eventCb
|
||||||
|
eventCb(Event{Type: testEventType})
|
||||||
|
if eventCount != 1 {
|
||||||
|
t.Errorf("Server event callback not called before unsubscribe")
|
||||||
|
}
|
||||||
|
srv.unsubscribe()
|
||||||
|
if rs.eventCb != nil {
|
||||||
|
t.Errorf("Server event callback not removed after unsubscribe")
|
||||||
|
}
|
||||||
|
eventCb(Event{Type: testEventType})
|
||||||
|
if eventCount != 1 {
|
||||||
|
t.Errorf("Server event callback called after unsubscribe")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type testRequestServer struct {
|
type testRequestServer struct {
|
||||||
|
|
@ -156,4 +179,4 @@ type testRequestServer struct {
|
||||||
func (rs *testRequestServer) Name() string { return "" }
|
func (rs *testRequestServer) Name() string { return "" }
|
||||||
func (rs *testRequestServer) Subscribe(eventCb func(Event)) { rs.eventCb = eventCb }
|
func (rs *testRequestServer) Subscribe(eventCb func(Event)) { rs.eventCb = eventCb }
|
||||||
func (rs *testRequestServer) SendRequest(ID, Request) {}
|
func (rs *testRequestServer) SendRequest(ID, Request) {}
|
||||||
func (rs *testRequestServer) Unsubscribe() {}
|
func (rs *testRequestServer) Unsubscribe() { rs.eventCb = nil }
|
||||||
|
|
|
||||||
|
|
@ -173,24 +173,24 @@ type TestCommitteeChain struct {
|
||||||
init bool
|
init bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TestCommitteeChain) CheckpointInit(bootstrap types.BootstrapData) error {
|
func (tc *TestCommitteeChain) CheckpointInit(bootstrap types.BootstrapData) error {
|
||||||
t.fsp, t.nsp, t.init = bootstrap.Header.SyncPeriod(), bootstrap.Header.SyncPeriod()+2, true
|
tc.fsp, tc.nsp, tc.init = bootstrap.Header.SyncPeriod(), bootstrap.Header.SyncPeriod()+2, true
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TestCommitteeChain) InsertUpdate(update *types.LightClientUpdate, nextCommittee *types.SerializedSyncCommittee) error {
|
func (tc *TestCommitteeChain) InsertUpdate(update *types.LightClientUpdate, nextCommittee *types.SerializedSyncCommittee) error {
|
||||||
period := update.AttestedHeader.Header.SyncPeriod()
|
period := update.AttestedHeader.Header.SyncPeriod()
|
||||||
if period < t.fsp || period > t.nsp || !t.init {
|
if period < tc.fsp || period > tc.nsp || !tc.init {
|
||||||
return light.ErrInvalidPeriod
|
return light.ErrInvalidPeriod
|
||||||
}
|
}
|
||||||
if period == t.nsp {
|
if period == tc.nsp {
|
||||||
t.nsp++
|
tc.nsp++
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TestCommitteeChain) NextSyncPeriod() (uint64, bool) {
|
func (tc *TestCommitteeChain) NextSyncPeriod() (uint64, bool) {
|
||||||
return t.nsp, t.init
|
return tc.nsp, tc.init
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tc *TestCommitteeChain) ExpInit(t *testing.T, ExpInit bool) {
|
func (tc *TestCommitteeChain) ExpInit(t *testing.T, ExpInit bool) {
|
||||||
|
|
@ -199,8 +199,8 @@ func (tc *TestCommitteeChain) ExpInit(t *testing.T, ExpInit bool) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TestCommitteeChain) SetNextSyncPeriod(nsp uint64) {
|
func (tc *TestCommitteeChain) SetNextSyncPeriod(nsp uint64) {
|
||||||
t.init, t.nsp = true, nsp
|
tc.init, tc.nsp = true, nsp
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tc *TestCommitteeChain) ExpNextSyncPeriod(t *testing.T, expNsp uint64) {
|
func (tc *TestCommitteeChain) ExpNextSyncPeriod(t *testing.T, expNsp uint64) {
|
||||||
|
|
|
||||||
|
|
@ -109,7 +109,7 @@ func rlpxPing(ctx *cli.Context) error {
|
||||||
}
|
}
|
||||||
return fmt.Errorf("received disconnect message: %v", msg[0])
|
return fmt.Errorf("received disconnect message: %v", msg[0])
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("invalid message code %d, expected handshake (code zero)", code)
|
return fmt.Errorf("invalid message code %d, expected handshake (code zero) or disconnect (code one)", code)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -156,6 +156,7 @@ var (
|
||||||
utils.BeaconGenesisRootFlag,
|
utils.BeaconGenesisRootFlag,
|
||||||
utils.BeaconGenesisTimeFlag,
|
utils.BeaconGenesisTimeFlag,
|
||||||
utils.BeaconCheckpointFlag,
|
utils.BeaconCheckpointFlag,
|
||||||
|
utils.CollectWitnessFlag,
|
||||||
}, utils.NetworkFlags, utils.DatabaseFlags)
|
}, utils.NetworkFlags, utils.DatabaseFlags)
|
||||||
|
|
||||||
rpcFlags = []cli.Flag{
|
rpcFlags = []cli.Flag{
|
||||||
|
|
|
||||||
|
|
@ -604,6 +604,11 @@ var (
|
||||||
Usage: "Disables db compaction after import",
|
Usage: "Disables db compaction after import",
|
||||||
Category: flags.LoggingCategory,
|
Category: flags.LoggingCategory,
|
||||||
}
|
}
|
||||||
|
CollectWitnessFlag = &cli.BoolFlag{
|
||||||
|
Name: "collectwitness",
|
||||||
|
Usage: "Enable state witness generation during block execution. Work in progress flag, don't use.",
|
||||||
|
Category: flags.MiscCategory,
|
||||||
|
}
|
||||||
|
|
||||||
// MISC settings
|
// MISC settings
|
||||||
SyncTargetFlag = &cli.StringFlag{
|
SyncTargetFlag = &cli.StringFlag{
|
||||||
|
|
@ -1760,6 +1765,9 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
|
||||||
// TODO(fjl): force-enable this in --dev mode
|
// TODO(fjl): force-enable this in --dev mode
|
||||||
cfg.EnablePreimageRecording = ctx.Bool(VMEnableDebugFlag.Name)
|
cfg.EnablePreimageRecording = ctx.Bool(VMEnableDebugFlag.Name)
|
||||||
}
|
}
|
||||||
|
if ctx.IsSet(CollectWitnessFlag.Name) {
|
||||||
|
cfg.EnableWitnessCollection = ctx.Bool(CollectWitnessFlag.Name)
|
||||||
|
}
|
||||||
|
|
||||||
if ctx.IsSet(RPCGlobalGasCapFlag.Name) {
|
if ctx.IsSet(RPCGlobalGasCapFlag.Name) {
|
||||||
cfg.RPCGasCap = ctx.Uint64(RPCGlobalGasCapFlag.Name)
|
cfg.RPCGasCap = ctx.Uint64(RPCGlobalGasCapFlag.Name)
|
||||||
|
|
@ -2190,7 +2198,10 @@ func MakeChain(ctx *cli.Context, stack *node.Node, readonly bool) (*core.BlockCh
|
||||||
if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheGCFlag.Name) {
|
if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheGCFlag.Name) {
|
||||||
cache.TrieDirtyLimit = ctx.Int(CacheFlag.Name) * ctx.Int(CacheGCFlag.Name) / 100
|
cache.TrieDirtyLimit = ctx.Int(CacheFlag.Name) * ctx.Int(CacheGCFlag.Name) / 100
|
||||||
}
|
}
|
||||||
vmcfg := vm.Config{EnablePreimageRecording: ctx.Bool(VMEnableDebugFlag.Name)}
|
vmcfg := vm.Config{
|
||||||
|
EnablePreimageRecording: ctx.Bool(VMEnableDebugFlag.Name),
|
||||||
|
EnableWitnessCollection: ctx.Bool(CollectWitnessFlag.Name),
|
||||||
|
}
|
||||||
if ctx.IsSet(VMTraceFlag.Name) {
|
if ctx.IsSet(VMTraceFlag.Name) {
|
||||||
if name := ctx.String(VMTraceFlag.Name); name != "" {
|
if name := ctx.String(VMTraceFlag.Name); name != "" {
|
||||||
var config json.RawMessage
|
var config json.RawMessage
|
||||||
|
|
|
||||||
|
|
@ -1809,7 +1809,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error)
|
||||||
// while processing transactions. Before Byzantium the prefetcher is mostly
|
// while processing transactions. Before Byzantium the prefetcher is mostly
|
||||||
// useless due to the intermediate root hashing after each transaction.
|
// useless due to the intermediate root hashing after each transaction.
|
||||||
if bc.chainConfig.IsByzantium(block.Number()) {
|
if bc.chainConfig.IsByzantium(block.Number()) {
|
||||||
statedb.StartPrefetcher("chain")
|
statedb.StartPrefetcher("chain", !bc.vmConfig.EnableWitnessCollection)
|
||||||
}
|
}
|
||||||
activeState = statedb
|
activeState = statedb
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -60,11 +60,11 @@ func newAccessList() *accessList {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy creates an independent copy of an accessList.
|
// Copy creates an independent copy of an accessList.
|
||||||
func (a *accessList) Copy() *accessList {
|
func (al *accessList) Copy() *accessList {
|
||||||
cp := newAccessList()
|
cp := newAccessList()
|
||||||
cp.addresses = maps.Clone(a.addresses)
|
cp.addresses = maps.Clone(al.addresses)
|
||||||
cp.slots = make([]map[common.Hash]struct{}, len(a.slots))
|
cp.slots = make([]map[common.Hash]struct{}, len(al.slots))
|
||||||
for i, slotMap := range a.slots {
|
for i, slotMap := range al.slots {
|
||||||
cp.slots[i] = maps.Clone(slotMap)
|
cp.slots[i] = maps.Clone(slotMap)
|
||||||
}
|
}
|
||||||
return cp
|
return cp
|
||||||
|
|
|
||||||
|
|
@ -123,7 +123,7 @@ type Trie interface {
|
||||||
// The returned nodeset can be nil if the trie is clean(nothing to commit).
|
// The returned nodeset can be nil if the trie is clean(nothing to commit).
|
||||||
// Once the trie is committed, it's not usable anymore. A new trie must
|
// Once the trie is committed, it's not usable anymore. A new trie must
|
||||||
// be created with new root and updated trie database for following usage
|
// be created with new root and updated trie database for following usage
|
||||||
Commit(collectLeaf bool) (common.Hash, *trienode.NodeSet, error)
|
Commit(collectLeaf bool) (common.Hash, *trienode.NodeSet)
|
||||||
|
|
||||||
// NodeIterator returns an iterator that returns nodes of the trie. Iteration
|
// NodeIterator returns an iterator that returns nodes of the trie. Iteration
|
||||||
// starts at the key after the given start key. And error will be returned
|
// starts at the key after the given start key. And error will be returned
|
||||||
|
|
|
||||||
|
|
@ -360,10 +360,7 @@ func (dl *diskLayer) generateRange(ctx *generatorContext, trieId *trie.ID, prefi
|
||||||
for i, key := range result.keys {
|
for i, key := range result.keys {
|
||||||
snapTrie.Update(key, result.vals[i])
|
snapTrie.Update(key, result.vals[i])
|
||||||
}
|
}
|
||||||
root, nodes, err := snapTrie.Commit(false)
|
root, nodes := snapTrie.Commit(false)
|
||||||
if err != nil {
|
|
||||||
return false, nil, err
|
|
||||||
}
|
|
||||||
if nodes != nil {
|
if nodes != nil {
|
||||||
tdb.Update(root, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), nil)
|
tdb.Update(root, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), nil)
|
||||||
tdb.Commit(root, false)
|
tdb.Commit(root, false)
|
||||||
|
|
|
||||||
|
|
@ -210,7 +210,7 @@ func (t *testHelper) makeStorageTrie(owner common.Hash, keys []string, vals []st
|
||||||
if !commit {
|
if !commit {
|
||||||
return stTrie.Hash()
|
return stTrie.Hash()
|
||||||
}
|
}
|
||||||
root, nodes, _ := stTrie.Commit(false)
|
root, nodes := stTrie.Commit(false)
|
||||||
if nodes != nil {
|
if nodes != nil {
|
||||||
t.nodes.Merge(nodes)
|
t.nodes.Merge(nodes)
|
||||||
}
|
}
|
||||||
|
|
@ -218,7 +218,7 @@ func (t *testHelper) makeStorageTrie(owner common.Hash, keys []string, vals []st
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *testHelper) Commit() common.Hash {
|
func (t *testHelper) Commit() common.Hash {
|
||||||
root, nodes, _ := t.accTrie.Commit(true)
|
root, nodes := t.accTrie.Commit(true)
|
||||||
if nodes != nil {
|
if nodes != nil {
|
||||||
t.nodes.Merge(nodes)
|
t.nodes.Merge(nodes)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -815,7 +815,7 @@ func TestStorageIteratorDeletions(t *testing.T) {
|
||||||
verifyIterator(t, 2, snaps.Snapshot(common.HexToHash("0x06")).(*diffLayer).newBinaryStorageIterator(common.HexToHash("0xaa")), verifyStorage)
|
verifyIterator(t, 2, snaps.Snapshot(common.HexToHash("0x06")).(*diffLayer).newBinaryStorageIterator(common.HexToHash("0xaa")), verifyStorage)
|
||||||
}
|
}
|
||||||
|
|
||||||
// BenchmarkAccountIteratorTraversal is a bit a bit notorious -- all layers contain the
|
// BenchmarkAccountIteratorTraversal is a bit notorious -- all layers contain the
|
||||||
// exact same 200 accounts. That means that we need to process 2000 items, but
|
// exact same 200 accounts. That means that we need to process 2000 items, but
|
||||||
// only spit out 200 values eventually.
|
// only spit out 200 values eventually.
|
||||||
//
|
//
|
||||||
|
|
|
||||||
|
|
@ -230,6 +230,14 @@ func (s *stateObject) GetCommittedState(key common.Hash) common.Hash {
|
||||||
}
|
}
|
||||||
value.SetBytes(val)
|
value.SetBytes(val)
|
||||||
}
|
}
|
||||||
|
// Independent of where we loaded the data from, add it to the prefetcher.
|
||||||
|
// Whilst this would be a bit weird if snapshots are disabled, but we still
|
||||||
|
// want the trie nodes to end up in the prefetcher too, so just push through.
|
||||||
|
if s.db.prefetcher != nil && s.data.Root != types.EmptyRootHash {
|
||||||
|
if err = s.db.prefetcher.prefetch(s.addrHash, s.origin.Root, s.address, [][]byte{key[:]}, true); err != nil {
|
||||||
|
log.Error("Failed to prefetch storage slot", "addr", s.address, "key", key, "err", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
s.originStorage[key] = value
|
s.originStorage[key] = value
|
||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
|
|
@ -293,7 +301,7 @@ func (s *stateObject) finalise() {
|
||||||
s.pendingStorage[key] = value
|
s.pendingStorage[key] = value
|
||||||
}
|
}
|
||||||
if s.db.prefetcher != nil && len(slotsToPrefetch) > 0 && s.data.Root != types.EmptyRootHash {
|
if s.db.prefetcher != nil && len(slotsToPrefetch) > 0 && s.data.Root != types.EmptyRootHash {
|
||||||
if err := s.db.prefetcher.prefetch(s.addrHash, s.data.Root, s.address, slotsToPrefetch); err != nil {
|
if err := s.db.prefetcher.prefetch(s.addrHash, s.data.Root, s.address, slotsToPrefetch, false); err != nil {
|
||||||
log.Error("Failed to prefetch slots", "addr", s.address, "slots", len(slotsToPrefetch), "err", err)
|
log.Error("Failed to prefetch slots", "addr", s.address, "slots", len(slotsToPrefetch), "err", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -462,10 +470,7 @@ func (s *stateObject) commit() (*accountUpdate, *trienode.NodeSet, error) {
|
||||||
s.origin = s.data.Copy()
|
s.origin = s.data.Copy()
|
||||||
return op, nil, nil
|
return op, nil, nil
|
||||||
}
|
}
|
||||||
root, nodes, err := s.trie.Commit(false)
|
root, nodes := s.trie.Commit(false)
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
s.data.Root = root
|
s.data.Root = root
|
||||||
s.origin = s.data.Copy()
|
s.origin = s.data.Copy()
|
||||||
return op, nodes, nil
|
return op, nodes, nil
|
||||||
|
|
|
||||||
|
|
@ -200,14 +200,14 @@ func (s *StateDB) SetLogger(l *tracing.Hooks) {
|
||||||
// StartPrefetcher initializes a new trie prefetcher to pull in nodes from the
|
// StartPrefetcher initializes a new trie prefetcher to pull in nodes from the
|
||||||
// state trie concurrently while the state is mutated so that when we reach the
|
// state trie concurrently while the state is mutated so that when we reach the
|
||||||
// commit phase, most of the needed data is already hot.
|
// commit phase, most of the needed data is already hot.
|
||||||
func (s *StateDB) StartPrefetcher(namespace string) {
|
func (s *StateDB) StartPrefetcher(namespace string, noreads bool) {
|
||||||
if s.prefetcher != nil {
|
if s.prefetcher != nil {
|
||||||
s.prefetcher.terminate(false)
|
s.prefetcher.terminate(false)
|
||||||
s.prefetcher.report()
|
s.prefetcher.report()
|
||||||
s.prefetcher = nil
|
s.prefetcher = nil
|
||||||
}
|
}
|
||||||
if s.snap != nil {
|
if s.snap != nil {
|
||||||
s.prefetcher = newTriePrefetcher(s.db, s.originalRoot, namespace)
|
s.prefetcher = newTriePrefetcher(s.db, s.originalRoot, namespace, noreads)
|
||||||
|
|
||||||
// With the switch to the Proof-of-Stake consensus algorithm, block production
|
// With the switch to the Proof-of-Stake consensus algorithm, block production
|
||||||
// rewards are now handled at the consensus layer. Consequently, a block may
|
// rewards are now handled at the consensus layer. Consequently, a block may
|
||||||
|
|
@ -218,7 +218,7 @@ func (s *StateDB) StartPrefetcher(namespace string) {
|
||||||
// To prevent this, the account trie is always scheduled for prefetching once
|
// To prevent this, the account trie is always scheduled for prefetching once
|
||||||
// the prefetcher is constructed. For more details, see:
|
// the prefetcher is constructed. For more details, see:
|
||||||
// https://github.com/ethereum/go-ethereum/issues/29880
|
// https://github.com/ethereum/go-ethereum/issues/29880
|
||||||
if err := s.prefetcher.prefetch(common.Hash{}, s.originalRoot, common.Address{}, nil); err != nil {
|
if err := s.prefetcher.prefetch(common.Hash{}, s.originalRoot, common.Address{}, nil, false); err != nil {
|
||||||
log.Error("Failed to prefetch account trie", "root", s.originalRoot, "err", err)
|
log.Error("Failed to prefetch account trie", "root", s.originalRoot, "err", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -616,6 +616,14 @@ func (s *StateDB) getStateObject(addr common.Address) *stateObject {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Independent of where we loaded the data from, add it to the prefetcher.
|
||||||
|
// Whilst this would be a bit weird if snapshots are disabled, but we still
|
||||||
|
// want the trie nodes to end up in the prefetcher too, so just push through.
|
||||||
|
if s.prefetcher != nil {
|
||||||
|
if err := s.prefetcher.prefetch(common.Hash{}, s.originalRoot, common.Address{}, [][]byte{addr[:]}, true); err != nil {
|
||||||
|
log.Error("Failed to prefetch account", "addr", addr, "err", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
// Insert into the live set
|
// Insert into the live set
|
||||||
obj := newObject(s, addr, data)
|
obj := newObject(s, addr, data)
|
||||||
s.setStateObject(obj)
|
s.setStateObject(obj)
|
||||||
|
|
@ -792,7 +800,7 @@ func (s *StateDB) Finalise(deleteEmptyObjects bool) {
|
||||||
addressesToPrefetch = append(addressesToPrefetch, common.CopyBytes(addr[:])) // Copy needed for closure
|
addressesToPrefetch = append(addressesToPrefetch, common.CopyBytes(addr[:])) // Copy needed for closure
|
||||||
}
|
}
|
||||||
if s.prefetcher != nil && len(addressesToPrefetch) > 0 {
|
if s.prefetcher != nil && len(addressesToPrefetch) > 0 {
|
||||||
if err := s.prefetcher.prefetch(common.Hash{}, s.originalRoot, common.Address{}, addressesToPrefetch); err != nil {
|
if err := s.prefetcher.prefetch(common.Hash{}, s.originalRoot, common.Address{}, addressesToPrefetch, false); err != nil {
|
||||||
log.Error("Failed to prefetch addresses", "addresses", len(addressesToPrefetch), "err", err)
|
log.Error("Failed to prefetch addresses", "addresses", len(addressesToPrefetch), "err", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1171,10 +1179,7 @@ func (s *StateDB) commit(deleteEmptyObjects bool) (*stateUpdate, error) {
|
||||||
// code didn't anticipate for.
|
// code didn't anticipate for.
|
||||||
workers.Go(func() error {
|
workers.Go(func() error {
|
||||||
// Write the account trie changes, measuring the amount of wasted time
|
// Write the account trie changes, measuring the amount of wasted time
|
||||||
newroot, set, err := s.trie.Commit(true)
|
newroot, set := s.trie.Commit(true)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
root = newroot
|
root = newroot
|
||||||
|
|
||||||
if err := merge(set); err != nil {
|
if err := merge(set); err != nil {
|
||||||
|
|
|
||||||
|
|
@ -44,30 +44,48 @@ type triePrefetcher struct {
|
||||||
root common.Hash // Root hash of the account trie for metrics
|
root common.Hash // Root hash of the account trie for metrics
|
||||||
fetchers map[string]*subfetcher // Subfetchers for each trie
|
fetchers map[string]*subfetcher // Subfetchers for each trie
|
||||||
term chan struct{} // Channel to signal interruption
|
term chan struct{} // Channel to signal interruption
|
||||||
|
noreads bool // Whether to ignore state-read-only prefetch requests
|
||||||
|
|
||||||
deliveryMissMeter metrics.Meter
|
deliveryMissMeter metrics.Meter
|
||||||
accountLoadMeter metrics.Meter
|
|
||||||
accountDupMeter metrics.Meter
|
accountLoadReadMeter metrics.Meter
|
||||||
|
accountLoadWriteMeter metrics.Meter
|
||||||
|
accountDupReadMeter metrics.Meter
|
||||||
|
accountDupWriteMeter metrics.Meter
|
||||||
|
accountDupCrossMeter metrics.Meter
|
||||||
accountWasteMeter metrics.Meter
|
accountWasteMeter metrics.Meter
|
||||||
storageLoadMeter metrics.Meter
|
|
||||||
storageDupMeter metrics.Meter
|
storageLoadReadMeter metrics.Meter
|
||||||
|
storageLoadWriteMeter metrics.Meter
|
||||||
|
storageDupReadMeter metrics.Meter
|
||||||
|
storageDupWriteMeter metrics.Meter
|
||||||
|
storageDupCrossMeter metrics.Meter
|
||||||
storageWasteMeter metrics.Meter
|
storageWasteMeter metrics.Meter
|
||||||
}
|
}
|
||||||
|
|
||||||
func newTriePrefetcher(db Database, root common.Hash, namespace string) *triePrefetcher {
|
func newTriePrefetcher(db Database, root common.Hash, namespace string, noreads bool) *triePrefetcher {
|
||||||
prefix := triePrefetchMetricsPrefix + namespace
|
prefix := triePrefetchMetricsPrefix + namespace
|
||||||
return &triePrefetcher{
|
return &triePrefetcher{
|
||||||
db: db,
|
db: db,
|
||||||
root: root,
|
root: root,
|
||||||
fetchers: make(map[string]*subfetcher), // Active prefetchers use the fetchers map
|
fetchers: make(map[string]*subfetcher), // Active prefetchers use the fetchers map
|
||||||
term: make(chan struct{}),
|
term: make(chan struct{}),
|
||||||
|
noreads: noreads,
|
||||||
|
|
||||||
deliveryMissMeter: metrics.GetOrRegisterMeter(prefix+"/deliverymiss", nil),
|
deliveryMissMeter: metrics.GetOrRegisterMeter(prefix+"/deliverymiss", nil),
|
||||||
accountLoadMeter: metrics.GetOrRegisterMeter(prefix+"/account/load", nil),
|
|
||||||
accountDupMeter: metrics.GetOrRegisterMeter(prefix+"/account/dup", nil),
|
accountLoadReadMeter: metrics.GetOrRegisterMeter(prefix+"/account/load/read", nil),
|
||||||
|
accountLoadWriteMeter: metrics.GetOrRegisterMeter(prefix+"/account/load/write", nil),
|
||||||
|
accountDupReadMeter: metrics.GetOrRegisterMeter(prefix+"/account/dup/read", nil),
|
||||||
|
accountDupWriteMeter: metrics.GetOrRegisterMeter(prefix+"/account/dup/write", nil),
|
||||||
|
accountDupCrossMeter: metrics.GetOrRegisterMeter(prefix+"/account/dup/cross", nil),
|
||||||
accountWasteMeter: metrics.GetOrRegisterMeter(prefix+"/account/waste", nil),
|
accountWasteMeter: metrics.GetOrRegisterMeter(prefix+"/account/waste", nil),
|
||||||
storageLoadMeter: metrics.GetOrRegisterMeter(prefix+"/storage/load", nil),
|
|
||||||
storageDupMeter: metrics.GetOrRegisterMeter(prefix+"/storage/dup", nil),
|
storageLoadReadMeter: metrics.GetOrRegisterMeter(prefix+"/storage/load/read", nil),
|
||||||
|
storageLoadWriteMeter: metrics.GetOrRegisterMeter(prefix+"/storage/load/write", nil),
|
||||||
|
storageDupReadMeter: metrics.GetOrRegisterMeter(prefix+"/storage/dup/read", nil),
|
||||||
|
storageDupWriteMeter: metrics.GetOrRegisterMeter(prefix+"/storage/dup/write", nil),
|
||||||
|
storageDupCrossMeter: metrics.GetOrRegisterMeter(prefix+"/storage/dup/cross", nil),
|
||||||
storageWasteMeter: metrics.GetOrRegisterMeter(prefix+"/storage/waste", nil),
|
storageWasteMeter: metrics.GetOrRegisterMeter(prefix+"/storage/waste", nil),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -98,19 +116,31 @@ func (p *triePrefetcher) report() {
|
||||||
fetcher.wait() // ensure the fetcher's idle before poking in its internals
|
fetcher.wait() // ensure the fetcher's idle before poking in its internals
|
||||||
|
|
||||||
if fetcher.root == p.root {
|
if fetcher.root == p.root {
|
||||||
p.accountLoadMeter.Mark(int64(len(fetcher.seen)))
|
p.accountLoadReadMeter.Mark(int64(len(fetcher.seenRead)))
|
||||||
p.accountDupMeter.Mark(int64(fetcher.dups))
|
p.accountLoadWriteMeter.Mark(int64(len(fetcher.seenWrite)))
|
||||||
|
|
||||||
|
p.accountDupReadMeter.Mark(int64(fetcher.dupsRead))
|
||||||
|
p.accountDupWriteMeter.Mark(int64(fetcher.dupsWrite))
|
||||||
|
p.accountDupCrossMeter.Mark(int64(fetcher.dupsCross))
|
||||||
|
|
||||||
for _, key := range fetcher.used {
|
for _, key := range fetcher.used {
|
||||||
delete(fetcher.seen, string(key))
|
delete(fetcher.seenRead, string(key))
|
||||||
|
delete(fetcher.seenWrite, string(key))
|
||||||
}
|
}
|
||||||
p.accountWasteMeter.Mark(int64(len(fetcher.seen)))
|
p.accountWasteMeter.Mark(int64(len(fetcher.seenRead) + len(fetcher.seenWrite)))
|
||||||
} else {
|
} else {
|
||||||
p.storageLoadMeter.Mark(int64(len(fetcher.seen)))
|
p.storageLoadReadMeter.Mark(int64(len(fetcher.seenRead)))
|
||||||
p.storageDupMeter.Mark(int64(fetcher.dups))
|
p.storageLoadWriteMeter.Mark(int64(len(fetcher.seenWrite)))
|
||||||
|
|
||||||
|
p.storageDupReadMeter.Mark(int64(fetcher.dupsRead))
|
||||||
|
p.storageDupWriteMeter.Mark(int64(fetcher.dupsWrite))
|
||||||
|
p.storageDupCrossMeter.Mark(int64(fetcher.dupsCross))
|
||||||
|
|
||||||
for _, key := range fetcher.used {
|
for _, key := range fetcher.used {
|
||||||
delete(fetcher.seen, string(key))
|
delete(fetcher.seenRead, string(key))
|
||||||
|
delete(fetcher.seenWrite, string(key))
|
||||||
}
|
}
|
||||||
p.storageWasteMeter.Mark(int64(len(fetcher.seen)))
|
p.storageWasteMeter.Mark(int64(len(fetcher.seenRead) + len(fetcher.seenWrite)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -126,7 +156,11 @@ func (p *triePrefetcher) report() {
|
||||||
// upon the same contract, the parameters invoking this method may be
|
// upon the same contract, the parameters invoking this method may be
|
||||||
// repeated.
|
// repeated.
|
||||||
// 2. Finalize of the main account trie. This happens only once per block.
|
// 2. Finalize of the main account trie. This happens only once per block.
|
||||||
func (p *triePrefetcher) prefetch(owner common.Hash, root common.Hash, addr common.Address, keys [][]byte) error {
|
func (p *triePrefetcher) prefetch(owner common.Hash, root common.Hash, addr common.Address, keys [][]byte, read bool) error {
|
||||||
|
// If the state item is only being read, but reads are disabled, return
|
||||||
|
if read && p.noreads {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
// Ensure the subfetcher is still alive
|
// Ensure the subfetcher is still alive
|
||||||
select {
|
select {
|
||||||
case <-p.term:
|
case <-p.term:
|
||||||
|
|
@ -139,7 +173,7 @@ func (p *triePrefetcher) prefetch(owner common.Hash, root common.Hash, addr comm
|
||||||
fetcher = newSubfetcher(p.db, p.root, owner, root, addr)
|
fetcher = newSubfetcher(p.db, p.root, owner, root, addr)
|
||||||
p.fetchers[id] = fetcher
|
p.fetchers[id] = fetcher
|
||||||
}
|
}
|
||||||
return fetcher.schedule(keys)
|
return fetcher.schedule(keys, read)
|
||||||
}
|
}
|
||||||
|
|
||||||
// trie returns the trie matching the root hash, blocking until the fetcher of
|
// trie returns the trie matching the root hash, blocking until the fetcher of
|
||||||
|
|
@ -186,18 +220,30 @@ type subfetcher struct {
|
||||||
addr common.Address // Address of the account that the trie belongs to
|
addr common.Address // Address of the account that the trie belongs to
|
||||||
trie Trie // Trie being populated with nodes
|
trie Trie // Trie being populated with nodes
|
||||||
|
|
||||||
tasks [][]byte // Items queued up for retrieval
|
tasks []*subfetcherTask // Items queued up for retrieval
|
||||||
lock sync.Mutex // Lock protecting the task queue
|
lock sync.Mutex // Lock protecting the task queue
|
||||||
|
|
||||||
wake chan struct{} // Wake channel if a new task is scheduled
|
wake chan struct{} // Wake channel if a new task is scheduled
|
||||||
stop chan struct{} // Channel to interrupt processing
|
stop chan struct{} // Channel to interrupt processing
|
||||||
term chan struct{} // Channel to signal interruption
|
term chan struct{} // Channel to signal interruption
|
||||||
|
|
||||||
seen map[string]struct{} // Tracks the entries already loaded
|
seenRead map[string]struct{} // Tracks the entries already loaded via read operations
|
||||||
dups int // Number of duplicate preload tasks
|
seenWrite map[string]struct{} // Tracks the entries already loaded via write operations
|
||||||
|
|
||||||
|
dupsRead int // Number of duplicate preload tasks via reads only
|
||||||
|
dupsWrite int // Number of duplicate preload tasks via writes only
|
||||||
|
dupsCross int // Number of duplicate preload tasks via read-write-crosses
|
||||||
|
|
||||||
used [][]byte // Tracks the entries used in the end
|
used [][]byte // Tracks the entries used in the end
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// subfetcherTask is a trie path to prefetch, tagged with whether it originates
|
||||||
|
// from a read or a write request.
|
||||||
|
type subfetcherTask struct {
|
||||||
|
read bool
|
||||||
|
key []byte
|
||||||
|
}
|
||||||
|
|
||||||
// newSubfetcher creates a goroutine to prefetch state items belonging to a
|
// newSubfetcher creates a goroutine to prefetch state items belonging to a
|
||||||
// particular root hash.
|
// particular root hash.
|
||||||
func newSubfetcher(db Database, state common.Hash, owner common.Hash, root common.Hash, addr common.Address) *subfetcher {
|
func newSubfetcher(db Database, state common.Hash, owner common.Hash, root common.Hash, addr common.Address) *subfetcher {
|
||||||
|
|
@ -210,14 +256,15 @@ func newSubfetcher(db Database, state common.Hash, owner common.Hash, root commo
|
||||||
wake: make(chan struct{}, 1),
|
wake: make(chan struct{}, 1),
|
||||||
stop: make(chan struct{}),
|
stop: make(chan struct{}),
|
||||||
term: make(chan struct{}),
|
term: make(chan struct{}),
|
||||||
seen: make(map[string]struct{}),
|
seenRead: make(map[string]struct{}),
|
||||||
|
seenWrite: make(map[string]struct{}),
|
||||||
}
|
}
|
||||||
go sf.loop()
|
go sf.loop()
|
||||||
return sf
|
return sf
|
||||||
}
|
}
|
||||||
|
|
||||||
// schedule adds a batch of trie keys to the queue to prefetch.
|
// schedule adds a batch of trie keys to the queue to prefetch.
|
||||||
func (sf *subfetcher) schedule(keys [][]byte) error {
|
func (sf *subfetcher) schedule(keys [][]byte, read bool) error {
|
||||||
// Ensure the subfetcher is still alive
|
// Ensure the subfetcher is still alive
|
||||||
select {
|
select {
|
||||||
case <-sf.term:
|
case <-sf.term:
|
||||||
|
|
@ -226,7 +273,10 @@ func (sf *subfetcher) schedule(keys [][]byte) error {
|
||||||
}
|
}
|
||||||
// Append the tasks to the current queue
|
// Append the tasks to the current queue
|
||||||
sf.lock.Lock()
|
sf.lock.Lock()
|
||||||
sf.tasks = append(sf.tasks, keys...)
|
for _, key := range keys {
|
||||||
|
key := key // closure for the append below
|
||||||
|
sf.tasks = append(sf.tasks, &subfetcherTask{read: read, key: key})
|
||||||
|
}
|
||||||
sf.lock.Unlock()
|
sf.lock.Unlock()
|
||||||
|
|
||||||
// Notify the background thread to execute scheduled tasks
|
// Notify the background thread to execute scheduled tasks
|
||||||
|
|
@ -303,16 +353,36 @@ func (sf *subfetcher) loop() {
|
||||||
sf.lock.Unlock()
|
sf.lock.Unlock()
|
||||||
|
|
||||||
for _, task := range tasks {
|
for _, task := range tasks {
|
||||||
if _, ok := sf.seen[string(task)]; ok {
|
key := string(task.key)
|
||||||
sf.dups++
|
if task.read {
|
||||||
|
if _, ok := sf.seenRead[key]; ok {
|
||||||
|
sf.dupsRead++
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if len(task) == common.AddressLength {
|
if _, ok := sf.seenWrite[key]; ok {
|
||||||
sf.trie.GetAccount(common.BytesToAddress(task))
|
sf.dupsCross++
|
||||||
} else {
|
continue
|
||||||
sf.trie.GetStorage(sf.addr, task)
|
}
|
||||||
|
} else {
|
||||||
|
if _, ok := sf.seenRead[key]; ok {
|
||||||
|
sf.dupsCross++
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if _, ok := sf.seenWrite[key]; ok {
|
||||||
|
sf.dupsWrite++
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(task.key) == common.AddressLength {
|
||||||
|
sf.trie.GetAccount(common.BytesToAddress(task.key))
|
||||||
|
} else {
|
||||||
|
sf.trie.GetStorage(sf.addr, task.key)
|
||||||
|
}
|
||||||
|
if task.read {
|
||||||
|
sf.seenRead[key] = struct{}{}
|
||||||
|
} else {
|
||||||
|
sf.seenWrite[key] = struct{}{}
|
||||||
}
|
}
|
||||||
sf.seen[string(task)] = struct{}{}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case <-sf.stop:
|
case <-sf.stop:
|
||||||
|
|
|
||||||
|
|
@ -47,15 +47,15 @@ func filledStateDB() *StateDB {
|
||||||
|
|
||||||
func TestUseAfterTerminate(t *testing.T) {
|
func TestUseAfterTerminate(t *testing.T) {
|
||||||
db := filledStateDB()
|
db := filledStateDB()
|
||||||
prefetcher := newTriePrefetcher(db.db, db.originalRoot, "")
|
prefetcher := newTriePrefetcher(db.db, db.originalRoot, "", true)
|
||||||
skey := common.HexToHash("aaa")
|
skey := common.HexToHash("aaa")
|
||||||
|
|
||||||
if err := prefetcher.prefetch(common.Hash{}, db.originalRoot, common.Address{}, [][]byte{skey.Bytes()}); err != nil {
|
if err := prefetcher.prefetch(common.Hash{}, db.originalRoot, common.Address{}, [][]byte{skey.Bytes()}, false); err != nil {
|
||||||
t.Errorf("Prefetch failed before terminate: %v", err)
|
t.Errorf("Prefetch failed before terminate: %v", err)
|
||||||
}
|
}
|
||||||
prefetcher.terminate(false)
|
prefetcher.terminate(false)
|
||||||
|
|
||||||
if err := prefetcher.prefetch(common.Hash{}, db.originalRoot, common.Address{}, [][]byte{skey.Bytes()}); err == nil {
|
if err := prefetcher.prefetch(common.Hash{}, db.originalRoot, common.Address{}, [][]byte{skey.Bytes()}, false); err == nil {
|
||||||
t.Errorf("Prefetch succeeded after terminate: %v", err)
|
t.Errorf("Prefetch succeeded after terminate: %v", err)
|
||||||
}
|
}
|
||||||
if tr := prefetcher.trie(common.Hash{}, db.originalRoot); tr == nil {
|
if tr := prefetcher.trie(common.Hash{}, db.originalRoot); tr == nil {
|
||||||
|
|
|
||||||
|
|
@ -143,7 +143,7 @@ func (bc *testBlockChain) CurrentFinalBlock() *types.Header {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bt *testBlockChain) GetBlock(hash common.Hash, number uint64) *types.Block {
|
func (bc *testBlockChain) GetBlock(hash common.Hash, number uint64) *types.Block {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -459,11 +459,11 @@ func (s EIP155Signer) Hash(tx *Transaction) common.Hash {
|
||||||
// homestead rules.
|
// homestead rules.
|
||||||
type HomesteadSigner struct{ FrontierSigner }
|
type HomesteadSigner struct{ FrontierSigner }
|
||||||
|
|
||||||
func (s HomesteadSigner) ChainID() *big.Int {
|
func (hs HomesteadSigner) ChainID() *big.Int {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s HomesteadSigner) Equal(s2 Signer) bool {
|
func (hs HomesteadSigner) Equal(s2 Signer) bool {
|
||||||
_, ok := s2.(HomesteadSigner)
|
_, ok := s2.(HomesteadSigner)
|
||||||
return ok
|
return ok
|
||||||
}
|
}
|
||||||
|
|
@ -486,11 +486,11 @@ func (hs HomesteadSigner) Sender(tx *Transaction) (common.Address, error) {
|
||||||
// frontier rules.
|
// frontier rules.
|
||||||
type FrontierSigner struct{}
|
type FrontierSigner struct{}
|
||||||
|
|
||||||
func (s FrontierSigner) ChainID() *big.Int {
|
func (fs FrontierSigner) ChainID() *big.Int {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s FrontierSigner) Equal(s2 Signer) bool {
|
func (fs FrontierSigner) Equal(s2 Signer) bool {
|
||||||
_, ok := s2.(FrontierSigner)
|
_, ok := s2.(FrontierSigner)
|
||||||
return ok
|
return ok
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@ type Config struct {
|
||||||
NoBaseFee bool // Forces the EIP-1559 baseFee to 0 (needed for 0 price calls)
|
NoBaseFee bool // Forces the EIP-1559 baseFee to 0 (needed for 0 price calls)
|
||||||
EnablePreimageRecording bool // Enables recording of SHA3/keccak preimages
|
EnablePreimageRecording bool // Enables recording of SHA3/keccak preimages
|
||||||
ExtraEips []int // Additional EIPS that are to be enabled
|
ExtraEips []int // Additional EIPS that are to be enabled
|
||||||
|
EnableWitnessCollection bool // true if witness collection is enabled
|
||||||
}
|
}
|
||||||
|
|
||||||
// ScopeContext contains the things that are per-call, such as stack and memory,
|
// ScopeContext contains the things that are per-call, such as stack and memory,
|
||||||
|
|
|
||||||
|
|
@ -184,6 +184,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
|
||||||
var (
|
var (
|
||||||
vmConfig = vm.Config{
|
vmConfig = vm.Config{
|
||||||
EnablePreimageRecording: config.EnablePreimageRecording,
|
EnablePreimageRecording: config.EnablePreimageRecording,
|
||||||
|
EnableWitnessCollection: config.EnableWitnessCollection,
|
||||||
}
|
}
|
||||||
cacheConfig = &core.CacheConfig{
|
cacheConfig = &core.CacheConfig{
|
||||||
TrieCleanLimit: config.TrieCleanCache,
|
TrieCleanLimit: config.TrieCleanCache,
|
||||||
|
|
|
||||||
|
|
@ -141,6 +141,9 @@ type Config struct {
|
||||||
// Enables tracking of SHA3 preimages in the VM
|
// Enables tracking of SHA3 preimages in the VM
|
||||||
EnablePreimageRecording bool
|
EnablePreimageRecording bool
|
||||||
|
|
||||||
|
// Enables prefetching trie nodes for read operations too
|
||||||
|
EnableWitnessCollection bool `toml:"-"`
|
||||||
|
|
||||||
// Enables VM tracing
|
// Enables VM tracing
|
||||||
VMTrace string
|
VMTrace string
|
||||||
VMTraceJsonConfig string
|
VMTraceJsonConfig string
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,7 @@ func (c Config) MarshalTOML() (interface{}, error) {
|
||||||
BlobPool blobpool.Config
|
BlobPool blobpool.Config
|
||||||
GPO gasprice.Config
|
GPO gasprice.Config
|
||||||
EnablePreimageRecording bool
|
EnablePreimageRecording bool
|
||||||
|
EnableWitnessCollection bool `toml:"-"`
|
||||||
VMTrace string
|
VMTrace string
|
||||||
VMTraceJsonConfig string
|
VMTraceJsonConfig string
|
||||||
DocRoot string `toml:"-"`
|
DocRoot string `toml:"-"`
|
||||||
|
|
@ -93,6 +94,7 @@ func (c Config) MarshalTOML() (interface{}, error) {
|
||||||
enc.BlobPool = c.BlobPool
|
enc.BlobPool = c.BlobPool
|
||||||
enc.GPO = c.GPO
|
enc.GPO = c.GPO
|
||||||
enc.EnablePreimageRecording = c.EnablePreimageRecording
|
enc.EnablePreimageRecording = c.EnablePreimageRecording
|
||||||
|
enc.EnableWitnessCollection = c.EnableWitnessCollection
|
||||||
enc.VMTrace = c.VMTrace
|
enc.VMTrace = c.VMTrace
|
||||||
enc.VMTraceJsonConfig = c.VMTraceJsonConfig
|
enc.VMTraceJsonConfig = c.VMTraceJsonConfig
|
||||||
enc.DocRoot = c.DocRoot
|
enc.DocRoot = c.DocRoot
|
||||||
|
|
@ -140,6 +142,7 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error {
|
||||||
BlobPool *blobpool.Config
|
BlobPool *blobpool.Config
|
||||||
GPO *gasprice.Config
|
GPO *gasprice.Config
|
||||||
EnablePreimageRecording *bool
|
EnablePreimageRecording *bool
|
||||||
|
EnableWitnessCollection *bool `toml:"-"`
|
||||||
VMTrace *string
|
VMTrace *string
|
||||||
VMTraceJsonConfig *string
|
VMTraceJsonConfig *string
|
||||||
DocRoot *string `toml:"-"`
|
DocRoot *string `toml:"-"`
|
||||||
|
|
@ -252,6 +255,9 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error {
|
||||||
if dec.EnablePreimageRecording != nil {
|
if dec.EnablePreimageRecording != nil {
|
||||||
c.EnablePreimageRecording = *dec.EnablePreimageRecording
|
c.EnablePreimageRecording = *dec.EnablePreimageRecording
|
||||||
}
|
}
|
||||||
|
if dec.EnableWitnessCollection != nil {
|
||||||
|
c.EnableWitnessCollection = *dec.EnableWitnessCollection
|
||||||
|
}
|
||||||
if dec.VMTrace != nil {
|
if dec.VMTrace != nil {
|
||||||
c.VMTrace = *dec.VMTrace
|
c.VMTrace = *dec.VMTrace
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1525,7 +1525,7 @@ func makeAccountTrieNoStorage(n int, scheme string) (string, *trie.Trie, []*kv)
|
||||||
|
|
||||||
// Commit the state changes into db and re-create the trie
|
// Commit the state changes into db and re-create the trie
|
||||||
// for accessing later.
|
// for accessing later.
|
||||||
root, nodes, _ := accTrie.Commit(false)
|
root, nodes := accTrie.Commit(false)
|
||||||
db.Update(root, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), nil)
|
db.Update(root, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), nil)
|
||||||
|
|
||||||
accTrie, _ = trie.New(trie.StateTrieID(root), db)
|
accTrie, _ = trie.New(trie.StateTrieID(root), db)
|
||||||
|
|
@ -1587,7 +1587,7 @@ func makeBoundaryAccountTrie(scheme string, n int) (string, *trie.Trie, []*kv) {
|
||||||
|
|
||||||
// Commit the state changes into db and re-create the trie
|
// Commit the state changes into db and re-create the trie
|
||||||
// for accessing later.
|
// for accessing later.
|
||||||
root, nodes, _ := accTrie.Commit(false)
|
root, nodes := accTrie.Commit(false)
|
||||||
db.Update(root, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), nil)
|
db.Update(root, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), nil)
|
||||||
|
|
||||||
accTrie, _ = trie.New(trie.StateTrieID(root), db)
|
accTrie, _ = trie.New(trie.StateTrieID(root), db)
|
||||||
|
|
@ -1633,7 +1633,7 @@ func makeAccountTrieWithStorageWithUniqueStorage(scheme string, accounts, slots
|
||||||
slices.SortFunc(entries, (*kv).cmp)
|
slices.SortFunc(entries, (*kv).cmp)
|
||||||
|
|
||||||
// Commit account trie
|
// Commit account trie
|
||||||
root, set, _ := accTrie.Commit(true)
|
root, set := accTrie.Commit(true)
|
||||||
nodes.Merge(set)
|
nodes.Merge(set)
|
||||||
|
|
||||||
// Commit gathered dirty nodes into database
|
// Commit gathered dirty nodes into database
|
||||||
|
|
@ -1700,7 +1700,7 @@ func makeAccountTrieWithStorage(scheme string, accounts, slots int, code, bounda
|
||||||
slices.SortFunc(entries, (*kv).cmp)
|
slices.SortFunc(entries, (*kv).cmp)
|
||||||
|
|
||||||
// Commit account trie
|
// Commit account trie
|
||||||
root, set, _ := accTrie.Commit(true)
|
root, set := accTrie.Commit(true)
|
||||||
nodes.Merge(set)
|
nodes.Merge(set)
|
||||||
|
|
||||||
// Commit gathered dirty nodes into database
|
// Commit gathered dirty nodes into database
|
||||||
|
|
@ -1742,7 +1742,7 @@ func makeStorageTrieWithSeed(owner common.Hash, n, seed uint64, db *triedb.Datab
|
||||||
entries = append(entries, elem)
|
entries = append(entries, elem)
|
||||||
}
|
}
|
||||||
slices.SortFunc(entries, (*kv).cmp)
|
slices.SortFunc(entries, (*kv).cmp)
|
||||||
root, nodes, _ := trie.Commit(false)
|
root, nodes := trie.Commit(false)
|
||||||
return root, nodes, entries
|
return root, nodes, entries
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1793,7 +1793,7 @@ func makeBoundaryStorageTrie(owner common.Hash, n int, db *triedb.Database) (com
|
||||||
entries = append(entries, elem)
|
entries = append(entries, elem)
|
||||||
}
|
}
|
||||||
slices.SortFunc(entries, (*kv).cmp)
|
slices.SortFunc(entries, (*kv).cmp)
|
||||||
root, nodes, _ := trie.Commit(false)
|
root, nodes := trie.Commit(false)
|
||||||
return root, nodes, entries
|
return root, nodes, entries
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1825,7 +1825,7 @@ func makeUnevenStorageTrie(owner common.Hash, slots int, db *triedb.Database) (c
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
slices.SortFunc(entries, (*kv).cmp)
|
slices.SortFunc(entries, (*kv).cmp)
|
||||||
root, nodes, _ := tr.Commit(false)
|
root, nodes := tr.Commit(false)
|
||||||
return root, nodes, entries
|
return root, nodes, entries
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -101,10 +101,10 @@ func (h *TerminalHandler) WithAttrs(attrs []slog.Attr) slog.Handler {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ResetFieldPadding zeroes the field-padding for all attribute pairs.
|
// ResetFieldPadding zeroes the field-padding for all attribute pairs.
|
||||||
func (t *TerminalHandler) ResetFieldPadding() {
|
func (h *TerminalHandler) ResetFieldPadding() {
|
||||||
t.mu.Lock()
|
h.mu.Lock()
|
||||||
t.fieldPadding = make(map[string]int)
|
h.fieldPadding = make(map[string]int)
|
||||||
t.mu.Unlock()
|
h.mu.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
type leveler struct{ minLevel slog.Level }
|
type leveler struct{ minLevel slog.Level }
|
||||||
|
|
|
||||||
|
|
@ -123,9 +123,14 @@ The API is initialised with a particular node adapter and has the following
|
||||||
endpoints:
|
endpoints:
|
||||||
|
|
||||||
```
|
```
|
||||||
|
OPTIONS / Response 200 with "Access-Control-Allow-Headers"" header set to "Content-Type""
|
||||||
GET / Get network information
|
GET / Get network information
|
||||||
POST /start Start all nodes in the network
|
POST /start Start all nodes in the network
|
||||||
POST /stop Stop all nodes in the network
|
POST /stop Stop all nodes in the network
|
||||||
|
POST /mocker/start Start the mocker node simulation
|
||||||
|
POST /mocker/stop Stop the mocker node simulation
|
||||||
|
GET /mocker Get a list of available mockers
|
||||||
|
POST /reset Reset all properties of a network to initial (empty) state
|
||||||
GET /events Stream network events
|
GET /events Stream network events
|
||||||
GET /snapshot Take a network snapshot
|
GET /snapshot Take a network snapshot
|
||||||
POST /snapshot Load a network snapshot
|
POST /snapshot Load a network snapshot
|
||||||
|
|
|
||||||
|
|
@ -67,9 +67,9 @@ func (vs *ValidationMessages) Info(msg string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetWarnings returns an error with all messages of type WARN of above, or nil if no warnings were present
|
// GetWarnings returns an error with all messages of type WARN of above, or nil if no warnings were present
|
||||||
func (v *ValidationMessages) GetWarnings() error {
|
func (vs *ValidationMessages) GetWarnings() error {
|
||||||
var messages []string
|
var messages []string
|
||||||
for _, msg := range v.Messages {
|
for _, msg := range vs.Messages {
|
||||||
if msg.Typ == WARN || msg.Typ == CRIT {
|
if msg.Typ == WARN || msg.Typ == CRIT {
|
||||||
messages = append(messages, msg.Message)
|
messages = append(messages, msg.Message)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -52,9 +52,9 @@ func NewUIServerAPI(extapi *SignerAPI) *UIServerAPI {
|
||||||
// the full Account object and not only Address.
|
// the full Account object and not only Address.
|
||||||
// Example call
|
// Example call
|
||||||
// {"jsonrpc":"2.0","method":"clef_listAccounts","params":[], "id":4}
|
// {"jsonrpc":"2.0","method":"clef_listAccounts","params":[], "id":4}
|
||||||
func (s *UIServerAPI) ListAccounts(ctx context.Context) ([]accounts.Account, error) {
|
func (api *UIServerAPI) ListAccounts(ctx context.Context) ([]accounts.Account, error) {
|
||||||
var accs []accounts.Account
|
var accs []accounts.Account
|
||||||
for _, wallet := range s.am.Wallets() {
|
for _, wallet := range api.am.Wallets() {
|
||||||
accs = append(accs, wallet.Accounts()...)
|
accs = append(accs, wallet.Accounts()...)
|
||||||
}
|
}
|
||||||
return accs, nil
|
return accs, nil
|
||||||
|
|
@ -72,9 +72,9 @@ type rawWallet struct {
|
||||||
// ListWallets will return a list of wallets that clef manages
|
// ListWallets will return a list of wallets that clef manages
|
||||||
// Example call
|
// Example call
|
||||||
// {"jsonrpc":"2.0","method":"clef_listWallets","params":[], "id":5}
|
// {"jsonrpc":"2.0","method":"clef_listWallets","params":[], "id":5}
|
||||||
func (s *UIServerAPI) ListWallets() []rawWallet {
|
func (api *UIServerAPI) ListWallets() []rawWallet {
|
||||||
wallets := make([]rawWallet, 0) // return [] instead of nil if empty
|
wallets := make([]rawWallet, 0) // return [] instead of nil if empty
|
||||||
for _, wallet := range s.am.Wallets() {
|
for _, wallet := range api.am.Wallets() {
|
||||||
status, failure := wallet.Status()
|
status, failure := wallet.Status()
|
||||||
|
|
||||||
raw := rawWallet{
|
raw := rawWallet{
|
||||||
|
|
@ -94,8 +94,8 @@ func (s *UIServerAPI) ListWallets() []rawWallet {
|
||||||
// it for later reuse.
|
// it for later reuse.
|
||||||
// Example call
|
// Example call
|
||||||
// {"jsonrpc":"2.0","method":"clef_deriveAccount","params":["ledger://","m/44'/60'/0'", false], "id":6}
|
// {"jsonrpc":"2.0","method":"clef_deriveAccount","params":["ledger://","m/44'/60'/0'", false], "id":6}
|
||||||
func (s *UIServerAPI) DeriveAccount(url string, path string, pin *bool) (accounts.Account, error) {
|
func (api *UIServerAPI) DeriveAccount(url string, path string, pin *bool) (accounts.Account, error) {
|
||||||
wallet, err := s.am.Wallet(url)
|
wallet, err := api.am.Wallet(url)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return accounts.Account{}, err
|
return accounts.Account{}, err
|
||||||
}
|
}
|
||||||
|
|
@ -122,7 +122,7 @@ func fetchKeystore(am *accounts.Manager) *keystore.KeyStore {
|
||||||
// encrypting it with the passphrase.
|
// encrypting it with the passphrase.
|
||||||
// Example call (should fail on password too short)
|
// Example call (should fail on password too short)
|
||||||
// {"jsonrpc":"2.0","method":"clef_importRawKey","params":["1111111111111111111111111111111111111111111111111111111111111111","test"], "id":6}
|
// {"jsonrpc":"2.0","method":"clef_importRawKey","params":["1111111111111111111111111111111111111111111111111111111111111111","test"], "id":6}
|
||||||
func (s *UIServerAPI) ImportRawKey(privkey string, password string) (accounts.Account, error) {
|
func (api *UIServerAPI) ImportRawKey(privkey string, password string) (accounts.Account, error) {
|
||||||
key, err := crypto.HexToECDSA(privkey)
|
key, err := crypto.HexToECDSA(privkey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return accounts.Account{}, err
|
return accounts.Account{}, err
|
||||||
|
|
@ -131,7 +131,7 @@ func (s *UIServerAPI) ImportRawKey(privkey string, password string) (accounts.Ac
|
||||||
return accounts.Account{}, fmt.Errorf("password requirements not met: %v", err)
|
return accounts.Account{}, fmt.Errorf("password requirements not met: %v", err)
|
||||||
}
|
}
|
||||||
// No error
|
// No error
|
||||||
return fetchKeystore(s.am).ImportECDSA(key, password)
|
return fetchKeystore(api.am).ImportECDSA(key, password)
|
||||||
}
|
}
|
||||||
|
|
||||||
// OpenWallet initiates a hardware wallet opening procedure, establishing a USB
|
// OpenWallet initiates a hardware wallet opening procedure, establishing a USB
|
||||||
|
|
@ -140,8 +140,8 @@ func (s *UIServerAPI) ImportRawKey(privkey string, password string) (accounts.Ac
|
||||||
// Trezor PIN matrix challenge).
|
// Trezor PIN matrix challenge).
|
||||||
// Example
|
// Example
|
||||||
// {"jsonrpc":"2.0","method":"clef_openWallet","params":["ledger://",""], "id":6}
|
// {"jsonrpc":"2.0","method":"clef_openWallet","params":["ledger://",""], "id":6}
|
||||||
func (s *UIServerAPI) OpenWallet(url string, passphrase *string) error {
|
func (api *UIServerAPI) OpenWallet(url string, passphrase *string) error {
|
||||||
wallet, err := s.am.Wallet(url)
|
wallet, err := api.am.Wallet(url)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -155,24 +155,24 @@ func (s *UIServerAPI) OpenWallet(url string, passphrase *string) error {
|
||||||
// ChainId returns the chainid in use for Eip-155 replay protection
|
// ChainId returns the chainid in use for Eip-155 replay protection
|
||||||
// Example call
|
// Example call
|
||||||
// {"jsonrpc":"2.0","method":"clef_chainId","params":[], "id":8}
|
// {"jsonrpc":"2.0","method":"clef_chainId","params":[], "id":8}
|
||||||
func (s *UIServerAPI) ChainId() math.HexOrDecimal64 {
|
func (api *UIServerAPI) ChainId() math.HexOrDecimal64 {
|
||||||
return (math.HexOrDecimal64)(s.extApi.chainID.Uint64())
|
return (math.HexOrDecimal64)(api.extApi.chainID.Uint64())
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetChainId sets the chain id to use when signing transactions.
|
// SetChainId sets the chain id to use when signing transactions.
|
||||||
// Example call to set Ropsten:
|
// Example call to set Ropsten:
|
||||||
// {"jsonrpc":"2.0","method":"clef_setChainId","params":["3"], "id":8}
|
// {"jsonrpc":"2.0","method":"clef_setChainId","params":["3"], "id":8}
|
||||||
func (s *UIServerAPI) SetChainId(id math.HexOrDecimal64) math.HexOrDecimal64 {
|
func (api *UIServerAPI) SetChainId(id math.HexOrDecimal64) math.HexOrDecimal64 {
|
||||||
s.extApi.chainID = new(big.Int).SetUint64(uint64(id))
|
api.extApi.chainID = new(big.Int).SetUint64(uint64(id))
|
||||||
return s.ChainId()
|
return api.ChainId()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Export returns encrypted private key associated with the given address in web3 keystore format.
|
// Export returns encrypted private key associated with the given address in web3 keystore format.
|
||||||
// Example
|
// Example
|
||||||
// {"jsonrpc":"2.0","method":"clef_export","params":["0x19e7e376e7c213b7e7e7e46cc70a5dd086daff2a"], "id":4}
|
// {"jsonrpc":"2.0","method":"clef_export","params":["0x19e7e376e7c213b7e7e7e46cc70a5dd086daff2a"], "id":4}
|
||||||
func (s *UIServerAPI) Export(ctx context.Context, addr common.Address) (json.RawMessage, error) {
|
func (api *UIServerAPI) Export(ctx context.Context, addr common.Address) (json.RawMessage, error) {
|
||||||
// Look up the wallet containing the requested signer
|
// Look up the wallet containing the requested signer
|
||||||
wallet, err := s.am.Find(accounts.Account{Address: addr})
|
wallet, err := api.am.Find(accounts.Account{Address: addr})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@ func TestIterator(t *testing.T) {
|
||||||
all[val.k] = val.v
|
all[val.k] = val.v
|
||||||
trie.MustUpdate([]byte(val.k), []byte(val.v))
|
trie.MustUpdate([]byte(val.k), []byte(val.v))
|
||||||
}
|
}
|
||||||
root, nodes, _ := trie.Commit(false)
|
root, nodes := trie.Commit(false)
|
||||||
db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes))
|
db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes))
|
||||||
|
|
||||||
trie, _ = New(TrieID(root), db)
|
trie, _ = New(TrieID(root), db)
|
||||||
|
|
@ -257,7 +257,7 @@ func TestDifferenceIterator(t *testing.T) {
|
||||||
for _, val := range testdata1 {
|
for _, val := range testdata1 {
|
||||||
triea.MustUpdate([]byte(val.k), []byte(val.v))
|
triea.MustUpdate([]byte(val.k), []byte(val.v))
|
||||||
}
|
}
|
||||||
rootA, nodesA, _ := triea.Commit(false)
|
rootA, nodesA := triea.Commit(false)
|
||||||
dba.Update(rootA, types.EmptyRootHash, trienode.NewWithNodeSet(nodesA))
|
dba.Update(rootA, types.EmptyRootHash, trienode.NewWithNodeSet(nodesA))
|
||||||
triea, _ = New(TrieID(rootA), dba)
|
triea, _ = New(TrieID(rootA), dba)
|
||||||
|
|
||||||
|
|
@ -266,7 +266,7 @@ func TestDifferenceIterator(t *testing.T) {
|
||||||
for _, val := range testdata2 {
|
for _, val := range testdata2 {
|
||||||
trieb.MustUpdate([]byte(val.k), []byte(val.v))
|
trieb.MustUpdate([]byte(val.k), []byte(val.v))
|
||||||
}
|
}
|
||||||
rootB, nodesB, _ := trieb.Commit(false)
|
rootB, nodesB := trieb.Commit(false)
|
||||||
dbb.Update(rootB, types.EmptyRootHash, trienode.NewWithNodeSet(nodesB))
|
dbb.Update(rootB, types.EmptyRootHash, trienode.NewWithNodeSet(nodesB))
|
||||||
trieb, _ = New(TrieID(rootB), dbb)
|
trieb, _ = New(TrieID(rootB), dbb)
|
||||||
|
|
||||||
|
|
@ -299,7 +299,7 @@ func TestUnionIterator(t *testing.T) {
|
||||||
for _, val := range testdata1 {
|
for _, val := range testdata1 {
|
||||||
triea.MustUpdate([]byte(val.k), []byte(val.v))
|
triea.MustUpdate([]byte(val.k), []byte(val.v))
|
||||||
}
|
}
|
||||||
rootA, nodesA, _ := triea.Commit(false)
|
rootA, nodesA := triea.Commit(false)
|
||||||
dba.Update(rootA, types.EmptyRootHash, trienode.NewWithNodeSet(nodesA))
|
dba.Update(rootA, types.EmptyRootHash, trienode.NewWithNodeSet(nodesA))
|
||||||
triea, _ = New(TrieID(rootA), dba)
|
triea, _ = New(TrieID(rootA), dba)
|
||||||
|
|
||||||
|
|
@ -308,7 +308,7 @@ func TestUnionIterator(t *testing.T) {
|
||||||
for _, val := range testdata2 {
|
for _, val := range testdata2 {
|
||||||
trieb.MustUpdate([]byte(val.k), []byte(val.v))
|
trieb.MustUpdate([]byte(val.k), []byte(val.v))
|
||||||
}
|
}
|
||||||
rootB, nodesB, _ := trieb.Commit(false)
|
rootB, nodesB := trieb.Commit(false)
|
||||||
dbb.Update(rootB, types.EmptyRootHash, trienode.NewWithNodeSet(nodesB))
|
dbb.Update(rootB, types.EmptyRootHash, trienode.NewWithNodeSet(nodesB))
|
||||||
trieb, _ = New(TrieID(rootB), dbb)
|
trieb, _ = New(TrieID(rootB), dbb)
|
||||||
|
|
||||||
|
|
@ -371,7 +371,7 @@ func testIteratorContinueAfterError(t *testing.T, memonly bool, scheme string) {
|
||||||
for _, val := range testdata1 {
|
for _, val := range testdata1 {
|
||||||
tr.MustUpdate([]byte(val.k), []byte(val.v))
|
tr.MustUpdate([]byte(val.k), []byte(val.v))
|
||||||
}
|
}
|
||||||
root, nodes, _ := tr.Commit(false)
|
root, nodes := tr.Commit(false)
|
||||||
tdb.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes))
|
tdb.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes))
|
||||||
if !memonly {
|
if !memonly {
|
||||||
tdb.Commit(root)
|
tdb.Commit(root)
|
||||||
|
|
@ -481,7 +481,7 @@ func testIteratorContinueAfterSeekError(t *testing.T, memonly bool, scheme strin
|
||||||
for _, val := range testdata1 {
|
for _, val := range testdata1 {
|
||||||
ctr.MustUpdate([]byte(val.k), []byte(val.v))
|
ctr.MustUpdate([]byte(val.k), []byte(val.v))
|
||||||
}
|
}
|
||||||
root, nodes, _ := ctr.Commit(false)
|
root, nodes := ctr.Commit(false)
|
||||||
for path, n := range nodes.Nodes {
|
for path, n := range nodes.Nodes {
|
||||||
if n.Hash == barNodeHash {
|
if n.Hash == barNodeHash {
|
||||||
barNodePath = []byte(path)
|
barNodePath = []byte(path)
|
||||||
|
|
@ -561,7 +561,7 @@ func testIteratorNodeBlob(t *testing.T, scheme string) {
|
||||||
all[val.k] = val.v
|
all[val.k] = val.v
|
||||||
trie.MustUpdate([]byte(val.k), []byte(val.v))
|
trie.MustUpdate([]byte(val.k), []byte(val.v))
|
||||||
}
|
}
|
||||||
root, nodes, _ := trie.Commit(false)
|
root, nodes := trie.Commit(false)
|
||||||
triedb.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes))
|
triedb.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes))
|
||||||
triedb.Commit(root)
|
triedb.Commit(root)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -221,7 +221,7 @@ func (t *StateTrie) GetKey(shaKey []byte) []byte {
|
||||||
// All cached preimages will be also flushed if preimages recording is enabled.
|
// All cached preimages will be also flushed if preimages recording is enabled.
|
||||||
// Once the trie is committed, it's not usable anymore. A new trie must
|
// Once the trie is committed, it's not usable anymore. A new trie must
|
||||||
// be created with new root and updated trie database for following usage
|
// be created with new root and updated trie database for following usage
|
||||||
func (t *StateTrie) Commit(collectLeaf bool) (common.Hash, *trienode.NodeSet, error) {
|
func (t *StateTrie) Commit(collectLeaf bool) (common.Hash, *trienode.NodeSet) {
|
||||||
// Write all the pre-images to the actual disk database
|
// Write all the pre-images to the actual disk database
|
||||||
if len(t.getSecKeyCache()) > 0 {
|
if len(t.getSecKeyCache()) > 0 {
|
||||||
preimages := make(map[common.Hash][]byte)
|
preimages := make(map[common.Hash][]byte)
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,7 @@ func makeTestStateTrie() (*testDb, *StateTrie, map[string][]byte) {
|
||||||
trie.MustUpdate(key, val)
|
trie.MustUpdate(key, val)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
root, nodes, _ := trie.Commit(false)
|
root, nodes := trie.Commit(false)
|
||||||
if err := triedb.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes)); err != nil {
|
if err := triedb.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes)); err != nil {
|
||||||
panic(fmt.Errorf("failed to commit db %v", err))
|
panic(fmt.Errorf("failed to commit db %v", err))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -79,10 +79,7 @@ func fuzz(data []byte, debugging bool) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// Flush trie -> database
|
// Flush trie -> database
|
||||||
rootA, nodes, err := trieA.Commit(false)
|
rootA, nodes := trieA.Commit(false)
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
if nodes != nil {
|
if nodes != nil {
|
||||||
dbA.Update(rootA, types.EmptyRootHash, trienode.NewWithNodeSet(nodes))
|
dbA.Update(rootA, types.EmptyRootHash, trienode.NewWithNodeSet(nodes))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,7 @@ func makeTestTrie(scheme string) (ethdb.Database, *testDb, *StateTrie, map[strin
|
||||||
trie.MustUpdate(key, val)
|
trie.MustUpdate(key, val)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
root, nodes, _ := trie.Commit(false)
|
root, nodes := trie.Commit(false)
|
||||||
if err := triedb.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes)); err != nil {
|
if err := triedb.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes)); err != nil {
|
||||||
panic(fmt.Errorf("failed to commit db %v", err))
|
panic(fmt.Errorf("failed to commit db %v", err))
|
||||||
}
|
}
|
||||||
|
|
@ -771,7 +771,7 @@ func testSyncMovingTarget(t *testing.T, scheme string) {
|
||||||
srcTrie.MustUpdate(key, val)
|
srcTrie.MustUpdate(key, val)
|
||||||
diff[string(key)] = val
|
diff[string(key)] = val
|
||||||
}
|
}
|
||||||
root, nodes, _ := srcTrie.Commit(false)
|
root, nodes := srcTrie.Commit(false)
|
||||||
if err := srcDb.Update(root, preRoot, trienode.NewWithNodeSet(nodes)); err != nil {
|
if err := srcDb.Update(root, preRoot, trienode.NewWithNodeSet(nodes)); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
@ -796,7 +796,7 @@ func testSyncMovingTarget(t *testing.T, scheme string) {
|
||||||
srcTrie.MustUpdate([]byte(k), val)
|
srcTrie.MustUpdate([]byte(k), val)
|
||||||
reverted[k] = val
|
reverted[k] = val
|
||||||
}
|
}
|
||||||
root, nodes, _ = srcTrie.Commit(false)
|
root, nodes = srcTrie.Commit(false)
|
||||||
if err := srcDb.Update(root, preRoot, trienode.NewWithNodeSet(nodes)); err != nil {
|
if err := srcDb.Update(root, preRoot, trienode.NewWithNodeSet(nodes)); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
@ -847,7 +847,7 @@ func testPivotMove(t *testing.T, scheme string, tiny bool) {
|
||||||
writeFn([]byte{0x02, 0x34}, nil, srcTrie, stateA)
|
writeFn([]byte{0x02, 0x34}, nil, srcTrie, stateA)
|
||||||
writeFn([]byte{0x13, 0x44}, nil, srcTrie, stateA)
|
writeFn([]byte{0x13, 0x44}, nil, srcTrie, stateA)
|
||||||
|
|
||||||
rootA, nodesA, _ := srcTrie.Commit(false)
|
rootA, nodesA := srcTrie.Commit(false)
|
||||||
if err := srcTrieDB.Update(rootA, types.EmptyRootHash, trienode.NewWithNodeSet(nodesA)); err != nil {
|
if err := srcTrieDB.Update(rootA, types.EmptyRootHash, trienode.NewWithNodeSet(nodesA)); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
@ -866,7 +866,7 @@ func testPivotMove(t *testing.T, scheme string, tiny bool) {
|
||||||
deleteFn([]byte{0x13, 0x44}, srcTrie, stateB)
|
deleteFn([]byte{0x13, 0x44}, srcTrie, stateB)
|
||||||
writeFn([]byte{0x01, 0x24}, nil, srcTrie, stateB)
|
writeFn([]byte{0x01, 0x24}, nil, srcTrie, stateB)
|
||||||
|
|
||||||
rootB, nodesB, _ := srcTrie.Commit(false)
|
rootB, nodesB := srcTrie.Commit(false)
|
||||||
if err := srcTrieDB.Update(rootB, rootA, trienode.NewWithNodeSet(nodesB)); err != nil {
|
if err := srcTrieDB.Update(rootB, rootA, trienode.NewWithNodeSet(nodesB)); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
@ -884,7 +884,7 @@ func testPivotMove(t *testing.T, scheme string, tiny bool) {
|
||||||
writeFn([]byte{0x02, 0x34}, nil, srcTrie, stateC)
|
writeFn([]byte{0x02, 0x34}, nil, srcTrie, stateC)
|
||||||
writeFn([]byte{0x13, 0x44}, nil, srcTrie, stateC)
|
writeFn([]byte{0x13, 0x44}, nil, srcTrie, stateC)
|
||||||
|
|
||||||
rootC, nodesC, _ := srcTrie.Commit(false)
|
rootC, nodesC := srcTrie.Commit(false)
|
||||||
if err := srcTrieDB.Update(rootC, rootB, trienode.NewWithNodeSet(nodesC)); err != nil {
|
if err := srcTrieDB.Update(rootC, rootB, trienode.NewWithNodeSet(nodesC)); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
@ -946,7 +946,7 @@ func testSyncAbort(t *testing.T, scheme string) {
|
||||||
}
|
}
|
||||||
writeFn(key, val, srcTrie, stateA)
|
writeFn(key, val, srcTrie, stateA)
|
||||||
|
|
||||||
rootA, nodesA, _ := srcTrie.Commit(false)
|
rootA, nodesA := srcTrie.Commit(false)
|
||||||
if err := srcTrieDB.Update(rootA, types.EmptyRootHash, trienode.NewWithNodeSet(nodesA)); err != nil {
|
if err := srcTrieDB.Update(rootA, types.EmptyRootHash, trienode.NewWithNodeSet(nodesA)); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
@ -963,7 +963,7 @@ func testSyncAbort(t *testing.T, scheme string) {
|
||||||
srcTrie, _ = New(TrieID(rootA), srcTrieDB)
|
srcTrie, _ = New(TrieID(rootA), srcTrieDB)
|
||||||
deleteFn(key, srcTrie, stateB)
|
deleteFn(key, srcTrie, stateB)
|
||||||
|
|
||||||
rootB, nodesB, _ := srcTrie.Commit(false)
|
rootB, nodesB := srcTrie.Commit(false)
|
||||||
if err := srcTrieDB.Update(rootB, rootA, trienode.NewWithNodeSet(nodesB)); err != nil {
|
if err := srcTrieDB.Update(rootB, rootA, trienode.NewWithNodeSet(nodesB)); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
@ -990,7 +990,7 @@ func testSyncAbort(t *testing.T, scheme string) {
|
||||||
srcTrie, _ = New(TrieID(rootB), srcTrieDB)
|
srcTrie, _ = New(TrieID(rootB), srcTrieDB)
|
||||||
|
|
||||||
writeFn(key, val, srcTrie, stateC)
|
writeFn(key, val, srcTrie, stateC)
|
||||||
rootC, nodesC, _ := srcTrie.Commit(false)
|
rootC, nodesC := srcTrie.Commit(false)
|
||||||
if err := srcTrieDB.Update(rootC, rootB, trienode.NewWithNodeSet(nodesC)); err != nil {
|
if err := srcTrieDB.Update(rootC, rootB, trienode.NewWithNodeSet(nodesC)); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -70,7 +70,7 @@ func testTrieTracer(t *testing.T, vals []struct{ k, v string }) {
|
||||||
}
|
}
|
||||||
insertSet := copySet(trie.tracer.inserts) // copy before commit
|
insertSet := copySet(trie.tracer.inserts) // copy before commit
|
||||||
deleteSet := copySet(trie.tracer.deletes) // copy before commit
|
deleteSet := copySet(trie.tracer.deletes) // copy before commit
|
||||||
root, nodes, _ := trie.Commit(false)
|
root, nodes := trie.Commit(false)
|
||||||
db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes))
|
db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes))
|
||||||
|
|
||||||
seen := setKeys(iterNodes(db, root))
|
seen := setKeys(iterNodes(db, root))
|
||||||
|
|
@ -137,7 +137,7 @@ func testAccessList(t *testing.T, vals []struct{ k, v string }) {
|
||||||
for _, val := range vals {
|
for _, val := range vals {
|
||||||
trie.MustUpdate([]byte(val.k), []byte(val.v))
|
trie.MustUpdate([]byte(val.k), []byte(val.v))
|
||||||
}
|
}
|
||||||
root, nodes, _ := trie.Commit(false)
|
root, nodes := trie.Commit(false)
|
||||||
db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes))
|
db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes))
|
||||||
|
|
||||||
trie, _ = New(TrieID(root), db)
|
trie, _ = New(TrieID(root), db)
|
||||||
|
|
@ -152,7 +152,7 @@ func testAccessList(t *testing.T, vals []struct{ k, v string }) {
|
||||||
for _, val := range vals {
|
for _, val := range vals {
|
||||||
trie.MustUpdate([]byte(val.k), randBytes(32))
|
trie.MustUpdate([]byte(val.k), randBytes(32))
|
||||||
}
|
}
|
||||||
root, nodes, _ = trie.Commit(false)
|
root, nodes = trie.Commit(false)
|
||||||
db.Update(root, parent, trienode.NewWithNodeSet(nodes))
|
db.Update(root, parent, trienode.NewWithNodeSet(nodes))
|
||||||
|
|
||||||
trie, _ = New(TrieID(root), db)
|
trie, _ = New(TrieID(root), db)
|
||||||
|
|
@ -170,7 +170,7 @@ func testAccessList(t *testing.T, vals []struct{ k, v string }) {
|
||||||
keys = append(keys, string(key))
|
keys = append(keys, string(key))
|
||||||
trie.MustUpdate(key, randBytes(32))
|
trie.MustUpdate(key, randBytes(32))
|
||||||
}
|
}
|
||||||
root, nodes, _ = trie.Commit(false)
|
root, nodes = trie.Commit(false)
|
||||||
db.Update(root, parent, trienode.NewWithNodeSet(nodes))
|
db.Update(root, parent, trienode.NewWithNodeSet(nodes))
|
||||||
|
|
||||||
trie, _ = New(TrieID(root), db)
|
trie, _ = New(TrieID(root), db)
|
||||||
|
|
@ -185,7 +185,7 @@ func testAccessList(t *testing.T, vals []struct{ k, v string }) {
|
||||||
for _, key := range keys {
|
for _, key := range keys {
|
||||||
trie.MustUpdate([]byte(key), nil)
|
trie.MustUpdate([]byte(key), nil)
|
||||||
}
|
}
|
||||||
root, nodes, _ = trie.Commit(false)
|
root, nodes = trie.Commit(false)
|
||||||
db.Update(root, parent, trienode.NewWithNodeSet(nodes))
|
db.Update(root, parent, trienode.NewWithNodeSet(nodes))
|
||||||
|
|
||||||
trie, _ = New(TrieID(root), db)
|
trie, _ = New(TrieID(root), db)
|
||||||
|
|
@ -200,7 +200,7 @@ func testAccessList(t *testing.T, vals []struct{ k, v string }) {
|
||||||
for _, val := range vals {
|
for _, val := range vals {
|
||||||
trie.MustUpdate([]byte(val.k), nil)
|
trie.MustUpdate([]byte(val.k), nil)
|
||||||
}
|
}
|
||||||
root, nodes, _ = trie.Commit(false)
|
root, nodes = trie.Commit(false)
|
||||||
db.Update(root, parent, trienode.NewWithNodeSet(nodes))
|
db.Update(root, parent, trienode.NewWithNodeSet(nodes))
|
||||||
|
|
||||||
trie, _ = New(TrieID(root), db)
|
trie, _ = New(TrieID(root), db)
|
||||||
|
|
@ -219,7 +219,7 @@ func TestAccessListLeak(t *testing.T) {
|
||||||
for _, val := range standard {
|
for _, val := range standard {
|
||||||
trie.MustUpdate([]byte(val.k), []byte(val.v))
|
trie.MustUpdate([]byte(val.k), []byte(val.v))
|
||||||
}
|
}
|
||||||
root, nodes, _ := trie.Commit(false)
|
root, nodes := trie.Commit(false)
|
||||||
db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes))
|
db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes))
|
||||||
|
|
||||||
var cases = []struct {
|
var cases = []struct {
|
||||||
|
|
@ -269,7 +269,7 @@ func TestTinyTree(t *testing.T) {
|
||||||
for _, val := range tiny {
|
for _, val := range tiny {
|
||||||
trie.MustUpdate([]byte(val.k), randBytes(32))
|
trie.MustUpdate([]byte(val.k), randBytes(32))
|
||||||
}
|
}
|
||||||
root, set, _ := trie.Commit(false)
|
root, set := trie.Commit(false)
|
||||||
db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(set))
|
db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(set))
|
||||||
|
|
||||||
parent := root
|
parent := root
|
||||||
|
|
@ -278,7 +278,7 @@ func TestTinyTree(t *testing.T) {
|
||||||
for _, val := range tiny {
|
for _, val := range tiny {
|
||||||
trie.MustUpdate([]byte(val.k), []byte(val.v))
|
trie.MustUpdate([]byte(val.k), []byte(val.v))
|
||||||
}
|
}
|
||||||
root, set, _ = trie.Commit(false)
|
root, set = trie.Commit(false)
|
||||||
db.Update(root, parent, trienode.NewWithNodeSet(set))
|
db.Update(root, parent, trienode.NewWithNodeSet(set))
|
||||||
|
|
||||||
trie, _ = New(TrieID(root), db)
|
trie, _ = New(TrieID(root), db)
|
||||||
|
|
|
||||||
10
trie/trie.go
10
trie/trie.go
|
|
@ -608,7 +608,7 @@ func (t *Trie) Hash() common.Hash {
|
||||||
// The returned nodeset can be nil if the trie is clean (nothing to commit).
|
// The returned nodeset can be nil if the trie is clean (nothing to commit).
|
||||||
// Once the trie is committed, it's not usable anymore. A new trie must
|
// Once the trie is committed, it's not usable anymore. A new trie must
|
||||||
// be created with new root and updated trie database for following usage
|
// be created with new root and updated trie database for following usage
|
||||||
func (t *Trie) Commit(collectLeaf bool) (common.Hash, *trienode.NodeSet, error) {
|
func (t *Trie) Commit(collectLeaf bool) (common.Hash, *trienode.NodeSet) {
|
||||||
defer t.tracer.reset()
|
defer t.tracer.reset()
|
||||||
defer func() {
|
defer func() {
|
||||||
t.committed = true
|
t.committed = true
|
||||||
|
|
@ -620,13 +620,13 @@ func (t *Trie) Commit(collectLeaf bool) (common.Hash, *trienode.NodeSet, error)
|
||||||
if t.root == nil {
|
if t.root == nil {
|
||||||
paths := t.tracer.deletedNodes()
|
paths := t.tracer.deletedNodes()
|
||||||
if len(paths) == 0 {
|
if len(paths) == 0 {
|
||||||
return types.EmptyRootHash, nil, nil // case (a)
|
return types.EmptyRootHash, nil // case (a)
|
||||||
}
|
}
|
||||||
nodes := trienode.NewNodeSet(t.owner)
|
nodes := trienode.NewNodeSet(t.owner)
|
||||||
for _, path := range paths {
|
for _, path := range paths {
|
||||||
nodes.AddNode([]byte(path), trienode.NewDeleted())
|
nodes.AddNode([]byte(path), trienode.NewDeleted())
|
||||||
}
|
}
|
||||||
return types.EmptyRootHash, nodes, nil // case (b)
|
return types.EmptyRootHash, nodes // case (b)
|
||||||
}
|
}
|
||||||
// Derive the hash for all dirty nodes first. We hold the assumption
|
// Derive the hash for all dirty nodes first. We hold the assumption
|
||||||
// in the following procedure that all nodes are hashed.
|
// in the following procedure that all nodes are hashed.
|
||||||
|
|
@ -638,14 +638,14 @@ func (t *Trie) Commit(collectLeaf bool) (common.Hash, *trienode.NodeSet, error)
|
||||||
// Replace the root node with the origin hash in order to
|
// Replace the root node with the origin hash in order to
|
||||||
// ensure all resolved nodes are dropped after the commit.
|
// ensure all resolved nodes are dropped after the commit.
|
||||||
t.root = hashedNode
|
t.root = hashedNode
|
||||||
return rootHash, nil, nil
|
return rootHash, nil
|
||||||
}
|
}
|
||||||
nodes := trienode.NewNodeSet(t.owner)
|
nodes := trienode.NewNodeSet(t.owner)
|
||||||
for _, path := range t.tracer.deletedNodes() {
|
for _, path := range t.tracer.deletedNodes() {
|
||||||
nodes.AddNode([]byte(path), trienode.NewDeleted())
|
nodes.AddNode([]byte(path), trienode.NewDeleted())
|
||||||
}
|
}
|
||||||
t.root = newCommitter(nodes, t.tracer, collectLeaf).Commit(t.root)
|
t.root = newCommitter(nodes, t.tracer, collectLeaf).Commit(t.root)
|
||||||
return rootHash, nodes, nil
|
return rootHash, nodes
|
||||||
}
|
}
|
||||||
|
|
||||||
// hashRoot calculates the root hash of the given trie
|
// hashRoot calculates the root hash of the given trie
|
||||||
|
|
|
||||||
|
|
@ -95,7 +95,7 @@ func testMissingNode(t *testing.T, memonly bool, scheme string) {
|
||||||
trie := NewEmpty(triedb)
|
trie := NewEmpty(triedb)
|
||||||
updateString(trie, "120000", "qwerqwerqwerqwerqwerqwerqwerqwer")
|
updateString(trie, "120000", "qwerqwerqwerqwerqwerqwerqwerqwer")
|
||||||
updateString(trie, "123456", "asdfasdfasdfasdfasdfasdfasdfasdf")
|
updateString(trie, "123456", "asdfasdfasdfasdfasdfasdfasdfasdf")
|
||||||
root, nodes, _ := trie.Commit(false)
|
root, nodes := trie.Commit(false)
|
||||||
triedb.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes))
|
triedb.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes))
|
||||||
|
|
||||||
if !memonly {
|
if !memonly {
|
||||||
|
|
@ -184,7 +184,7 @@ func TestInsert(t *testing.T) {
|
||||||
updateString(trie, "A", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
|
updateString(trie, "A", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
|
||||||
|
|
||||||
exp = common.HexToHash("d23786fb4a010da3ce639d66d5e904a11dbc02746d1ce25029e53290cabf28ab")
|
exp = common.HexToHash("d23786fb4a010da3ce639d66d5e904a11dbc02746d1ce25029e53290cabf28ab")
|
||||||
root, _, _ = trie.Commit(false)
|
root, _ = trie.Commit(false)
|
||||||
if root != exp {
|
if root != exp {
|
||||||
t.Errorf("case 2: exp %x got %x", exp, root)
|
t.Errorf("case 2: exp %x got %x", exp, root)
|
||||||
}
|
}
|
||||||
|
|
@ -209,7 +209,7 @@ func TestGet(t *testing.T) {
|
||||||
if i == 1 {
|
if i == 1 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
root, nodes, _ := trie.Commit(false)
|
root, nodes := trie.Commit(false)
|
||||||
db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes))
|
db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes))
|
||||||
trie, _ = New(TrieID(root), db)
|
trie, _ = New(TrieID(root), db)
|
||||||
}
|
}
|
||||||
|
|
@ -282,7 +282,7 @@ func TestReplication(t *testing.T) {
|
||||||
for _, val := range vals {
|
for _, val := range vals {
|
||||||
updateString(trie, val.k, val.v)
|
updateString(trie, val.k, val.v)
|
||||||
}
|
}
|
||||||
root, nodes, _ := trie.Commit(false)
|
root, nodes := trie.Commit(false)
|
||||||
db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes))
|
db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes))
|
||||||
|
|
||||||
// create a new trie on top of the database and check that lookups work.
|
// create a new trie on top of the database and check that lookups work.
|
||||||
|
|
@ -295,7 +295,7 @@ func TestReplication(t *testing.T) {
|
||||||
t.Errorf("trie2 doesn't have %q => %q", kv.k, kv.v)
|
t.Errorf("trie2 doesn't have %q => %q", kv.k, kv.v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hash, nodes, _ := trie2.Commit(false)
|
hash, nodes := trie2.Commit(false)
|
||||||
if hash != root {
|
if hash != root {
|
||||||
t.Errorf("root failure. expected %x got %x", root, hash)
|
t.Errorf("root failure. expected %x got %x", root, hash)
|
||||||
}
|
}
|
||||||
|
|
@ -531,7 +531,7 @@ func runRandTest(rt randTest) error {
|
||||||
case opHash:
|
case opHash:
|
||||||
tr.Hash()
|
tr.Hash()
|
||||||
case opCommit:
|
case opCommit:
|
||||||
root, nodes, _ := tr.Commit(true)
|
root, nodes := tr.Commit(true)
|
||||||
if nodes != nil {
|
if nodes != nil {
|
||||||
triedb.Update(root, origin, trienode.NewWithNodeSet(nodes))
|
triedb.Update(root, origin, trienode.NewWithNodeSet(nodes))
|
||||||
}
|
}
|
||||||
|
|
@ -768,7 +768,7 @@ func TestCommitAfterHash(t *testing.T) {
|
||||||
if exp != root {
|
if exp != root {
|
||||||
t.Errorf("got %x, exp %x", root, exp)
|
t.Errorf("got %x, exp %x", root, exp)
|
||||||
}
|
}
|
||||||
root, _, _ = trie.Commit(false)
|
root, _ = trie.Commit(false)
|
||||||
if exp != root {
|
if exp != root {
|
||||||
t.Errorf("got %x, exp %x", root, exp)
|
t.Errorf("got %x, exp %x", root, exp)
|
||||||
}
|
}
|
||||||
|
|
@ -894,7 +894,7 @@ func TestCommitSequence(t *testing.T) {
|
||||||
trie.MustUpdate(crypto.Keccak256(addresses[i][:]), accounts[i])
|
trie.MustUpdate(crypto.Keccak256(addresses[i][:]), accounts[i])
|
||||||
}
|
}
|
||||||
// Flush trie -> database
|
// Flush trie -> database
|
||||||
root, nodes, _ := trie.Commit(false)
|
root, nodes := trie.Commit(false)
|
||||||
db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes))
|
db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes))
|
||||||
// Flush memdb -> disk (sponge)
|
// Flush memdb -> disk (sponge)
|
||||||
db.Commit(root)
|
db.Commit(root)
|
||||||
|
|
@ -935,7 +935,7 @@ func TestCommitSequenceRandomBlobs(t *testing.T) {
|
||||||
trie.MustUpdate(key, val)
|
trie.MustUpdate(key, val)
|
||||||
}
|
}
|
||||||
// Flush trie -> database
|
// Flush trie -> database
|
||||||
root, nodes, _ := trie.Commit(false)
|
root, nodes := trie.Commit(false)
|
||||||
db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes))
|
db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes))
|
||||||
// Flush memdb -> disk (sponge)
|
// Flush memdb -> disk (sponge)
|
||||||
db.Commit(root)
|
db.Commit(root)
|
||||||
|
|
@ -984,7 +984,7 @@ func TestCommitSequenceStackTrie(t *testing.T) {
|
||||||
stTrie.Update(key, val)
|
stTrie.Update(key, val)
|
||||||
}
|
}
|
||||||
// Flush trie -> database
|
// Flush trie -> database
|
||||||
root, nodes, _ := trie.Commit(false)
|
root, nodes := trie.Commit(false)
|
||||||
// Flush memdb -> disk (sponge)
|
// Flush memdb -> disk (sponge)
|
||||||
db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes))
|
db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes))
|
||||||
db.Commit(root)
|
db.Commit(root)
|
||||||
|
|
@ -1042,7 +1042,7 @@ func TestCommitSequenceSmallRoot(t *testing.T) {
|
||||||
stTrie.Update(key, []byte{0x1})
|
stTrie.Update(key, []byte{0x1})
|
||||||
|
|
||||||
// Flush trie -> database
|
// Flush trie -> database
|
||||||
root, nodes, _ := trie.Commit(false)
|
root, nodes := trie.Commit(false)
|
||||||
// Flush memdb -> disk (sponge)
|
// Flush memdb -> disk (sponge)
|
||||||
db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes))
|
db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes))
|
||||||
db.Commit(root)
|
db.Commit(root)
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ type Trie interface {
|
||||||
|
|
||||||
// Commit the trie and returns a set of dirty nodes generated along with
|
// Commit the trie and returns a set of dirty nodes generated along with
|
||||||
// the new root hash.
|
// the new root hash.
|
||||||
Commit(collectLeaf bool) (common.Hash, *trienode.NodeSet, error)
|
Commit(collectLeaf bool) (common.Hash, *trienode.NodeSet)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TrieLoader wraps functions to load tries.
|
// TrieLoader wraps functions to load tries.
|
||||||
|
|
@ -125,10 +125,7 @@ func Apply(prevRoot common.Hash, postRoot common.Hash, accounts map[common.Addre
|
||||||
return nil, fmt.Errorf("failed to revert state, err: %w", err)
|
return nil, fmt.Errorf("failed to revert state, err: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
root, result, err := tr.Commit(false)
|
root, result := tr.Commit(false)
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if root != prevRoot {
|
if root != prevRoot {
|
||||||
return nil, fmt.Errorf("failed to revert state, want %#x, got %#x", prevRoot, root)
|
return nil, fmt.Errorf("failed to revert state, want %#x, got %#x", prevRoot, root)
|
||||||
}
|
}
|
||||||
|
|
@ -180,10 +177,7 @@ func updateAccount(ctx *context, loader TrieLoader, addr common.Address) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
root, result, err := st.Commit(false)
|
root, result := st.Commit(false)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if root != prev.Root {
|
if root != prev.Root {
|
||||||
return errors.New("failed to reset storage trie")
|
return errors.New("failed to reset storage trie")
|
||||||
}
|
}
|
||||||
|
|
@ -234,10 +228,7 @@ func deleteAccount(ctx *context, loader TrieLoader, addr common.Address) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
root, result, err := st.Commit(false)
|
root, result := st.Commit(false)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if root != types.EmptyRootHash {
|
if root != types.EmptyRootHash {
|
||||||
return errors.New("failed to clear storage trie")
|
return errors.New("failed to clear storage trie")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -217,22 +217,21 @@ func (t *VerkleTrie) Hash() common.Hash {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Commit writes all nodes to the tree's memory database.
|
// Commit writes all nodes to the tree's memory database.
|
||||||
func (t *VerkleTrie) Commit(_ bool) (common.Hash, *trienode.NodeSet, error) {
|
func (t *VerkleTrie) Commit(_ bool) (common.Hash, *trienode.NodeSet) {
|
||||||
root, ok := t.root.(*verkle.InternalNode)
|
root := t.root.(*verkle.InternalNode)
|
||||||
if !ok {
|
|
||||||
return common.Hash{}, nil, errors.New("unexpected root node type")
|
|
||||||
}
|
|
||||||
nodes, err := root.BatchSerialize()
|
nodes, err := root.BatchSerialize()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return common.Hash{}, nil, fmt.Errorf("serializing tree nodes: %s", err)
|
// Error return from this function indicates error in the code logic
|
||||||
|
// of BatchSerialize, and we fail catastrophically if this is the case.
|
||||||
|
panic(fmt.Errorf("BatchSerialize failed: %v", err))
|
||||||
}
|
}
|
||||||
nodeset := trienode.NewNodeSet(common.Hash{})
|
nodeset := trienode.NewNodeSet(common.Hash{})
|
||||||
for _, node := range nodes {
|
for _, node := range nodes {
|
||||||
// hash parameter is not used in pathdb
|
// Hash parameter is not used in pathdb
|
||||||
nodeset.AddNode(node.Path, trienode.New(common.Hash{}, node.SerializedBytes))
|
nodeset.AddNode(node.Path, trienode.New(common.Hash{}, node.SerializedBytes))
|
||||||
}
|
}
|
||||||
// Serialize root commitment form
|
// Serialize root commitment form
|
||||||
return t.Hash(), nodeset, nil
|
return t.Hash(), nodeset
|
||||||
}
|
}
|
||||||
|
|
||||||
// NodeIterator implements state.Trie, returning an iterator that returns
|
// NodeIterator implements state.Trie, returning an iterator that returns
|
||||||
|
|
|
||||||
|
|
@ -46,11 +46,7 @@ func updateTrie(addrHash common.Hash, root common.Hash, dirties, cleans map[comm
|
||||||
h.Update(key.Bytes(), val)
|
h.Update(key.Bytes(), val)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
root, nodes, err := h.Commit(false)
|
return h.Commit(false)
|
||||||
if err != nil {
|
|
||||||
panic(fmt.Errorf("failed to commit hasher, err: %w", err))
|
|
||||||
}
|
|
||||||
return root, nodes
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func generateAccount(storageRoot common.Hash) types.StateAccount {
|
func generateAccount(storageRoot common.Hash) types.StateAccount {
|
||||||
|
|
|
||||||
|
|
@ -80,7 +80,7 @@ func (h *testHasher) Delete(key []byte) error {
|
||||||
|
|
||||||
// Commit computes the new hash of the states and returns the set with all
|
// Commit computes the new hash of the states and returns the set with all
|
||||||
// state changes.
|
// state changes.
|
||||||
func (h *testHasher) Commit(collectLeaf bool) (common.Hash, *trienode.NodeSet, error) {
|
func (h *testHasher) Commit(collectLeaf bool) (common.Hash, *trienode.NodeSet) {
|
||||||
var (
|
var (
|
||||||
nodes = make(map[common.Hash][]byte)
|
nodes = make(map[common.Hash][]byte)
|
||||||
set = trienode.NewNodeSet(h.owner)
|
set = trienode.NewNodeSet(h.owner)
|
||||||
|
|
@ -111,7 +111,7 @@ func (h *testHasher) Commit(collectLeaf bool) (common.Hash, *trienode.NodeSet, e
|
||||||
if root == types.EmptyRootHash && h.root != types.EmptyRootHash {
|
if root == types.EmptyRootHash && h.root != types.EmptyRootHash {
|
||||||
set.AddNode(nil, trienode.NewDeleted())
|
set.AddNode(nil, trienode.NewDeleted())
|
||||||
}
|
}
|
||||||
return root, set, nil
|
return root, set
|
||||||
}
|
}
|
||||||
|
|
||||||
// hash performs the hash computation upon the provided states.
|
// hash performs the hash computation upon the provided states.
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue