mirror of
https://gitlab.com/pulsechaincom/erigon-pulse.git
synced 2025-01-10 13:01:21 +00:00
529d359ca6
An update to the devnet to introduce a local heimdall to facilitate multiple validators without the need for an external process, and hence validator registration/staking etc. In this initial release only span generation is supported. It has the following changes: * Introduction of a local grpc heimdall interface * Allocation of accounts via a devnet account generator () * Introduction on 'Services' for the network config "--chain bor-devnet --bor.localheimdall" will run a 2 validator network with a local service "--chain bor-devnet --bor.withoutheimdall" will sun a single validator with no heimdall service as before --------- Co-authored-by: Alex Sharp <alexsharp@Alexs-MacBook-Pro-2.local>
116 lines
3.6 KiB
Go
116 lines
3.6 KiB
Go
package transactions
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"time"
|
|
|
|
libcommon "github.com/ledgerwatch/erigon-lib/common"
|
|
"github.com/ledgerwatch/log/v3"
|
|
|
|
"github.com/ledgerwatch/erigon/cmd/devnet/devnetutils"
|
|
"github.com/ledgerwatch/erigon/cmd/devnet/requests"
|
|
"github.com/ledgerwatch/erigon/cmd/devnet/services"
|
|
"github.com/ledgerwatch/erigon/common/hexutil"
|
|
"github.com/ledgerwatch/erigon/rpc"
|
|
)
|
|
|
|
// MaxNumberOfBlockChecks is the max number of blocks to look for a transaction in
|
|
var MaxNumberOfEmptyBlockChecks = 25
|
|
|
|
func SearchReservesForTransactionHash(hashes map[libcommon.Hash]bool, logger log.Logger) (*map[libcommon.Hash]string, error) {
|
|
logger.Info("Searching for transactions in reserved blocks...")
|
|
m, err := searchBlockForHashes(hashes, logger)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to search reserves for hashes: %v", err)
|
|
}
|
|
|
|
return m, nil
|
|
}
|
|
|
|
func searchBlockForHashes(hashmap map[libcommon.Hash]bool, logger log.Logger) (*map[libcommon.Hash]string, error) {
|
|
if len(hashmap) == 0 {
|
|
return nil, fmt.Errorf("no hashes to search for")
|
|
}
|
|
|
|
txToBlock := make(map[libcommon.Hash]string, len(hashmap))
|
|
|
|
methodSub := (*services.Subscriptions)[requests.Methods.ETHNewHeads]
|
|
if methodSub == nil {
|
|
return nil, fmt.Errorf("client subscription should not be nil")
|
|
}
|
|
|
|
headsSub := (*services.Subscriptions)[requests.Methods.ETHNewHeads]
|
|
|
|
// get a block from the new heads channel
|
|
if headsSub == nil {
|
|
return nil, fmt.Errorf("no block heads subscription")
|
|
}
|
|
|
|
var blockCount int
|
|
for {
|
|
block := <-headsSub.SubChan
|
|
blockNum := block.(map[string]interface{})["number"].(string)
|
|
_, numFound, foundErr := txHashInBlock(methodSub.Client, hashmap, blockNum, txToBlock, logger)
|
|
|
|
if foundErr != nil {
|
|
return nil, fmt.Errorf("failed to find hash in block with number %q: %v", foundErr, blockNum)
|
|
}
|
|
|
|
if len(hashmap) == 0 { // this means we have found all the txs we're looking for
|
|
logger.Info("All the transactions created have been included in blocks")
|
|
return &txToBlock, nil
|
|
}
|
|
|
|
if numFound == 0 {
|
|
blockCount++ // increment the number of blocks seen to check against the max number of blocks to iterate over
|
|
}
|
|
|
|
if blockCount == MaxNumberOfEmptyBlockChecks {
|
|
for h := range hashmap {
|
|
logger.Error("Missing Tx", "txHash", h)
|
|
}
|
|
|
|
return nil, fmt.Errorf("timeout when searching for tx")
|
|
}
|
|
}
|
|
}
|
|
|
|
// Block represents a simple block for queries
|
|
type Block struct {
|
|
Number *hexutil.Big
|
|
Transactions []libcommon.Hash
|
|
BlockHash libcommon.Hash
|
|
}
|
|
|
|
// txHashInBlock checks if the block with block number has the transaction hash in its list of transactions
|
|
func txHashInBlock(client *rpc.Client, hashmap map[libcommon.Hash]bool, blockNumber string, txToBlockMap map[libcommon.Hash]string, logger log.Logger) (uint64, int, error) {
|
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
|
defer cancel() // releases the resources held by the context
|
|
|
|
var (
|
|
currBlock Block
|
|
numFound int
|
|
)
|
|
err := client.CallContext(ctx, &currBlock, string(requests.Methods.ETHGetBlockByNumber), blockNumber, false)
|
|
if err != nil {
|
|
return uint64(0), 0, fmt.Errorf("failed to get block by number: %v", err)
|
|
}
|
|
|
|
for _, txnHash := range currBlock.Transactions {
|
|
// check if tx is in the hash set and remove it from the set if it is present
|
|
if _, ok := hashmap[txnHash]; ok {
|
|
numFound++
|
|
logger.Info("SUCCESS => Tx included into block", "txHash", txnHash, "blockNum", blockNumber)
|
|
// add the block number as an entry to the map
|
|
txToBlockMap[txnHash] = blockNumber
|
|
delete(hashmap, txnHash)
|
|
if len(hashmap) == 0 {
|
|
return devnetutils.HexToInt(blockNumber), numFound, nil
|
|
}
|
|
}
|
|
}
|
|
|
|
return uint64(0), 0, nil
|
|
}
|