2022-07-06 06:49:00 +00:00
|
|
|
package state
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"container/heap"
|
|
|
|
"encoding/binary"
|
|
|
|
"fmt"
|
2022-07-28 11:16:37 +00:00
|
|
|
"math/bits"
|
2022-07-23 17:39:08 +00:00
|
|
|
"sort"
|
2022-07-06 06:49:00 +00:00
|
|
|
"sync"
|
2022-07-23 17:39:08 +00:00
|
|
|
"unsafe"
|
2022-07-06 06:49:00 +00:00
|
|
|
|
2022-07-23 17:39:08 +00:00
|
|
|
"github.com/google/btree"
|
2022-07-06 06:49:00 +00:00
|
|
|
"github.com/holiman/uint256"
|
2022-07-23 17:39:08 +00:00
|
|
|
libcommon "github.com/ledgerwatch/erigon-lib/common"
|
2022-07-06 06:49:00 +00:00
|
|
|
"github.com/ledgerwatch/erigon-lib/kv"
|
2022-07-28 11:16:37 +00:00
|
|
|
libstate "github.com/ledgerwatch/erigon-lib/state"
|
2022-07-06 06:49:00 +00:00
|
|
|
"github.com/ledgerwatch/erigon/common"
|
|
|
|
"github.com/ledgerwatch/erigon/common/dbutils"
|
|
|
|
"github.com/ledgerwatch/erigon/core/types"
|
|
|
|
"github.com/ledgerwatch/erigon/core/types/accounts"
|
2022-07-23 17:39:08 +00:00
|
|
|
"github.com/ledgerwatch/erigon/params"
|
2022-07-06 06:49:00 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// ReadWriteSet contains ReadSet, WriteSet and BalanceIncrease of a transaction,
|
|
|
|
// which is processed by a single thread that writes into the ReconState1 and
|
|
|
|
// flushes to the database
|
|
|
|
type TxTask struct {
|
|
|
|
TxNum uint64
|
|
|
|
BlockNum uint64
|
2022-07-23 17:39:08 +00:00
|
|
|
Rules *params.Rules
|
2022-07-06 06:49:00 +00:00
|
|
|
Header *types.Header
|
|
|
|
Block *types.Block
|
|
|
|
BlockHash common.Hash
|
|
|
|
Sender *common.Address
|
|
|
|
TxIndex int // -1 for block initialisation
|
|
|
|
Final bool
|
|
|
|
Tx types.Transaction
|
|
|
|
BalanceIncreaseSet map[common.Address]uint256.Int
|
2022-07-23 17:39:08 +00:00
|
|
|
ReadLists map[string]*KvList
|
|
|
|
WriteLists map[string]*KvList
|
2022-07-28 11:16:37 +00:00
|
|
|
AccountPrevs map[string][]byte
|
|
|
|
AccountDels map[string]*accounts.Account
|
|
|
|
StoragePrevs map[string][]byte
|
|
|
|
CodePrevs map[string][]byte
|
2022-07-23 17:39:08 +00:00
|
|
|
ResultsSize int64
|
2022-07-06 06:49:00 +00:00
|
|
|
Error error
|
|
|
|
}
|
|
|
|
|
|
|
|
type TxTaskQueue []TxTask
|
|
|
|
|
|
|
|
func (h TxTaskQueue) Len() int {
|
|
|
|
return len(h)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (h TxTaskQueue) Less(i, j int) bool {
|
|
|
|
return h[i].TxNum < h[j].TxNum
|
|
|
|
}
|
|
|
|
|
|
|
|
func (h TxTaskQueue) Swap(i, j int) {
|
|
|
|
h[i], h[j] = h[j], h[i]
|
|
|
|
}
|
|
|
|
|
|
|
|
func (h *TxTaskQueue) Push(a interface{}) {
|
|
|
|
*h = append(*h, a.(TxTask))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (h *TxTaskQueue) Pop() interface{} {
|
|
|
|
c := *h
|
|
|
|
*h = c[:len(c)-1]
|
|
|
|
return c[len(c)-1]
|
|
|
|
}
|
|
|
|
|
2022-07-23 17:39:08 +00:00
|
|
|
const CodeSizeTable = "CodeSize"
|
|
|
|
|
2022-07-28 11:16:37 +00:00
|
|
|
type State22 struct {
|
2022-07-23 17:39:08 +00:00
|
|
|
lock sync.RWMutex
|
|
|
|
receiveWork *sync.Cond
|
|
|
|
triggers map[uint64]TxTask
|
|
|
|
senderTxNums map[common.Address]uint64
|
|
|
|
triggerLock sync.RWMutex
|
|
|
|
queue TxTaskQueue
|
|
|
|
queueLock sync.Mutex
|
2022-07-28 11:16:37 +00:00
|
|
|
changes map[string]*btree.BTreeG[StateItem]
|
2022-07-23 17:39:08 +00:00
|
|
|
sizeEstimate uint64
|
|
|
|
txsDone uint64
|
|
|
|
finished bool
|
|
|
|
}
|
|
|
|
|
2022-07-28 11:16:37 +00:00
|
|
|
type StateItem struct {
|
2022-07-23 17:39:08 +00:00
|
|
|
key []byte
|
|
|
|
val []byte
|
|
|
|
}
|
|
|
|
|
2022-07-28 11:16:37 +00:00
|
|
|
func stateItemLess(i, j StateItem) bool {
|
2022-07-23 17:39:08 +00:00
|
|
|
return bytes.Compare(i.key, j.key) < 0
|
|
|
|
}
|
|
|
|
|
2022-07-28 11:16:37 +00:00
|
|
|
func NewState22() *State22 {
|
|
|
|
rs := &State22{
|
2022-07-06 06:49:00 +00:00
|
|
|
triggers: map[uint64]TxTask{},
|
|
|
|
senderTxNums: map[common.Address]uint64{},
|
2022-07-28 11:16:37 +00:00
|
|
|
changes: map[string]*btree.BTreeG[StateItem]{},
|
2022-07-06 06:49:00 +00:00
|
|
|
}
|
2022-07-23 17:39:08 +00:00
|
|
|
rs.receiveWork = sync.NewCond(&rs.queueLock)
|
2022-07-06 06:49:00 +00:00
|
|
|
return rs
|
|
|
|
}
|
|
|
|
|
2022-07-28 11:16:37 +00:00
|
|
|
func (rs *State22) put(table string, key, val []byte) {
|
2022-07-06 06:49:00 +00:00
|
|
|
t, ok := rs.changes[table]
|
|
|
|
if !ok {
|
2022-07-28 11:16:37 +00:00
|
|
|
t = btree.NewG[StateItem](32, stateItemLess)
|
2022-07-06 06:49:00 +00:00
|
|
|
rs.changes[table] = t
|
|
|
|
}
|
2022-07-28 11:16:37 +00:00
|
|
|
item := StateItem{key: key, val: val}
|
2022-07-23 17:39:08 +00:00
|
|
|
t.ReplaceOrInsert(item)
|
|
|
|
rs.sizeEstimate += uint64(unsafe.Sizeof(item)) + uint64(len(key)) + uint64(len(val))
|
2022-07-06 06:49:00 +00:00
|
|
|
}
|
|
|
|
|
2022-07-28 11:16:37 +00:00
|
|
|
func (rs *State22) Get(table string, key []byte) []byte {
|
2022-07-06 06:49:00 +00:00
|
|
|
rs.lock.RLock()
|
|
|
|
defer rs.lock.RUnlock()
|
|
|
|
return rs.get(table, key)
|
|
|
|
}
|
|
|
|
|
2022-07-28 11:16:37 +00:00
|
|
|
func (rs *State22) get(table string, key []byte) []byte {
|
2022-07-06 06:49:00 +00:00
|
|
|
t, ok := rs.changes[table]
|
|
|
|
if !ok {
|
|
|
|
return nil
|
|
|
|
}
|
2022-07-28 11:16:37 +00:00
|
|
|
if i, ok := t.Get(StateItem{key: key}); ok {
|
2022-07-23 17:39:08 +00:00
|
|
|
return i.val
|
|
|
|
}
|
|
|
|
return nil
|
2022-07-06 06:49:00 +00:00
|
|
|
}
|
|
|
|
|
2022-07-28 11:16:37 +00:00
|
|
|
func (rs *State22) Flush(rwTx kv.RwTx) error {
|
2022-07-06 06:49:00 +00:00
|
|
|
rs.lock.Lock()
|
|
|
|
defer rs.lock.Unlock()
|
|
|
|
for table, t := range rs.changes {
|
2022-07-23 17:39:08 +00:00
|
|
|
var err error
|
2022-07-28 11:16:37 +00:00
|
|
|
t.Ascend(func(item StateItem) bool {
|
2022-07-23 17:39:08 +00:00
|
|
|
if len(item.val) == 0 {
|
2022-07-26 05:47:05 +00:00
|
|
|
if err = rwTx.Delete(table, item.key); err != nil {
|
2022-07-23 17:39:08 +00:00
|
|
|
return false
|
|
|
|
}
|
|
|
|
//fmt.Printf("Flush [%x]=>\n", ks)
|
|
|
|
} else {
|
|
|
|
if err = rwTx.Put(table, item.key, item.val); err != nil {
|
|
|
|
return false
|
2022-07-06 06:49:00 +00:00
|
|
|
}
|
2022-07-23 17:39:08 +00:00
|
|
|
//fmt.Printf("Flush [%x]=>[%x]\n", ks, val)
|
2022-07-06 06:49:00 +00:00
|
|
|
}
|
2022-07-23 17:39:08 +00:00
|
|
|
return true
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
return err
|
2022-07-06 06:49:00 +00:00
|
|
|
}
|
2022-07-23 17:39:08 +00:00
|
|
|
t.Clear(true)
|
2022-07-06 06:49:00 +00:00
|
|
|
}
|
|
|
|
rs.sizeEstimate = 0
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2022-07-28 11:16:37 +00:00
|
|
|
func (rs *State22) Schedule() (TxTask, bool) {
|
2022-07-23 17:39:08 +00:00
|
|
|
rs.queueLock.Lock()
|
|
|
|
defer rs.queueLock.Unlock()
|
|
|
|
for !rs.finished && rs.queue.Len() == 0 {
|
|
|
|
rs.receiveWork.Wait()
|
2022-07-06 06:49:00 +00:00
|
|
|
}
|
|
|
|
if rs.queue.Len() > 0 {
|
|
|
|
return heap.Pop(&rs.queue).(TxTask), true
|
|
|
|
}
|
|
|
|
return TxTask{}, false
|
|
|
|
}
|
|
|
|
|
2022-07-28 11:16:37 +00:00
|
|
|
func (rs *State22) RegisterSender(txTask TxTask) bool {
|
2022-07-23 17:39:08 +00:00
|
|
|
rs.triggerLock.Lock()
|
|
|
|
defer rs.triggerLock.Unlock()
|
2022-07-06 06:49:00 +00:00
|
|
|
lastTxNum, deferral := rs.senderTxNums[*txTask.Sender]
|
|
|
|
if deferral {
|
|
|
|
// Transactions with the same sender have obvious data dependency, no point running it before lastTxNum
|
|
|
|
// So we add this data dependency as a trigger
|
|
|
|
//fmt.Printf("trigger[%d] sender [%x]<=%x\n", lastTxNum, *txTask.Sender, txTask.Tx.Hash())
|
|
|
|
rs.triggers[lastTxNum] = txTask
|
|
|
|
}
|
|
|
|
//fmt.Printf("senderTxNums[%x]=%d\n", *txTask.Sender, txTask.TxNum)
|
|
|
|
rs.senderTxNums[*txTask.Sender] = txTask.TxNum
|
|
|
|
return !deferral
|
|
|
|
}
|
|
|
|
|
2022-07-28 11:16:37 +00:00
|
|
|
func (rs *State22) CommitTxNum(sender *common.Address, txNum uint64) uint64 {
|
2022-07-23 17:39:08 +00:00
|
|
|
rs.queueLock.Lock()
|
|
|
|
defer rs.queueLock.Unlock()
|
|
|
|
rs.triggerLock.Lock()
|
|
|
|
defer rs.triggerLock.Unlock()
|
|
|
|
count := uint64(0)
|
2022-07-06 06:49:00 +00:00
|
|
|
if triggered, ok := rs.triggers[txNum]; ok {
|
|
|
|
heap.Push(&rs.queue, triggered)
|
2022-07-23 17:39:08 +00:00
|
|
|
rs.receiveWork.Signal()
|
|
|
|
count++
|
2022-07-06 06:49:00 +00:00
|
|
|
delete(rs.triggers, txNum)
|
|
|
|
}
|
|
|
|
if sender != nil {
|
|
|
|
if lastTxNum, ok := rs.senderTxNums[*sender]; ok && lastTxNum == txNum {
|
|
|
|
// This is the last transaction so far with this sender, remove
|
|
|
|
delete(rs.senderTxNums, *sender)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
rs.txsDone++
|
2022-07-23 17:39:08 +00:00
|
|
|
return count
|
2022-07-06 06:49:00 +00:00
|
|
|
}
|
|
|
|
|
2022-07-28 11:16:37 +00:00
|
|
|
func (rs *State22) AddWork(txTask TxTask) {
|
2022-07-23 17:39:08 +00:00
|
|
|
txTask.BalanceIncreaseSet = nil
|
|
|
|
txTask.ReadLists = nil
|
|
|
|
txTask.WriteLists = nil
|
|
|
|
txTask.ResultsSize = 0
|
|
|
|
rs.queueLock.Lock()
|
|
|
|
defer rs.queueLock.Unlock()
|
2022-07-06 06:49:00 +00:00
|
|
|
heap.Push(&rs.queue, txTask)
|
2022-07-23 17:39:08 +00:00
|
|
|
rs.receiveWork.Signal()
|
2022-07-06 06:49:00 +00:00
|
|
|
}
|
|
|
|
|
2022-07-28 11:16:37 +00:00
|
|
|
func (rs *State22) Finish() {
|
2022-07-23 17:39:08 +00:00
|
|
|
rs.queueLock.Lock()
|
|
|
|
defer rs.queueLock.Unlock()
|
|
|
|
rs.finished = true
|
|
|
|
rs.receiveWork.Broadcast()
|
|
|
|
}
|
|
|
|
|
2022-07-28 11:16:37 +00:00
|
|
|
func serialise2(a *accounts.Account) []byte {
|
|
|
|
var l int
|
|
|
|
l++
|
|
|
|
if a.Nonce > 0 {
|
|
|
|
l += (bits.Len64(a.Nonce) + 7) / 8
|
|
|
|
}
|
|
|
|
l++
|
|
|
|
if !a.Balance.IsZero() {
|
|
|
|
l += a.Balance.ByteLen()
|
|
|
|
}
|
|
|
|
l++
|
|
|
|
if !a.IsEmptyCodeHash() {
|
|
|
|
l += 32
|
|
|
|
}
|
|
|
|
l++
|
|
|
|
if a.Incarnation > 0 {
|
|
|
|
l += (bits.Len64(a.Incarnation) + 7) / 8
|
|
|
|
}
|
|
|
|
value := make([]byte, l)
|
|
|
|
pos := 0
|
|
|
|
if a.Nonce == 0 {
|
|
|
|
value[pos] = 0
|
|
|
|
pos++
|
|
|
|
} else {
|
|
|
|
nonceBytes := (bits.Len64(a.Nonce) + 7) / 8
|
|
|
|
value[pos] = byte(nonceBytes)
|
|
|
|
var nonce = a.Nonce
|
|
|
|
for i := nonceBytes; i > 0; i-- {
|
|
|
|
value[pos+i] = byte(nonce)
|
|
|
|
nonce >>= 8
|
|
|
|
}
|
|
|
|
pos += nonceBytes + 1
|
|
|
|
}
|
|
|
|
if a.Balance.IsZero() {
|
|
|
|
value[pos] = 0
|
|
|
|
pos++
|
|
|
|
} else {
|
|
|
|
balanceBytes := a.Balance.ByteLen()
|
|
|
|
value[pos] = byte(balanceBytes)
|
|
|
|
pos++
|
|
|
|
a.Balance.WriteToSlice(value[pos : pos+balanceBytes])
|
|
|
|
pos += balanceBytes
|
|
|
|
}
|
|
|
|
if a.IsEmptyCodeHash() {
|
|
|
|
value[pos] = 0
|
|
|
|
pos++
|
|
|
|
} else {
|
|
|
|
value[pos] = 32
|
|
|
|
pos++
|
|
|
|
copy(value[pos:pos+32], a.CodeHash[:])
|
|
|
|
pos += 32
|
|
|
|
}
|
|
|
|
if a.Incarnation == 0 {
|
|
|
|
value[pos] = 0
|
|
|
|
} else {
|
|
|
|
incBytes := (bits.Len64(a.Incarnation) + 7) / 8
|
|
|
|
value[pos] = byte(incBytes)
|
|
|
|
var inc = a.Incarnation
|
|
|
|
for i := incBytes; i > 0; i-- {
|
|
|
|
value[pos+i] = byte(inc)
|
|
|
|
inc >>= 8
|
2022-07-06 06:49:00 +00:00
|
|
|
}
|
|
|
|
}
|
2022-07-28 11:16:37 +00:00
|
|
|
return value
|
|
|
|
}
|
|
|
|
|
|
|
|
func (rs *State22) Apply(emptyRemoval bool, roTx kv.Tx, txTask TxTask, agg *libstate.Aggregator22) error {
|
|
|
|
rs.lock.Lock()
|
|
|
|
defer rs.lock.Unlock()
|
|
|
|
agg.SetTxNum(txTask.TxNum)
|
2022-07-23 17:39:08 +00:00
|
|
|
for addr, increase := range txTask.BalanceIncreaseSet {
|
2022-07-28 11:16:37 +00:00
|
|
|
enc0 := rs.get(kv.PlainState, addr.Bytes())
|
|
|
|
if enc0 == nil {
|
2022-07-23 17:39:08 +00:00
|
|
|
var err error
|
2022-07-28 11:16:37 +00:00
|
|
|
enc0, err = roTx.GetOne(kv.PlainState, addr.Bytes())
|
2022-07-23 17:39:08 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
2022-07-06 06:49:00 +00:00
|
|
|
var a accounts.Account
|
2022-07-28 11:16:37 +00:00
|
|
|
if err := a.DecodeForStorage(enc0); err != nil {
|
2022-07-23 17:39:08 +00:00
|
|
|
return err
|
2022-07-06 06:49:00 +00:00
|
|
|
}
|
2022-07-28 11:16:37 +00:00
|
|
|
if len(enc0) > 0 {
|
|
|
|
// Need to convert before balance increase
|
|
|
|
enc0 = serialise2(&a)
|
|
|
|
}
|
2022-07-06 06:49:00 +00:00
|
|
|
a.Balance.Add(&a.Balance, &increase)
|
2022-07-28 11:16:37 +00:00
|
|
|
var enc1 []byte
|
2022-07-23 17:39:08 +00:00
|
|
|
if emptyRemoval && a.Nonce == 0 && a.Balance.IsZero() && a.IsEmptyCodeHash() {
|
2022-07-28 11:16:37 +00:00
|
|
|
enc1 = []byte{}
|
2022-07-23 17:39:08 +00:00
|
|
|
} else {
|
|
|
|
l := a.EncodingLengthForStorage()
|
2022-07-28 11:16:37 +00:00
|
|
|
enc1 = make([]byte, l)
|
|
|
|
a.EncodeForStorage(enc1)
|
|
|
|
}
|
|
|
|
rs.put(kv.PlainState, addr.Bytes(), enc1)
|
|
|
|
if err := agg.AddAccountPrev(addr.Bytes(), enc0); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for addrS, original := range txTask.AccountDels {
|
|
|
|
addr := []byte(addrS)
|
|
|
|
addr1 := make([]byte, len(addr)+8)
|
|
|
|
copy(addr1, addr)
|
|
|
|
binary.BigEndian.PutUint64(addr1[len(addr):], original.Incarnation)
|
|
|
|
prev := serialise2(original)
|
|
|
|
if err := agg.AddAccountPrev(addr, prev); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
codePrev := rs.get(kv.Code, original.CodeHash.Bytes())
|
|
|
|
if codePrev == nil {
|
|
|
|
var err error
|
|
|
|
codePrev, err = roTx.GetOne(kv.Code, original.CodeHash.Bytes())
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if err := agg.AddCodePrev(addr, codePrev); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
// Iterate over storage
|
|
|
|
cursor, err := roTx.Cursor(kv.PlainState)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
defer cursor.Close()
|
|
|
|
var k, v []byte
|
|
|
|
var e error
|
|
|
|
if k, v, e = cursor.Seek(addr1); err != nil {
|
|
|
|
return e
|
|
|
|
}
|
|
|
|
if !bytes.HasPrefix(k, addr1) {
|
|
|
|
k = nil
|
|
|
|
}
|
|
|
|
rs.changes[kv.PlainState].AscendGreaterOrEqual(StateItem{key: addr1}, func(item StateItem) bool {
|
|
|
|
if !bytes.HasPrefix(item.key, addr1) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
for ; e == nil && k != nil && bytes.Compare(k, item.key) <= 0; k, v, e = cursor.Next() {
|
|
|
|
if !bytes.HasPrefix(k, addr1) {
|
|
|
|
k = nil
|
|
|
|
}
|
|
|
|
if !bytes.Equal(k, item.key) {
|
|
|
|
if e = agg.AddStoragePrev(addr, libcommon.Copy(k[28:]), libcommon.Copy(v)); e != nil {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if e != nil {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
if e = agg.AddStoragePrev(addr, item.key[28:], item.val); e != nil {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
})
|
|
|
|
for ; e == nil && k != nil && bytes.HasPrefix(k, addr1); k, v, e = cursor.Next() {
|
|
|
|
if e = agg.AddStoragePrev(addr, libcommon.Copy(k[28:]), libcommon.Copy(v)); e != nil {
|
|
|
|
return e
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if e != nil {
|
|
|
|
return e
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for addrS, enc0 := range txTask.AccountPrevs {
|
|
|
|
if err := agg.AddAccountPrev([]byte(addrS), enc0); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for compositeS, val := range txTask.StoragePrevs {
|
|
|
|
composite := []byte(compositeS)
|
|
|
|
if err := agg.AddStoragePrev(composite[:20], composite[28:], val); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for addrS, val := range txTask.CodePrevs {
|
|
|
|
if err := agg.AddCodePrev([]byte(addrS), val); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if err := agg.FinishTx(); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if txTask.WriteLists == nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
for table, list := range txTask.WriteLists {
|
|
|
|
for i, key := range list.Keys {
|
|
|
|
val := list.Vals[i]
|
|
|
|
rs.put(table, key, val)
|
2022-07-23 17:39:08 +00:00
|
|
|
}
|
2022-07-06 06:49:00 +00:00
|
|
|
}
|
2022-07-23 17:39:08 +00:00
|
|
|
return nil
|
2022-07-06 06:49:00 +00:00
|
|
|
}
|
|
|
|
|
2022-07-28 11:16:37 +00:00
|
|
|
func (rs *State22) DoneCount() uint64 {
|
2022-07-06 06:49:00 +00:00
|
|
|
rs.lock.RLock()
|
|
|
|
defer rs.lock.RUnlock()
|
|
|
|
return rs.txsDone
|
|
|
|
}
|
|
|
|
|
2022-07-28 11:16:37 +00:00
|
|
|
func (rs *State22) SizeEstimate() uint64 {
|
2022-07-06 06:49:00 +00:00
|
|
|
rs.lock.RLock()
|
|
|
|
defer rs.lock.RUnlock()
|
|
|
|
return rs.sizeEstimate
|
|
|
|
}
|
|
|
|
|
2022-07-28 11:16:37 +00:00
|
|
|
func (rs *State22) ReadsValid(readLists map[string]*KvList) bool {
|
2022-07-06 06:49:00 +00:00
|
|
|
rs.lock.RLock()
|
|
|
|
defer rs.lock.RUnlock()
|
2022-07-23 17:39:08 +00:00
|
|
|
//fmt.Printf("ValidReads\n")
|
|
|
|
for table, list := range readLists {
|
|
|
|
//fmt.Printf("Table %s\n", table)
|
2022-07-28 11:16:37 +00:00
|
|
|
var t *btree.BTreeG[StateItem]
|
2022-07-23 17:39:08 +00:00
|
|
|
var ok bool
|
|
|
|
if table == CodeSizeTable {
|
|
|
|
t, ok = rs.changes[kv.Code]
|
|
|
|
} else {
|
|
|
|
t, ok = rs.changes[table]
|
|
|
|
}
|
2022-07-06 06:49:00 +00:00
|
|
|
if !ok {
|
|
|
|
continue
|
|
|
|
}
|
2022-07-23 17:39:08 +00:00
|
|
|
for i, key := range list.Keys {
|
|
|
|
val := list.Vals[i]
|
2022-07-28 11:16:37 +00:00
|
|
|
if item, ok := t.Get(StateItem{key: key}); ok {
|
2022-07-23 17:39:08 +00:00
|
|
|
//fmt.Printf("key [%x] => [%x] vs [%x]\n", key, val, rereadVal)
|
|
|
|
if table == CodeSizeTable {
|
|
|
|
if binary.BigEndian.Uint64(val) != uint64(len(item.val)) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
} else if !bytes.Equal(val, item.val) {
|
2022-07-06 06:49:00 +00:00
|
|
|
return false
|
|
|
|
}
|
2022-07-23 17:39:08 +00:00
|
|
|
} else {
|
|
|
|
//fmt.Printf("key [%x] => [%x] not present in changes\n", key, val)
|
2022-07-06 06:49:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
2022-07-23 17:39:08 +00:00
|
|
|
// KvList sort.Interface to sort write list by keys
|
|
|
|
type KvList struct {
|
|
|
|
Keys, Vals [][]byte
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l KvList) Len() int {
|
|
|
|
return len(l.Keys)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l KvList) Less(i, j int) bool {
|
|
|
|
return bytes.Compare(l.Keys[i], l.Keys[j]) < 0
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l *KvList) Swap(i, j int) {
|
|
|
|
l.Keys[i], l.Keys[j] = l.Keys[j], l.Keys[i]
|
|
|
|
l.Vals[i], l.Vals[j] = l.Vals[j], l.Vals[i]
|
|
|
|
}
|
|
|
|
|
2022-07-28 11:16:37 +00:00
|
|
|
type StateWriter22 struct {
|
|
|
|
rs *State22
|
|
|
|
txNum uint64
|
|
|
|
writeLists map[string]*KvList
|
|
|
|
accountPrevs map[string][]byte
|
|
|
|
accountDels map[string]*accounts.Account
|
|
|
|
storagePrevs map[string][]byte
|
|
|
|
codePrevs map[string][]byte
|
2022-07-06 06:49:00 +00:00
|
|
|
}
|
|
|
|
|
2022-07-28 11:16:37 +00:00
|
|
|
func NewStateWriter22(rs *State22) *StateWriter22 {
|
|
|
|
return &StateWriter22{
|
2022-07-06 06:49:00 +00:00
|
|
|
rs: rs,
|
2022-07-23 17:39:08 +00:00
|
|
|
writeLists: map[string]*KvList{
|
|
|
|
kv.PlainState: {},
|
|
|
|
kv.Code: {},
|
|
|
|
kv.PlainContractCode: {},
|
|
|
|
kv.IncarnationMap: {},
|
|
|
|
},
|
2022-07-28 11:16:37 +00:00
|
|
|
accountPrevs: map[string][]byte{},
|
|
|
|
accountDels: map[string]*accounts.Account{},
|
|
|
|
storagePrevs: map[string][]byte{},
|
|
|
|
codePrevs: map[string][]byte{},
|
2022-07-06 06:49:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-07-28 11:16:37 +00:00
|
|
|
func (w *StateWriter22) SetTxNum(txNum uint64) {
|
2022-07-06 06:49:00 +00:00
|
|
|
w.txNum = txNum
|
|
|
|
}
|
|
|
|
|
2022-07-28 11:16:37 +00:00
|
|
|
func (w *StateWriter22) ResetWriteSet() {
|
2022-07-23 17:39:08 +00:00
|
|
|
w.writeLists = map[string]*KvList{
|
|
|
|
kv.PlainState: {},
|
|
|
|
kv.Code: {},
|
|
|
|
kv.PlainContractCode: {},
|
|
|
|
kv.IncarnationMap: {},
|
|
|
|
}
|
2022-07-28 11:16:37 +00:00
|
|
|
w.accountPrevs = map[string][]byte{}
|
|
|
|
w.accountDels = map[string]*accounts.Account{}
|
|
|
|
w.storagePrevs = map[string][]byte{}
|
|
|
|
w.codePrevs = map[string][]byte{}
|
2022-07-06 06:49:00 +00:00
|
|
|
}
|
|
|
|
|
2022-07-28 11:16:37 +00:00
|
|
|
func (w *StateWriter22) WriteSet() map[string]*KvList {
|
2022-07-23 17:39:08 +00:00
|
|
|
for _, list := range w.writeLists {
|
|
|
|
sort.Sort(list)
|
|
|
|
}
|
|
|
|
return w.writeLists
|
2022-07-06 06:49:00 +00:00
|
|
|
}
|
|
|
|
|
2022-07-28 11:16:37 +00:00
|
|
|
func (w *StateWriter22) PrevAndDels() (map[string][]byte, map[string]*accounts.Account, map[string][]byte, map[string][]byte) {
|
|
|
|
return w.accountPrevs, w.accountDels, w.storagePrevs, w.codePrevs
|
|
|
|
}
|
|
|
|
|
|
|
|
func (w *StateWriter22) UpdateAccountData(address common.Address, original, account *accounts.Account) error {
|
2022-07-06 06:49:00 +00:00
|
|
|
value := make([]byte, account.EncodingLengthForStorage())
|
|
|
|
account.EncodeForStorage(value)
|
|
|
|
//fmt.Printf("account [%x]=>{Balance: %d, Nonce: %d, Root: %x, CodeHash: %x} txNum: %d\n", address, &account.Balance, account.Nonce, account.Root, account.CodeHash, w.txNum)
|
2022-07-23 17:39:08 +00:00
|
|
|
w.writeLists[kv.PlainState].Keys = append(w.writeLists[kv.PlainState].Keys, address.Bytes())
|
|
|
|
w.writeLists[kv.PlainState].Vals = append(w.writeLists[kv.PlainState].Vals, value)
|
2022-07-28 11:16:37 +00:00
|
|
|
var prev []byte
|
|
|
|
if original.Initialised {
|
|
|
|
prev = serialise2(original)
|
|
|
|
}
|
|
|
|
w.accountPrevs[string(address.Bytes())] = prev
|
2022-07-06 06:49:00 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2022-07-28 11:16:37 +00:00
|
|
|
func (w *StateWriter22) UpdateAccountCode(address common.Address, incarnation uint64, codeHash common.Hash, code []byte) error {
|
2022-07-23 17:39:08 +00:00
|
|
|
w.writeLists[kv.Code].Keys = append(w.writeLists[kv.Code].Keys, codeHash.Bytes())
|
|
|
|
w.writeLists[kv.Code].Vals = append(w.writeLists[kv.Code].Vals, code)
|
2022-07-06 06:49:00 +00:00
|
|
|
if len(code) > 0 {
|
|
|
|
//fmt.Printf("code [%x] => [%x] CodeHash: %x, txNum: %d\n", address, code, codeHash, w.txNum)
|
2022-07-23 17:39:08 +00:00
|
|
|
w.writeLists[kv.PlainContractCode].Keys = append(w.writeLists[kv.PlainContractCode].Keys, dbutils.PlainGenerateStoragePrefix(address[:], incarnation))
|
|
|
|
w.writeLists[kv.PlainContractCode].Vals = append(w.writeLists[kv.PlainContractCode].Vals, codeHash.Bytes())
|
2022-07-06 06:49:00 +00:00
|
|
|
}
|
2022-07-28 11:16:37 +00:00
|
|
|
w.codePrevs[string(address.Bytes())] = nil
|
2022-07-06 06:49:00 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2022-07-28 11:16:37 +00:00
|
|
|
func (w *StateWriter22) DeleteAccount(address common.Address, original *accounts.Account) error {
|
2022-07-23 17:39:08 +00:00
|
|
|
w.writeLists[kv.PlainState].Keys = append(w.writeLists[kv.PlainState].Keys, address.Bytes())
|
|
|
|
w.writeLists[kv.PlainState].Vals = append(w.writeLists[kv.PlainState].Vals, []byte{})
|
2022-07-06 06:49:00 +00:00
|
|
|
if original.Incarnation > 0 {
|
|
|
|
var b [8]byte
|
|
|
|
binary.BigEndian.PutUint64(b[:], original.Incarnation)
|
2022-07-23 17:39:08 +00:00
|
|
|
w.writeLists[kv.IncarnationMap].Keys = append(w.writeLists[kv.IncarnationMap].Keys, address.Bytes())
|
|
|
|
w.writeLists[kv.IncarnationMap].Vals = append(w.writeLists[kv.IncarnationMap].Vals, b[:])
|
2022-07-06 06:49:00 +00:00
|
|
|
}
|
2022-07-28 11:16:37 +00:00
|
|
|
if original.Initialised {
|
|
|
|
w.accountDels[string(address.Bytes())] = original
|
|
|
|
}
|
2022-07-06 06:49:00 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2022-07-28 11:16:37 +00:00
|
|
|
func (w *StateWriter22) WriteAccountStorage(address common.Address, incarnation uint64, key *common.Hash, original, value *uint256.Int) error {
|
2022-07-06 06:49:00 +00:00
|
|
|
if *original == *value {
|
|
|
|
return nil
|
|
|
|
}
|
2022-07-28 11:16:37 +00:00
|
|
|
composite := dbutils.PlainGenerateCompositeStorageKey(address.Bytes(), incarnation, key.Bytes())
|
|
|
|
w.writeLists[kv.PlainState].Keys = append(w.writeLists[kv.PlainState].Keys, composite)
|
2022-07-23 17:39:08 +00:00
|
|
|
w.writeLists[kv.PlainState].Vals = append(w.writeLists[kv.PlainState].Vals, value.Bytes())
|
2022-07-06 06:49:00 +00:00
|
|
|
//fmt.Printf("storage [%x] [%x] => [%x], txNum: %d\n", address, *key, v, w.txNum)
|
2022-07-28 11:16:37 +00:00
|
|
|
w.storagePrevs[string(composite)] = original.Bytes()
|
2022-07-06 06:49:00 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2022-07-28 11:16:37 +00:00
|
|
|
func (w *StateWriter22) CreateContract(address common.Address) error {
|
2022-07-06 06:49:00 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2022-07-28 11:16:37 +00:00
|
|
|
type StateReader22 struct {
|
2022-07-06 06:49:00 +00:00
|
|
|
tx kv.Tx
|
|
|
|
txNum uint64
|
|
|
|
trace bool
|
2022-07-28 11:16:37 +00:00
|
|
|
rs *State22
|
2022-07-06 06:49:00 +00:00
|
|
|
readError bool
|
|
|
|
stateTxNum uint64
|
|
|
|
composite []byte
|
2022-07-23 17:39:08 +00:00
|
|
|
readLists map[string]*KvList
|
2022-07-06 06:49:00 +00:00
|
|
|
}
|
|
|
|
|
2022-07-28 11:16:37 +00:00
|
|
|
func NewStateReader22(rs *State22) *StateReader22 {
|
|
|
|
return &StateReader22{
|
2022-07-23 17:39:08 +00:00
|
|
|
rs: rs,
|
|
|
|
readLists: map[string]*KvList{
|
|
|
|
kv.PlainState: {},
|
|
|
|
kv.Code: {},
|
|
|
|
CodeSizeTable: {},
|
|
|
|
kv.IncarnationMap: {},
|
|
|
|
},
|
|
|
|
}
|
2022-07-06 06:49:00 +00:00
|
|
|
}
|
|
|
|
|
2022-07-28 11:16:37 +00:00
|
|
|
func (r *StateReader22) SetTxNum(txNum uint64) {
|
2022-07-06 06:49:00 +00:00
|
|
|
r.txNum = txNum
|
|
|
|
}
|
|
|
|
|
2022-07-28 11:16:37 +00:00
|
|
|
func (r *StateReader22) SetTx(tx kv.Tx) {
|
2022-07-06 06:49:00 +00:00
|
|
|
r.tx = tx
|
|
|
|
}
|
|
|
|
|
2022-07-28 11:16:37 +00:00
|
|
|
func (r *StateReader22) ResetReadSet() {
|
2022-07-23 17:39:08 +00:00
|
|
|
r.readLists = map[string]*KvList{
|
|
|
|
kv.PlainState: {},
|
|
|
|
kv.Code: {},
|
|
|
|
CodeSizeTable: {},
|
|
|
|
kv.IncarnationMap: {},
|
|
|
|
}
|
2022-07-06 06:49:00 +00:00
|
|
|
}
|
|
|
|
|
2022-07-28 11:16:37 +00:00
|
|
|
func (r *StateReader22) ReadSet() map[string]*KvList {
|
2022-07-23 17:39:08 +00:00
|
|
|
for _, list := range r.readLists {
|
|
|
|
sort.Sort(list)
|
|
|
|
}
|
|
|
|
return r.readLists
|
2022-07-06 06:49:00 +00:00
|
|
|
}
|
|
|
|
|
2022-07-28 11:16:37 +00:00
|
|
|
func (r *StateReader22) SetTrace(trace bool) {
|
2022-07-06 06:49:00 +00:00
|
|
|
r.trace = trace
|
|
|
|
}
|
|
|
|
|
2022-07-28 11:16:37 +00:00
|
|
|
func (r *StateReader22) ReadAccountData(address common.Address) (*accounts.Account, error) {
|
2022-07-06 06:49:00 +00:00
|
|
|
enc := r.rs.Get(kv.PlainState, address.Bytes())
|
|
|
|
if enc == nil {
|
|
|
|
var err error
|
|
|
|
enc, err = r.tx.GetOne(kv.PlainState, address.Bytes())
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
}
|
2022-07-23 17:39:08 +00:00
|
|
|
r.readLists[kv.PlainState].Keys = append(r.readLists[kv.PlainState].Keys, address.Bytes())
|
|
|
|
r.readLists[kv.PlainState].Vals = append(r.readLists[kv.PlainState].Vals, common.CopyBytes(enc))
|
2022-07-06 06:49:00 +00:00
|
|
|
if len(enc) == 0 {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
var a accounts.Account
|
|
|
|
if err := a.DecodeForStorage(enc); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
if r.trace {
|
|
|
|
fmt.Printf("ReadAccountData [%x] => [nonce: %d, balance: %d, codeHash: %x], txNum: %d\n", address, a.Nonce, &a.Balance, a.CodeHash, r.txNum)
|
|
|
|
}
|
|
|
|
return &a, nil
|
|
|
|
}
|
|
|
|
|
2022-07-28 11:16:37 +00:00
|
|
|
func (r *StateReader22) ReadAccountStorage(address common.Address, incarnation uint64, key *common.Hash) ([]byte, error) {
|
2022-07-06 06:49:00 +00:00
|
|
|
if cap(r.composite) < 20+8+32 {
|
|
|
|
r.composite = make([]byte, 20+8+32)
|
|
|
|
} else if len(r.composite) != 20+8+32 {
|
|
|
|
r.composite = r.composite[:20+8+32]
|
|
|
|
}
|
|
|
|
copy(r.composite, address.Bytes())
|
|
|
|
binary.BigEndian.PutUint64(r.composite[20:], incarnation)
|
|
|
|
copy(r.composite[20+8:], key.Bytes())
|
|
|
|
|
|
|
|
enc := r.rs.Get(kv.PlainState, r.composite)
|
|
|
|
if enc == nil {
|
|
|
|
var err error
|
|
|
|
enc, err = r.tx.GetOne(kv.PlainState, r.composite)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
}
|
2022-07-23 17:39:08 +00:00
|
|
|
r.readLists[kv.PlainState].Keys = append(r.readLists[kv.PlainState].Keys, common.CopyBytes(r.composite))
|
|
|
|
r.readLists[kv.PlainState].Vals = append(r.readLists[kv.PlainState].Vals, common.CopyBytes(enc))
|
2022-07-06 06:49:00 +00:00
|
|
|
if r.trace {
|
|
|
|
if enc == nil {
|
|
|
|
fmt.Printf("ReadAccountStorage [%x] [%x] => [], txNum: %d\n", address, key.Bytes(), r.txNum)
|
|
|
|
} else {
|
|
|
|
fmt.Printf("ReadAccountStorage [%x] [%x] => [%x], txNum: %d\n", address, key.Bytes(), enc, r.txNum)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if enc == nil {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
return enc, nil
|
|
|
|
}
|
|
|
|
|
2022-07-28 11:16:37 +00:00
|
|
|
func (r *StateReader22) ReadAccountCode(address common.Address, incarnation uint64, codeHash common.Hash) ([]byte, error) {
|
2022-07-06 06:49:00 +00:00
|
|
|
enc := r.rs.Get(kv.Code, codeHash.Bytes())
|
|
|
|
if enc == nil {
|
|
|
|
var err error
|
|
|
|
enc, err = r.tx.GetOne(kv.Code, codeHash.Bytes())
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
}
|
2022-07-23 17:39:08 +00:00
|
|
|
r.readLists[kv.Code].Keys = append(r.readLists[kv.Code].Keys, address.Bytes())
|
|
|
|
r.readLists[kv.Code].Vals = append(r.readLists[kv.Code].Vals, common.CopyBytes(enc))
|
2022-07-06 06:49:00 +00:00
|
|
|
if r.trace {
|
|
|
|
fmt.Printf("ReadAccountCode [%x] => [%x], txNum: %d\n", address, enc, r.txNum)
|
|
|
|
}
|
|
|
|
return enc, nil
|
|
|
|
}
|
|
|
|
|
2022-07-28 11:16:37 +00:00
|
|
|
func (r *StateReader22) ReadAccountCodeSize(address common.Address, incarnation uint64, codeHash common.Hash) (int, error) {
|
2022-07-06 06:49:00 +00:00
|
|
|
enc := r.rs.Get(kv.Code, codeHash.Bytes())
|
|
|
|
if enc == nil {
|
|
|
|
var err error
|
|
|
|
enc, err = r.tx.GetOne(kv.Code, codeHash.Bytes())
|
|
|
|
if err != nil {
|
|
|
|
return 0, err
|
|
|
|
}
|
|
|
|
}
|
2022-07-23 17:39:08 +00:00
|
|
|
var sizebuf [8]byte
|
|
|
|
binary.BigEndian.PutUint64(sizebuf[:], uint64(len(enc)))
|
|
|
|
r.readLists[CodeSizeTable].Keys = append(r.readLists[CodeSizeTable].Keys, address.Bytes())
|
|
|
|
r.readLists[CodeSizeTable].Vals = append(r.readLists[CodeSizeTable].Vals, sizebuf[:])
|
2022-07-06 06:49:00 +00:00
|
|
|
size := len(enc)
|
|
|
|
if r.trace {
|
|
|
|
fmt.Printf("ReadAccountCodeSize [%x] => [%d], txNum: %d\n", address, size, r.txNum)
|
|
|
|
}
|
|
|
|
return size, nil
|
|
|
|
}
|
|
|
|
|
2022-07-28 11:16:37 +00:00
|
|
|
func (r *StateReader22) ReadAccountIncarnation(address common.Address) (uint64, error) {
|
2022-07-06 06:49:00 +00:00
|
|
|
enc := r.rs.Get(kv.IncarnationMap, address.Bytes())
|
|
|
|
if enc == nil {
|
|
|
|
var err error
|
|
|
|
enc, err = r.tx.GetOne(kv.IncarnationMap, address.Bytes())
|
|
|
|
if err != nil {
|
|
|
|
return 0, err
|
|
|
|
}
|
|
|
|
}
|
2022-07-23 17:39:08 +00:00
|
|
|
r.readLists[kv.IncarnationMap].Keys = append(r.readLists[kv.IncarnationMap].Keys, address.Bytes())
|
|
|
|
r.readLists[kv.IncarnationMap].Vals = append(r.readLists[kv.IncarnationMap].Vals, common.CopyBytes(enc))
|
2022-07-06 06:49:00 +00:00
|
|
|
if len(enc) == 0 {
|
|
|
|
return 0, nil
|
|
|
|
}
|
|
|
|
return binary.BigEndian.Uint64(enc), nil
|
|
|
|
}
|