-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge remote-tracking branch 'origin/develop' into vcastellm/run-erigon
- Loading branch information
Showing
93 changed files
with
7,009 additions
and
1,068 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
package chaingersender | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"math/big" | ||
"time" | ||
|
||
"github.com/0xPolygon/cdk-contracts-tooling/contracts/manual/pessimisticglobalexitroot" | ||
cfgTypes "github.com/0xPolygon/cdk/config/types" | ||
"github.com/0xPolygon/cdk/log" | ||
"github.com/0xPolygonHermez/zkevm-ethtx-manager/ethtxmanager" | ||
"github.com/ethereum/go-ethereum" | ||
"github.com/ethereum/go-ethereum/accounts/abi/bind" | ||
"github.com/ethereum/go-ethereum/common" | ||
"github.com/ethereum/go-ethereum/core/types" | ||
) | ||
|
||
type EthClienter interface { | ||
ethereum.LogFilterer | ||
ethereum.BlockNumberReader | ||
ethereum.ChainReader | ||
bind.ContractBackend | ||
} | ||
|
||
type EthTxManager interface { | ||
Remove(ctx context.Context, id common.Hash) error | ||
ResultsByStatus(ctx context.Context, statuses []ethtxmanager.MonitoredTxStatus) ([]ethtxmanager.MonitoredTxResult, error) | ||
Result(ctx context.Context, id common.Hash) (ethtxmanager.MonitoredTxResult, error) | ||
Add(ctx context.Context, to *common.Address, forcedNonce *uint64, value *big.Int, data []byte, gasOffset uint64, sidecar *types.BlobTxSidecar) (common.Hash, error) | ||
} | ||
|
||
type EVMChainGERSender struct { | ||
gerContract *pessimisticglobalexitroot.Pessimisticglobalexitroot | ||
gerAddr common.Address | ||
sender common.Address | ||
client EthClienter | ||
ethTxMan EthTxManager | ||
gasOffset uint64 | ||
waitPeriodMonitorTx time.Duration | ||
} | ||
|
||
type EVMConfig struct { | ||
GlobalExitRootL2Addr common.Address `mapstructure:"GlobalExitRootL2"` | ||
URLRPCL2 string `mapstructure:"URLRPCL2"` | ||
ChainIDL2 uint64 `mapstructure:"ChainIDL2"` | ||
GasOffset uint64 `mapstructure:"GasOffset"` | ||
WaitPeriodMonitorTx cfgTypes.Duration `mapstructure:"WaitPeriodMonitorTx"` | ||
SenderAddr common.Address `mapstructure:"SenderAddr"` | ||
EthTxManager ethtxmanager.Config `mapstructure:"EthTxManager"` | ||
} | ||
|
||
func NewEVMChainGERSender( | ||
l2GlobalExitRoot, sender common.Address, | ||
l2Client EthClienter, | ||
ethTxMan EthTxManager, | ||
gasOffset uint64, | ||
waitPeriodMonitorTx time.Duration, | ||
) (*EVMChainGERSender, error) { | ||
gerContract, err := pessimisticglobalexitroot.NewPessimisticglobalexitroot(l2GlobalExitRoot, l2Client) | ||
if err != nil { | ||
return nil, err | ||
} | ||
return &EVMChainGERSender{ | ||
gerContract: gerContract, | ||
gerAddr: l2GlobalExitRoot, | ||
sender: sender, | ||
client: l2Client, | ||
ethTxMan: ethTxMan, | ||
gasOffset: gasOffset, | ||
waitPeriodMonitorTx: waitPeriodMonitorTx, | ||
}, nil | ||
} | ||
|
||
func (c *EVMChainGERSender) IsGERAlreadyInjected(ger common.Hash) (bool, error) { | ||
timestamp, err := c.gerContract.GlobalExitRootMap(&bind.CallOpts{Pending: false}, ger) | ||
if err != nil { | ||
return false, fmt.Errorf("error calling gerContract.GlobalExitRootMap: %w", err) | ||
} | ||
return timestamp.Cmp(big.NewInt(0)) != 0, nil | ||
} | ||
|
||
func (c *EVMChainGERSender) UpdateGERWaitUntilMined(ctx context.Context, ger common.Hash) error { | ||
abi, err := pessimisticglobalexitroot.PessimisticglobalexitrootMetaData.GetAbi() | ||
if err != nil { | ||
return err | ||
} | ||
data, err := abi.Pack("updateGlobalExitRoot", ger) | ||
if err != nil { | ||
return err | ||
} | ||
id, err := c.ethTxMan.Add(ctx, &c.gerAddr, nil, big.NewInt(0), data, c.gasOffset, nil) | ||
if err != nil { | ||
return err | ||
} | ||
for { | ||
time.Sleep(c.waitPeriodMonitorTx) | ||
log.Debugf("waiting for tx %s to be mined", id.Hex()) | ||
res, err := c.ethTxMan.Result(ctx, id) | ||
if err != nil { | ||
log.Error("error calling ethTxMan.Result: ", err) | ||
} | ||
switch res.Status { | ||
case ethtxmanager.MonitoredTxStatusCreated, | ||
ethtxmanager.MonitoredTxStatusSent: | ||
continue | ||
case ethtxmanager.MonitoredTxStatusFailed: | ||
return fmt.Errorf("tx %s failed", res.ID) | ||
case ethtxmanager.MonitoredTxStatusMined, | ||
ethtxmanager.MonitoredTxStatusSafe, | ||
ethtxmanager.MonitoredTxStatusFinalized: | ||
return nil | ||
default: | ||
log.Error("unexpected tx status: ", res.Status) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
package aggoracle | ||
|
||
import ( | ||
"github.com/0xPolygon/cdk/aggoracle/chaingersender" | ||
"github.com/0xPolygon/cdk/config/types" | ||
) | ||
|
||
type TargetChainType string | ||
|
||
const ( | ||
EVMChain TargetChainType = "EVM" | ||
) | ||
|
||
var ( | ||
SupportedChainTypes = []TargetChainType{EVMChain} | ||
) | ||
|
||
type Config struct { | ||
TargetChainType TargetChainType `mapstructure:"TargetChainType"` | ||
URLRPCL1 string `mapstructure:"URLRPCL1"` | ||
// TODO: BlockFinality doesnt work as per the jsonschema | ||
BlockFinality string `jsonschema:"enum=latest,enum=safe, enum=pending, enum=finalized" mapstructure:"BlockFinality"` | ||
WaitPeriodNextGER types.Duration `mapstructure:"WaitPeriodNextGER"` | ||
EVMSender chaingersender.EVMConfig `mapstructure:"EVMSender"` | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,214 @@ | ||
package aggoracle_test | ||
|
||
import ( | ||
"context" | ||
"errors" | ||
"fmt" | ||
"math/big" | ||
"strconv" | ||
"testing" | ||
"time" | ||
|
||
gerContractL1 "github.com/0xPolygon/cdk-contracts-tooling/contracts/manual/globalexitrootnopush0" | ||
gerContractEVMChain "github.com/0xPolygon/cdk-contracts-tooling/contracts/manual/pessimisticglobalexitrootnopush0" | ||
"github.com/0xPolygon/cdk/aggoracle" | ||
"github.com/0xPolygon/cdk/aggoracle/chaingersender" | ||
"github.com/0xPolygon/cdk/etherman" | ||
"github.com/0xPolygon/cdk/l1infotreesync" | ||
"github.com/0xPolygon/cdk/log" | ||
"github.com/0xPolygon/cdk/reorgdetector" | ||
ethtxmanager "github.com/0xPolygonHermez/zkevm-ethtx-manager/ethtxmanager" | ||
"github.com/ethereum/go-ethereum" | ||
"github.com/ethereum/go-ethereum/accounts/abi/bind" | ||
"github.com/ethereum/go-ethereum/common" | ||
"github.com/ethereum/go-ethereum/core/types" | ||
"github.com/ethereum/go-ethereum/crypto" | ||
"github.com/ethereum/go-ethereum/ethclient/simulated" | ||
mock "github.com/stretchr/testify/mock" | ||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
func TestEVM(t *testing.T) { | ||
ctx := context.Background() | ||
l1Client, syncer, gerL1Contract, authL1 := commonSetup(t) | ||
sender := evmSetup(t) | ||
oracle, err := aggoracle.New(sender, l1Client.Client(), syncer, etherman.LatestBlock, time.Millisecond) | ||
require.NoError(t, err) | ||
go oracle.Start(ctx) | ||
|
||
runTest(t, gerL1Contract, sender, l1Client, authL1) | ||
} | ||
|
||
func commonSetup(t *testing.T) ( | ||
*simulated.Backend, | ||
*l1infotreesync.L1InfoTreeSync, | ||
*gerContractL1.Globalexitrootnopush0, | ||
*bind.TransactOpts, | ||
) { | ||
// Config and spin up | ||
ctx := context.Background() | ||
// Simulated L1 | ||
privateKeyL1, err := crypto.GenerateKey() | ||
require.NoError(t, err) | ||
authL1, err := bind.NewKeyedTransactorWithChainID(privateKeyL1, big.NewInt(1337)) | ||
require.NoError(t, err) | ||
l1Client, gerL1Addr, gerL1Contract, err := newSimulatedL1(authL1) | ||
require.NoError(t, err) | ||
// Reorg detector | ||
dbPathReorgDetector := t.TempDir() | ||
reorg, err := reorgdetector.New(ctx, l1Client.Client(), dbPathReorgDetector) | ||
require.NoError(t, err) | ||
// Syncer | ||
dbPathSyncer := t.TempDir() | ||
syncer, err := l1infotreesync.New(ctx, dbPathSyncer, gerL1Addr, 10, etherman.LatestBlock, reorg, l1Client.Client(), time.Millisecond, 0, 100*time.Millisecond, 3) | ||
require.NoError(t, err) | ||
go syncer.Start(ctx) | ||
|
||
return l1Client, syncer, gerL1Contract, authL1 | ||
} | ||
|
||
func evmSetup(t *testing.T) aggoracle.ChainSender { | ||
privateKeyL2, err := crypto.GenerateKey() | ||
require.NoError(t, err) | ||
authL2, err := bind.NewKeyedTransactorWithChainID(privateKeyL2, big.NewInt(1337)) | ||
require.NoError(t, err) | ||
l2Client, gerL2Addr, _, err := newSimulatedEVMAggSovereignChain(authL2) | ||
require.NoError(t, err) | ||
ethTxManMock := aggoracle.NewEthTxManagerMock(t) | ||
// id, err := c.ethTxMan.Add(ctx, &c.gerAddr, nil, big.NewInt(0), tx.Data(), c.gasOffset, nil) | ||
ethTxManMock.On("Add", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything). | ||
Run(func(args mock.Arguments) { | ||
ctx := context.Background() | ||
nonce, err := l2Client.Client().PendingNonceAt(ctx, authL2.From) | ||
if err != nil { | ||
log.Error(err) | ||
return | ||
} | ||
gas, err := l2Client.Client().EstimateGas(ctx, ethereum.CallMsg{ | ||
From: authL2.From, | ||
To: args.Get(1).(*common.Address), | ||
Value: big.NewInt(0), | ||
Data: args.Get(4).([]byte), | ||
}) | ||
if err != nil { | ||
log.Error(err) | ||
res, err := l2Client.Client().CallContract(ctx, ethereum.CallMsg{ | ||
From: authL2.From, | ||
To: args.Get(1).(*common.Address), | ||
Value: big.NewInt(0), | ||
Data: args.Get(4).([]byte), | ||
}, nil) | ||
log.Debugf("contract call: %s", res) | ||
if err != nil { | ||
log.Error(err) | ||
} | ||
return | ||
} | ||
price, err := l2Client.Client().SuggestGasPrice(ctx) | ||
if err != nil { | ||
log.Error(err) | ||
} | ||
tx := types.NewTx(&types.LegacyTx{ | ||
To: args.Get(1).(*common.Address), | ||
Nonce: nonce, | ||
Value: big.NewInt(0), | ||
Data: args.Get(4).([]byte), | ||
Gas: gas, | ||
GasPrice: price, | ||
}) | ||
tx.Gas() | ||
signedTx, err := authL2.Signer(authL2.From, tx) | ||
if err != nil { | ||
log.Error(err) | ||
return | ||
} | ||
err = l2Client.Client().SendTransaction(ctx, signedTx) | ||
if err != nil { | ||
log.Error(err) | ||
return | ||
} | ||
l2Client.Commit() | ||
}). | ||
Return(common.Hash{}, nil) | ||
// res, err := c.ethTxMan.Result(ctx, id) | ||
ethTxManMock.On("Result", mock.Anything, mock.Anything). | ||
Return(ethtxmanager.MonitoredTxResult{Status: ethtxmanager.MonitoredTxStatusMined}, nil) | ||
sender, err := chaingersender.NewEVMChainGERSender(gerL2Addr, authL2.From, l2Client.Client(), ethTxManMock, 0, time.Millisecond*50) | ||
require.NoError(t, err) | ||
|
||
return sender | ||
} | ||
|
||
func newSimulatedL1(auth *bind.TransactOpts) ( | ||
client *simulated.Backend, | ||
gerAddr common.Address, | ||
gerContract *gerContractL1.Globalexitrootnopush0, | ||
err error, | ||
) { | ||
balance, _ := new(big.Int).SetString("10000000000000000000000000", 10) //nolint:gomnd | ||
address := auth.From | ||
genesisAlloc := map[common.Address]types.Account{ | ||
address: { | ||
Balance: balance, | ||
}, | ||
} | ||
blockGasLimit := uint64(999999999999999999) //nolint:gomnd | ||
client = simulated.NewBackend(genesisAlloc, simulated.WithBlockGasLimit(blockGasLimit)) | ||
|
||
gerAddr, _, gerContract, err = gerContractL1.DeployGlobalexitrootnopush0(auth, client.Client(), auth.From, auth.From) | ||
|
||
client.Commit() | ||
return | ||
} | ||
|
||
func newSimulatedEVMAggSovereignChain(auth *bind.TransactOpts) ( | ||
client *simulated.Backend, | ||
gerAddr common.Address, | ||
gerContract *gerContractEVMChain.Pessimisticglobalexitrootnopush0, | ||
err error, | ||
) { | ||
balance, _ := new(big.Int).SetString("10000000000000000000000000", 10) //nolint:gomnd | ||
address := auth.From | ||
genesisAlloc := map[common.Address]types.Account{ | ||
address: { | ||
Balance: balance, | ||
}, | ||
} | ||
blockGasLimit := uint64(999999999999999999) //nolint:gomnd | ||
client = simulated.NewBackend(genesisAlloc, simulated.WithBlockGasLimit(blockGasLimit)) | ||
|
||
gerAddr, _, gerContract, err = gerContractEVMChain.DeployPessimisticglobalexitrootnopush0(auth, client.Client(), auth.From) | ||
if err != nil { | ||
return | ||
} | ||
client.Commit() | ||
|
||
_GLOBAL_EXIT_ROOT_SETTER_ROLE := common.HexToHash("0x7b95520991dfda409891be0afa2635b63540f92ee996fda0bf695a166e5c5176") | ||
_, err = gerContract.GrantRole(auth, _GLOBAL_EXIT_ROOT_SETTER_ROLE, auth.From) | ||
client.Commit() | ||
hasRole, _ := gerContract.HasRole(&bind.CallOpts{Pending: false}, _GLOBAL_EXIT_ROOT_SETTER_ROLE, auth.From) | ||
if !hasRole { | ||
err = errors.New("failed to set role") | ||
} | ||
return | ||
} | ||
|
||
func runTest( | ||
t *testing.T, | ||
gerL1Contract *gerContractL1.Globalexitrootnopush0, | ||
sender aggoracle.ChainSender, | ||
l1Client *simulated.Backend, | ||
authL1 *bind.TransactOpts, | ||
) { | ||
for i := 0; i < 10; i++ { | ||
_, err := gerL1Contract.UpdateExitRoot(authL1, common.HexToHash(strconv.Itoa(i))) | ||
require.NoError(t, err) | ||
l1Client.Commit() | ||
time.Sleep(time.Millisecond * 50) | ||
expectedGER, err := gerL1Contract.GetLastGlobalExitRoot(&bind.CallOpts{Pending: false}) | ||
require.NoError(t, err) | ||
isInjected, err := sender.IsGERAlreadyInjected(expectedGER) | ||
require.NoError(t, err) | ||
require.True(t, isInjected, fmt.Sprintf("iteration %d, GER: %s", i, common.Bytes2Hex(expectedGER[:]))) | ||
} | ||
} |
Oops, something went wrong.