erigon-pulse/cmd/devnet/accounts/steps/steps.go
Mark Holt c51573f333
Bor eth event flow (#8068)
Implemented polygon->eth flow
2023-08-25 12:19:39 +01:00

215 lines
5.7 KiB
Go

package accounts_steps
import (
"context"
"encoding/json"
"fmt"
"math/big"
libcommon "github.com/ledgerwatch/erigon-lib/common"
"github.com/ledgerwatch/erigon/accounts/abi/bind"
"github.com/ledgerwatch/erigon/cmd/devnet/accounts"
"github.com/ledgerwatch/erigon/cmd/devnet/devnet"
"github.com/ledgerwatch/erigon/cmd/devnet/requests"
"github.com/ledgerwatch/erigon/cmd/devnet/scenarios"
"github.com/ledgerwatch/erigon/cmd/devnet/services"
"github.com/ledgerwatch/erigon/cmd/devnet/transactions"
"github.com/ledgerwatch/erigon/rpc"
"github.com/ledgerwatch/erigon/turbo/adapter/ethapi"
)
func init() {
scenarios.MustRegisterStepHandlers(
scenarios.StepHandler(CreateAccount),
scenarios.StepHandler(CreateAccountWithFunds),
scenarios.StepHandler(SendFunds),
scenarios.StepHandler(GetBalance),
scenarios.StepHandler(GetNonce),
)
}
func CreateAccount(ctx context.Context, name string) (*accounts.Account, error) {
if account := accounts.GetAccount(name); account != nil {
return account, nil
}
return accounts.NewAccount(name), nil
}
func CreateAccountWithFunds(ctx context.Context, chainName string, name string, ethAmount float64) (*accounts.Account, error) {
account, err := CreateAccount(ctx, name)
if err != nil {
return nil, err
}
if _, err = SendFunds(ctx, chainName, name, ethAmount); err != nil {
return nil, err
}
return account, nil
}
func SendFunds(ctx context.Context, chainName string, name string, ethAmount float64) (uint64, error) {
chainCtx := devnet.WithCurrentNetwork(ctx, chainName)
faucet := services.Faucet(chainCtx)
account := accounts.GetAccount(name)
if account == nil {
return 0, fmt.Errorf("Unknown account: %s", name)
}
facuetStartingBalance, _ := faucet.Balance(chainCtx)
sent, hash, err := faucet.Send(chainCtx, account, ethAmount)
if err != nil {
return 0, err
}
blockMap, err := transactions.AwaitTransactions(chainCtx, hash)
if err != nil {
return 0, fmt.Errorf("Failed to get transfer tx: %w", err)
}
blockNum, _ := blockMap[hash]
logs, err := faucet.Contract().FilterSent(&bind.FilterOpts{
Start: blockNum,
End: &blockNum,
})
if err != nil {
return 0, fmt.Errorf("Failed to get post transfer logs: %w", err)
}
sendConfirmed := false
for logs.Next() {
if account.Address != logs.Event.Destination {
return 0, fmt.Errorf("Unexpected send destination: %s", logs.Event.Destination)
}
if sent.Cmp(logs.Event.Amount) != 0 {
return 0, fmt.Errorf("Unexpected send amount: %s", logs.Event.Amount)
}
sendConfirmed = true
}
node := devnet.SelectBlockProducer(chainCtx)
if !sendConfirmed {
logger := devnet.Logger(chainCtx)
traceResults, err := node.TraceTransaction(hash)
if err != nil {
return 0, fmt.Errorf("Send transaction failure: transaction trace failed: %w", err)
}
for _, traceResult := range traceResults {
accountResult, err := node.DebugAccountAt(traceResult.BlockHash, traceResult.TransactionPosition, faucet.Address())
if err != nil {
return 0, fmt.Errorf("Send transaction failure: account debug failed: %w", err)
}
logger.Info("Faucet account details", "address", faucet.Address(), "account", accountResult)
accountCode, err := node.GetCode(faucet.Address(), rpc.AsBlockReference(traceResult.BlockHash))
if err != nil {
return 0, fmt.Errorf("Send transaction failure: get account code failed: %w", err)
}
logger.Info("Faucet account code", "address", faucet.Address(), "code", accountCode)
callResults, err := node.TraceCall(rpc.AsBlockReference(blockNum), ethapi.CallArgs{
From: &traceResult.Action.From,
To: &traceResult.Action.To,
Data: &traceResult.Action.Input,
}, requests.TraceOpts.StateDiff, requests.TraceOpts.Trace, requests.TraceOpts.VmTrace)
if err != nil {
return 0, fmt.Errorf("Send transaction failure: trace call failed: %w", err)
}
results, _ := json.MarshalIndent(callResults, " ", " ")
logger.Debug("Send transaction call trace", "hash", hash, "trace", string(results))
}
}
balance, err := faucet.Balance(chainCtx)
if err != nil {
return 0, fmt.Errorf("Failed to get post transfer faucet balance: %w", err)
}
if balance.Cmp((&big.Int{}).Sub(facuetStartingBalance, sent)) != 0 {
return 0, fmt.Errorf("Unexpected post transfer faucet balance got: %s:, expected: %s", balance, (&big.Int{}).Sub(facuetStartingBalance, sent))
}
balance, err = node.GetBalance(account.Address, rpc.LatestBlock)
if err != nil {
return 0, fmt.Errorf("Failed to get post transfer balance: %w", err)
}
if balance.Cmp(sent) != 0 {
return 0, fmt.Errorf("Unexpected post transfer balance got: %s:, expected: %s", balance, sent)
}
return balance.Uint64(), nil
}
func GetBalance(ctx context.Context, accountName string, blockNum rpc.BlockNumber) (uint64, error) {
logger := devnet.Logger(ctx)
node := devnet.CurrentNode(ctx)
if node == nil {
node = devnet.SelectBlockProducer(ctx)
}
account := accounts.GetAccount(accountName)
if account == nil {
err := fmt.Errorf("Unknown account: %s", accountName)
logger.Error("FAILURE", "error", err)
return 0, err
}
logger.Info("Getting balance", "address", account.Address)
bal, err := node.GetBalance(account.Address, rpc.AsBlockReference(blockNum))
if err != nil {
logger.Error("FAILURE", "error", err)
return 0, err
}
logger.Info("SUCCESS", "balance", bal)
return bal.Uint64(), nil
}
func GetNonce(ctx context.Context, address libcommon.Address) (uint64, error) {
node := devnet.CurrentNode(ctx)
if node == nil {
node = devnet.SelectBlockProducer(ctx)
}
res, err := node.GetTransactionCount(address, rpc.LatestBlock)
if err != nil {
return 0, fmt.Errorf("failed to get transaction count for address 0x%x: %v", address, err)
}
return res.Uint64(), nil
}