github.com/ledgerwatch/erigon-lib@v1.0.0/commitment/bin_patricia_hashed.go (about)

     1  /*
     2     Copyright 2022 The Erigon contributors
     3  
     4     Licensed under the Apache License, Version 2.0 (the "License");
     5     you may not use this file except in compliance with the License.
     6     You may obtain a copy of the License at
     7  
     8         http://www.apache.org/licenses/LICENSE-2.0
     9  
    10     Unless required by applicable law or agreed to in writing, software
    11     distributed under the License is distributed on an "AS IS" BASIS,
    12     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13     See the License for the specific language governing permissions and
    14     limitations under the License.
    15  */
    16  
    17  package commitment
    18  
    19  import (
    20  	"bytes"
    21  	"encoding/binary"
    22  	"encoding/hex"
    23  	"fmt"
    24  	"io"
    25  	"math/bits"
    26  
    27  	"github.com/holiman/uint256"
    28  	"github.com/ledgerwatch/log/v3"
    29  	"golang.org/x/crypto/sha3"
    30  
    31  	"github.com/ledgerwatch/erigon-lib/common"
    32  	"github.com/ledgerwatch/erigon-lib/common/length"
    33  	"github.com/ledgerwatch/erigon-lib/rlp"
    34  )
    35  
    36  const (
    37  	maxKeySize  = 512
    38  	halfKeySize = maxKeySize / 2
    39  	maxChild    = 2
    40  )
    41  
    42  type bitstring []uint8
    43  
    44  // converts slice of nibbles (lowest 4 bits of each byte) to bitstring
    45  func hexToBin(hex []byte) bitstring {
    46  	bin := make([]byte, 4*len(hex))
    47  	for i := range bin {
    48  		if hex[i/4]&(1<<(3-i%4)) != 0 {
    49  			bin[i] = 1
    50  		}
    51  	}
    52  	return bin
    53  }
    54  
    55  // encodes bitstring to its compact representation
    56  func binToCompact(bin []byte) []byte {
    57  	compact := make([]byte, 2+common.BitLenToByteLen(len(bin)))
    58  	binary.BigEndian.PutUint16(compact, uint16(len(bin)))
    59  	for i := 0; i < len(bin); i++ {
    60  		if bin[i] != 0 {
    61  			compact[2+i/8] |= byte(1) << (i % 8)
    62  		}
    63  	}
    64  	return compact
    65  }
    66  
    67  // decodes compact bitstring representation into actual bitstring
    68  func compactToBin(compact []byte) []byte {
    69  	bin := make([]byte, binary.BigEndian.Uint16(compact))
    70  	for i := 0; i < len(bin); i++ {
    71  		if compact[2+i/8]&(byte(1)<<(i%8)) == 0 {
    72  			bin[i] = 0
    73  		} else {
    74  			bin[i] = 1
    75  		}
    76  	}
    77  	return bin
    78  }
    79  
    80  // BinHashed implements commitment based on patricia merkle tree with radix 16,
    81  // with keys pre-hashed by keccak256
    82  type BinPatriciaHashed struct {
    83  	root BinaryCell // Root cell of the tree
    84  	// Rows of the grid correspond to the level of depth in the patricia tree
    85  	// Columns of the grid correspond to pointers to the nodes further from the root
    86  	grid [maxKeySize][maxChild]BinaryCell // First halfKeySize rows of this grid are for account trie, and next halfKeySize rows are for storage trie
    87  	// How many rows (starting from row 0) are currently active and have corresponding selected columns
    88  	// Last active row does not have selected column
    89  	activeRows int
    90  	// Length of the key that reflects current positioning of the grid. It maybe larger than number of active rows,
    91  	// if a account leaf cell represents multiple nibbles in the key
    92  	currentKeyLen int
    93  	currentKey    [maxKeySize]byte // For each row indicates which column is currently selected
    94  	depths        [maxKeySize]int  // For each row, the depth of cells in that row
    95  	rootChecked   bool             // Set to false if it is not known whether the root is empty, set to true if it is checked
    96  	rootTouched   bool
    97  	rootPresent   bool
    98  	branchBefore  [maxKeySize]bool   // For each row, whether there was a branch node in the database loaded in unfold
    99  	touchMap      [maxKeySize]uint16 // For each row, bitmap of cells that were either present before modification, or modified or deleted
   100  	afterMap      [maxKeySize]uint16 // For each row, bitmap of cells that were present after modification
   101  	keccak        keccakState
   102  	keccak2       keccakState
   103  	accountKeyLen int
   104  	trace         bool
   105  	hashAuxBuffer [maxKeySize]byte // buffer to compute cell hash or write hash-related things
   106  	auxBuffer     *bytes.Buffer    // auxiliary buffer used during branch updates encoding
   107  
   108  	// Function used to load branch node and fill up the cells
   109  	// For each cell, it sets the cell type, clears the modified flag, fills the hash,
   110  	// and for the extension, account, and leaf type, the `l` and `k`
   111  	branchFn func(prefix []byte) ([]byte, error)
   112  	// Function used to fetch account with given plain key
   113  	accountFn func(plainKey []byte, cell *BinaryCell) error
   114  	// Function used to fetch account with given plain key
   115  	storageFn func(plainKey []byte, cell *BinaryCell) error
   116  }
   117  
   118  func NewBinPatriciaHashed(accountKeyLen int,
   119  	branchFn func(prefix []byte) ([]byte, error),
   120  	accountFn func(plainKey []byte, cell *Cell) error,
   121  	storageFn func(plainKey []byte, cell *Cell) error,
   122  ) *BinPatriciaHashed {
   123  	return &BinPatriciaHashed{
   124  		keccak:        sha3.NewLegacyKeccak256().(keccakState),
   125  		keccak2:       sha3.NewLegacyKeccak256().(keccakState),
   126  		accountKeyLen: accountKeyLen,
   127  		branchFn:      branchFn,
   128  		accountFn:     wrapAccountStorageFn(accountFn),
   129  		storageFn:     wrapAccountStorageFn(storageFn),
   130  		auxBuffer:     bytes.NewBuffer(make([]byte, 8192)),
   131  	}
   132  }
   133  
   134  type BinaryCell struct {
   135  	h             [length.Hash]byte               // cell hash
   136  	hl            int                             // Length of the hash (or embedded)
   137  	apk           [length.Addr]byte               // account plain key
   138  	apl           int                             // length of account plain key
   139  	spk           [length.Addr + length.Hash]byte // storage plain key
   140  	spl           int                             // length of the storage plain key
   141  	downHashedKey [maxKeySize]byte
   142  	downHashedLen int
   143  	extension     [halfKeySize]byte
   144  	extLen        int
   145  	Nonce         uint64
   146  	Balance       uint256.Int
   147  	CodeHash      [length.Hash]byte // hash of the bytecode
   148  	Storage       [length.Hash]byte
   149  	StorageLen    int
   150  	Delete        bool
   151  }
   152  
   153  func (cell *BinaryCell) unwrapToHexCell() (cl *Cell) {
   154  	cl = new(Cell)
   155  	cl.Balance = *cell.Balance.Clone()
   156  	cl.Nonce = cell.Nonce
   157  	cl.StorageLen = cell.StorageLen
   158  	cl.apl = cell.apl
   159  	cl.spl = cell.spl
   160  	cl.hl = cell.hl
   161  
   162  	copy(cl.apk[:], cell.apk[:])
   163  	copy(cl.spk[:], cell.spk[:])
   164  	copy(cl.h[:], cell.h[:])
   165  
   166  	if cell.extLen > 0 {
   167  		compactedExt := binToCompact(cell.extension[:cell.extLen])
   168  		copy(cl.extension[:], compactedExt)
   169  		cl.extLen = len(compactedExt)
   170  	}
   171  	if cell.downHashedLen > 0 {
   172  		compactedDHK := binToCompact(cell.downHashedKey[:cell.downHashedLen])
   173  		copy(cl.downHashedKey[:], compactedDHK)
   174  		cl.downHashedLen = len(compactedDHK)
   175  	}
   176  
   177  	copy(cl.CodeHash[:], cell.CodeHash[:])
   178  	copy(cl.Storage[:], cell.Storage[:])
   179  	cl.Delete = cell.Delete
   180  	return cl
   181  }
   182  
   183  var ( // TODO REEAVL
   184  	EmptyBinRootHash, _ = hex.DecodeString("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")
   185  	EmptyBinCodeHash, _ = hex.DecodeString("c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470")
   186  )
   187  
   188  func (cell *BinaryCell) fillEmpty() {
   189  	cell.apl = 0
   190  	cell.spl = 0
   191  	cell.downHashedLen = 0
   192  	cell.extLen = 0
   193  	cell.hl = 0
   194  	cell.Nonce = 0
   195  	cell.Balance.Clear()
   196  	copy(cell.CodeHash[:], EmptyCodeHash)
   197  	cell.StorageLen = 0
   198  	cell.Delete = false
   199  }
   200  
   201  func (cell *BinaryCell) fillFromUpperCell(upBinaryCell *BinaryCell, depth, depthIncrement int) {
   202  	if upBinaryCell.downHashedLen >= depthIncrement {
   203  		cell.downHashedLen = upBinaryCell.downHashedLen - depthIncrement
   204  	} else {
   205  		cell.downHashedLen = 0
   206  	}
   207  	if upBinaryCell.downHashedLen > depthIncrement {
   208  		copy(cell.downHashedKey[:], upBinaryCell.downHashedKey[depthIncrement:upBinaryCell.downHashedLen])
   209  	}
   210  	if upBinaryCell.extLen >= depthIncrement {
   211  		cell.extLen = upBinaryCell.extLen - depthIncrement
   212  	} else {
   213  		cell.extLen = 0
   214  	}
   215  	if upBinaryCell.extLen > depthIncrement {
   216  		copy(cell.extension[:], upBinaryCell.extension[depthIncrement:upBinaryCell.extLen])
   217  	}
   218  	if depth <= halfKeySize {
   219  		cell.apl = upBinaryCell.apl
   220  		if upBinaryCell.apl > 0 {
   221  			copy(cell.apk[:], upBinaryCell.apk[:cell.apl])
   222  			cell.Balance.Set(&upBinaryCell.Balance)
   223  			cell.Nonce = upBinaryCell.Nonce
   224  			copy(cell.CodeHash[:], upBinaryCell.CodeHash[:])
   225  			cell.extLen = upBinaryCell.extLen
   226  			if upBinaryCell.extLen > 0 {
   227  				copy(cell.extension[:], upBinaryCell.extension[:upBinaryCell.extLen])
   228  			}
   229  		}
   230  	} else {
   231  		cell.apl = 0
   232  	}
   233  	cell.spl = upBinaryCell.spl
   234  	if upBinaryCell.spl > 0 {
   235  		copy(cell.spk[:], upBinaryCell.spk[:upBinaryCell.spl])
   236  		cell.StorageLen = upBinaryCell.StorageLen
   237  		if upBinaryCell.StorageLen > 0 {
   238  			copy(cell.Storage[:], upBinaryCell.Storage[:upBinaryCell.StorageLen])
   239  		}
   240  	}
   241  	cell.hl = upBinaryCell.hl
   242  	if upBinaryCell.hl > 0 {
   243  		copy(cell.h[:], upBinaryCell.h[:upBinaryCell.hl])
   244  	}
   245  }
   246  
   247  func (cell *BinaryCell) fillFromLowerBinaryCell(lowBinaryCell *BinaryCell, lowDepth int, preExtension []byte, nibble int) {
   248  	if lowBinaryCell.apl > 0 || lowDepth < halfKeySize {
   249  		cell.apl = lowBinaryCell.apl
   250  	}
   251  	if lowBinaryCell.apl > 0 {
   252  		copy(cell.apk[:], lowBinaryCell.apk[:cell.apl])
   253  		cell.Balance.Set(&lowBinaryCell.Balance)
   254  		cell.Nonce = lowBinaryCell.Nonce
   255  		copy(cell.CodeHash[:], lowBinaryCell.CodeHash[:])
   256  	}
   257  	cell.spl = lowBinaryCell.spl
   258  	if lowBinaryCell.spl > 0 {
   259  		copy(cell.spk[:], lowBinaryCell.spk[:cell.spl])
   260  		cell.StorageLen = lowBinaryCell.StorageLen
   261  		if lowBinaryCell.StorageLen > 0 {
   262  			copy(cell.Storage[:], lowBinaryCell.Storage[:lowBinaryCell.StorageLen])
   263  		}
   264  	}
   265  	if lowBinaryCell.hl > 0 {
   266  		if (lowBinaryCell.apl == 0 && lowDepth < halfKeySize) || (lowBinaryCell.spl == 0 && lowDepth > halfKeySize) {
   267  			// Extension is related to either accounts branch node, or storage branch node, we prepend it by preExtension | nibble
   268  			if len(preExtension) > 0 {
   269  				copy(cell.extension[:], preExtension)
   270  			}
   271  			cell.extension[len(preExtension)] = byte(nibble)
   272  			if lowBinaryCell.extLen > 0 {
   273  				copy(cell.extension[1+len(preExtension):], lowBinaryCell.extension[:lowBinaryCell.extLen])
   274  			}
   275  			cell.extLen = lowBinaryCell.extLen + 1 + len(preExtension)
   276  		} else {
   277  			// Extension is related to a storage branch node, so we copy it upwards as is
   278  			cell.extLen = lowBinaryCell.extLen
   279  			if lowBinaryCell.extLen > 0 {
   280  				copy(cell.extension[:], lowBinaryCell.extension[:lowBinaryCell.extLen])
   281  			}
   282  		}
   283  	}
   284  	cell.hl = lowBinaryCell.hl
   285  	if lowBinaryCell.hl > 0 {
   286  		copy(cell.h[:], lowBinaryCell.h[:lowBinaryCell.hl])
   287  	}
   288  }
   289  
   290  func (cell *BinaryCell) deriveHashedKeys(depth int, keccak keccakState, accountKeyLen int) error {
   291  	extraLen := 0
   292  	if cell.apl > 0 {
   293  		if depth > halfKeySize {
   294  			return fmt.Errorf("deriveHashedKeys accountPlainKey present at depth > halfKeySize")
   295  		}
   296  		extraLen = halfKeySize - depth
   297  	}
   298  	if cell.spl > 0 {
   299  		if depth >= halfKeySize {
   300  			extraLen = maxKeySize - depth
   301  		} else {
   302  			extraLen += halfKeySize
   303  		}
   304  	}
   305  	if extraLen > 0 {
   306  		if cell.downHashedLen > 0 {
   307  			copy(cell.downHashedKey[extraLen:], cell.downHashedKey[:cell.downHashedLen])
   308  		}
   309  		cell.downHashedLen += extraLen
   310  		var hashedKeyOffset, downOffset int
   311  		if cell.apl > 0 {
   312  			if err := binHashKey(keccak, cell.apk[:cell.apl], cell.downHashedKey[:], depth); err != nil {
   313  				return err
   314  			}
   315  			downOffset = halfKeySize - depth
   316  		}
   317  		if cell.spl > 0 {
   318  			if depth >= halfKeySize {
   319  				hashedKeyOffset = depth - halfKeySize
   320  			}
   321  			if err := binHashKey(keccak, cell.spk[accountKeyLen:cell.spl], cell.downHashedKey[downOffset:], hashedKeyOffset); err != nil {
   322  				return err
   323  			}
   324  		}
   325  	}
   326  	return nil
   327  }
   328  
   329  func (cell *BinaryCell) fillFromFields(data []byte, pos int, fieldBits PartFlags) (int, error) {
   330  	if fieldBits&HashedKeyPart != 0 {
   331  		l, n := binary.Uvarint(data[pos:])
   332  		if n == 0 {
   333  			return 0, fmt.Errorf("fillFromFields buffer too small for hashedKey len")
   334  		} else if n < 0 {
   335  			return 0, fmt.Errorf("fillFromFields value overflow for hashedKey len")
   336  		}
   337  		pos += n
   338  		if len(data) < pos+int(l) {
   339  			return 0, fmt.Errorf("fillFromFields buffer too small for hashedKey exp %d got %d", pos+int(l), len(data))
   340  		}
   341  		cell.downHashedLen = int(l)
   342  		cell.extLen = int(l)
   343  		if l > 0 {
   344  			copy(cell.downHashedKey[:], data[pos:pos+int(l)])
   345  			copy(cell.extension[:], data[pos:pos+int(l)])
   346  			pos += int(l)
   347  		}
   348  	} else {
   349  		cell.downHashedLen = 0
   350  		cell.extLen = 0
   351  	}
   352  	if fieldBits&AccountPlainPart != 0 {
   353  		l, n := binary.Uvarint(data[pos:])
   354  		if n == 0 {
   355  			return 0, fmt.Errorf("fillFromFields buffer too small for accountPlainKey len")
   356  		} else if n < 0 {
   357  			return 0, fmt.Errorf("fillFromFields value overflow for accountPlainKey len")
   358  		}
   359  		pos += n
   360  		if len(data) < pos+int(l) {
   361  			return 0, fmt.Errorf("fillFromFields buffer too small for accountPlainKey")
   362  		}
   363  		cell.apl = int(l)
   364  		if l > 0 {
   365  			copy(cell.apk[:], data[pos:pos+int(l)])
   366  			pos += int(l)
   367  		}
   368  	} else {
   369  		cell.apl = 0
   370  	}
   371  	if fieldBits&StoragePlainPart != 0 {
   372  		l, n := binary.Uvarint(data[pos:])
   373  		if n == 0 {
   374  			return 0, fmt.Errorf("fillFromFields buffer too small for storagePlainKey len")
   375  		} else if n < 0 {
   376  			return 0, fmt.Errorf("fillFromFields value overflow for storagePlainKey len")
   377  		}
   378  		pos += n
   379  		if len(data) < pos+int(l) {
   380  			return 0, fmt.Errorf("fillFromFields buffer too small for storagePlainKey")
   381  		}
   382  		cell.spl = int(l)
   383  		if l > 0 {
   384  			copy(cell.spk[:], data[pos:pos+int(l)])
   385  			pos += int(l)
   386  		}
   387  	} else {
   388  		cell.spl = 0
   389  	}
   390  	if fieldBits&HashPart != 0 {
   391  		l, n := binary.Uvarint(data[pos:])
   392  		if n == 0 {
   393  			return 0, fmt.Errorf("fillFromFields buffer too small for hash len")
   394  		} else if n < 0 {
   395  			return 0, fmt.Errorf("fillFromFields value overflow for hash len")
   396  		}
   397  		pos += n
   398  		if len(data) < pos+int(l) {
   399  			return 0, fmt.Errorf("fillFromFields buffer too small for hash")
   400  		}
   401  		cell.hl = int(l)
   402  		if l > 0 {
   403  			copy(cell.h[:], data[pos:pos+int(l)])
   404  			pos += int(l)
   405  		}
   406  	} else {
   407  		cell.hl = 0
   408  	}
   409  	return pos, nil
   410  }
   411  
   412  func (cell *BinaryCell) setStorage(value []byte) {
   413  	cell.StorageLen = len(value)
   414  	if len(value) > 0 {
   415  		copy(cell.Storage[:], value)
   416  	}
   417  }
   418  
   419  func (cell *BinaryCell) setAccountFields(codeHash []byte, balance *uint256.Int, nonce uint64) {
   420  	copy(cell.CodeHash[:], codeHash)
   421  
   422  	cell.Balance.SetBytes(balance.Bytes())
   423  	cell.Nonce = nonce
   424  }
   425  
   426  func (cell *BinaryCell) accountForHashing(buffer []byte, storageRootHash [length.Hash]byte) int {
   427  	balanceBytes := 0
   428  	if !cell.Balance.LtUint64(128) {
   429  		balanceBytes = cell.Balance.ByteLen()
   430  	}
   431  
   432  	var nonceBytes int
   433  	if cell.Nonce < 128 && cell.Nonce != 0 {
   434  		nonceBytes = 0
   435  	} else {
   436  		nonceBytes = common.BitLenToByteLen(bits.Len64(cell.Nonce))
   437  	}
   438  
   439  	var structLength = uint(balanceBytes + nonceBytes + 2)
   440  	structLength += 66 // Two 32-byte arrays + 2 prefixes
   441  
   442  	var pos int
   443  	if structLength < 56 {
   444  		buffer[0] = byte(192 + structLength)
   445  		pos = 1
   446  	} else {
   447  		lengthBytes := common.BitLenToByteLen(bits.Len(structLength))
   448  		buffer[0] = byte(247 + lengthBytes)
   449  
   450  		for i := lengthBytes; i > 0; i-- {
   451  			buffer[i] = byte(structLength)
   452  			structLength >>= 8
   453  		}
   454  
   455  		pos = lengthBytes + 1
   456  	}
   457  
   458  	// Encoding nonce
   459  	if cell.Nonce < 128 && cell.Nonce != 0 {
   460  		buffer[pos] = byte(cell.Nonce)
   461  	} else {
   462  		buffer[pos] = byte(128 + nonceBytes)
   463  		var nonce = cell.Nonce
   464  		for i := nonceBytes; i > 0; i-- {
   465  			buffer[pos+i] = byte(nonce)
   466  			nonce >>= 8
   467  		}
   468  	}
   469  	pos += 1 + nonceBytes
   470  
   471  	// Encoding balance
   472  	if cell.Balance.LtUint64(128) && !cell.Balance.IsZero() {
   473  		buffer[pos] = byte(cell.Balance.Uint64())
   474  		pos++
   475  	} else {
   476  		buffer[pos] = byte(128 + balanceBytes)
   477  		pos++
   478  		cell.Balance.WriteToSlice(buffer[pos : pos+balanceBytes])
   479  		pos += balanceBytes
   480  	}
   481  
   482  	// Encoding Root and CodeHash
   483  	buffer[pos] = 128 + 32
   484  	pos++
   485  	copy(buffer[pos:], storageRootHash[:])
   486  	pos += 32
   487  	buffer[pos] = 128 + 32
   488  	pos++
   489  	copy(buffer[pos:], cell.CodeHash[:])
   490  	pos += 32
   491  	return pos
   492  }
   493  
   494  func (bph *BinPatriciaHashed) completeLeafHash(buf, keyPrefix []byte, kp, kl, compactLen int, key []byte, compact0 byte, ni int, val rlp.RlpSerializable, singleton bool) ([]byte, error) {
   495  	totalLen := kp + kl + val.DoubleRLPLen()
   496  	var lenPrefix [4]byte
   497  	pt := rlp.GenerateStructLen(lenPrefix[:], totalLen)
   498  	embedded := !singleton && totalLen+pt < length.Hash
   499  	var writer io.Writer
   500  	if embedded {
   501  		//bph.byteArrayWriter.Setup(buf)
   502  		bph.auxBuffer.Reset()
   503  		writer = bph.auxBuffer
   504  	} else {
   505  		bph.keccak.Reset()
   506  		writer = bph.keccak
   507  	}
   508  	if _, err := writer.Write(lenPrefix[:pt]); err != nil {
   509  		return nil, err
   510  	}
   511  	if _, err := writer.Write(keyPrefix[:kp]); err != nil {
   512  		return nil, err
   513  	}
   514  	var b [1]byte
   515  	b[0] = compact0
   516  	if _, err := writer.Write(b[:]); err != nil {
   517  		return nil, err
   518  	}
   519  	for i := 1; i < compactLen; i++ {
   520  		b[0] = key[ni]*16 + key[ni+1]
   521  		if _, err := writer.Write(b[:]); err != nil {
   522  			return nil, err
   523  		}
   524  		ni += 2
   525  	}
   526  	var prefixBuf [8]byte
   527  	if err := val.ToDoubleRLP(writer, prefixBuf[:]); err != nil {
   528  		return nil, err
   529  	}
   530  	if embedded {
   531  		buf = bph.auxBuffer.Bytes()
   532  	} else {
   533  		var hashBuf [33]byte
   534  		hashBuf[0] = 0x80 + length.Hash
   535  		if _, err := bph.keccak.Read(hashBuf[1:]); err != nil {
   536  			return nil, err
   537  		}
   538  		buf = append(buf, hashBuf[:]...)
   539  	}
   540  	return buf, nil
   541  }
   542  
   543  func (bph *BinPatriciaHashed) leafHashWithKeyVal(buf, key []byte, val rlp.RlpSerializableBytes, singleton bool) ([]byte, error) {
   544  	// Compute the total length of binary representation
   545  	var kp, kl int
   546  	// Write key
   547  	var compactLen int
   548  	var ni int
   549  	var compact0 byte
   550  	compactLen = (len(key)-1)/2 + 1
   551  	if len(key)&1 == 0 {
   552  		compact0 = 0x30 + key[0] // Odd: (3<<4) + first nibble
   553  		ni = 1
   554  	} else {
   555  		compact0 = 0x20
   556  	}
   557  	var keyPrefix [1]byte
   558  	if compactLen > 1 {
   559  		keyPrefix[0] = 0x80 + byte(compactLen)
   560  		kp = 1
   561  		kl = compactLen
   562  	} else {
   563  		kl = 1
   564  	}
   565  	return bph.completeLeafHash(buf, keyPrefix[:], kp, kl, compactLen, key, compact0, ni, val, singleton)
   566  }
   567  
   568  func (bph *BinPatriciaHashed) accountLeafHashWithKey(buf, key []byte, val rlp.RlpSerializable) ([]byte, error) {
   569  	// Compute the total length of binary representation
   570  	var kp, kl int
   571  	// Write key
   572  	var compactLen int
   573  	var ni int
   574  	var compact0 byte
   575  	if hasTerm(key) {
   576  		compactLen = (len(key)-1)/2 + 1
   577  		if len(key)&1 == 0 {
   578  			compact0 = 48 + key[0] // Odd (1<<4) + first nibble
   579  			ni = 1
   580  		} else {
   581  			compact0 = 32
   582  		}
   583  	} else {
   584  		compactLen = len(key)/2 + 1
   585  		if len(key)&1 == 1 {
   586  			compact0 = 16 + key[0] // Odd (1<<4) + first nibble
   587  			ni = 1
   588  		}
   589  	}
   590  	var keyPrefix [1]byte
   591  	if compactLen > 1 {
   592  		keyPrefix[0] = byte(128 + compactLen)
   593  		kp = 1
   594  		kl = compactLen
   595  	} else {
   596  		kl = 1
   597  	}
   598  	return bph.completeLeafHash(buf, keyPrefix[:], kp, kl, compactLen, key, compact0, ni, val, true)
   599  }
   600  
   601  func (bph *BinPatriciaHashed) extensionHash(key []byte, hash []byte) ([length.Hash]byte, error) {
   602  	var hashBuf [length.Hash]byte
   603  
   604  	// Compute the total length of binary representation
   605  	var kp, kl int
   606  	// Write key
   607  	var compactLen int
   608  	var ni int
   609  	var compact0 byte
   610  	if hasTerm(key) {
   611  		compactLen = (len(key)-1)/2 + 1
   612  		if len(key)&1 == 0 {
   613  			compact0 = 0x30 + key[0] // Odd: (3<<4) + first nibble
   614  			ni = 1
   615  		} else {
   616  			compact0 = 0x20
   617  		}
   618  	} else {
   619  		compactLen = len(key)/2 + 1
   620  		if len(key)&1 == 1 {
   621  			compact0 = 0x10 + key[0] // Odd: (1<<4) + first nibble
   622  			ni = 1
   623  		}
   624  	}
   625  	var keyPrefix [1]byte
   626  	if compactLen > 1 {
   627  		keyPrefix[0] = 0x80 + byte(compactLen)
   628  		kp = 1
   629  		kl = compactLen
   630  	} else {
   631  		kl = 1
   632  	}
   633  	totalLen := kp + kl + 33
   634  	var lenPrefix [4]byte
   635  	pt := rlp.GenerateStructLen(lenPrefix[:], totalLen)
   636  	bph.keccak.Reset()
   637  	if _, err := bph.keccak.Write(lenPrefix[:pt]); err != nil {
   638  		return hashBuf, err
   639  	}
   640  	if _, err := bph.keccak.Write(keyPrefix[:kp]); err != nil {
   641  		return hashBuf, err
   642  	}
   643  	var b [1]byte
   644  	b[0] = compact0
   645  	if _, err := bph.keccak.Write(b[:]); err != nil {
   646  		return hashBuf, err
   647  	}
   648  	for i := 1; i < compactLen; i++ {
   649  		b[0] = key[ni]*16 + key[ni+1]
   650  		if _, err := bph.keccak.Write(b[:]); err != nil {
   651  			return hashBuf, err
   652  		}
   653  		ni += 2
   654  	}
   655  	b[0] = 0x80 + length.Hash
   656  	if _, err := bph.keccak.Write(b[:]); err != nil {
   657  		return hashBuf, err
   658  	}
   659  	if _, err := bph.keccak.Write(hash); err != nil {
   660  		return hashBuf, err
   661  	}
   662  	// Replace previous hash with the new one
   663  	if _, err := bph.keccak.Read(hashBuf[:]); err != nil {
   664  		return hashBuf, err
   665  	}
   666  	return hashBuf, nil
   667  }
   668  
   669  func (bph *BinPatriciaHashed) computeBinaryCellHashLen(cell *BinaryCell, depth int) int {
   670  	if cell.spl > 0 && depth >= halfKeySize {
   671  		keyLen := 128 - depth + 1 // Length of hex key with terminator character
   672  		var kp, kl int
   673  		compactLen := (keyLen-1)/2 + 1
   674  		if compactLen > 1 {
   675  			kp = 1
   676  			kl = compactLen
   677  		} else {
   678  			kl = 1
   679  		}
   680  		val := rlp.RlpSerializableBytes(cell.Storage[:cell.StorageLen])
   681  		totalLen := kp + kl + val.DoubleRLPLen()
   682  		var lenPrefix [4]byte
   683  		pt := rlp.GenerateStructLen(lenPrefix[:], totalLen)
   684  		if totalLen+pt < length.Hash {
   685  			return totalLen + pt
   686  		}
   687  	}
   688  	return length.Hash + 1
   689  }
   690  
   691  func (bph *BinPatriciaHashed) computeBinaryCellHash(cell *BinaryCell, depth int, buf []byte) ([]byte, error) {
   692  	var err error
   693  	var storageRootHash [length.Hash]byte
   694  	storageRootHashIsSet := false
   695  	if cell.spl > 0 {
   696  		var hashedKeyOffset int
   697  		if depth >= halfKeySize {
   698  			hashedKeyOffset = depth - halfKeySize
   699  		}
   700  		singleton := depth <= halfKeySize
   701  		if err := binHashKey(bph.keccak, cell.spk[bph.accountKeyLen:cell.spl], cell.downHashedKey[:], hashedKeyOffset); err != nil {
   702  			return nil, err
   703  		}
   704  		cell.downHashedKey[halfKeySize-hashedKeyOffset] = 16 // Add terminator
   705  		if singleton {
   706  			if bph.trace {
   707  				fmt.Printf("leafHashWithKeyVal(singleton) for [%x]=>[%x]\n", cell.downHashedKey[:halfKeySize-hashedKeyOffset+1], cell.Storage[:cell.StorageLen])
   708  			}
   709  			aux := make([]byte, 0, 33)
   710  			if aux, err = bph.leafHashWithKeyVal(aux, cell.downHashedKey[:halfKeySize-hashedKeyOffset+1], cell.Storage[:cell.StorageLen], true); err != nil {
   711  				return nil, err
   712  			}
   713  			storageRootHash = *(*[length.Hash]byte)(aux[1:])
   714  			storageRootHashIsSet = true
   715  		} else {
   716  			if bph.trace {
   717  				fmt.Printf("leafHashWithKeyVal for [%x]=>[%x]\n", cell.downHashedKey[:halfKeySize-hashedKeyOffset+1], cell.Storage[:cell.StorageLen])
   718  			}
   719  			return bph.leafHashWithKeyVal(buf, cell.downHashedKey[:halfKeySize-hashedKeyOffset+1], cell.Storage[:cell.StorageLen], false)
   720  		}
   721  	}
   722  	if cell.apl > 0 {
   723  		if err := binHashKey(bph.keccak, cell.apk[:cell.apl], cell.downHashedKey[:], depth); err != nil {
   724  			return nil, err
   725  		}
   726  		cell.downHashedKey[halfKeySize-depth] = 16 // Add terminator
   727  		if !storageRootHashIsSet {
   728  			if cell.extLen > 0 {
   729  				// Extension
   730  				if cell.hl > 0 {
   731  					if bph.trace {
   732  						fmt.Printf("extensionHash for [%x]=>[%x]\n", cell.extension[:cell.extLen], cell.h[:cell.hl])
   733  					}
   734  					if storageRootHash, err = bph.extensionHash(cell.extension[:cell.extLen], cell.h[:cell.hl]); err != nil {
   735  						return nil, err
   736  					}
   737  				} else {
   738  					return nil, fmt.Errorf("computeBinaryCellHash extension without hash")
   739  				}
   740  			} else if cell.hl > 0 {
   741  				storageRootHash = cell.h
   742  			} else {
   743  				storageRootHash = *(*[length.Hash]byte)(EmptyRootHash)
   744  			}
   745  		}
   746  		var valBuf [128]byte
   747  		valLen := cell.accountForHashing(valBuf[:], storageRootHash)
   748  		if bph.trace {
   749  			fmt.Printf("accountLeafHashWithKey for [%x]=>[%x]\n", bph.hashAuxBuffer[:halfKeySize+1-depth], valBuf[:valLen])
   750  		}
   751  		return bph.accountLeafHashWithKey(buf, cell.downHashedKey[:halfKeySize+1-depth], rlp.RlpEncodedBytes(valBuf[:valLen]))
   752  	}
   753  	buf = append(buf, 0x80+32)
   754  	if cell.extLen > 0 {
   755  		// Extension
   756  		if cell.hl > 0 {
   757  			if bph.trace {
   758  				fmt.Printf("extensionHash for [%x]=>[%x]\n", cell.extension[:cell.extLen], cell.h[:cell.hl])
   759  			}
   760  			var hash [length.Hash]byte
   761  			if hash, err = bph.extensionHash(cell.extension[:cell.extLen], cell.h[:cell.hl]); err != nil {
   762  				return nil, err
   763  			}
   764  			buf = append(buf, hash[:]...)
   765  		} else {
   766  			return nil, fmt.Errorf("computeBinaryCellHash extension without hash")
   767  		}
   768  	} else if cell.hl > 0 {
   769  		buf = append(buf, cell.h[:cell.hl]...)
   770  	} else {
   771  		buf = append(buf, EmptyRootHash...)
   772  	}
   773  	return buf, nil
   774  }
   775  
   776  func (bph *BinPatriciaHashed) needUnfolding(hashedKey []byte) int {
   777  	var cell *BinaryCell
   778  	var depth int
   779  	if bph.activeRows == 0 {
   780  		if bph.trace {
   781  			fmt.Printf("needUnfolding root, rootChecked = %t\n", bph.rootChecked)
   782  		}
   783  		if bph.rootChecked && bph.root.downHashedLen == 0 && bph.root.hl == 0 {
   784  			// Previously checked, empty root, no unfolding needed
   785  			return 0
   786  		}
   787  		cell = &bph.root
   788  		if cell.downHashedLen == 0 && cell.hl == 0 && !bph.rootChecked {
   789  			// Need to attempt to unfold the root
   790  			return 1
   791  		}
   792  	} else {
   793  		col := int(hashedKey[bph.currentKeyLen])
   794  		cell = &bph.grid[bph.activeRows-1][col]
   795  		depth = bph.depths[bph.activeRows-1]
   796  		if bph.trace {
   797  			fmt.Printf("needUnfolding cell (%d, %x), currentKey=[%x], depth=%d, cell.h=[%x]\n", bph.activeRows-1, col, bph.currentKey[:bph.currentKeyLen], depth, cell.h[:cell.hl])
   798  		}
   799  	}
   800  	if len(hashedKey) <= depth {
   801  		return 0
   802  	}
   803  	if cell.downHashedLen == 0 {
   804  		if cell.hl == 0 {
   805  			// cell is empty, no need to unfold further
   806  			return 0
   807  		}
   808  		// unfold branch node
   809  		return 1
   810  	}
   811  	cpl := commonPrefixLen(hashedKey[depth:], cell.downHashedKey[:cell.downHashedLen-1])
   812  	if bph.trace {
   813  		fmt.Printf("cpl=%d, cell.downHashedKey=[%x], depth=%d, hashedKey[depth:]=[%x]\n", cpl, cell.downHashedKey[:cell.downHashedLen], depth, hashedKey[depth:])
   814  	}
   815  	unfolding := cpl + 1
   816  	if depth < halfKeySize && depth+unfolding > halfKeySize {
   817  		// This is to make sure that unfolding always breaks at the level where storage subtrees start
   818  		unfolding = halfKeySize - depth
   819  		if bph.trace {
   820  			fmt.Printf("adjusted unfolding=%d\n", unfolding)
   821  		}
   822  	}
   823  	return unfolding
   824  }
   825  
   826  // unfoldBranchNode returns true if unfolding has been done
   827  func (bph *BinPatriciaHashed) unfoldBranchNode(row int, deleted bool, depth int) (bool, error) {
   828  	branchData, err := bph.branchFn(binToCompact(bph.currentKey[:bph.currentKeyLen]))
   829  	if err != nil {
   830  		return false, err
   831  	}
   832  	if !bph.rootChecked && bph.currentKeyLen == 0 && len(branchData) == 0 {
   833  		// Special case - empty or deleted root
   834  		bph.rootChecked = true
   835  		return false, nil
   836  	}
   837  	if len(branchData) == 0 {
   838  		log.Warn("got empty branch data during unfold", "row", row, "depth", depth, "deleted", deleted)
   839  	}
   840  	bph.branchBefore[row] = true
   841  	bitmap := binary.BigEndian.Uint16(branchData[0:])
   842  	pos := 2
   843  	if deleted {
   844  		// All cells come as deleted (touched but not present after)
   845  		bph.afterMap[row] = 0
   846  		bph.touchMap[row] = bitmap
   847  	} else {
   848  		bph.afterMap[row] = bitmap
   849  		bph.touchMap[row] = 0
   850  	}
   851  	//fmt.Printf("unfoldBranchNode [%x], afterMap = [%016b], touchMap = [%016b]\n", branchData, bph.afterMap[row], bph.touchMap[row])
   852  	// Loop iterating over the set bits of modMask
   853  	for bitset, j := bitmap, 0; bitset != 0; j++ {
   854  		bit := bitset & -bitset
   855  		nibble := bits.TrailingZeros16(bit)
   856  		cell := &bph.grid[row][nibble]
   857  		fieldBits := branchData[pos]
   858  		pos++
   859  		var err error
   860  		if pos, err = cell.fillFromFields(branchData, pos, PartFlags(fieldBits)); err != nil {
   861  			return false, fmt.Errorf("prefix [%x], branchData[%x]: %w", bph.currentKey[:bph.currentKeyLen], branchData, err)
   862  		}
   863  		if bph.trace {
   864  			fmt.Printf("cell (%d, %x) depth=%d, hash=[%x], a=[%x], s=[%x], ex=[%x]\n", row, nibble, depth, cell.h[:cell.hl], cell.apk[:cell.apl], cell.spk[:cell.spl], cell.extension[:cell.extLen])
   865  		}
   866  		if cell.apl > 0 {
   867  			bph.accountFn(cell.apk[:cell.apl], cell)
   868  			if bph.trace {
   869  				fmt.Printf("accountFn[%x] return balance=%d, nonce=%d code=%x\n", cell.apk[:cell.apl], &cell.Balance, cell.Nonce, cell.CodeHash[:])
   870  			}
   871  		}
   872  		if cell.spl > 0 {
   873  			bph.storageFn(cell.spk[:cell.spl], cell)
   874  		}
   875  		if err = cell.deriveHashedKeys(depth, bph.keccak, bph.accountKeyLen); err != nil {
   876  			return false, err
   877  		}
   878  		bitset ^= bit
   879  	}
   880  	return true, nil
   881  }
   882  
   883  func (bph *BinPatriciaHashed) unfold(hashedKey []byte, unfolding int) error {
   884  	if bph.trace {
   885  		fmt.Printf("unfold %d: activeRows: %d\n", unfolding, bph.activeRows)
   886  	}
   887  	var upCell *BinaryCell
   888  	var touched, present bool
   889  	var col byte
   890  	var upDepth, depth int
   891  	if bph.activeRows == 0 {
   892  		if bph.rootChecked && bph.root.hl == 0 && bph.root.downHashedLen == 0 {
   893  			// No unfolding for empty root
   894  			return nil
   895  		}
   896  		upCell = &bph.root
   897  		touched = bph.rootTouched
   898  		present = bph.rootPresent
   899  		if bph.trace {
   900  			fmt.Printf("unfold root, touched %t, present %t, column %d\n", touched, present, col)
   901  		}
   902  	} else {
   903  		upDepth = bph.depths[bph.activeRows-1]
   904  		col = hashedKey[upDepth-1]
   905  		upCell = &bph.grid[bph.activeRows-1][col]
   906  		touched = bph.touchMap[bph.activeRows-1]&(uint16(1)<<col) != 0
   907  		present = bph.afterMap[bph.activeRows-1]&(uint16(1)<<col) != 0
   908  		if bph.trace {
   909  			fmt.Printf("upCell (%d, %x), touched %t, present %t\n", bph.activeRows-1, col, touched, present)
   910  		}
   911  		bph.currentKey[bph.currentKeyLen] = col
   912  		bph.currentKeyLen++
   913  	}
   914  	row := bph.activeRows
   915  	for i := 0; i < maxChild; i++ {
   916  		bph.grid[row][i].fillEmpty()
   917  	}
   918  	bph.touchMap[row] = 0
   919  	bph.afterMap[row] = 0
   920  	bph.branchBefore[row] = false
   921  	if upCell.downHashedLen == 0 {
   922  		depth = upDepth + 1
   923  		if unfolded, err := bph.unfoldBranchNode(row, touched && !present /* deleted */, depth); err != nil {
   924  			return err
   925  		} else if !unfolded {
   926  			// Return here to prevent activeRow from being incremented
   927  			return nil
   928  		}
   929  	} else if upCell.downHashedLen >= unfolding {
   930  		depth = upDepth + unfolding
   931  		nibble := upCell.downHashedKey[unfolding-1]
   932  		if touched {
   933  			bph.touchMap[row] = uint16(1) << nibble
   934  		}
   935  		if present {
   936  			bph.afterMap[row] = uint16(1) << nibble
   937  		}
   938  		cell := &bph.grid[row][nibble]
   939  		cell.fillFromUpperCell(upCell, depth, unfolding)
   940  		if bph.trace {
   941  			fmt.Printf("cell (%d, %x) depth=%d\n", row, nibble, depth)
   942  		}
   943  		if row >= halfKeySize {
   944  			cell.apl = 0
   945  		}
   946  		if unfolding > 1 {
   947  			copy(bph.currentKey[bph.currentKeyLen:], upCell.downHashedKey[:unfolding-1])
   948  		}
   949  		bph.currentKeyLen += unfolding - 1
   950  	} else {
   951  		// upCell.downHashedLen < unfolding
   952  		depth = upDepth + upCell.downHashedLen
   953  		nibble := upCell.downHashedKey[upCell.downHashedLen-1]
   954  		if touched {
   955  			bph.touchMap[row] = uint16(1) << nibble
   956  		}
   957  		if present {
   958  			bph.afterMap[row] = uint16(1) << nibble
   959  		}
   960  		cell := &bph.grid[row][nibble]
   961  		cell.fillFromUpperCell(upCell, depth, upCell.downHashedLen)
   962  		if bph.trace {
   963  			fmt.Printf("cell (%d, %x) depth=%d\n", row, nibble, depth)
   964  		}
   965  		if row >= halfKeySize {
   966  			cell.apl = 0
   967  		}
   968  		if upCell.downHashedLen > 1 {
   969  			copy(bph.currentKey[bph.currentKeyLen:], upCell.downHashedKey[:upCell.downHashedLen-1])
   970  		}
   971  		bph.currentKeyLen += upCell.downHashedLen - 1
   972  	}
   973  	bph.depths[bph.activeRows] = depth
   974  	bph.activeRows++
   975  	return nil
   976  }
   977  
   978  func (bph *BinPatriciaHashed) needFolding(hashedKey []byte) bool {
   979  	return !bytes.HasPrefix(hashedKey, bph.currentKey[:bph.currentKeyLen])
   980  }
   981  
   982  // The purpose of fold is to reduce hph.currentKey[:hph.currentKeyLen]. It should be invoked
   983  // until that current key becomes a prefix of hashedKey that we will proccess next
   984  // (in other words until the needFolding function returns 0)
   985  func (bph *BinPatriciaHashed) fold() (branchData BranchData, updateKey []byte, err error) {
   986  	updateKeyLen := bph.currentKeyLen
   987  	if bph.activeRows == 0 {
   988  		return nil, nil, fmt.Errorf("cannot fold - no active rows")
   989  	}
   990  	if bph.trace {
   991  		fmt.Printf("fold: activeRows: %d, currentKey: [%x], touchMap: %016b, afterMap: %016b\n", bph.activeRows, bph.currentKey[:bph.currentKeyLen], bph.touchMap[bph.activeRows-1], bph.afterMap[bph.activeRows-1])
   992  	}
   993  	// Move information to the row above
   994  	row := bph.activeRows - 1
   995  	var upBinaryCell *BinaryCell
   996  	var col int
   997  	var upDepth int
   998  	if bph.activeRows == 1 {
   999  		if bph.trace {
  1000  			fmt.Printf("upcell is root\n")
  1001  		}
  1002  		upBinaryCell = &bph.root
  1003  	} else {
  1004  		upDepth = bph.depths[bph.activeRows-2]
  1005  		col = int(bph.currentKey[upDepth-1])
  1006  		if bph.trace {
  1007  			fmt.Printf("upcell is (%d x %x), upDepth=%d\n", row-1, col, upDepth)
  1008  		}
  1009  		upBinaryCell = &bph.grid[row-1][col]
  1010  	}
  1011  
  1012  	depth := bph.depths[bph.activeRows-1]
  1013  	updateKey = binToCompact(bph.currentKey[:updateKeyLen])
  1014  	partsCount := bits.OnesCount16(bph.afterMap[row])
  1015  
  1016  	if bph.trace {
  1017  		fmt.Printf("touchMap[%d]=%016b, afterMap[%d]=%016b\n", row, bph.touchMap[row], row, bph.afterMap[row])
  1018  	}
  1019  	switch partsCount {
  1020  	case 0:
  1021  		// Everything deleted
  1022  		if bph.touchMap[row] != 0 {
  1023  			if row == 0 {
  1024  				// Root is deleted because the tree is empty
  1025  				bph.rootTouched = true
  1026  				bph.rootPresent = false
  1027  			} else if upDepth == halfKeySize {
  1028  				// Special case - all storage items of an account have been deleted, but it does not automatically delete the account, just makes it empty storage
  1029  				// Therefore we are not propagating deletion upwards, but turn it into a modification
  1030  				bph.touchMap[row-1] |= uint16(1) << col
  1031  			} else {
  1032  				// Deletion is propagated upwards
  1033  				bph.touchMap[row-1] |= uint16(1) << col
  1034  				bph.afterMap[row-1] &^= uint16(1) << col
  1035  			}
  1036  		}
  1037  		upBinaryCell.hl = 0
  1038  		upBinaryCell.apl = 0
  1039  		upBinaryCell.spl = 0
  1040  		upBinaryCell.extLen = 0
  1041  		upBinaryCell.downHashedLen = 0
  1042  		if bph.branchBefore[row] {
  1043  			branchData, _, err = EncodeBranch(0, bph.touchMap[row], 0, func(nibble int, skip bool) (*Cell, error) { return nil, nil })
  1044  			if err != nil {
  1045  				return nil, updateKey, fmt.Errorf("failed to encode leaf node update: %w", err)
  1046  			}
  1047  		}
  1048  		bph.activeRows--
  1049  		if upDepth > 0 {
  1050  			bph.currentKeyLen = upDepth - 1
  1051  		} else {
  1052  			bph.currentKeyLen = 0
  1053  		}
  1054  	case 1:
  1055  		// Leaf or extension node
  1056  		if bph.touchMap[row] != 0 {
  1057  			// any modifications
  1058  			if row == 0 {
  1059  				bph.rootTouched = true
  1060  			} else {
  1061  				// Modifiction is propagated upwards
  1062  				bph.touchMap[row-1] |= uint16(1) << col
  1063  			}
  1064  		}
  1065  		nibble := bits.TrailingZeros16(bph.afterMap[row])
  1066  		cell := &bph.grid[row][nibble]
  1067  		upBinaryCell.extLen = 0
  1068  		upBinaryCell.fillFromLowerBinaryCell(cell, depth, bph.currentKey[upDepth:bph.currentKeyLen], nibble)
  1069  		// Delete if it existed
  1070  		if bph.branchBefore[row] {
  1071  			//branchData, _, err = bph.EncodeBranchDirectAccess(0, row, depth)
  1072  			branchData, _, err = EncodeBranch(0, bph.touchMap[row], 0, func(nibble int, skip bool) (*Cell, error) { return nil, nil })
  1073  			if err != nil {
  1074  				return nil, updateKey, fmt.Errorf("failed to encode leaf node update: %w", err)
  1075  			}
  1076  		}
  1077  		bph.activeRows--
  1078  		if upDepth > 0 {
  1079  			bph.currentKeyLen = upDepth - 1
  1080  		} else {
  1081  			bph.currentKeyLen = 0
  1082  		}
  1083  	default:
  1084  		// Branch node
  1085  		if bph.touchMap[row] != 0 {
  1086  			// any modifications
  1087  			if row == 0 {
  1088  				bph.rootTouched = true
  1089  			} else {
  1090  				// Modifiction is propagated upwards
  1091  				bph.touchMap[row-1] |= uint16(1) << col
  1092  			}
  1093  		}
  1094  		bitmap := bph.touchMap[row] & bph.afterMap[row]
  1095  		if !bph.branchBefore[row] {
  1096  			// There was no branch node before, so we need to touch even the singular child that existed
  1097  			bph.touchMap[row] |= bph.afterMap[row]
  1098  			bitmap |= bph.afterMap[row]
  1099  		}
  1100  		// Calculate total length of all hashes
  1101  		totalBranchLen := 17 - partsCount // For every empty cell, one byte
  1102  		for bitset, j := bph.afterMap[row], 0; bitset != 0; j++ {
  1103  			bit := bitset & -bitset
  1104  			nibble := bits.TrailingZeros16(bit)
  1105  			cell := &bph.grid[row][nibble]
  1106  			totalBranchLen += bph.computeBinaryCellHashLen(cell, depth)
  1107  			bitset ^= bit
  1108  		}
  1109  
  1110  		bph.keccak2.Reset()
  1111  		pt := rlp.GenerateStructLen(bph.hashAuxBuffer[:], totalBranchLen)
  1112  		if _, err := bph.keccak2.Write(bph.hashAuxBuffer[:pt]); err != nil {
  1113  			return nil, nil, err
  1114  		}
  1115  
  1116  		b := [...]byte{0x80}
  1117  		cellGetter := func(nibble int, skip bool) (*Cell, error) {
  1118  			if skip {
  1119  				if _, err := bph.keccak2.Write(b[:]); err != nil {
  1120  					return nil, fmt.Errorf("failed to write empty nibble to hash: %w", err)
  1121  				}
  1122  				if bph.trace {
  1123  					fmt.Printf("%x: empty(%d,%x)\n", nibble, row, nibble)
  1124  				}
  1125  				return nil, nil
  1126  			}
  1127  			cell := &bph.grid[row][nibble]
  1128  			cellHash, err := bph.computeBinaryCellHash(cell, depth, bph.hashAuxBuffer[:0])
  1129  			if err != nil {
  1130  				return nil, err
  1131  			}
  1132  			if bph.trace {
  1133  				fmt.Printf("%x: computeBinaryCellHash(%d,%x,depth=%d)=[%x]\n", nibble, row, nibble, depth, cellHash)
  1134  			}
  1135  			if _, err := bph.keccak2.Write(cellHash); err != nil {
  1136  				return nil, err
  1137  			}
  1138  
  1139  			// TODO extension and downHashedKey should be encoded to hex format and vice versa, data loss due to array sizes
  1140  			return cell.unwrapToHexCell(), nil
  1141  		}
  1142  
  1143  		var lastNibble int
  1144  		var err error
  1145  		_ = cellGetter
  1146  
  1147  		//branchData, lastNibble, err = bph.EncodeBranchDirectAccess(bitmap, row, depth, branchData)
  1148  		branchData, lastNibble, err = EncodeBranch(bitmap, bph.touchMap[row], bph.afterMap[row], cellGetter)
  1149  		if err != nil {
  1150  			return nil, nil, fmt.Errorf("failed to encode branch update: %w", err)
  1151  		}
  1152  		for i := lastNibble; i <= maxChild; i++ {
  1153  			if _, err := bph.keccak2.Write(b[:]); err != nil {
  1154  				return nil, nil, err
  1155  			}
  1156  			if bph.trace {
  1157  				fmt.Printf("%x: empty(%d,%x)\n", i, row, i)
  1158  			}
  1159  		}
  1160  		upBinaryCell.extLen = depth - upDepth - 1
  1161  		upBinaryCell.downHashedLen = upBinaryCell.extLen
  1162  		if upBinaryCell.extLen > 0 {
  1163  			copy(upBinaryCell.extension[:], bph.currentKey[upDepth:bph.currentKeyLen])
  1164  			copy(upBinaryCell.downHashedKey[:], bph.currentKey[upDepth:bph.currentKeyLen])
  1165  		}
  1166  		if depth < halfKeySize {
  1167  			upBinaryCell.apl = 0
  1168  		}
  1169  		upBinaryCell.spl = 0
  1170  		upBinaryCell.hl = 32
  1171  		if _, err := bph.keccak2.Read(upBinaryCell.h[:]); err != nil {
  1172  			return nil, nil, err
  1173  		}
  1174  		if bph.trace {
  1175  			fmt.Printf("} [%x]\n", upBinaryCell.h[:])
  1176  		}
  1177  		bph.activeRows--
  1178  		if upDepth > 0 {
  1179  			bph.currentKeyLen = upDepth - 1
  1180  		} else {
  1181  			bph.currentKeyLen = 0
  1182  		}
  1183  	}
  1184  	if branchData != nil {
  1185  		if bph.trace {
  1186  			fmt.Printf("fold: update key: %x, branchData: [%x]\n", CompactedKeyToHex(updateKey), branchData)
  1187  		}
  1188  	}
  1189  	return branchData, updateKey, nil
  1190  }
  1191  
  1192  func (bph *BinPatriciaHashed) deleteBinaryCell(hashedKey []byte) {
  1193  	if bph.trace {
  1194  		fmt.Printf("deleteBinaryCell, activeRows = %d\n", bph.activeRows)
  1195  	}
  1196  	var cell *BinaryCell
  1197  	if bph.activeRows == 0 {
  1198  		// Remove the root
  1199  		cell = &bph.root
  1200  		bph.rootTouched = true
  1201  		bph.rootPresent = false
  1202  	} else {
  1203  		row := bph.activeRows - 1
  1204  		if bph.depths[row] < len(hashedKey) {
  1205  			if bph.trace {
  1206  				fmt.Printf("deleteBinaryCell skipping spurious delete depth=%d, len(hashedKey)=%d\n", bph.depths[row], len(hashedKey))
  1207  			}
  1208  			return
  1209  		}
  1210  		col := int(hashedKey[bph.currentKeyLen])
  1211  		cell = &bph.grid[row][col]
  1212  		if bph.afterMap[row]&(uint16(1)<<col) != 0 {
  1213  			// Prevent "spurios deletions", i.e. deletion of absent items
  1214  			bph.touchMap[row] |= uint16(1) << col
  1215  			bph.afterMap[row] &^= uint16(1) << col
  1216  			if bph.trace {
  1217  				fmt.Printf("deleteBinaryCell setting (%d, %x)\n", row, col)
  1218  			}
  1219  		} else {
  1220  			if bph.trace {
  1221  				fmt.Printf("deleteBinaryCell ignoring (%d, %x)\n", row, col)
  1222  			}
  1223  		}
  1224  	}
  1225  	cell.extLen = 0
  1226  	cell.Balance.Clear()
  1227  	copy(cell.CodeHash[:], EmptyCodeHash)
  1228  	cell.Nonce = 0
  1229  }
  1230  
  1231  func (bph *BinPatriciaHashed) updateBinaryCell(plainKey, hashedKey []byte) *BinaryCell {
  1232  	var cell *BinaryCell
  1233  	var col, depth int
  1234  	if bph.activeRows == 0 {
  1235  		cell = &bph.root
  1236  		bph.rootTouched, bph.rootPresent = true, true
  1237  	} else {
  1238  		row := bph.activeRows - 1
  1239  		depth = bph.depths[row]
  1240  		col = int(hashedKey[bph.currentKeyLen])
  1241  		cell = &bph.grid[row][col]
  1242  		bph.touchMap[row] |= uint16(1) << col
  1243  		bph.afterMap[row] |= uint16(1) << col
  1244  		if bph.trace {
  1245  			fmt.Printf("updateBinaryCell setting (%d, %x), depth=%d\n", row, col, depth)
  1246  		}
  1247  	}
  1248  	if cell.downHashedLen == 0 {
  1249  		copy(cell.downHashedKey[:], hashedKey[depth:])
  1250  		cell.downHashedLen = len(hashedKey) - depth
  1251  		if bph.trace {
  1252  			fmt.Printf("set downHasheKey=[%x]\n", cell.downHashedKey[:cell.downHashedLen])
  1253  		}
  1254  	} else {
  1255  		if bph.trace {
  1256  			fmt.Printf("left downHasheKey=[%x]\n", cell.downHashedKey[:cell.downHashedLen])
  1257  		}
  1258  	}
  1259  	if len(hashedKey) == halfKeySize { // set account key
  1260  		cell.apl = len(plainKey)
  1261  		copy(cell.apk[:], plainKey)
  1262  	} else { // set storage key
  1263  		cell.spl = len(plainKey)
  1264  		copy(cell.spk[:], plainKey)
  1265  	}
  1266  	return cell
  1267  }
  1268  
  1269  func (bph *BinPatriciaHashed) RootHash() ([]byte, error) {
  1270  	hash, err := bph.computeBinaryCellHash(&bph.root, 0, nil)
  1271  	if err != nil {
  1272  		return nil, err
  1273  	}
  1274  	return hash[1:], nil // first byte is 128+hash_len
  1275  }
  1276  
  1277  func (bph *BinPatriciaHashed) ReviewKeys(plainKeys, hashedKeys [][]byte) (rootHash []byte, branchNodeUpdates map[string]BranchData, err error) {
  1278  	branchNodeUpdates = make(map[string]BranchData)
  1279  
  1280  	stagedBinaryCell := new(BinaryCell)
  1281  	for i, hashedKey := range hashedKeys {
  1282  		plainKey := plainKeys[i]
  1283  		hashedKey = hexToBin(hashedKey)
  1284  		if bph.trace {
  1285  			fmt.Printf("plainKey=[%x], hashedKey=[%x], currentKey=[%x]\n", plainKey, hashedKey, bph.currentKey[:bph.currentKeyLen])
  1286  		}
  1287  		// Keep folding until the currentKey is the prefix of the key we modify
  1288  		for bph.needFolding(hashedKey) {
  1289  			if branchData, updateKey, err := bph.fold(); err != nil {
  1290  				return nil, nil, fmt.Errorf("fold: %w", err)
  1291  			} else if branchData != nil {
  1292  				branchNodeUpdates[string(updateKey)] = branchData
  1293  			}
  1294  		}
  1295  		// Now unfold until we step on an empty cell
  1296  		for unfolding := bph.needUnfolding(hashedKey); unfolding > 0; unfolding = bph.needUnfolding(hashedKey) {
  1297  			if err := bph.unfold(hashedKey, unfolding); err != nil {
  1298  				return nil, nil, fmt.Errorf("unfold: %w", err)
  1299  			}
  1300  		}
  1301  
  1302  		// Update the cell
  1303  		stagedBinaryCell.fillEmpty()
  1304  		if len(plainKey) == bph.accountKeyLen {
  1305  			if err := bph.accountFn(plainKey, stagedBinaryCell); err != nil {
  1306  				return nil, nil, fmt.Errorf("accountFn for key %x failed: %w", plainKey, err)
  1307  			}
  1308  			if !stagedBinaryCell.Delete {
  1309  				cell := bph.updateBinaryCell(plainKey, hashedKey)
  1310  				cell.setAccountFields(stagedBinaryCell.CodeHash[:], &stagedBinaryCell.Balance, stagedBinaryCell.Nonce)
  1311  
  1312  				if bph.trace {
  1313  					fmt.Printf("accountFn reading key %x => balance=%v nonce=%v codeHash=%x\n", cell.apk, cell.Balance.Uint64(), cell.Nonce, cell.CodeHash)
  1314  				}
  1315  			}
  1316  		} else {
  1317  			if err = bph.storageFn(plainKey, stagedBinaryCell); err != nil {
  1318  				return nil, nil, fmt.Errorf("storageFn for key %x failed: %w", plainKey, err)
  1319  			}
  1320  			if !stagedBinaryCell.Delete {
  1321  				bph.updateBinaryCell(plainKey, hashedKey).setStorage(stagedBinaryCell.Storage[:stagedBinaryCell.StorageLen])
  1322  				if bph.trace {
  1323  					fmt.Printf("storageFn reading key %x => %x\n", plainKey, stagedBinaryCell.Storage[:stagedBinaryCell.StorageLen])
  1324  				}
  1325  			}
  1326  		}
  1327  
  1328  		if stagedBinaryCell.Delete {
  1329  			if bph.trace {
  1330  				fmt.Printf("delete cell %x hash %x\n", plainKey, hashedKey)
  1331  			}
  1332  			bph.deleteBinaryCell(hashedKey)
  1333  		}
  1334  	}
  1335  	// Folding everything up to the root
  1336  	for bph.activeRows > 0 {
  1337  		if branchData, updateKey, err := bph.fold(); err != nil {
  1338  			return nil, nil, fmt.Errorf("final fold: %w", err)
  1339  		} else if branchData != nil {
  1340  			branchNodeUpdates[string(updateKey)] = branchData
  1341  		}
  1342  	}
  1343  
  1344  	rootHash, err = bph.RootHash()
  1345  	if err != nil {
  1346  		return nil, branchNodeUpdates, fmt.Errorf("root hash evaluation failed: %w", err)
  1347  	}
  1348  	return rootHash, branchNodeUpdates, nil
  1349  }
  1350  
  1351  func (bph *BinPatriciaHashed) SetTrace(trace bool) { bph.trace = trace }
  1352  
  1353  func (bph *BinPatriciaHashed) Variant() TrieVariant { return VariantBinPatriciaTrie }
  1354  
  1355  // Reset allows BinPatriciaHashed instance to be reused for the new commitment calculation
  1356  func (bph *BinPatriciaHashed) Reset() {
  1357  	bph.rootChecked = false
  1358  	bph.root.hl = 0
  1359  	bph.root.downHashedLen = 0
  1360  	bph.root.apl = 0
  1361  	bph.root.spl = 0
  1362  	bph.root.extLen = 0
  1363  	copy(bph.root.CodeHash[:], EmptyCodeHash)
  1364  	bph.root.StorageLen = 0
  1365  	bph.root.Balance.Clear()
  1366  	bph.root.Nonce = 0
  1367  	bph.rootTouched = false
  1368  	bph.rootPresent = true
  1369  }
  1370  
  1371  func (bph *BinPatriciaHashed) ResetFns(
  1372  	branchFn func(prefix []byte) ([]byte, error),
  1373  	accountFn func(plainKey []byte, cell *Cell) error,
  1374  	storageFn func(plainKey []byte, cell *Cell) error,
  1375  ) {
  1376  	bph.branchFn = branchFn
  1377  	bph.accountFn = wrapAccountStorageFn(accountFn)
  1378  	bph.storageFn = wrapAccountStorageFn(storageFn)
  1379  }
  1380  
  1381  func (c *BinaryCell) bytes() []byte {
  1382  	var pos = 1
  1383  	size := 1 + c.hl + 1 + c.apl + c.spl + 1 + c.downHashedLen + 1 + c.extLen + 1 // max size
  1384  	buf := make([]byte, size)
  1385  
  1386  	var flags uint8
  1387  	if c.hl != 0 {
  1388  		flags |= 1
  1389  		buf[pos] = byte(c.hl)
  1390  		pos++
  1391  		copy(buf[pos:pos+c.hl], c.h[:])
  1392  		pos += c.hl
  1393  	}
  1394  	if c.apl != 0 {
  1395  		flags |= 2
  1396  		buf[pos] = byte(c.hl)
  1397  		pos++
  1398  		copy(buf[pos:pos+c.apl], c.apk[:])
  1399  		pos += c.apl
  1400  	}
  1401  	if c.spl != 0 {
  1402  		flags |= 4
  1403  		buf[pos] = byte(c.spl)
  1404  		pos++
  1405  		copy(buf[pos:pos+c.spl], c.spk[:])
  1406  		pos += c.spl
  1407  	}
  1408  	if c.downHashedLen != 0 {
  1409  		flags |= 8
  1410  		buf[pos] = byte(c.downHashedLen)
  1411  		pos++
  1412  		copy(buf[pos:pos+c.downHashedLen], c.downHashedKey[:])
  1413  		pos += c.downHashedLen
  1414  	}
  1415  	if c.extLen != 0 {
  1416  		flags |= 16
  1417  		buf[pos] = byte(c.extLen)
  1418  		pos++
  1419  		copy(buf[pos:pos+c.downHashedLen], c.downHashedKey[:])
  1420  		//pos += c.downHashedLen
  1421  	}
  1422  	buf[0] = flags
  1423  	return buf
  1424  }
  1425  
  1426  func (c *BinaryCell) decodeBytes(buf []byte) error {
  1427  	if len(buf) < 1 {
  1428  		return fmt.Errorf("invalid buffer size to contain BinaryCell (at least 1 byte expected)")
  1429  	}
  1430  	c.fillEmpty()
  1431  
  1432  	var pos int
  1433  	flags := buf[pos]
  1434  	pos++
  1435  
  1436  	if flags&1 != 0 {
  1437  		c.hl = int(buf[pos])
  1438  		pos++
  1439  		copy(c.h[:], buf[pos:pos+c.hl])
  1440  		pos += c.hl
  1441  	}
  1442  	if flags&2 != 0 {
  1443  		c.apl = int(buf[pos])
  1444  		pos++
  1445  		copy(c.apk[:], buf[pos:pos+c.apl])
  1446  		pos += c.apl
  1447  	}
  1448  	if flags&4 != 0 {
  1449  		c.spl = int(buf[pos])
  1450  		pos++
  1451  		copy(c.spk[:], buf[pos:pos+c.spl])
  1452  		pos += c.spl
  1453  	}
  1454  	if flags&8 != 0 {
  1455  		c.downHashedLen = int(buf[pos])
  1456  		pos++
  1457  		copy(c.downHashedKey[:], buf[pos:pos+c.downHashedLen])
  1458  		pos += c.downHashedLen
  1459  	}
  1460  	if flags&16 != 0 {
  1461  		c.extLen = int(buf[pos])
  1462  		pos++
  1463  		copy(c.extension[:], buf[pos:pos+c.extLen])
  1464  		//pos += c.extLen
  1465  	}
  1466  	return nil
  1467  }
  1468  
  1469  // Encode current state of hph into bytes
  1470  func (bph *BinPatriciaHashed) EncodeCurrentState(buf []byte) ([]byte, error) {
  1471  	s := binState{
  1472  		CurrentKeyLen: int16(bph.currentKeyLen),
  1473  		RootChecked:   bph.rootChecked,
  1474  		RootTouched:   bph.rootTouched,
  1475  		RootPresent:   bph.rootPresent,
  1476  		Root:          make([]byte, 0),
  1477  	}
  1478  
  1479  	s.Root = bph.root.bytes()
  1480  	copy(s.CurrentKey[:], bph.currentKey[:])
  1481  	copy(s.Depths[:], bph.depths[:])
  1482  	copy(s.BranchBefore[:], bph.branchBefore[:])
  1483  	copy(s.TouchMap[:], bph.touchMap[:])
  1484  	copy(s.AfterMap[:], bph.afterMap[:])
  1485  
  1486  	return s.Encode(buf)
  1487  }
  1488  
  1489  // buf expected to be encoded hph state. Decode state and set up hph to that state.
  1490  func (bph *BinPatriciaHashed) SetState(buf []byte) error {
  1491  	if bph.activeRows != 0 {
  1492  		return fmt.Errorf("has active rows, could not reset state")
  1493  	}
  1494  
  1495  	var s state
  1496  	if err := s.Decode(buf); err != nil {
  1497  		return err
  1498  	}
  1499  
  1500  	bph.Reset()
  1501  
  1502  	if err := bph.root.decodeBytes(s.Root); err != nil {
  1503  		return err
  1504  	}
  1505  
  1506  	bph.currentKeyLen = int(s.CurrentKeyLen)
  1507  	bph.rootChecked = s.RootChecked
  1508  	bph.rootTouched = s.RootTouched
  1509  	bph.rootPresent = s.RootPresent
  1510  
  1511  	copy(bph.currentKey[:], s.CurrentKey[:])
  1512  	copy(bph.depths[:], s.Depths[:])
  1513  	copy(bph.branchBefore[:], s.BranchBefore[:])
  1514  	copy(bph.touchMap[:], s.TouchMap[:])
  1515  	copy(bph.afterMap[:], s.AfterMap[:])
  1516  
  1517  	return nil
  1518  }
  1519  
  1520  func (bph *BinPatriciaHashed) ProcessUpdates(plainKeys, hashedKeys [][]byte, updates []Update) (rootHash []byte, branchNodeUpdates map[string]BranchData, err error) {
  1521  	branchNodeUpdates = make(map[string]BranchData)
  1522  
  1523  	for i, plainKey := range plainKeys {
  1524  		hashedKey := hashedKeys[i]
  1525  		if bph.trace {
  1526  			fmt.Printf("plainKey=[%x], hashedKey=[%x], currentKey=[%x]\n", plainKey, hashedKey, bph.currentKey[:bph.currentKeyLen])
  1527  		}
  1528  		// Keep folding until the currentKey is the prefix of the key we modify
  1529  		for bph.needFolding(hashedKey) {
  1530  			if branchData, updateKey, err := bph.fold(); err != nil {
  1531  				return nil, nil, fmt.Errorf("fold: %w", err)
  1532  			} else if branchData != nil {
  1533  				branchNodeUpdates[string(updateKey)] = branchData
  1534  			}
  1535  		}
  1536  		// Now unfold until we step on an empty cell
  1537  		for unfolding := bph.needUnfolding(hashedKey); unfolding > 0; unfolding = bph.needUnfolding(hashedKey) {
  1538  			if err := bph.unfold(hashedKey, unfolding); err != nil {
  1539  				return nil, nil, fmt.Errorf("unfold: %w", err)
  1540  			}
  1541  		}
  1542  
  1543  		update := updates[i]
  1544  		// Update the cell
  1545  		if update.Flags == DeleteUpdate {
  1546  			bph.deleteBinaryCell(hashedKey)
  1547  			if bph.trace {
  1548  				fmt.Printf("key %x deleted\n", plainKey)
  1549  			}
  1550  		} else {
  1551  			cell := bph.updateBinaryCell(plainKey, hashedKey)
  1552  			if bph.trace {
  1553  				fmt.Printf("accountFn updated key %x =>", plainKey)
  1554  			}
  1555  			if update.Flags&BalanceUpdate != 0 {
  1556  				if bph.trace {
  1557  					fmt.Printf(" balance=%d", update.Balance.Uint64())
  1558  				}
  1559  				cell.Balance.Set(&update.Balance)
  1560  			}
  1561  			if update.Flags&NonceUpdate != 0 {
  1562  				if bph.trace {
  1563  					fmt.Printf(" nonce=%d", update.Nonce)
  1564  				}
  1565  				cell.Nonce = update.Nonce
  1566  			}
  1567  			if update.Flags&CodeUpdate != 0 {
  1568  				if bph.trace {
  1569  					fmt.Printf(" codeHash=%x", update.CodeHashOrStorage)
  1570  				}
  1571  				copy(cell.CodeHash[:], update.CodeHashOrStorage[:])
  1572  			}
  1573  			if bph.trace {
  1574  				fmt.Printf("\n")
  1575  			}
  1576  			if update.Flags&StorageUpdate != 0 {
  1577  				cell.setStorage(update.CodeHashOrStorage[:update.ValLength])
  1578  				if bph.trace {
  1579  					fmt.Printf("\rstorageFn filled key %x => %x\n", plainKey, update.CodeHashOrStorage[:update.ValLength])
  1580  				}
  1581  			}
  1582  		}
  1583  	}
  1584  	// Folding everything up to the root
  1585  	for bph.activeRows > 0 {
  1586  		if branchData, updateKey, err := bph.fold(); err != nil {
  1587  			return nil, nil, fmt.Errorf("final fold: %w", err)
  1588  		} else if branchData != nil {
  1589  			branchNodeUpdates[string(updateKey)] = branchData
  1590  		}
  1591  	}
  1592  
  1593  	rootHash, err = bph.RootHash()
  1594  	if err != nil {
  1595  		return nil, branchNodeUpdates, fmt.Errorf("root hash evaluation failed: %w", err)
  1596  	}
  1597  	return rootHash, branchNodeUpdates, nil
  1598  }
  1599  
  1600  // Hashes provided key and expands resulting hash into nibbles (each byte split into two nibbles by 4 bits)
  1601  func (bph *BinPatriciaHashed) hashAndNibblizeKey2(key []byte) []byte { //nolint
  1602  	hashedKey := make([]byte, length.Hash)
  1603  
  1604  	bph.keccak.Reset()
  1605  	bph.keccak.Write(key[:length.Addr])
  1606  	copy(hashedKey[:length.Hash], bph.keccak.Sum(nil))
  1607  
  1608  	if len(key[length.Addr:]) > 0 {
  1609  		hashedKey = append(hashedKey, make([]byte, length.Hash)...)
  1610  		bph.keccak.Reset()
  1611  		bph.keccak.Write(key[length.Addr:])
  1612  		copy(hashedKey[length.Hash:], bph.keccak.Sum(nil))
  1613  	}
  1614  
  1615  	nibblized := make([]byte, len(hashedKey)*2)
  1616  	for i, b := range hashedKey {
  1617  		nibblized[i*2] = (b >> 4) & 0xf
  1618  		nibblized[i*2+1] = b & 0xf
  1619  	}
  1620  	return nibblized
  1621  }
  1622  
  1623  func binHashKey(keccak keccakState, plainKey []byte, dest []byte, hashedKeyOffset int) error {
  1624  	keccak.Reset()
  1625  	var hashBufBack [length.Hash]byte
  1626  	hashBuf := hashBufBack[:]
  1627  	if _, err := keccak.Write(plainKey); err != nil {
  1628  		return err
  1629  	}
  1630  	if _, err := keccak.Read(hashBuf); err != nil {
  1631  		return err
  1632  	}
  1633  	for k := hashedKeyOffset; k < 256; k++ {
  1634  		if hashBuf[k/8]&(1<<(7-k%8)) == 0 {
  1635  			dest[k-hashedKeyOffset] = 0
  1636  		} else {
  1637  			dest[k-hashedKeyOffset] = 1
  1638  		}
  1639  	}
  1640  	return nil
  1641  }
  1642  
  1643  func wrapAccountStorageFn(fn func([]byte, *Cell) error) func(pk []byte, bc *BinaryCell) error {
  1644  	return func(pk []byte, bc *BinaryCell) error {
  1645  		cl := bc.unwrapToHexCell()
  1646  
  1647  		if err := fn(pk, cl); err != nil {
  1648  			return err
  1649  		}
  1650  
  1651  		bc.Balance = *cl.Balance.Clone()
  1652  		bc.Nonce = cl.Nonce
  1653  		bc.StorageLen = cl.StorageLen
  1654  		bc.apl = cl.apl
  1655  		bc.spl = cl.spl
  1656  		bc.hl = cl.hl
  1657  		copy(bc.apk[:], cl.apk[:])
  1658  		copy(bc.spk[:], cl.spk[:])
  1659  		copy(bc.h[:], cl.h[:])
  1660  
  1661  		if cl.extLen > 0 {
  1662  			binExt := compactToBin(cl.extension[:cl.extLen])
  1663  			copy(bc.extension[:], binExt)
  1664  			bc.extLen = len(binExt)
  1665  		}
  1666  		if cl.downHashedLen > 0 {
  1667  			bindhk := compactToBin(cl.downHashedKey[:cl.downHashedLen])
  1668  			copy(bc.downHashedKey[:], bindhk)
  1669  			bc.downHashedLen = len(bindhk)
  1670  		}
  1671  
  1672  		copy(bc.CodeHash[:], cl.CodeHash[:])
  1673  		copy(bc.Storage[:], cl.Storage[:])
  1674  		bc.Delete = cl.Delete
  1675  		return nil
  1676  	}
  1677  }
  1678  
  1679  // represents state of the tree
  1680  type binState struct {
  1681  	TouchMap      [maxKeySize]uint16 // For each row, bitmap of cells that were either present before modification, or modified or deleted
  1682  	AfterMap      [maxKeySize]uint16 // For each row, bitmap of cells that were present after modification
  1683  	CurrentKeyLen int16
  1684  	Root          []byte // encoded root cell
  1685  	RootChecked   bool   // Set to false if it is not known whether the root is empty, set to true if it is checked
  1686  	RootTouched   bool
  1687  	RootPresent   bool
  1688  	BranchBefore  [maxKeySize]bool // For each row, whether there was a branch node in the database loaded in unfold
  1689  	CurrentKey    [maxKeySize]byte // For each row indicates which column is currently selected
  1690  	Depths        [maxKeySize]int  // For each row, the depth of cells in that row
  1691  }
  1692  
  1693  func (s *binState) Encode(buf []byte) ([]byte, error) {
  1694  	var rootFlags stateRootFlag
  1695  	if s.RootPresent {
  1696  		rootFlags |= stateRootPresent
  1697  	}
  1698  	if s.RootChecked {
  1699  		rootFlags |= stateRootChecked
  1700  	}
  1701  	if s.RootTouched {
  1702  		rootFlags |= stateRootTouched
  1703  	}
  1704  
  1705  	ee := bytes.NewBuffer(buf)
  1706  	if err := binary.Write(ee, binary.BigEndian, s.CurrentKeyLen); err != nil {
  1707  		return nil, fmt.Errorf("encode currentKeyLen: %w", err)
  1708  	}
  1709  	if err := binary.Write(ee, binary.BigEndian, int8(rootFlags)); err != nil {
  1710  		return nil, fmt.Errorf("encode rootFlags: %w", err)
  1711  	}
  1712  	if n, err := ee.Write(s.CurrentKey[:]); err != nil || n != len(s.CurrentKey) {
  1713  		return nil, fmt.Errorf("encode currentKey: %w", err)
  1714  	}
  1715  	if err := binary.Write(ee, binary.BigEndian, uint16(len(s.Root))); err != nil {
  1716  		return nil, fmt.Errorf("encode root len: %w", err)
  1717  	}
  1718  	if n, err := ee.Write(s.Root); err != nil || n != len(s.Root) {
  1719  		return nil, fmt.Errorf("encode root: %w", err)
  1720  	}
  1721  	d := make([]byte, len(s.Depths))
  1722  	for i := 0; i < len(s.Depths); i++ {
  1723  		d[i] = byte(s.Depths[i])
  1724  	}
  1725  	if n, err := ee.Write(d); err != nil || n != len(s.Depths) {
  1726  		return nil, fmt.Errorf("encode depths: %w", err)
  1727  	}
  1728  	if err := binary.Write(ee, binary.BigEndian, s.TouchMap); err != nil {
  1729  		return nil, fmt.Errorf("encode touchMap: %w", err)
  1730  	}
  1731  	if err := binary.Write(ee, binary.BigEndian, s.AfterMap); err != nil {
  1732  		return nil, fmt.Errorf("encode afterMap: %w", err)
  1733  	}
  1734  
  1735  	var before1, before2 uint64
  1736  	for i := 0; i < halfKeySize; i++ {
  1737  		if s.BranchBefore[i] {
  1738  			before1 |= 1 << i
  1739  		}
  1740  	}
  1741  	for i, j := halfKeySize, 0; i < maxKeySize; i, j = i+1, j+1 {
  1742  		if s.BranchBefore[i] {
  1743  			before2 |= 1 << j
  1744  		}
  1745  	}
  1746  	if err := binary.Write(ee, binary.BigEndian, before1); err != nil {
  1747  		return nil, fmt.Errorf("encode branchBefore_1: %w", err)
  1748  	}
  1749  	if err := binary.Write(ee, binary.BigEndian, before2); err != nil {
  1750  		return nil, fmt.Errorf("encode branchBefore_2: %w", err)
  1751  	}
  1752  	return ee.Bytes(), nil
  1753  }
  1754  
  1755  func (s *binState) Decode(buf []byte) error {
  1756  	aux := bytes.NewBuffer(buf)
  1757  	if err := binary.Read(aux, binary.BigEndian, &s.CurrentKeyLen); err != nil {
  1758  		return fmt.Errorf("currentKeyLen: %w", err)
  1759  	}
  1760  	var rootFlags stateRootFlag
  1761  	if err := binary.Read(aux, binary.BigEndian, &rootFlags); err != nil {
  1762  		return fmt.Errorf("rootFlags: %w", err)
  1763  	}
  1764  
  1765  	if rootFlags&stateRootPresent != 0 {
  1766  		s.RootPresent = true
  1767  	}
  1768  	if rootFlags&stateRootTouched != 0 {
  1769  		s.RootTouched = true
  1770  	}
  1771  	if rootFlags&stateRootChecked != 0 {
  1772  		s.RootChecked = true
  1773  	}
  1774  	if n, err := aux.Read(s.CurrentKey[:]); err != nil || n != maxKeySize {
  1775  		return fmt.Errorf("currentKey: %w", err)
  1776  	}
  1777  	var rootSize uint16
  1778  	if err := binary.Read(aux, binary.BigEndian, &rootSize); err != nil {
  1779  		return fmt.Errorf("root size: %w", err)
  1780  	}
  1781  	s.Root = make([]byte, rootSize)
  1782  	if _, err := aux.Read(s.Root); err != nil {
  1783  		return fmt.Errorf("root: %w", err)
  1784  	}
  1785  	d := make([]byte, len(s.Depths))
  1786  	if err := binary.Read(aux, binary.BigEndian, &d); err != nil {
  1787  		return fmt.Errorf("depths: %w", err)
  1788  	}
  1789  	for i := 0; i < len(s.Depths); i++ {
  1790  		s.Depths[i] = int(d[i])
  1791  	}
  1792  	if err := binary.Read(aux, binary.BigEndian, &s.TouchMap); err != nil {
  1793  		return fmt.Errorf("touchMap: %w", err)
  1794  	}
  1795  	if err := binary.Read(aux, binary.BigEndian, &s.AfterMap); err != nil {
  1796  		return fmt.Errorf("afterMap: %w", err)
  1797  	}
  1798  	var branch1, branch2 uint64
  1799  	if err := binary.Read(aux, binary.BigEndian, &branch1); err != nil {
  1800  		return fmt.Errorf("branchBefore1: %w", err)
  1801  	}
  1802  	if err := binary.Read(aux, binary.BigEndian, &branch2); err != nil {
  1803  		return fmt.Errorf("branchBefore2: %w", err)
  1804  	}
  1805  
  1806  	// TODO invalid branch encode
  1807  	for i := 0; i < halfKeySize; i++ {
  1808  		if branch1&(1<<i) != 0 {
  1809  			s.BranchBefore[i] = true
  1810  		}
  1811  	}
  1812  	for i, j := halfKeySize, 0; i < maxKeySize; i, j = i+1, j+1 {
  1813  		if branch2&(1<<j) != 0 {
  1814  			s.BranchBefore[i] = true
  1815  		}
  1816  	}
  1817  	return nil
  1818  }