Skip to content

Commit

Permalink
merge
Browse files Browse the repository at this point in the history
  • Loading branch information
badgersrus committed May 31, 2024
2 parents 0f8a812 + b335bd1 commit 33c5c55
Show file tree
Hide file tree
Showing 36 changed files with 390 additions and 181 deletions.
3 changes: 2 additions & 1 deletion go/common/errutil/errors_util.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ var (
ErrBlockAncestorNotFound = errors.New("block ancestor not found")
ErrBlockForBatchNotFound = errors.New("block for batch not found")
ErrAncestorBatchNotFound = errors.New("parent for batch not found")
ErrCrossChainBundleRepublished = errors.New("Root already added to the message bus")
ErrCrossChainBundleRepublished = errors.New("root already added to the message bus")
ErrCrossChainBundleNoBatches = errors.New("no batches for cross chain bundle")
)

// BlockRejectError is used as a standard format for error response from enclave for block submission errors
Expand Down
74 changes: 20 additions & 54 deletions go/common/gethencoding/geth_encoding.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,54 +77,6 @@ func NewGethEncodingService(storage storage.Storage, logger gethlog.Logger) Enco
}
}

// ExtractEthCallMapString extracts the eth_call gethapi.TransactionArgs from an interface{}
// it ensures that :
// - All types are string
// - All keys are lowercase
// - There is only one key per value
// - From field is set by default
func ExtractEthCallMapString(paramBytes interface{}) (map[string]string, error) {
// geth lowercase the field name and uses the last seen value
var valString string
var ok bool
callMsg := map[string]string{
// From field is set by default
"from": gethcommon.HexToAddress("0x0").Hex(),
}
for field, val := range paramBytes.(map[string]interface{}) {
if val == nil {
continue
}
valString, ok = val.(string)
if !ok {
return nil, fmt.Errorf("unexpected type supplied in `%s` field", field)
}
if len(strings.TrimSpace(valString)) == 0 {
continue
}
switch strings.ToLower(field) {
case callFieldTo:
callMsg[callFieldTo] = valString
case CallFieldFrom:
callMsg[CallFieldFrom] = valString
case callFieldData, callFieldInput:
callMsg[callFieldInput] = valString
case callFieldValue:
callMsg[callFieldValue] = valString
case callFieldGas:
callMsg[callFieldGas] = valString
case callFieldMaxFeePerGas:
callMsg[callFieldMaxFeePerGas] = valString
case callFieldMaxPriorityFeePerGas:
callMsg[callFieldMaxPriorityFeePerGas] = valString
default:
callMsg[field] = valString
}
}

return callMsg, nil
}

