Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Filter for tx receipts with any obscuro interactions #1509

Merged
merged 1 commit into from
Sep 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion go/common/host/services.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ type L1BlockRepository interface {
// It returns the new block, a bool which is true if the block is the current L1 head and a bool if the block is on a different fork to prevBlock
FetchNextBlock(prevBlock gethcommon.Hash) (*types.Block, bool, error)
// FetchObscuroReceipts returns the receipts for a given L1 block
FetchObscuroReceipts(block *common.L1Block) types.Receipts
FetchObscuroReceipts(block *common.L1Block) (types.Receipts, error)
}

// L1BlockHandler is an interface for receiving new blocks from the repository as they arrive
Expand Down
7 changes: 7 additions & 0 deletions go/ethadapter/geth_rpc_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,13 @@ func (e *gethRPCClient) BalanceAt(address gethcommon.Address, blockNum *big.Int)
return e.client.BalanceAt(ctx, address, blockNum)
}

func (e *gethRPCClient) GetLogs(q ethereum.FilterQuery) ([]types.Log, error) {
ctx, cancel := context.WithTimeout(context.Background(), e.timeout)
defer cancel()

return e.client.FilterLogs(ctx, q)
}

func (e *gethRPCClient) Stop() {
e.client.Close()
}
Expand Down
1 change: 1 addition & 0 deletions go/ethadapter/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ type EthClient interface {
TransactionReceipt(hash gethcommon.Hash) (*types.Receipt, error) // fetches the ethereum transaction receipt
Nonce(address gethcommon.Address) (uint64, error) // fetches the account nonce to use in the next transaction
BalanceAt(account gethcommon.Address, blockNumber *big.Int) (*big.Int, error) // fetches the balance of the account
GetLogs(q ethereum.FilterQuery) ([]types.Log, error) // fetches the logs for a given query

Info() Info // retrieves the node Info
FetchHeadBlock() (*types.Block, error) // retrieves the block at head height
Expand Down
5 changes: 4 additions & 1 deletion go/host/enclave/guardian.go
Original file line number Diff line number Diff line change
Expand Up @@ -381,12 +381,15 @@ func (g *Guardian) catchupWithL2() error {
// todo - @matt - think about removing the TryLock
func (g *Guardian) submitL1Block(block *common.L1Block, isLatest bool) (bool, error) {
g.logger.Trace("submitting L1 block", log.BlockHashKey, block.Hash(), log.BlockHeightKey, block.Number())
receipts := g.sl.L1Repo().FetchObscuroReceipts(block)
if !g.submitDataLock.TryLock() {
g.logger.Info("Unable to submit block, already submitting another block")
// we are already submitting a block, and we don't want to leak goroutines, we wil catch up with the block later
return false, nil
}
receipts, err := g.sl.L1Repo().FetchObscuroReceipts(block)
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I moved this after the TryLock because we sometimes end up duplicating the effort otherwise.

if err != nil {
return false, fmt.Errorf("could not fetch obscuro receipts for block=%s - %w", block.Hash(), err)
}
resp, err := g.enclaveClient.SubmitL1Block(*block, receipts, isLatest)
g.submitDataLock.Unlock()
if err != nil {
Expand Down
20 changes: 16 additions & 4 deletions go/host/l1/blockrepository.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,11 +128,23 @@ func (r *Repository) latestCanonAncestor(blkHash gethcommon.Hash) (*types.Block,
}

// FetchObscuroReceipts returns all obscuro-relevant receipts for an L1 block
func (r *Repository) FetchObscuroReceipts(block *common.L1Block) types.Receipts {
func (r *Repository) FetchObscuroReceipts(block *common.L1Block) (types.Receipts, error) {
receipts := make([]*types.Receipt, len(block.Transactions()))

blkHash := block.Hash()
// we want to send receipts for any transactions that produced obscuro-relevant log events
logs, err := r.ethClient.GetLogs(ethereum.FilterQuery{BlockHash: &blkHash, Addresses: r.obscuroRelevantContracts})
if err != nil {
return nil, fmt.Errorf("unable to fetch logs for L1 block - %w", err)
}
// make a lookup map of the relevant tx hashes which need receipts
relevantTx := make(map[gethcommon.Hash]bool)
for _, l := range logs {
relevantTx[l.TxHash] = true
}

for idx, transaction := range block.Transactions() {
if !r.isObscuroTransaction(transaction) {
if !relevantTx[transaction.Hash()] && !r.isObscuroTransaction(transaction) {
// put in a dummy receipt so that the index matches the transaction index
// (the receipts list maintains the indexes of the transactions, it is a sparse list)
receipts[idx] = &types.Receipt{Status: types.ReceiptStatusFailed}
Expand All @@ -146,12 +158,12 @@ func (r *Repository) FetchObscuroReceipts(block *common.L1Block) types.Receipts
}

r.logger.Trace("Adding receipt", "status", receipt.Status, log.TxKey, transaction.Hash(),
log.BlockHashKey, block.Hash(), log.CmpKey, log.CrossChainCmp)
log.BlockHashKey, blkHash, log.CmpKey, log.CrossChainCmp)

receipts[idx] = receipt
}

return receipts
return receipts, nil
}

// stream blocks from L1 as they arrive and forward them to subscribers, no guarantee of perfect ordering or that there won't be gaps.
Expand Down
21 changes: 21 additions & 0 deletions integration/ethereummock/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,27 @@ func (m *Node) BalanceAt(gethcommon.Address, *big.Int) (*big.Int, error) {
panic("not implemented")
}

// GetLogs is a mock method - we don't really have logs on the mock transactions, so it returns a basic log for every tx
// so the host recognises them as relevant
func (m *Node) GetLogs(fq ethereum.FilterQuery) ([]types.Log, error) {
logs := make([]types.Log, 0)
if fq.BlockHash == nil {
return logs, nil
}
blk, err := m.BlockByHash(*fq.BlockHash)
if err != nil {
return nil, fmt.Errorf("could not retrieve block. Cause: %w", err)
}
for _, tx := range blk.Transactions() {
dummyLog := types.Log{
BlockHash: blk.Hash(),
TxHash: tx.Hash(),
}
logs = append(logs, dummyLog)
}
return logs, nil
}

// Start runs an infinite loop that listens to the two block producing channels and processes them.
func (m *Node) Start() {
if m.mining {
Expand Down
Loading