mirror of
https://gitlab.com/pulsechaincom/erigon-pulse.git
synced 2025-01-19 00:54:12 +00:00
298 lines
7.9 KiB
Go
298 lines
7.9 KiB
Go
package contracts_steps
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"math/big"
|
|
|
|
"github.com/ledgerwatch/erigon-lib/chain/networkname"
|
|
libcommon "github.com/ledgerwatch/erigon-lib/common"
|
|
"github.com/ledgerwatch/erigon/accounts/abi"
|
|
"github.com/ledgerwatch/erigon/accounts/abi/bind"
|
|
"github.com/ledgerwatch/erigon/cmd/devnet/accounts"
|
|
"github.com/ledgerwatch/erigon/cmd/devnet/blocks"
|
|
"github.com/ledgerwatch/erigon/cmd/devnet/contracts"
|
|
"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/rpc"
|
|
"github.com/ledgerwatch/erigon/turbo/adapter/ethapi"
|
|
)
|
|
|
|
func init() {
|
|
scenarios.MustRegisterStepHandlers(
|
|
scenarios.StepHandler(DeployChildChainSender),
|
|
scenarios.StepHandler(DeployRootChainReceiver),
|
|
scenarios.StepHandler(ProcessChildTransfers),
|
|
)
|
|
}
|
|
|
|
func DeployChildChainSender(ctx context.Context, deployerName string) (context.Context, error) {
|
|
deployer := accounts.GetAccount(deployerName)
|
|
ctx = devnet.WithCurrentNetwork(ctx, networkname.BorDevnetChainName)
|
|
|
|
auth, backend, err := contracts.DeploymentTransactor(ctx, deployer.Address)
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
receiverAddress, _ := scenarios.Param[libcommon.Address](ctx, "rootReceiverAddress")
|
|
|
|
waiter, cancel := blocks.BlockWaiter(ctx, contracts.DeploymentChecker)
|
|
defer cancel()
|
|
|
|
address, transaction, contract, err := contracts.DeployChildSender(auth, backend, receiverAddress)
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
block, err := waiter.Await(transaction.Hash())
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
devnet.Logger(ctx).Info("ChildSender deployed", "chain", networkname.BorDevnetChainName, "block", block.Number, "addr", address)
|
|
|
|
return scenarios.WithParam(ctx, "childSenderAddress", address).
|
|
WithParam("childSender", contract), nil
|
|
}
|
|
|
|
func DeployRootChainReceiver(ctx context.Context, deployerName string) (context.Context, error) {
|
|
deployer := accounts.GetAccount(deployerName)
|
|
ctx = devnet.WithCurrentNetwork(ctx, networkname.DevChainName)
|
|
|
|
auth, backend, err := contracts.DeploymentTransactor(ctx, deployer.Address)
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
waiter, cancel := blocks.BlockWaiter(ctx, contracts.DeploymentChecker)
|
|
defer cancel()
|
|
|
|
heimdall := services.Heimdall(ctx)
|
|
|
|
address, transaction, contract, err := contracts.DeployChildSender(auth, backend, heimdall.RootChainAddress())
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
block, err := waiter.Await(transaction.Hash())
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
devnet.Logger(ctx).Info("RootReceiver deployed", "chain", networkname.BorDevnetChainName, "block", block.Number, "addr", address)
|
|
|
|
return scenarios.WithParam(ctx, "rootReceiverAddress", address).
|
|
WithParam("rootReceiver", contract), nil
|
|
}
|
|
|
|
func ProcessChildTransfers(ctx context.Context, sourceName string, numberOfTransfers int, minTransfer int, maxTransfer int) error {
|
|
source := accounts.GetAccount(sourceName)
|
|
ctx = devnet.WithCurrentNetwork(ctx, networkname.DevChainName)
|
|
|
|
auth, err := contracts.TransactOpts(ctx, source.Address)
|
|
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
sender, _ := scenarios.Param[*contracts.ChildSender](ctx, "childSender")
|
|
|
|
receiver, _ := scenarios.Param[*contracts.RootReceiver](ctx, "rootReceiver")
|
|
receiverAddress, _ := scenarios.Param[libcommon.Address](ctx, "rootReceiverAddress")
|
|
|
|
receivedChan := make(chan *contracts.RootReceiverReceived)
|
|
receiverSubscription, err := receiver.WatchReceived(&bind.WatchOpts{}, receivedChan)
|
|
|
|
if err != nil {
|
|
return fmt.Errorf("Receiver subscription failed: %w", err)
|
|
}
|
|
|
|
defer receiverSubscription.Unsubscribe()
|
|
|
|
Uint256, _ := abi.NewType("uint256", "", nil)
|
|
Address, _ := abi.NewType("address", "", nil)
|
|
|
|
args := abi.Arguments{
|
|
{Name: "from", Type: Address},
|
|
{Name: "amount", Type: Uint256},
|
|
}
|
|
|
|
heimdall := services.Heimdall(ctx)
|
|
proofGenerator := services.ProofGenerator(ctx)
|
|
|
|
var sendTxHashes []libcommon.Hash
|
|
var lastTxBlockNum *big.Int
|
|
var receiptTopic libcommon.Hash
|
|
|
|
zeroHash := libcommon.Hash{}
|
|
|
|
for i := 0; i < numberOfTransfers; i++ {
|
|
amount := accounts.EtherAmount(float64(minTransfer))
|
|
|
|
err = func() error {
|
|
waiter, cancel := blocks.BlockWaiter(ctx, blocks.CompletionChecker)
|
|
defer cancel()
|
|
|
|
transaction, err := sender.SendToRoot(auth, amount)
|
|
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
block, terr := waiter.Await(transaction.Hash())
|
|
|
|
if terr != nil {
|
|
node := devnet.SelectBlockProducer(ctx)
|
|
|
|
traceResults, err := node.TraceTransaction(transaction.Hash())
|
|
|
|
if err != nil {
|
|
return fmt.Errorf("Send transaction failure: transaction trace failed: %w", err)
|
|
}
|
|
|
|
for _, traceResult := range traceResults {
|
|
callResults, err := node.TraceCall(rpc.AsBlockReference(block.Number), 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 fmt.Errorf("Send transaction failure: trace call failed: %w", err)
|
|
}
|
|
|
|
results, _ := json.MarshalIndent(callResults, " ", " ")
|
|
fmt.Println(string(results))
|
|
}
|
|
|
|
return terr
|
|
}
|
|
|
|
sendTxHashes = append(sendTxHashes, transaction.Hash())
|
|
lastTxBlockNum = block.Number
|
|
|
|
blockNum := block.Number.Uint64()
|
|
|
|
logs, err := sender.FilterMessageSent(&bind.FilterOpts{
|
|
Start: blockNum,
|
|
End: &blockNum,
|
|
})
|
|
|
|
if err != nil {
|
|
return fmt.Errorf("Failed to get post sync logs: %w", err)
|
|
}
|
|
|
|
for logs.Next() {
|
|
values, err := args.Unpack(logs.Event.Message)
|
|
|
|
if err != nil {
|
|
return fmt.Errorf("Failed unpack log args: %w", err)
|
|
}
|
|
|
|
recceiverAddressValue, ok := values[0].(libcommon.Address)
|
|
|
|
if !ok {
|
|
return fmt.Errorf("Unexpected arg type: expected: %T, got %T", libcommon.Address{}, values[0])
|
|
}
|
|
|
|
sender, ok := values[1].(libcommon.Address)
|
|
|
|
if !ok {
|
|
return fmt.Errorf("Unexpected arg type: expected: %T, got %T", libcommon.Address{}, values[0])
|
|
}
|
|
|
|
sentAmount, ok := values[1].(*big.Int)
|
|
|
|
if !ok {
|
|
return fmt.Errorf("Unexpected arg type: expected: %T, got %T", &big.Int{}, values[1])
|
|
}
|
|
|
|
if recceiverAddressValue != receiverAddress {
|
|
return fmt.Errorf("Unexpected sender: expected: %s, got %s", receiverAddress, recceiverAddressValue)
|
|
}
|
|
|
|
if sender != source.Address {
|
|
return fmt.Errorf("Unexpected sender: expected: %s, got %s", source.Address, sender)
|
|
}
|
|
|
|
if amount.Cmp(sentAmount) != 0 {
|
|
return fmt.Errorf("Unexpected sent amount: expected: %s, got %s", amount, sentAmount)
|
|
}
|
|
|
|
if receiptTopic == zeroHash {
|
|
receiptTopic = logs.Event.Raw.Topics[0]
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}()
|
|
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
auth.Nonce = (&big.Int{}).Add(auth.Nonce, big.NewInt(1))
|
|
}
|
|
|
|
devnet.Logger(ctx).Info("Waiting for checkpoint")
|
|
|
|
err = heimdall.AwaitCheckpoint(ctx, lastTxBlockNum)
|
|
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
for _, hash := range sendTxHashes {
|
|
payload, err := proofGenerator.GenerateExitPayload(ctx, hash, receiptTopic, 0)
|
|
|
|
waiter, cancel := blocks.BlockWaiter(ctx, blocks.CompletionChecker)
|
|
defer cancel()
|
|
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
transaction, err := receiver.ReceiveMessage(auth, payload)
|
|
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if _, err := waiter.Await(transaction.Hash()); err != nil {
|
|
return err
|
|
}
|
|
|
|
}
|
|
|
|
receivedCount := 0
|
|
|
|
devnet.Logger(ctx).Info("Waiting for receive events")
|
|
|
|
for received := range receivedChan {
|
|
if received.Source != source.Address {
|
|
return fmt.Errorf("Source address mismatched: expected: %s, got: %s", source.Address, received.Source)
|
|
}
|
|
|
|
if received.Amount.Cmp(accounts.EtherAmount(float64(minTransfer))) != 0 {
|
|
return fmt.Errorf("Amount mismatched: expected: %s, got: %s", accounts.EtherAmount(float64(minTransfer)), received.Amount)
|
|
}
|
|
|
|
receivedCount++
|
|
if receivedCount == numberOfTransfers {
|
|
break
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|