mirror of
https://gitlab.com/pulsechaincom/erigon-pulse.git
synced 2024-12-25 13:07:17 +00:00
7352b81122
* convert contracts after block execution * check if has tevm code * after review-1 * handle ErrNotFound * typo * tests * tevm code bucket * testdata * execute pre-stage * after merge * test fix * test fix * fix test after merge * disable translation stage * after merge * rename params * rename to Erigon * parallelize EVM translation * fix * logging and fixes * fix * todos * cleanup * revert erigorn renaming * unwind * tevm unwind * fix AppData * non-parallel version * comments
173 lines
3.6 KiB
Go
173 lines
3.6 KiB
Go
package ethdb
|
|
|
|
import (
|
|
"bytes"
|
|
"errors"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"os"
|
|
"time"
|
|
|
|
"github.com/ledgerwatch/erigon/common"
|
|
"github.com/ledgerwatch/erigon/common/dbutils"
|
|
"github.com/ledgerwatch/erigon/log"
|
|
)
|
|
|
|
func Get(tx Tx, bucket string, key []byte) ([]byte, error) {
|
|
var dat []byte
|
|
v, err := tx.GetOne(bucket, key)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if v != nil {
|
|
dat = make([]byte, len(v))
|
|
copy(dat, v)
|
|
}
|
|
if dat == nil {
|
|
return nil, ErrKeyNotFound
|
|
}
|
|
return dat, err
|
|
}
|
|
|
|
func ForEach(c Cursor, walker func(k, v []byte) (bool, error)) error {
|
|
for k, v, err := c.First(); k != nil; k, v, err = c.Next() {
|
|
if err != nil {
|
|
return err
|
|
}
|
|
ok, err := walker(k, v)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !ok {
|
|
return nil
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func Walk(c Cursor, startkey []byte, fixedbits int, walker func(k, v []byte) (bool, error)) error {
|
|
fixedbytes, mask := Bytesmask(fixedbits)
|
|
k, v, err := c.Seek(startkey)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
for k != nil && len(k) >= fixedbytes && (fixedbits == 0 || bytes.Equal(k[:fixedbytes-1], startkey[:fixedbytes-1]) && (k[fixedbytes-1]&mask) == (startkey[fixedbytes-1]&mask)) {
|
|
goOn, err := walker(k, v)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !goOn {
|
|
break
|
|
}
|
|
k, v, err = c.Next()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func MultiPut(tx RwTx, tuples ...[]byte) error {
|
|
logEvery := time.NewTicker(30 * time.Second)
|
|
defer logEvery.Stop()
|
|
|
|
count := 0
|
|
total := float64(len(tuples)) / 3
|
|
for bucketStart := 0; bucketStart < len(tuples); {
|
|
bucketEnd := bucketStart
|
|
for ; bucketEnd < len(tuples) && bytes.Equal(tuples[bucketEnd], tuples[bucketStart]); bucketEnd += 3 {
|
|
}
|
|
bucketName := string(tuples[bucketStart])
|
|
c, err := tx.RwCursor(bucketName)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// move cursor to a first element in batch
|
|
// if it's nil, it means all keys in batch gonna be inserted after end of bucket (batch is sorted and has no duplicates here)
|
|
// can apply optimisations for this case
|
|
firstKey, _, err := c.Seek(tuples[bucketStart+1])
|
|
if err != nil {
|
|
return err
|
|
}
|
|
isEndOfBucket := firstKey == nil
|
|
|
|
l := (bucketEnd - bucketStart) / 3
|
|
for i := 0; i < l; i++ {
|
|
k := tuples[bucketStart+3*i+1]
|
|
v := tuples[bucketStart+3*i+2]
|
|
if isEndOfBucket {
|
|
if v == nil {
|
|
// nothing to delete after end of bucket
|
|
} else {
|
|
if err := c.Append(k, v); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
} else {
|
|
if v == nil {
|
|
if err := c.Delete(k, nil); err != nil {
|
|
return err
|
|
}
|
|
} else {
|
|
if err := c.Put(k, v); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
|
|
count++
|
|
|
|
select {
|
|
default:
|
|
case <-logEvery.C:
|
|
progress := fmt.Sprintf("%.1fM/%.1fM", float64(count)/1_000_000, total/1_000_000)
|
|
log.Info("Write to db", "progress", progress, "current table", bucketName)
|
|
}
|
|
}
|
|
|
|
bucketStart = bucketEnd
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func testKVPath() string {
|
|
dir, err := ioutil.TempDir(os.TempDir(), "erigon-test-db")
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
return dir
|
|
}
|
|
|
|
// todo: return TEVM code and use it
|
|
func GetCheckTEVM(db KVGetter) func(codeHash common.Hash) (bool, error) {
|
|
checked := map[common.Hash]struct{}{}
|
|
var ok bool
|
|
|
|
return func(codeHash common.Hash) (bool, error) {
|
|
if _, ok = checked[codeHash]; ok {
|
|
return true, nil
|
|
}
|
|
|
|
ok, err := db.Has(dbutils.ContractTEVMCodeStatusBucket, codeHash.Bytes())
|
|
if !errors.Is(err, ErrKeyNotFound) {
|
|
return false, err
|
|
}
|
|
|
|
if ok {
|
|
return false, ErrKeyNotFound
|
|
}
|
|
|
|
ok, err = db.Has(dbutils.ContractTEVMCodeBucket, codeHash.Bytes())
|
|
if !errors.Is(err, ErrKeyNotFound) {
|
|
return false, err
|
|
}
|
|
|
|
if !ok {
|
|
checked[codeHash] = struct{}{}
|
|
}
|
|
|
|
return ok, nil
|
|
}
|
|
}
|