Skip to content

Commit

Permalink
Ashraf Basic snap algo .. Did something + #1925
Browse files Browse the repository at this point in the history
This is a combination of 24 commits.
  • Loading branch information
asdacap authored and pnowosie committed Aug 14, 2024
1 parent dc46ab3 commit 499d0a1
Show file tree
Hide file tree
Showing 27 changed files with 5,302 additions and 16 deletions.
74 changes: 72 additions & 2 deletions blockchain/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,18 +74,28 @@ type Blockchain struct {
network *utils.Network
database db.DB

snapshots []*snapshotRecord

listener EventListener

cachedPending atomic.Pointer[Pending]
}

func New(database db.DB, network *utils.Network) *Blockchain {
RegisterCoreTypesToEncoder()
return &Blockchain{
bc := &Blockchain{
database: database,
network: network,
listener: &SelectiveListener{},
}

// TODO: Used only for testing though...
err := bc.seedSnapshot()
if err != nil {
fmt.Printf("Error seeding snapshot %s", err)
}

return bc
}

func (b *Blockchain) WithListener(listener EventListener) *Blockchain {
Expand Down Expand Up @@ -336,7 +346,7 @@ func (b *Blockchain) SetL1Head(update *core.L1Head) error {
func (b *Blockchain) Store(block *core.Block, blockCommitments *core.BlockCommitments,
stateUpdate *core.StateUpdate, newClasses map[felt.Felt]core.Class,
) error {
return b.database.Update(func(txn db.Transaction) error {
err := b.database.Update(func(txn db.Transaction) error {
if err := verifyBlock(txn, block); err != nil {
return err
}
Expand Down Expand Up @@ -372,6 +382,49 @@ func (b *Blockchain) Store(block *core.Block, blockCommitments *core.BlockCommit
heightBin := core.MarshalBlockNumber(block.Number)
return txn.Set(db.ChainHeight.Key(), heightBin)
})
if err != nil {
return err
}

err = b.seedSnapshot()
if err != nil {
return err
}

return nil
}

func (b *Blockchain) StoreRaw(blockNumber uint64, stateDiff *core.StateDiff) error {
return b.database.Update(func(txn db.Transaction) error {
return core.NewState(txn).UpdateNoVerify(blockNumber, stateDiff, make(map[felt.Felt]core.Class))
})
}

func (b *Blockchain) PutClasses(blockNumber uint64, classHashes map[felt.Felt]*felt.Felt, newClasses map[felt.Felt]core.Class) error {
return b.database.Update(func(txn db.Transaction) error {
v1ClassHashes := map[felt.Felt]*felt.Felt{}
for ch, class := range newClasses {
if class.Version() == 1 {
v1ClassHashes[ch] = classHashes[ch]
}
}

return core.NewState(txn).UpdateNoVerify(blockNumber, &core.StateDiff{
DeclaredV1Classes: v1ClassHashes,
}, newClasses)
})
}

func (b *Blockchain) PutContracts(address, nonces, classHash []*felt.Felt) error {
return b.database.Update(func(txn db.Transaction) error {
return core.NewState(txn).UpdateContractNoLog(address, nonces, classHash)
})
}

func (b *Blockchain) PutStorage(storage map[felt.Felt]map[felt.Felt]*felt.Felt) error {
return b.database.Update(func(txn db.Transaction) error {
return core.NewState(txn).UpdateContractStorages(storage)
})
}

// VerifyBlock assumes the block has already been sanity-checked.
Expand Down Expand Up @@ -769,6 +822,23 @@ func (b *Blockchain) HeadState() (core.StateReader, StateCloser, error) {
return core.NewState(txn), txn.Discard, nil
}

func (b *Blockchain) HeadStateFreakingState() (*core.State, StateCloser, error) {
b.listener.OnRead("HeadState")
txn, err := b.database.NewTransaction(false)
if err != nil {
return nil, nil, err
}

/*
_, err = chainHeight(txn)
if err != nil {
return nil, nil, utils.RunAndWrapOnError(txn.Discard, err)
}
*/

return core.NewState(txn), txn.Discard, nil
}

// StateAtBlockNumber returns a StateReader that provides a stable view to the state at the given block number
func (b *Blockchain) StateAtBlockNumber(blockNumber uint64) (core.StateReader, StateCloser, error) {
b.listener.OnRead("StateAtBlockNumber")
Expand Down
161 changes: 161 additions & 0 deletions blockchain/snap_server_interface.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
package blockchain

import (
"errors"
"fmt"

"github.com/NethermindEth/juno/core"
"github.com/NethermindEth/juno/core/felt"
"github.com/NethermindEth/juno/db"
)

type snapshotRecord struct {
stateRoot *felt.Felt
contractsRoot *felt.Felt
classRoot *felt.Felt
blockHash *felt.Felt
txn db.Transaction
closer func() error
}

var ErrMissingSnapshot = errors.New("missing snapshot")

func (b *Blockchain) GetStateForStateRoot(stateRoot *felt.Felt) (*core.State, error) {
snapshot, err := b.findSnapshotMatching(func(record *snapshotRecord) bool {
return record.stateRoot.Equal(stateRoot)
})
if err != nil {
return nil, err
}

s := core.NewState(snapshot.txn)

return s, nil
}

func (b *Blockchain) findSnapshotMatching(filter func(record *snapshotRecord) bool) (*snapshotRecord, error) {
var snapshot *snapshotRecord
for _, record := range b.snapshots {
if filter(record) {
snapshot = record
break
}
}

if snapshot == nil {
return nil, ErrMissingSnapshot
}

return snapshot, nil
}

func (b *Blockchain) GetClasses(felts []*felt.Felt) ([]core.Class, error) {
classes := make([]core.Class, len(felts))
err := b.database.View(func(txn db.Transaction) error {
state := core.NewState(txn)
for i, f := range felts {
d, err := state.Class(f)
if err != nil && !errors.Is(err, db.ErrKeyNotFound) {
return err
} else if errors.Is(err, db.ErrKeyNotFound) {
classes[i] = nil
} else {
classes[i] = d.Class
}
}

return nil
})
if err != nil {
return nil, err
}

return classes, nil
}

func (b *Blockchain) GetDClasses(felts []*felt.Felt) ([]*core.DeclaredClass, error) {
classes := make([]*core.DeclaredClass, len(felts))
err := b.database.View(func(txn db.Transaction) error {
state := core.NewState(txn)
for i, f := range felts {
d, err := state.Class(f)
if err != nil && !errors.Is(err, db.ErrKeyNotFound) {
return err
} else if errors.Is(err, db.ErrKeyNotFound) {
classes[i] = nil
} else {
classes[i] = d
}
}

return nil
})
if err != nil {
return nil, err
}

return classes, nil
}

func (b *Blockchain) seedSnapshot() error {
headheader, err := b.HeadsHeader()
if err != nil {
return err
}

state, scloser, err := b.HeadState()
if err != nil {
return err
}

defer scloser()

stateS := state.(*core.State)
contractsRoot, theclassroot, err := stateS.StateAndClassRoot()
if err != nil {
return err
}

thestateroot, err := stateS.Root()
if err != nil {
return err
}

txn, closer, err := b.database.PersistedView()
if err != nil {
return err
}

dbsnap := snapshotRecord{
stateRoot: thestateroot,
contractsRoot: contractsRoot,
classRoot: theclassroot,
blockHash: headheader.Hash,
txn: txn,
closer: closer,
}

fmt.Printf("Snapshot %d %s %s\n", headheader.Number, headheader.GlobalStateRoot, thestateroot)

// TODO: Reorgs
b.snapshots = append(b.snapshots, &dbsnap)
if len(b.snapshots) > 128 {
toremove := b.snapshots[0]
err = toremove.closer()
if err != nil {
return err
}

// TODO: I think internally, it keep the old array.
// maybe the append copy it to a new array, who knows...
b.snapshots = b.snapshots[1:]
}

return nil
}

func (b *Blockchain) Close() {
for _, snapshot := range b.snapshots {
snapshot.closer()
}
}
31 changes: 30 additions & 1 deletion core/contract.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ import (
)

// contract storage has fixed height at 251
const ContractStorageTrieHeight = 251
const (
GlobalTrieHeight = 251
ContractStorageTrieHeight = 251
)

var (
ErrContractNotDeployed = errors.New("contract not deployed")
Expand Down Expand Up @@ -168,6 +171,32 @@ func (c *ContractUpdater) UpdateStorage(diff map[felt.Felt]*felt.Felt, cb OnValu
return cStorage.Commit()
}

// UpdateStorage applies a change-set to the contract storage.
func (c *ContractUpdater) UpdateStorageKV(diff []FeltKV, cb OnValueChanged) error {
cStorage, err := storage(c.Address, c.txn)
if err != nil {
return err
}

// apply the diff
for _, kv := range diff {
key := kv.Key
value := kv.Value
oldValue, pErr := cStorage.Put(key, value)
if pErr != nil {
return pErr
}

if oldValue != nil {
if err = cb(key, oldValue); err != nil {
return err
}
}
}

return cStorage.Commit()
}

func ContractStorage(addr, key *felt.Felt, txn db.Transaction) (*felt.Felt, error) {
cStorage, err := storage(addr, txn)
if err != nil {
Expand Down
Loading

0 comments on commit 499d0a1

Please sign in to comment.