// ExtractAddress returns a gethcommon.Address given an interface{}, errors if unexpected values are used
func ExtractAddress(param interface{}) (*gethcommon.Address, error) {
if param == nil {
Expand All @@ -140,7 +92,7 @@ func ExtractAddress(param interface{}) (*gethcommon.Address, error) {
return nil, fmt.Errorf("no address specified")
}

addr := gethcommon.HexToAddress(param.(string))
addr := gethcommon.HexToAddress(paramStr)
return &addr, nil
}

Expand Down Expand Up @@ -183,10 +135,13 @@ func ExtractBlockNumber(param interface{}) (*gethrpc.BlockNumberOrHash, error) {

blockAndHash, ok := param.(map[string]any)
if !ok {
return nil, fmt.Errorf("invalid block or hash parameter %s", param.(string))
return nil, fmt.Errorf("invalid block or hash parameter")
}
if blockAndHash["blockNumber"] != nil {
b := blockAndHash["blockNumber"].(string)
b, ok := blockAndHash["blockNumber"].(string)
if !ok {
return nil, fmt.Errorf("invalid blockNumber parameter")
}
blockNumber := gethrpc.BlockNumber(0)
err := blockNumber.UnmarshalJSON([]byte(b))
if err != nil {
Expand All @@ -195,11 +150,17 @@ func ExtractBlockNumber(param interface{}) (*gethrpc.BlockNumberOrHash, error) {
blockNo = &blockNumber
}
if blockAndHash["blockHash"] != nil {
bh := blockAndHash["blockHash"].(gethcommon.Hash)
bh, ok := blockAndHash["blockHash"].(gethcommon.Hash)
if !ok {
return nil, fmt.Errorf("invalid blockhash parameter")
}
blockHa = &bh
}
if blockAndHash["RequireCanonical"] != nil {
reqCanon = blockAndHash["RequireCanonical"].(bool)
reqCanon, ok = blockAndHash["RequireCanonical"].(bool)
if !ok {
return nil, fmt.Errorf("invalid RequireCanonical parameter")
}
}

return &gethrpc.BlockNumberOrHash{
Expand All @@ -222,7 +183,12 @@ func ExtractEthCall(param interface{}) (*gethapi.TransactionArgs, error) {
// if gas is not set it should be null
gas := (*hexutil.Uint64)(nil)

for field, val := range param.(map[string]interface{}) {
ethCallMap, ok := param.(map[string]interface{})
if !ok {
return nil, fmt.Errorf("invalid eth call parameter")
}

for field, val := range ethCallMap {
if val == nil {
continue
}
Expand Down
29 changes: 11 additions & 18 deletions go/common/gethutil/gethutil.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package gethutil

import (
"bytes"
"context"
"fmt"

Expand All @@ -20,14 +19,7 @@ var EmptyHash = gethcommon.Hash{}
// LCA - returns the latest common ancestor of the 2 blocks or an error if no common ancestor is found
// it also returns the blocks that became canonical, and the once that are now the fork
func LCA(ctx context.Context, newCanonical *types.Block, oldCanonical *types.Block, resolver storage.BlockResolver) (*common.ChainFork, error) {
b, cp, ncp, err := internalLCA(ctx, newCanonical, oldCanonical, resolver, []common.L1BlockHash{}, []common.L1BlockHash{oldCanonical.Hash()})
// remove the common ancestor
if len(cp) > 0 {
cp = cp[0 : len(cp)-1]
}
if len(ncp) > 0 {
ncp = ncp[0 : len(ncp)-1]
}
b, cp, ncp, err := internalLCA(ctx, newCanonical, oldCanonical, resolver, []common.L1BlockHash{}, []common.L1BlockHash{})
return &common.ChainFork{
NewCanonical: newCanonical,
OldCanonical: oldCanonical,
Expand All @@ -41,33 +33,34 @@ func internalLCA(ctx context.Context, newCanonical *types.Block, oldCanonical *t
if newCanonical.NumberU64() == common.L1GenesisHeight || oldCanonical.NumberU64() == common.L1GenesisHeight {
return newCanonical, canonicalPath, nonCanonicalPath, nil
}
if bytes.Equal(newCanonical.Hash().Bytes(), oldCanonical.Hash().Bytes()) {
return newCanonical, canonicalPath, nonCanonicalPath, nil
if newCanonical.Hash() == oldCanonical.Hash() {
// this is where we reach the common ancestor, which we add to the canonical path
return newCanonical, append(canonicalPath, newCanonical.Hash()), nonCanonicalPath, nil
}
if newCanonical.NumberU64() > oldCanonical.NumberU64() {
p, err := resolver.FetchBlock(ctx, newCanonical.ParentHash())
if err != nil {
return nil, nil, nil, fmt.Errorf("could not retrieve parent block. Cause: %w", err)
return nil, nil, nil, fmt.Errorf("could not retrieve parent block %s. Cause: %w", newCanonical.ParentHash(), err)
}

return internalLCA(ctx, p, oldCanonical, resolver, append(canonicalPath, p.Hash()), nonCanonicalPath)
return internalLCA(ctx, p, oldCanonical, resolver, append(canonicalPath, newCanonical.Hash()), nonCanonicalPath)
}
if oldCanonical.NumberU64() > newCanonical.NumberU64() {
p, err := resolver.FetchBlock(ctx, oldCanonical.ParentHash())
if err != nil {
return nil, nil, nil, fmt.Errorf("could not retrieve parent block. Cause: %w", err)
return nil, nil, nil, fmt.Errorf("could not retrieve parent block %s. Cause: %w", oldCanonical.ParentHash(), err)
}

return internalLCA(ctx, newCanonical, p, resolver, canonicalPath, append(nonCanonicalPath, p.Hash()))
return internalLCA(ctx, newCanonical, p, resolver, canonicalPath, append(nonCanonicalPath, oldCanonical.Hash()))
}
parentBlockA, err := resolver.FetchBlock(ctx, newCanonical.ParentHash())
if err != nil {
return nil, nil, nil, fmt.Errorf("could not retrieve parent block. Cause: %w", err)
return nil, nil, nil, fmt.Errorf("could not retrieve parent block %s. Cause: %w", newCanonical.ParentHash(), err)
}
parentBlockB, err := resolver.FetchBlock(ctx, oldCanonical.ParentHash())
if err != nil {
return nil, nil, nil, fmt.Errorf("could not retrieve parent block. Cause: %w", err)
return nil, nil, nil, fmt.Errorf("could not retrieve parent block %s. Cause: %w", oldCanonical.ParentHash(), err)
}

return internalLCA(ctx, parentBlockA, parentBlockB, resolver, append(canonicalPath, parentBlockA.Hash()), append(nonCanonicalPath, parentBlockB.Hash()))
return internalLCA(ctx, parentBlockA, parentBlockB, resolver, append(canonicalPath, newCanonical.Hash()), append(nonCanonicalPath, oldCanonical.Hash()))
}
12 changes: 6 additions & 6 deletions go/enclave/components/batch_executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ func (executor *batchExecutor) ComputeBatch(ctx context.Context, context *BatchE
}

// These variables will be used to create the new batch
parent, err := executor.storage.FetchBatch(ctx, context.ParentPtr)
parentBatch, err := executor.storage.FetchBatch(ctx, context.ParentPtr)
if errors.Is(err, errutil.ErrNotFound) {
executor.logger.Error(fmt.Sprintf("can't find parent batch %s. Seq %d", context.ParentPtr, context.SequencerNo))
return nil, errutil.ErrAncestorBatchNotFound
Expand All @@ -154,17 +154,17 @@ func (executor *batchExecutor) ComputeBatch(ctx context.Context, context *BatchE
}

parentBlock := block
if parent.Header.L1Proof != block.Hash() {
if parentBatch.Header.L1Proof != block.Hash() {
var err error
parentBlock, err = executor.storage.FetchBlock(ctx, parent.Header.L1Proof)
parentBlock, err = executor.storage.FetchBlock(ctx, parentBatch.Header.L1Proof)
if err != nil {
executor.logger.Error(fmt.Sprintf("Could not retrieve a proof for batch %s", parent.Hash()), log.ErrKey, err)
executor.logger.Error(fmt.Sprintf("Could not retrieve a proof for batch %s", parentBatch.Hash()), log.ErrKey, err)
return nil, err
}
}

// Create a new batch based on the fromBlock of inclusion of the previous, including all new transactions
batch := core.DeterministicEmptyBatch(parent.Header, block, context.AtTime, context.SequencerNo, context.BaseFee, context.Creator)
batch := core.DeterministicEmptyBatch(parentBatch.Header, block, context.AtTime, context.SequencerNo, context.BaseFee, context.Creator)

stateDB, err := executor.batchRegistry.GetBatchState(ctx, &batch.Header.ParentHash)
if err != nil {
Expand Down Expand Up @@ -379,7 +379,7 @@ func (executor *batchExecutor) populateOutboundCrossChainData(ctx context.Contex

encodedTree, err := json.Marshal(xchainTree)
if err != nil {
panic(err) //todo: figure out what to do
panic(err) // todo: figure out what to do
}

batch.Header.CrossChainTree = encodedTree
Expand Down
8 changes: 4 additions & 4 deletions go/enclave/components/batch_registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,12 +100,12 @@ func (br *batchRegistry) OnBatchExecuted(batch *core.Batch, receipts types.Recei
}

func (br *batchRegistry) HasGenesisBatch() (bool, error) {
return br.headBatchSeq != nil, nil
return br.HeadBatchSeq() != nil, nil
}

func (br *batchRegistry) BatchesAfter(ctx context.Context, batchSeqNo uint64, upToL1Height uint64, rollupLimiter limiters.RollupLimiter) ([]*core.Batch, []*types.Block, error) {
// sanity check
headBatch, err := br.storage.FetchBatchBySeqNo(ctx, br.headBatchSeq.Uint64())
headBatch, err := br.storage.FetchBatchBySeqNo(ctx, br.HeadBatchSeq().Uint64())
if err != nil {
return nil, nil, err
}
Expand Down Expand Up @@ -199,7 +199,7 @@ func getBatchState(ctx context.Context, storage storage.Storage, batch *core.Bat
}

func (br *batchRegistry) GetBatchAtHeight(ctx context.Context, height gethrpc.BlockNumber) (*core.Batch, error) {
if br.headBatchSeq == nil {
if br.HeadBatchSeq() == nil {
return nil, fmt.Errorf("chain not initialised")
}
var batch *core.Batch
Expand All @@ -212,7 +212,7 @@ func (br *batchRegistry) GetBatchAtHeight(ctx context.Context, height gethrpc.Bl
batch = genesisBatch
// note: our API currently treats all these block statuses the same for obscuro batches
case gethrpc.SafeBlockNumber, gethrpc.FinalizedBlockNumber, gethrpc.LatestBlockNumber, gethrpc.PendingBlockNumber:
headBatch, err := br.storage.FetchBatchBySeqNo(ctx, br.headBatchSeq.Uint64())
headBatch, err := br.storage.FetchBatchBySeqNo(ctx, br.HeadBatchSeq().Uint64())
if err != nil {
return nil, fmt.Errorf("batch with requested height %d was not found. Cause: %w", height, err)
}
Expand Down
32 changes: 19 additions & 13 deletions go/enclave/components/block_processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,29 +100,27 @@ func (bp *l1BlockProcessor) HealthCheck() (bool, error) {
func (bp *l1BlockProcessor) tryAndInsertBlock(ctx context.Context, br *common.BlockAndReceipts) (*BlockIngestionType, error) {
block := br.Block

_, err := bp.storage.FetchBlock(ctx, block.Hash())
if err == nil {
return nil, errutil.ErrBlockAlreadyProcessed
}

if !errors.Is(err, errutil.ErrNotFound) {
return nil, fmt.Errorf("could not retrieve block. Cause: %w", err)
}

// We insert the block into the L1 chain and store it.
// in case the block already exists in the database, this will be treated like a fork, because the head changes to
// the block that was already saved
ingestionType, err := bp.ingestBlock(ctx, block)
if err != nil {
// Do not store the block if the L1 chain insertion failed
return nil, err
}
bp.logger.Trace("Block inserted successfully",
log.BlockHeightKey, block.NumberU64(), log.BlockHashKey, block.Hash(), "ingestionType", ingestionType)

if ingestionType.OldCanonicalBlock {
return nil, errutil.ErrBlockAlreadyProcessed
}

err = bp.storage.StoreBlock(ctx, block, ingestionType.ChainFork)
if err != nil {
return nil, fmt.Errorf("1. could not store block. Cause: %w", err)
}

bp.logger.Trace("Block inserted successfully",
log.BlockHeightKey, block.NumberU64(), log.BlockHashKey, block.Hash(), "ingestionType", ingestionType)

return ingestionType, nil
}

Expand All @@ -138,9 +136,17 @@ func (bp *l1BlockProcessor) ingestBlock(ctx context.Context, block *common.L1Blo
}
// we do a basic sanity check, comparing the received block to the head block on the chain
if block.ParentHash() != prevL1Head.Hash() {
isCanon, err := bp.storage.IsBlockCanonical(ctx, block.Hash())
if err != nil {
return nil, fmt.Errorf("could not check if block is canonical. Cause: %w", err)
}
if isCanon {
return &BlockIngestionType{OldCanonicalBlock: true}, nil
}

chainFork, err := gethutil.LCA(ctx, block, prevL1Head, bp.storage)
if err != nil {
bp.logger.Trace("parent not found",
bp.logger.Trace("cannot calculate the fork for received block",
"blkHeight", block.NumberU64(), log.BlockHashKey, block.Hash(),
"l1HeadHeight", prevL1Head.NumberU64(), "l1HeadHash", prevL1Head.Hash(),
log.ErrKey, err,
Expand All @@ -149,7 +155,7 @@ func (bp *l1BlockProcessor) ingestBlock(ctx context.Context, block *common.L1Blo
}

if chainFork.IsFork() {
bp.logger.Info("Fork detected in the l1 chain", "can", chainFork.CommonAncestor.Hash().Hex(), "noncan", prevL1Head.Hash().Hex())
bp.logger.Info("Fork detected in the l1 chain", "can", chainFork.CommonAncestor.Hash(), "noncan", prevL1Head.Hash())
}
return &BlockIngestionType{ChainFork: chainFork, PreGenesis: false}, nil
}
Expand Down
3 changes: 3 additions & 0 deletions go/enclave/components/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ type BlockIngestionType struct {

// ChainFork contains information about the status of the new block in the chain
ChainFork *common.ChainFork

// Block that is already on the canonical chain
OldCanonicalBlock bool
}

func (bit *BlockIngestionType) IsFork() bool {
Expand Down
1 change: 1 addition & 0 deletions go/enclave/components/rollup_compression.go
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ func (rc *RollupCompression) createRollupHeader(ctx context.Context, rollup *cor
}
reorgMap := make(map[uint64]bool)
for _, batch := range reorgedBatches {
rc.logger.Info("Reorg batch", log.BatchSeqNoKey, batch.SeqNo().Uint64())
reorgMap[batch.SeqNo().Uint64()] = true
}

Expand Down
2 changes: 1 addition & 1 deletion go/enclave/crosschain/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ func (ms MessageStructs) HashPacked(index int) gethcommon.Hash {
},
}

//todo @siliev: err
// todo @siliev: err
packed, _ := args.Pack(messageStruct.Sender, messageStruct.Sequence, messageStruct.Nonce, messageStruct.Topic, messageStruct.Payload, messageStruct.ConsistencyLevel)
hash := crypto.Keccak256Hash(packed)
return hash
Expand Down
1 change: 0 additions & 1 deletion go/enclave/enclave.go
Original file line number Diff line number Diff line change
Expand Up @@ -572,7 +572,6 @@ func (e *enclaveImpl) CreateRollup(ctx context.Context, fromSeqNo uint64) (*comm
return nil, responses.ToInternalError(fmt.Errorf("requested GenerateRollup with the enclave stopping"))
}

// todo - remove once the db operations are more atomic
e.mainMutex.Lock()
defer e.mainMutex.Unlock()

Expand Down
6 changes: 4 additions & 2 deletions go/enclave/genesis/testnet_genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ import (
)

const TestnetPrefundedPK = "8dfb8083da6275ae3e4f41e3e8a8c19d028d32c9247e24530933782f2a05035b" // The genesis main account private key.
var GasBridgingKeys, _ = crypto.GenerateKey() // todo - make static
var GasWithdrawalKeys, _ = crypto.GenerateKey() // todo - make static
var (
GasBridgingKeys, _ = crypto.GenerateKey() // todo - make static
GasWithdrawalKeys, _ = crypto.GenerateKey() // todo - make static
)

var TestnetGenesis = Genesis{
Accounts: []Account{
Expand Down
Loading

0 comments on commit 33c5c55

Please sign in to comment.