diff --git a/trie/hashbuilder.go b/trie/hashbuilder.go index ab85cdb0e..d249dfdb2 100644 --- a/trie/hashbuilder.go +++ b/trie/hashbuilder.go @@ -260,13 +260,13 @@ func (hb *HashBuilder) accountLeafHash(length int, keyHex []byte, storageSize ui hb.acc.Incarnation = incarnation popped := 0 - if fieldSet&uint32(4) != 0 { + if fieldSet&AccountFieldStorageOnly != 0 { copy(hb.acc.Root[:], hb.hashStack[len(hb.hashStack)-popped*hashStackStride-common.HashLength:len(hb.hashStack)-popped*hashStackStride]) popped++ } else { copy(hb.acc.Root[:], EmptyRoot[:]) } - if fieldSet&uint32(8) != 0 { + if fieldSet&AccountFieldCodeOnly != 0 { copy(hb.acc.CodeHash[:], hb.hashStack[len(hb.hashStack)-popped*hashStackStride-common.HashLength:len(hb.hashStack)-popped*hashStackStride]) popped++ } else { diff --git a/trie/resolver.go b/trie/resolver.go index fc8615277..d56641d9a 100644 --- a/trie/resolver.go +++ b/trie/resolver.go @@ -144,13 +144,10 @@ func (tr *Resolver) Print() { const ( AccountFieldNonceOnly uint32 = 0x01 AccountFieldBalanceOnly uint32 = 0x02 - AccountFieldRootOnly uint32 = 0x04 - AccountFieldCodeHashOnly uint32 = 0x08 + AccountFieldStorageOnly uint32 = 0x04 + AccountFieldCodeOnly uint32 = 0x08 AccountFieldSSizeOnly uint32 = 0x10 AccountFieldSetNotAccount uint32 = 0x00 - AccountFieldSetNotContract uint32 = 0x03 // Bit 0 is set for nonce, bit 1 is set for balance - AccountFieldSetContract uint32 = 0x0f // Bits 0-3 are set for nonce, balance, storageRoot and codeHash - AccountFieldSetContractWithSize uint32 = 0x1f // Bits 0-4 are set for nonce, balance, storageRoot, codeHash and storageSize ) // ResolveWithDb resolves and hooks subtries using a state database. diff --git a/trie/resolver_stateful.go b/trie/resolver_stateful.go index ea987e4ec..35f93678a 100644 --- a/trie/resolver_stateful.go +++ b/trie/resolver_stateful.go @@ -221,34 +221,35 @@ func (tr *ResolverStateful) finaliseRoot() error { tr.currStorage.Reset() tr.succStorage.Reset() } - - if tr.a.IsEmptyCodeHash() && tr.a.IsEmptyRoot() { - tr.accData.FieldSet = AccountFieldSetNotContract - } else { - tr.accData.FieldSet = AccountFieldSetContract + tr.accData.FieldSet = 0 + if !tr.a.IsEmptyCodeHash() { + tr.accData.FieldSet |= AccountFieldCodeOnly + } + if storageNode != nil || !tr.a.IsEmptyRoot() { + tr.accData.FieldSet |= AccountFieldStorageOnly } tr.accData.Balance.Set(&tr.a.Balance) + if tr.a.Balance.Sign() != 0 { + tr.accData.FieldSet |= AccountFieldBalanceOnly + } tr.accData.Nonce = tr.a.Nonce + if tr.a.Nonce != 0 { + tr.accData.FieldSet |= AccountFieldNonceOnly + } tr.accData.Incarnation = tr.a.Incarnation data = &tr.accData - if !tr.a.IsEmptyCodeHash() || !tr.a.IsEmptyRoot() { + if !tr.a.IsEmptyCodeHash() { // the first item ends up deepest on the stack, the second item - on the top err = tr.hb.hash(tr.a.CodeHash[:]) if err != nil { return err } - - //if tr.hb.trace { - // fmt.Printf("HASH\n") - //} + } + if storageNode != nil || !tr.a.IsEmptyRoot() { tr.hb.hashStack = append(tr.hb.hashStack, 0x80+common.HashLength) tr.hb.hashStack = append(tr.hb.hashStack, tr.a.Root[:]...) tr.hb.nodeStack = append(tr.hb.nodeStack, storageNode) - // err = tr.hb.hash(tr.a.Root[:]) - // if err != nil { - // return err - // } } } tr.groups, err = GenStructStep(tr.currentRsChopped.HashOnly, tr.curr.Bytes(), tr.succ.Bytes(), tr.hb, data, tr.groups, false) @@ -602,24 +603,32 @@ func (tr *ResolverStateful) WalkerAccount(isIH bool, keyIdx int, k, v []byte) er } } } - - if tr.a.IsEmptyCodeHash() && tr.a.IsEmptyRoot() { - tr.accData.FieldSet = AccountFieldSetNotContract - } else { - tr.accData.FieldSet = AccountFieldSetContract + tr.accData.FieldSet = 0 + if !tr.a.IsEmptyCodeHash() { + tr.accData.FieldSet |= AccountFieldCodeOnly + } + if storageNode != nil || !tr.a.IsEmptyRoot() { + tr.accData.FieldSet |= AccountFieldStorageOnly } tr.accData.Balance.Set(&tr.a.Balance) + if tr.a.Balance.Sign() != 0 { + tr.accData.FieldSet |= AccountFieldBalanceOnly + } tr.accData.Nonce = tr.a.Nonce + if tr.a.Nonce != 0 { + tr.accData.FieldSet |= AccountFieldNonceOnly + } tr.accData.Incarnation = tr.a.Incarnation data = &tr.accData - if !tr.a.IsEmptyCodeHash() || !tr.a.IsEmptyRoot() { + if !tr.a.IsEmptyCodeHash() { // the first item ends up deepest on the stack, the second item - on the top err = tr.hb.hash(tr.a.CodeHash[:]) if err != nil { return err } - + } + if storageNode != nil || !tr.a.IsEmptyRoot() { tr.hb.hashStack = append(tr.hb.hashStack, 0x80+common.HashLength) tr.hb.hashStack = append(tr.hb.hashStack, tr.a.Root[:]...) tr.hb.nodeStack = append(tr.hb.nodeStack, storageNode) diff --git a/trie/stream.go b/trie/stream.go index d406da88f..884d715af 100644 --- a/trie/stream.go +++ b/trie/stream.go @@ -583,6 +583,7 @@ func StreamHash(it *StreamMergeIterator, storagePrefixLen int, hb *HashBuilder, var groups, sGroups []uint16 // Separate groups slices for storage items and for accounts var aRoot common.Hash var aEmptyRoot = true + var isAccount bool var fieldSet uint32 var itemType, sItemType StreamItem var hashData GenStructStepHashData @@ -597,7 +598,7 @@ func StreamHash(it *StreamMergeIterator, storagePrefixLen int, hb *HashBuilder, if hashRef != nil { copy(hashData.Hash[:], hashRef) return &hashData - } else if fieldSet == AccountFieldSetNotAccount { + } else if !isAccount { leafData.Value = rlphacks.RlpSerializableBytes(value.Bytes()) return &leafData } else { @@ -615,25 +616,27 @@ func StreamHash(it *StreamMergeIterator, storagePrefixLen int, hb *HashBuilder, currStorage.Write(succStorage.Bytes()) succStorage.Reset() if currStorage.Len() > 0 { + isAccount = false var err error sGroups, err = GenStructStep(hashOnly, currStorage.Bytes(), succStorage.Bytes(), hb, makeData(AccountFieldSetNotAccount, hashRefStorage), sGroups, trace) if err != nil { return common.Hash{}, err } currStorage.Reset() - fieldSet += AccountFieldRootOnly + fieldSet += AccountFieldStorageOnly } } else if itemType == AccountStreamItem && !aEmptyRoot { if err := hb.hash(aRoot[:]); err != nil { return common.Hash{}, err } - fieldSet += AccountFieldRootOnly + fieldSet += AccountFieldStorageOnly } curr.Reset() curr.Write(succ.Bytes()) succ.Reset() succ.Write(hex) if curr.Len() > 0 { + isAccount = true var err error groups, err = GenStructStep(hashOnly, curr.Bytes(), succ.Bytes(), hb, makeData(fieldSet, hashRef), groups, trace) if err != nil { @@ -649,9 +652,15 @@ func StreamHash(it *StreamMergeIterator, storagePrefixLen int, hb *HashBuilder, accData.Incarnation = a.Incarnation aEmptyRoot = a.IsEmptyRoot() copy(aRoot[:], a.Root[:]) - fieldSet = AccountFieldSetNotContract // base level - nonce and balance + fieldSet = 0 + if a.Balance.Sign() != 0 { + fieldSet |= AccountFieldBalanceOnly + } + if a.Nonce != 0 { + fieldSet |= AccountFieldNonceOnly + } if !a.IsEmptyCodeHash() { - fieldSet += AccountFieldCodeHashOnly + fieldSet |= AccountFieldCodeOnly if err := hb.hash(a.CodeHash[:]); err != nil { return common.Hash{}, err } @@ -667,6 +676,7 @@ func StreamHash(it *StreamMergeIterator, storagePrefixLen int, hb *HashBuilder, succStorage.Reset() succStorage.Write(hex[2*storagePrefixLen+1:]) if currStorage.Len() > 0 { + isAccount = false var err error sGroups, err = GenStructStep(hashOnly, currStorage.Bytes(), succStorage.Bytes(), hb, makeData(AccountFieldSetNotAccount, hashRefStorage), sGroups, trace) if err != nil { @@ -691,24 +701,26 @@ func StreamHash(it *StreamMergeIterator, storagePrefixLen int, hb *HashBuilder, currStorage.Write(succStorage.Bytes()) succStorage.Reset() if currStorage.Len() > 0 { + isAccount = false var err error _, err = GenStructStep(hashOnly, currStorage.Bytes(), succStorage.Bytes(), hb, makeData(AccountFieldSetNotAccount, hashRefStorage), sGroups, trace) if err != nil { return common.Hash{}, err } currStorage.Reset() - fieldSet += AccountFieldRootOnly + fieldSet |= AccountFieldStorageOnly } } else if itemType == AccountStreamItem && !aEmptyRoot { if err := hb.hash(aRoot[:]); err != nil { return common.Hash{}, err } - fieldSet += AccountFieldRootOnly + fieldSet |= AccountFieldStorageOnly } curr.Reset() curr.Write(succ.Bytes()) succ.Reset() if curr.Len() > 0 { + isAccount = true var err error _, err = GenStructStep(hashOnly, curr.Bytes(), succ.Bytes(), hb, makeData(fieldSet, hashRef), groups, trace) if err != nil {