Commit a145e096 authored by mergify[bot]'s avatar mergify[bot] Committed by GitHub

Merge branch 'develop' into dependabot/npm_and_yarn/eslint-plugin-prettier-4.2.1

parents fd71b159 2963dd94
...@@ -46,7 +46,7 @@ func newDepositResponse(deposits *database.L1BridgeDepositsResponse) DepositResp ...@@ -46,7 +46,7 @@ func newDepositResponse(deposits *database.L1BridgeDepositsResponse) DepositResp
}, },
From: deposit.L1BridgeDeposit.Tx.FromAddress.String(), From: deposit.L1BridgeDeposit.Tx.FromAddress.String(),
To: deposit.L1BridgeDeposit.Tx.ToAddress.String(), To: deposit.L1BridgeDeposit.Tx.ToAddress.String(),
Amount: deposit.L1BridgeDeposit.Tx.Amount.Int.String(), Amount: deposit.L1BridgeDeposit.Tx.Amount.String(),
L1Token: TokenInfo{ L1Token: TokenInfo{
ChainId: 1, ChainId: 1,
Address: deposit.L1BridgeDeposit.TokenPair.LocalTokenAddress.String(), Address: deposit.L1BridgeDeposit.TokenPair.LocalTokenAddress.String(),
......
...@@ -60,7 +60,7 @@ func newWithdrawalResponse(withdrawals *database.L2BridgeWithdrawalsResponse) Wi ...@@ -60,7 +60,7 @@ func newWithdrawalResponse(withdrawals *database.L2BridgeWithdrawalsResponse) Wi
From: withdrawal.L2BridgeWithdrawal.Tx.FromAddress.String(), From: withdrawal.L2BridgeWithdrawal.Tx.FromAddress.String(),
To: withdrawal.L2BridgeWithdrawal.Tx.ToAddress.String(), To: withdrawal.L2BridgeWithdrawal.Tx.ToAddress.String(),
TransactionHash: withdrawal.L2TransactionHash.String(), TransactionHash: withdrawal.L2TransactionHash.String(),
Amount: withdrawal.L2BridgeWithdrawal.Tx.Amount.Int.String(), Amount: withdrawal.L2BridgeWithdrawal.Tx.Amount.String(),
Proof: Proof{ Proof: Proof{
TransactionHash: withdrawal.ProvenL1TransactionHash.String(), TransactionHash: withdrawal.ProvenL1TransactionHash.String(),
BlockTimestamp: withdrawal.L2BridgeWithdrawal.Tx.Timestamp, BlockTimestamp: withdrawal.L2BridgeWithdrawal.Tx.Timestamp,
......
...@@ -20,7 +20,7 @@ import ( ...@@ -20,7 +20,7 @@ import (
type BlockHeader struct { type BlockHeader struct {
Hash common.Hash `gorm:"primaryKey;serializer:bytes"` Hash common.Hash `gorm:"primaryKey;serializer:bytes"`
ParentHash common.Hash `gorm:"serializer:bytes"` ParentHash common.Hash `gorm:"serializer:bytes"`
Number U256 Number *big.Int `gorm:"serializer:u256"`
Timestamp uint64 Timestamp uint64
RLPHeader *RLPHeader `gorm:"serializer:rlp;column:rlp_bytes"` RLPHeader *RLPHeader `gorm:"serializer:rlp;column:rlp_bytes"`
...@@ -30,7 +30,7 @@ func BlockHeaderFromHeader(header *types.Header) BlockHeader { ...@@ -30,7 +30,7 @@ func BlockHeaderFromHeader(header *types.Header) BlockHeader {
return BlockHeader{ return BlockHeader{
Hash: header.Hash(), Hash: header.Hash(),
ParentHash: header.ParentHash, ParentHash: header.ParentHash,
Number: U256{Int: header.Number}, Number: header.Number,
Timestamp: header.Time, Timestamp: header.Time,
RLPHeader: (*RLPHeader)(header), RLPHeader: (*RLPHeader)(header),
...@@ -58,8 +58,8 @@ type LegacyStateBatch struct { ...@@ -58,8 +58,8 @@ type LegacyStateBatch struct {
type OutputProposal struct { type OutputProposal struct {
OutputRoot common.Hash `gorm:"primaryKey;serializer:bytes"` OutputRoot common.Hash `gorm:"primaryKey;serializer:bytes"`
L2OutputIndex U256 L2OutputIndex *big.Int `gorm:"serializer:u256"`
L2BlockNumber U256 L2BlockNumber *big.Int `gorm:"serializer:u256"`
L1ContractEventGUID uuid.UUID L1ContractEventGUID uuid.UUID
} }
...@@ -165,7 +165,7 @@ func (db *blocksDB) LatestCheckpointedOutput() (*OutputProposal, error) { ...@@ -165,7 +165,7 @@ func (db *blocksDB) LatestCheckpointedOutput() (*OutputProposal, error) {
func (db *blocksDB) OutputProposal(index *big.Int) (*OutputProposal, error) { func (db *blocksDB) OutputProposal(index *big.Int) (*OutputProposal, error) {
var outputProposal OutputProposal var outputProposal OutputProposal
result := db.gorm.Where(&OutputProposal{L2OutputIndex: U256{Int: index}}).Take(&outputProposal) result := db.gorm.Where(&OutputProposal{L2OutputIndex: index}).Take(&outputProposal)
if result.Error != nil { if result.Error != nil {
if errors.Is(result.Error, gorm.ErrRecordNotFound) { if errors.Is(result.Error, gorm.ErrRecordNotFound) {
return nil, nil return nil, nil
......
...@@ -3,6 +3,7 @@ package database ...@@ -3,6 +3,7 @@ package database
import ( import (
"errors" "errors"
"fmt" "fmt"
"math/big"
"gorm.io/gorm" "gorm.io/gorm"
...@@ -17,13 +18,13 @@ import ( ...@@ -17,13 +18,13 @@ import (
type BridgeMessage struct { type BridgeMessage struct {
MessageHash common.Hash `gorm:"primaryKey;serializer:bytes"` MessageHash common.Hash `gorm:"primaryKey;serializer:bytes"`
Nonce U256 Nonce *big.Int `gorm:"serializer:u256"`
SentMessageEventGUID uuid.UUID SentMessageEventGUID uuid.UUID
RelayedMessageEventGUID *uuid.UUID RelayedMessageEventGUID *uuid.UUID
Tx Transaction `gorm:"embedded"` Tx Transaction `gorm:"embedded"`
GasLimit U256 GasLimit *big.Int `gorm:"serializer:u256"`
} }
type L1BridgeMessage struct { type L1BridgeMessage struct {
......
...@@ -3,6 +3,7 @@ package database ...@@ -3,6 +3,7 @@ package database
import ( import (
"errors" "errors"
"fmt" "fmt"
"math/big"
"github.com/google/uuid" "github.com/google/uuid"
"gorm.io/gorm" "gorm.io/gorm"
...@@ -17,8 +18,8 @@ import ( ...@@ -17,8 +18,8 @@ import (
type Transaction struct { type Transaction struct {
FromAddress common.Address `gorm:"serializer:bytes"` FromAddress common.Address `gorm:"serializer:bytes"`
ToAddress common.Address `gorm:"serializer:bytes"` ToAddress common.Address `gorm:"serializer:bytes"`
Amount U256 Amount *big.Int `gorm:"serializer:u256"`
Data Bytes `gorm:"serializer:bytes"` Data Bytes `gorm:"serializer:bytes"`
Timestamp uint64 Timestamp uint64
} }
...@@ -28,12 +29,12 @@ type L1TransactionDeposit struct { ...@@ -28,12 +29,12 @@ type L1TransactionDeposit struct {
InitiatedL1EventGUID uuid.UUID InitiatedL1EventGUID uuid.UUID
Tx Transaction `gorm:"embedded"` Tx Transaction `gorm:"embedded"`
GasLimit U256 GasLimit *big.Int `gorm:"serializer:u256"`
} }
type L2TransactionWithdrawal struct { type L2TransactionWithdrawal struct {
WithdrawalHash common.Hash `gorm:"serializer:bytes;primaryKey"` WithdrawalHash common.Hash `gorm:"serializer:bytes;primaryKey"`
Nonce U256 Nonce *big.Int `gorm:"serializer:u256"`
InitiatedL2EventGUID uuid.UUID InitiatedL2EventGUID uuid.UUID
ProvenL1EventGUID *uuid.UUID ProvenL1EventGUID *uuid.UUID
...@@ -41,7 +42,7 @@ type L2TransactionWithdrawal struct { ...@@ -41,7 +42,7 @@ type L2TransactionWithdrawal struct {
Succeeded *bool Succeeded *bool
Tx Transaction `gorm:"embedded"` Tx Transaction `gorm:"embedded"`
GasLimit U256 GasLimit *big.Int `gorm:"serializer:u256"`
} }
type BridgeTransactionsView interface { type BridgeTransactionsView interface {
......
package serializers
import (
"context"
"fmt"
"math/big"
"reflect"
"github.com/jackc/pgtype"
"gorm.io/gorm/schema"
)
var (
big10 = big.NewInt(10)
u256BigIntOverflow = new(big.Int).Exp(big.NewInt(2), big.NewInt(256), nil)
)
type U256Serializer struct{}
func init() {
schema.RegisterSerializer("u256", U256Serializer{})
}
func (U256Serializer) Scan(ctx context.Context, field *schema.Field, dst reflect.Value, dbValue interface{}) error {
if dbValue == nil {
return nil
} else if field.FieldType != reflect.TypeOf((*big.Int)(nil)) {
return fmt.Errorf("can only deserialize into a *big.Int: %T", field.FieldType)
}
numeric := new(pgtype.Numeric)
err := numeric.Scan(dbValue)
if err != nil {
return err
}
bigInt := numeric.Int
if numeric.Exp > 0 {
factor := new(big.Int).Exp(big10, big.NewInt(int64(numeric.Exp)), nil)
bigInt.Mul(bigInt, factor)
}
if bigInt.Cmp(u256BigIntOverflow) >= 0 {
return fmt.Errorf("deserialized number larger than u256 can hold: %s", bigInt)
}
field.ReflectValueOf(ctx, dst).Set(reflect.ValueOf(bigInt))
return nil
}
func (U256Serializer) Value(ctx context.Context, field *schema.Field, dst reflect.Value, fieldValue interface{}) (interface{}, error) {
if fieldValue == nil || (field.FieldType.Kind() == reflect.Pointer && reflect.ValueOf(fieldValue).IsNil()) {
return nil, nil
} else if field.FieldType != reflect.TypeOf((*big.Int)(nil)) {
return nil, fmt.Errorf("can only serialize a *big.Int: %T", field.FieldType)
}
numeric := pgtype.Numeric{Int: fieldValue.(*big.Int), Status: pgtype.Present}
return numeric.Value()
}
package database package database
import ( import (
"database/sql/driver"
"errors"
"io" "io"
"math/big"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
"github.com/jackc/pgtype"
) )
var u256BigIntOverflow = new(big.Int).Exp(big.NewInt(2), big.NewInt(256), nil) // Wrapper over types.Header such that we can get an RLP
var big10 = big.NewInt(10) // encoder over it via a `types.Block` wrapper
var ErrU256Overflow = errors.New("number exceeds u256")
var ErrU256ContainsDecimal = errors.New("number contains fractional digits")
var ErrU256Null = errors.New("number cannot be null")
// U256 is a wrapper over big.Int that conforms to the database U256 numeric domain type
type U256 struct {
Int *big.Int
}
// Scan implements the database/sql Scanner interface.
func (u256 *U256) Scan(src interface{}) error {
// deserialize as a numeric
var numeric pgtype.Numeric
err := numeric.Scan(src)
if err != nil {
return err
} else if numeric.Exp < 0 {
return ErrU256ContainsDecimal
} else if numeric.Status == pgtype.Null {
return ErrU256Null
}
// factor in the powers of 10
num := numeric.Int
if numeric.Exp > 0 {
factor := new(big.Int).Exp(big10, big.NewInt(int64(numeric.Exp)), nil)
num.Mul(num, factor)
}
// check bounds before setting the u256
if num.Cmp(u256BigIntOverflow) >= 0 {
return ErrU256Overflow
} else {
u256.Int = num
}
return nil
}
// Value implements the database/sql/driver Valuer interface.
func (u256 U256) Value() (driver.Value, error) {
// check bounds
if u256.Int == nil {
return nil, ErrU256Null
} else if u256.Int.Cmp(u256BigIntOverflow) >= 0 {
return nil, ErrU256Overflow
}
// simply encode as a numeric with no Exp set (non-decimal)
numeric := pgtype.Numeric{Int: u256.Int, Status: pgtype.Present}
return numeric.Value()
}
type RLPHeader types.Header type RLPHeader types.Header
...@@ -94,6 +37,9 @@ func (h *RLPHeader) Hash() common.Hash { ...@@ -94,6 +37,9 @@ func (h *RLPHeader) Hash() common.Hash {
return h.Header().Hash() return h.Header().Hash()
} }
// Type definition for []byte to conform to the
// interface expected by the `bytes` serializer
type Bytes []byte type Bytes []byte
func (b Bytes) Bytes() []byte { func (b Bytes) Bytes() []byte {
......
...@@ -59,9 +59,9 @@ func TestE2EBridgeL1CrossDomainMessenger(t *testing.T) { ...@@ -59,9 +59,9 @@ func TestE2EBridgeL1CrossDomainMessenger(t *testing.T) {
require.NotNil(t, sentMessage) require.NotNil(t, sentMessage)
require.NotNil(t, sentMessage.SentMessageEventGUID) require.NotNil(t, sentMessage.SentMessageEventGUID)
require.Equal(t, depositInfo.DepositTx.SourceHash, sentMessage.TransactionSourceHash) require.Equal(t, depositInfo.DepositTx.SourceHash, sentMessage.TransactionSourceHash)
require.Equal(t, nonce.Uint64(), sentMessage.Nonce.Int.Uint64()) require.Equal(t, nonce.Uint64(), sentMessage.Nonce.Uint64())
require.Equal(t, uint64(100_000), sentMessage.GasLimit.Int.Uint64()) require.Equal(t, uint64(100_000), sentMessage.GasLimit.Uint64())
require.Equal(t, big.NewInt(params.Ether), sentMessage.Tx.Amount.Int) require.Equal(t, uint64(params.Ether), sentMessage.Tx.Amount.Uint64())
require.Equal(t, aliceAddr, sentMessage.Tx.FromAddress) require.Equal(t, aliceAddr, sentMessage.Tx.FromAddress)
require.Equal(t, aliceAddr, sentMessage.Tx.ToAddress) require.Equal(t, aliceAddr, sentMessage.Tx.ToAddress)
require.ElementsMatch(t, calldata, sentMessage.Tx.Data) require.ElementsMatch(t, calldata, sentMessage.Tx.Data)
...@@ -146,9 +146,9 @@ func TestE2EBridgeL2CrossDomainMessenger(t *testing.T) { ...@@ -146,9 +146,9 @@ func TestE2EBridgeL2CrossDomainMessenger(t *testing.T) {
require.NotNil(t, sentMessage) require.NotNil(t, sentMessage)
require.NotNil(t, sentMessage.SentMessageEventGUID) require.NotNil(t, sentMessage.SentMessageEventGUID)
require.Equal(t, withdrawalHash, sentMessage.TransactionWithdrawalHash) require.Equal(t, withdrawalHash, sentMessage.TransactionWithdrawalHash)
require.Equal(t, nonce.Uint64(), sentMessage.Nonce.Int.Uint64()) require.Equal(t, nonce.Uint64(), sentMessage.Nonce.Uint64())
require.Equal(t, uint64(100_000), sentMessage.GasLimit.Int.Uint64()) require.Equal(t, uint64(100_000), sentMessage.GasLimit.Uint64())
require.Equal(t, big.NewInt(params.Ether), sentMessage.Tx.Amount.Int) require.Equal(t, uint64(params.Ether), sentMessage.Tx.Amount.Uint64())
require.Equal(t, aliceAddr, sentMessage.Tx.FromAddress) require.Equal(t, aliceAddr, sentMessage.Tx.FromAddress)
require.Equal(t, aliceAddr, sentMessage.Tx.ToAddress) require.Equal(t, aliceAddr, sentMessage.Tx.ToAddress)
require.ElementsMatch(t, calldata, sentMessage.Tx.Data) require.ElementsMatch(t, calldata, sentMessage.Tx.Data)
......
...@@ -54,8 +54,8 @@ func TestE2EBridgeTransactionsOptimismPortalDeposits(t *testing.T) { ...@@ -54,8 +54,8 @@ func TestE2EBridgeTransactionsOptimismPortalDeposits(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.NotNil(t, deposit) require.NotNil(t, deposit)
require.Equal(t, depositL2TxHash, deposit.L2TransactionHash) require.Equal(t, depositL2TxHash, deposit.L2TransactionHash)
require.Equal(t, big.NewInt(100_000), deposit.GasLimit.Int) require.Equal(t, uint64(100_000), deposit.GasLimit.Uint64())
require.Equal(t, big.NewInt(params.Ether), deposit.Tx.Amount.Int) require.Equal(t, uint64(params.Ether), deposit.Tx.Amount.Uint64())
require.Equal(t, aliceAddr, deposit.Tx.FromAddress) require.Equal(t, aliceAddr, deposit.Tx.FromAddress)
require.Equal(t, aliceAddr, deposit.Tx.ToAddress) require.Equal(t, aliceAddr, deposit.Tx.ToAddress)
require.ElementsMatch(t, calldata, deposit.Tx.Data) require.ElementsMatch(t, calldata, deposit.Tx.Data)
...@@ -113,9 +113,9 @@ func TestE2EBridgeTransactionsL2ToL1MessagePasserWithdrawal(t *testing.T) { ...@@ -113,9 +113,9 @@ func TestE2EBridgeTransactionsL2ToL1MessagePasserWithdrawal(t *testing.T) {
withdraw, err := testSuite.DB.BridgeTransactions.L2TransactionWithdrawal(withdrawalHash) withdraw, err := testSuite.DB.BridgeTransactions.L2TransactionWithdrawal(withdrawalHash)
require.NoError(t, err) require.NoError(t, err)
require.NotNil(t, withdraw) require.NotNil(t, withdraw)
require.Equal(t, msgPassed.Nonce.Uint64(), withdraw.Nonce.Int.Uint64()) require.Equal(t, msgPassed.Nonce.Uint64(), withdraw.Nonce.Uint64())
require.Equal(t, big.NewInt(100_000), withdraw.GasLimit.Int) require.Equal(t, uint64(100_000), withdraw.GasLimit.Uint64())
require.Equal(t, big.NewInt(params.Ether), withdraw.Tx.Amount.Int) require.Equal(t, uint64(params.Ether), withdraw.Tx.Amount.Uint64())
require.Equal(t, aliceAddr, withdraw.Tx.FromAddress) require.Equal(t, aliceAddr, withdraw.Tx.FromAddress)
require.Equal(t, aliceAddr, withdraw.Tx.ToAddress) require.Equal(t, aliceAddr, withdraw.Tx.ToAddress)
require.ElementsMatch(t, calldata, withdraw.Tx.Data) require.ElementsMatch(t, calldata, withdraw.Tx.Data)
......
...@@ -63,7 +63,7 @@ func TestE2EBridgeTransfersStandardBridgeETHDeposit(t *testing.T) { ...@@ -63,7 +63,7 @@ func TestE2EBridgeTransfersStandardBridgeETHDeposit(t *testing.T) {
require.Equal(t, depositInfo.DepositTx.SourceHash, deposit.TransactionSourceHash) require.Equal(t, depositInfo.DepositTx.SourceHash, deposit.TransactionSourceHash)
require.Equal(t, predeploys.LegacyERC20ETHAddr, deposit.TokenPair.LocalTokenAddress) require.Equal(t, predeploys.LegacyERC20ETHAddr, deposit.TokenPair.LocalTokenAddress)
require.Equal(t, predeploys.LegacyERC20ETHAddr, deposit.TokenPair.RemoteTokenAddress) require.Equal(t, predeploys.LegacyERC20ETHAddr, deposit.TokenPair.RemoteTokenAddress)
require.Equal(t, big.NewInt(params.Ether), deposit.Tx.Amount.Int) require.Equal(t, uint64(params.Ether), deposit.Tx.Amount.Uint64())
require.Equal(t, aliceAddr, deposit.Tx.FromAddress) require.Equal(t, aliceAddr, deposit.Tx.FromAddress)
require.Equal(t, aliceAddr, deposit.Tx.ToAddress) require.Equal(t, aliceAddr, deposit.Tx.ToAddress)
require.Equal(t, byte(1), deposit.Tx.Data[0]) require.Equal(t, byte(1), deposit.Tx.Data[0])
...@@ -235,7 +235,7 @@ func TestE2EBridgeTransfersOptimismPortalETHReceive(t *testing.T) { ...@@ -235,7 +235,7 @@ func TestE2EBridgeTransfersOptimismPortalETHReceive(t *testing.T) {
require.Equal(t, depositInfo.DepositTx.SourceHash, deposit.TransactionSourceHash) require.Equal(t, depositInfo.DepositTx.SourceHash, deposit.TransactionSourceHash)
require.Equal(t, predeploys.LegacyERC20ETHAddr, deposit.TokenPair.LocalTokenAddress) require.Equal(t, predeploys.LegacyERC20ETHAddr, deposit.TokenPair.LocalTokenAddress)
require.Equal(t, predeploys.LegacyERC20ETHAddr, deposit.TokenPair.RemoteTokenAddress) require.Equal(t, predeploys.LegacyERC20ETHAddr, deposit.TokenPair.RemoteTokenAddress)
require.Equal(t, big.NewInt(params.Ether), deposit.Tx.Amount.Int) require.Equal(t, uint64(params.Ether), deposit.Tx.Amount.Uint64())
require.Equal(t, aliceAddr, deposit.Tx.FromAddress) require.Equal(t, aliceAddr, deposit.Tx.FromAddress)
require.Equal(t, aliceAddr, deposit.Tx.ToAddress) require.Equal(t, aliceAddr, deposit.Tx.ToAddress)
require.Len(t, deposit.Tx.Data, 0) require.Len(t, deposit.Tx.Data, 0)
...@@ -306,7 +306,7 @@ func TestE2EBridgeTransfersStandardBridgeETHWithdrawal(t *testing.T) { ...@@ -306,7 +306,7 @@ func TestE2EBridgeTransfersStandardBridgeETHWithdrawal(t *testing.T) {
require.Equal(t, withdrawalHash, withdrawal.TransactionWithdrawalHash) require.Equal(t, withdrawalHash, withdrawal.TransactionWithdrawalHash)
require.Equal(t, predeploys.LegacyERC20ETHAddr, withdrawal.TokenPair.LocalTokenAddress) require.Equal(t, predeploys.LegacyERC20ETHAddr, withdrawal.TokenPair.LocalTokenAddress)
require.Equal(t, predeploys.LegacyERC20ETHAddr, withdrawal.TokenPair.RemoteTokenAddress) require.Equal(t, predeploys.LegacyERC20ETHAddr, withdrawal.TokenPair.RemoteTokenAddress)
require.Equal(t, big.NewInt(params.Ether), withdrawal.Tx.Amount.Int) require.Equal(t, uint64(params.Ether), withdrawal.Tx.Amount.Uint64())
require.Equal(t, aliceAddr, withdrawal.Tx.FromAddress) require.Equal(t, aliceAddr, withdrawal.Tx.FromAddress)
require.Equal(t, aliceAddr, withdrawal.Tx.ToAddress) require.Equal(t, aliceAddr, withdrawal.Tx.ToAddress)
require.Equal(t, byte(1), withdrawal.Tx.Data[0]) require.Equal(t, byte(1), withdrawal.Tx.Data[0])
...@@ -390,7 +390,7 @@ func TestE2EBridgeTransfersL2ToL1MessagePasserETHReceive(t *testing.T) { ...@@ -390,7 +390,7 @@ func TestE2EBridgeTransfersL2ToL1MessagePasserETHReceive(t *testing.T) {
require.Equal(t, withdrawalHash, withdrawal.TransactionWithdrawalHash) require.Equal(t, withdrawalHash, withdrawal.TransactionWithdrawalHash)
require.Equal(t, predeploys.LegacyERC20ETHAddr, withdrawal.TokenPair.LocalTokenAddress) require.Equal(t, predeploys.LegacyERC20ETHAddr, withdrawal.TokenPair.LocalTokenAddress)
require.Equal(t, predeploys.LegacyERC20ETHAddr, withdrawal.TokenPair.RemoteTokenAddress) require.Equal(t, predeploys.LegacyERC20ETHAddr, withdrawal.TokenPair.RemoteTokenAddress)
require.Equal(t, big.NewInt(params.Ether), withdrawal.Tx.Amount.Int) require.Equal(t, uint64(params.Ether), withdrawal.Tx.Amount.Uint64())
require.Equal(t, aliceAddr, withdrawal.Tx.FromAddress) require.Equal(t, aliceAddr, withdrawal.Tx.FromAddress)
require.Equal(t, aliceAddr, withdrawal.Tx.ToAddress) require.Equal(t, aliceAddr, withdrawal.Tx.ToAddress)
require.Len(t, withdrawal.Tx.Data, 0) require.Len(t, withdrawal.Tx.Data, 0)
......
...@@ -40,19 +40,19 @@ func TestE2EETL(t *testing.T) { ...@@ -40,19 +40,19 @@ func TestE2EETL(t *testing.T) {
l2Header, err := testSuite.DB.Blocks.L2LatestBlockHeader() l2Header, err := testSuite.DB.Blocks.L2LatestBlockHeader()
require.NoError(t, err) require.NoError(t, err)
return (l1Header != nil && l1Header.Number.Int.Uint64() >= l1Height) && (l2Header != nil && l2Header.Number.Int.Uint64() >= 9), nil return (l1Header != nil && l1Header.Number.Uint64() >= l1Height) && (l2Header != nil && l2Header.Number.Uint64() >= 9), nil
})) }))
t.Run("indexes all L2 blocks", func(t *testing.T) { t.Run("indexes all L2 blocks", func(t *testing.T) {
latestL2Header, err := testSuite.DB.Blocks.L2LatestBlockHeader() latestL2Header, err := testSuite.DB.Blocks.L2LatestBlockHeader()
require.NoError(t, err) require.NoError(t, err)
require.NotNil(t, latestL2Header) require.NotNil(t, latestL2Header)
require.True(t, latestL2Header.Number.Int.Uint64() >= 9) require.True(t, latestL2Header.Number.Uint64() >= 9)
for i := int64(0); i < 10; i++ { for i := int64(0); i < 10; i++ {
height := big.NewInt(i) height := big.NewInt(i)
indexedHeader, err := testSuite.DB.Blocks.L2BlockHeaderWithFilter(database.BlockHeader{Number: database.U256{Int: height}}) indexedHeader, err := testSuite.DB.Blocks.L2BlockHeaderWithFilter(database.BlockHeader{Number: height})
require.NoError(t, err) require.NoError(t, err)
require.NotNil(t, indexedHeader) require.NotNil(t, indexedHeader)
...@@ -60,7 +60,7 @@ func TestE2EETL(t *testing.T) { ...@@ -60,7 +60,7 @@ func TestE2EETL(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.NotNil(t, indexedHeader) require.NotNil(t, indexedHeader)
require.Equal(t, header.Number.Int64(), indexedHeader.Number.Int.Int64()) require.Equal(t, header.Number.Int64(), indexedHeader.Number.Int64())
require.Equal(t, header.Hash(), indexedHeader.Hash) require.Equal(t, header.Hash(), indexedHeader.Hash)
require.Equal(t, header.ParentHash, indexedHeader.ParentHash) require.Equal(t, header.ParentHash, indexedHeader.ParentHash)
require.Equal(t, header.Time, indexedHeader.Timestamp) require.Equal(t, header.Time, indexedHeader.Timestamp)
...@@ -144,7 +144,7 @@ func TestE2EETL(t *testing.T) { ...@@ -144,7 +144,7 @@ func TestE2EETL(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, block.Hash(), l1BlockHeader.Hash) require.Equal(t, block.Hash(), l1BlockHeader.Hash)
require.Equal(t, block.ParentHash(), l1BlockHeader.ParentHash) require.Equal(t, block.ParentHash(), l1BlockHeader.ParentHash)
require.Equal(t, block.Number(), l1BlockHeader.Number.Int) require.Equal(t, block.Number().Uint64(), l1BlockHeader.Number.Uint64())
require.Equal(t, block.Time(), l1BlockHeader.Timestamp) require.Equal(t, block.Time(), l1BlockHeader.Timestamp)
// ensure the right rlp encoding is stored. checking the hashes // ensure the right rlp encoding is stored. checking the hashes
......
...@@ -38,7 +38,7 @@ func NewL1ETL(log log.Logger, db *database.DB, client node.EthClient, startHeigh ...@@ -38,7 +38,7 @@ func NewL1ETL(log log.Logger, db *database.DB, client node.EthClient, startHeigh
// Determine the starting height for traversal // Determine the starting height for traversal
var fromHeader *types.Header var fromHeader *types.Header
if latestHeader != nil { if latestHeader != nil {
log.Info("detected last indexed block", "number", latestHeader.Number.Int, "hash", latestHeader.Hash) log.Info("detected last indexed block", "number", latestHeader.Number, "hash", latestHeader.Hash)
fromHeader = latestHeader.RLPHeader.Header() fromHeader = latestHeader.RLPHeader.Header()
} else if startHeight.BitLen() > 0 { } else if startHeight.BitLen() > 0 {
......
...@@ -35,7 +35,7 @@ func NewL2ETL(log log.Logger, db *database.DB, client node.EthClient) (*L2ETL, e ...@@ -35,7 +35,7 @@ func NewL2ETL(log log.Logger, db *database.DB, client node.EthClient) (*L2ETL, e
var fromHeader *types.Header var fromHeader *types.Header
if latestHeader != nil { if latestHeader != nil {
log.Info("detected last indexed block", "number", latestHeader.Number.Int, "hash", latestHeader.Hash) log.Info("detected last indexed block", "number", latestHeader.Number, "hash", latestHeader.Hash)
fromHeader = latestHeader.RLPHeader.Header() fromHeader = latestHeader.RLPHeader.Header()
} else { } else {
log.Info("no indexed state, starting from genesis") log.Info("no indexed state, starting from genesis")
......
...@@ -107,7 +107,7 @@ func (b *BridgeProcessor) Start(ctx context.Context) error { ...@@ -107,7 +107,7 @@ func (b *BridgeProcessor) Start(ctx context.Context) error {
continue continue
} }
toL1Height, toL2Height := latestEpoch.L1BlockHeader.Number.Int, latestEpoch.L2BlockHeader.Number.Int toL1Height, toL2Height := latestEpoch.L1BlockHeader.Number, latestEpoch.L2BlockHeader.Number
fromL1Height, fromL2Height := big.NewInt(0), big.NewInt(0) fromL1Height, fromL2Height := big.NewInt(0), big.NewInt(0)
if b.LatestL1Header != nil { if b.LatestL1Header != nil {
// `NewBridgeProcessor` ensures that LatestL2Header must not be nil if LatestL1Header is set // `NewBridgeProcessor` ensures that LatestL2Header must not be nil if LatestL1Header is set
......
...@@ -94,13 +94,13 @@ func CrossDomainMessengerSentMessageEvents(chainSelector string, contractAddress ...@@ -94,13 +94,13 @@ func CrossDomainMessengerSentMessageEvents(chainSelector string, contractAddress
Event: &sentMessageEvents[i], Event: &sentMessageEvents[i],
BridgeMessage: database.BridgeMessage{ BridgeMessage: database.BridgeMessage{
MessageHash: messageHash, MessageHash: messageHash,
Nonce: database.U256{Int: sentMessage.MessageNonce}, Nonce: sentMessage.MessageNonce,
SentMessageEventGUID: sentMessageEvents[i].GUID, SentMessageEventGUID: sentMessageEvents[i].GUID,
GasLimit: database.U256{Int: sentMessage.GasLimit}, GasLimit: sentMessage.GasLimit,
Tx: database.Transaction{ Tx: database.Transaction{
FromAddress: sentMessage.Sender, FromAddress: sentMessage.Sender,
ToAddress: sentMessage.Target, ToAddress: sentMessage.Target,
Amount: database.U256{Int: sentMessageExtension.Value}, Amount: sentMessageExtension.Value,
Data: sentMessage.Message, Data: sentMessage.Message,
Timestamp: sentMessageEvents[i].Timestamp, Timestamp: sentMessageEvents[i].Timestamp,
}, },
......
...@@ -11,8 +11,8 @@ import ( ...@@ -11,8 +11,8 @@ import (
type L2ToL1MessagePasserMessagePassed struct { type L2ToL1MessagePasserMessagePassed struct {
Event *database.ContractEvent Event *database.ContractEvent
WithdrawalHash common.Hash WithdrawalHash common.Hash
GasLimit database.U256 GasLimit *big.Int
Nonce database.U256 Nonce *big.Int
Tx database.Transaction Tx database.Transaction
} }
...@@ -40,12 +40,12 @@ func L2ToL1MessagePasserMessagePassedEvents(contractAddress common.Address, db * ...@@ -40,12 +40,12 @@ func L2ToL1MessagePasserMessagePassedEvents(contractAddress common.Address, db *
messagesPassed[i] = L2ToL1MessagePasserMessagePassed{ messagesPassed[i] = L2ToL1MessagePasserMessagePassed{
Event: &messagePassedEvents[i].ContractEvent, Event: &messagePassedEvents[i].ContractEvent,
WithdrawalHash: messagePassed.WithdrawalHash, WithdrawalHash: messagePassed.WithdrawalHash,
Nonce: database.U256{Int: messagePassed.Nonce}, Nonce: messagePassed.Nonce,
GasLimit: database.U256{Int: messagePassed.GasLimit}, GasLimit: messagePassed.GasLimit,
Tx: database.Transaction{ Tx: database.Transaction{
FromAddress: messagePassed.Sender, FromAddress: messagePassed.Sender,
ToAddress: messagePassed.Target, ToAddress: messagePassed.Target,
Amount: database.U256{Int: messagePassed.Value}, Amount: messagePassed.Value,
Data: messagePassed.Data, Data: messagePassed.Data,
Timestamp: messagePassedEvents[i].Timestamp, Timestamp: messagePassedEvents[i].Timestamp,
}, },
......
...@@ -16,7 +16,7 @@ type OptimismPortalTransactionDepositEvent struct { ...@@ -16,7 +16,7 @@ type OptimismPortalTransactionDepositEvent struct {
Event *database.ContractEvent Event *database.ContractEvent
DepositTx *types.DepositTx DepositTx *types.DepositTx
Tx database.Transaction Tx database.Transaction
GasLimit database.U256 GasLimit *big.Int
} }
type OptimismPortalWithdrawalProvenEvent struct { type OptimismPortalWithdrawalProvenEvent struct {
...@@ -67,11 +67,11 @@ func OptimismPortalTransactionDepositEvents(contractAddress common.Address, db * ...@@ -67,11 +67,11 @@ func OptimismPortalTransactionDepositEvents(contractAddress common.Address, db *
optimismPortalTxDeposits[i] = OptimismPortalTransactionDepositEvent{ optimismPortalTxDeposits[i] = OptimismPortalTransactionDepositEvent{
Event: &transactionDepositEvents[i].ContractEvent, Event: &transactionDepositEvents[i].ContractEvent,
DepositTx: depositTx, DepositTx: depositTx,
GasLimit: database.U256{Int: new(big.Int).SetUint64(depositTx.Gas)}, GasLimit: new(big.Int).SetUint64(depositTx.Gas),
Tx: database.Transaction{ Tx: database.Transaction{
FromAddress: txDeposit.From, FromAddress: txDeposit.From,
ToAddress: txDeposit.To, ToAddress: txDeposit.To,
Amount: database.U256{Int: depositTx.Value}, Amount: depositTx.Value,
Data: depositTx.Data, Data: depositTx.Data,
Timestamp: transactionDepositEvents[i].Timestamp, Timestamp: transactionDepositEvents[i].Timestamp,
}, },
......
...@@ -101,7 +101,7 @@ func _standardBridgeInitiatedEvents[BridgeEventType bindings.StandardBridgeETHBr ...@@ -101,7 +101,7 @@ func _standardBridgeInitiatedEvents[BridgeEventType bindings.StandardBridgeETHBr
Tx: database.Transaction{ Tx: database.Transaction{
FromAddress: erc20Bridge.From, FromAddress: erc20Bridge.From,
ToAddress: erc20Bridge.To, ToAddress: erc20Bridge.To,
Amount: database.U256{Int: erc20Bridge.Amount}, Amount: erc20Bridge.Amount,
Data: erc20Bridge.ExtraData, Data: erc20Bridge.ExtraData,
Timestamp: initiatedBridgeEvents[i].Timestamp, Timestamp: initiatedBridgeEvents[i].Timestamp,
}, },
...@@ -161,7 +161,7 @@ func _standardBridgeFinalizedEvents[BridgeEventType bindings.StandardBridgeETHBr ...@@ -161,7 +161,7 @@ func _standardBridgeFinalizedEvents[BridgeEventType bindings.StandardBridgeETHBr
Tx: database.Transaction{ Tx: database.Transaction{
FromAddress: erc20Bridge.From, FromAddress: erc20Bridge.From,
ToAddress: erc20Bridge.To, ToAddress: erc20Bridge.To,
Amount: database.U256{Int: erc20Bridge.Amount}, Amount: erc20Bridge.Amount,
Data: erc20Bridge.ExtraData, Data: erc20Bridge.ExtraData,
Timestamp: bridgeFinalizedEvents[i].Timestamp, Timestamp: bridgeFinalizedEvents[i].Timestamp,
}, },
......
...@@ -4,6 +4,7 @@ import ( ...@@ -4,6 +4,7 @@ import (
"context" "context"
"fmt" "fmt"
"testing" "testing"
"time"
"github.com/ethereum-optimism/optimism/op-challenger/config" "github.com/ethereum-optimism/optimism/op-challenger/config"
"github.com/ethereum-optimism/optimism/op-node/chaincfg" "github.com/ethereum-optimism/optimism/op-node/chaincfg"
...@@ -233,6 +234,23 @@ func TestCannonSnapshotFreq(t *testing.T) { ...@@ -233,6 +234,23 @@ func TestCannonSnapshotFreq(t *testing.T) {
}) })
} }
func TestGameWindow(t *testing.T) {
t.Run("UsesDefault", func(t *testing.T) {
cfg := configForArgs(t, addRequiredArgs(config.TraceTypeAlphabet))
require.Equal(t, config.DefaultGameWindow, cfg.GameWindow)
})
t.Run("Valid", func(t *testing.T) {
cfg := configForArgs(t, addRequiredArgs(config.TraceTypeAlphabet, "--game-window=1m"))
require.Equal(t, time.Duration(time.Minute), cfg.GameWindow)
})
t.Run("ParsesDefault", func(t *testing.T) {
cfg := configForArgs(t, addRequiredArgs(config.TraceTypeAlphabet, "--game-window=264h"))
require.Equal(t, config.DefaultGameWindow, cfg.GameWindow)
})
}
func TestRequireEitherCannonNetworkOrRollupAndGenesis(t *testing.T) { func TestRequireEitherCannonNetworkOrRollupAndGenesis(t *testing.T) {
verifyArgsInvalid( verifyArgsInvalid(
t, t,
......
...@@ -3,6 +3,7 @@ package config ...@@ -3,6 +3,7 @@ package config
import ( import (
"errors" "errors"
"fmt" "fmt"
"time"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
...@@ -73,7 +74,14 @@ func ValidTraceType(value TraceType) bool { ...@@ -73,7 +74,14 @@ func ValidTraceType(value TraceType) bool {
return false return false
} }
const DefaultCannonSnapshotFreq = uint(1_000_000_000) const (
DefaultCannonSnapshotFreq = uint(1_000_000_000)
// DefaultGameWindow is the default maximum time duration in the past
// that the challenger will look for games to progress.
// The default value is 11 days, which is a 4 day resolution buffer
// plus the 7 day game finalization window.
DefaultGameWindow = time.Duration(11 * 24 * time.Hour)
)
// Config is a well typed config that is parsed from the CLI params. // Config is a well typed config that is parsed from the CLI params.
// This also contains config options for auxiliary services. // This also contains config options for auxiliary services.
...@@ -82,9 +90,9 @@ type Config struct { ...@@ -82,9 +90,9 @@ type Config struct {
L1EthRpc string // L1 RPC Url L1EthRpc string // L1 RPC Url
GameFactoryAddress common.Address // Address of the dispute game factory GameFactoryAddress common.Address // Address of the dispute game factory
GameAllowlist []common.Address // Allowlist of fault game addresses GameAllowlist []common.Address // Allowlist of fault game addresses
GameWindow time.Duration // Maximum time duration to look for games to progress
AgreeWithProposedOutput bool // Temporary config if we agree or disagree with the posted output AgreeWithProposedOutput bool // Temporary config if we agree or disagree with the posted output
TraceType TraceType // Type of trace
TraceType TraceType // Type of trace
// Specific to the alphabet trace provider // Specific to the alphabet trace provider
AlphabetTrace string // String for the AlphabetTraceProvider AlphabetTrace string // String for the AlphabetTraceProvider
...@@ -124,6 +132,7 @@ func NewConfig( ...@@ -124,6 +132,7 @@ func NewConfig(
PprofConfig: oppprof.DefaultCLIConfig(), PprofConfig: oppprof.DefaultCLIConfig(),
CannonSnapshotFreq: DefaultCannonSnapshotFreq, CannonSnapshotFreq: DefaultCannonSnapshotFreq,
GameWindow: DefaultGameWindow,
} }
} }
......
...@@ -55,7 +55,7 @@ func TestBuildFaultDefendData(t *testing.T) { ...@@ -55,7 +55,7 @@ func TestBuildFaultDefendData(t *testing.T) {
_, opts, _, contract, err := setupFaultDisputeGame() _, opts, _, contract, err := setupFaultDisputeGame()
require.NoError(t, err) require.NoError(t, err)
responder, _ := newTestFaultResponder(t, false) responder, _ := newTestFaultResponder(t)
data, err := responder.buildFaultDefendData(1, [32]byte{0x02, 0x03}) data, err := responder.buildFaultDefendData(1, [32]byte{0x02, 0x03})
require.NoError(t, err) require.NoError(t, err)
...@@ -72,7 +72,7 @@ func TestBuildFaultAttackData(t *testing.T) { ...@@ -72,7 +72,7 @@ func TestBuildFaultAttackData(t *testing.T) {
_, opts, _, contract, err := setupFaultDisputeGame() _, opts, _, contract, err := setupFaultDisputeGame()
require.NoError(t, err) require.NoError(t, err)
responder, _ := newTestFaultResponder(t, false) responder, _ := newTestFaultResponder(t)
data, err := responder.buildFaultAttackData(1, [32]byte{0x02, 0x03}) data, err := responder.buildFaultAttackData(1, [32]byte{0x02, 0x03})
require.NoError(t, err) require.NoError(t, err)
...@@ -89,7 +89,7 @@ func TestBuildFaultStepData(t *testing.T) { ...@@ -89,7 +89,7 @@ func TestBuildFaultStepData(t *testing.T) {
_, opts, _, contract, err := setupFaultDisputeGame() _, opts, _, contract, err := setupFaultDisputeGame()
require.NoError(t, err) require.NoError(t, err)
responder, _ := newTestFaultResponder(t, false) responder, _ := newTestFaultResponder(t)
data, err := responder.buildStepTxData(types.StepCallData{ data, err := responder.buildStepTxData(types.StepCallData{
ClaimIndex: 2, ClaimIndex: 2,
......
...@@ -13,7 +13,7 @@ import ( ...@@ -13,7 +13,7 @@ import (
// Responder takes a response action & executes. // Responder takes a response action & executes.
// For full op-challenger this means executing the transaction on chain. // For full op-challenger this means executing the transaction on chain.
type Responder interface { type Responder interface {
CanResolve(ctx context.Context) bool CallResolve(ctx context.Context) (types.GameStatus, error)
Resolve(ctx context.Context) error Resolve(ctx context.Context) error
Respond(ctx context.Context, response types.Claim) error Respond(ctx context.Context, response types.Claim) error
Step(ctx context.Context, stepData types.StepCallData) error Step(ctx context.Context, stepData types.StepCallData) error
...@@ -65,10 +65,27 @@ func (a *Agent) Act(ctx context.Context) error { ...@@ -65,10 +65,27 @@ func (a *Agent) Act(ctx context.Context) error {
return nil return nil
} }
// shouldResolve returns true if the agent should resolve the game.
// This method will return false if the game is still in progress.
func (a *Agent) shouldResolve(ctx context.Context, status types.GameStatus) bool {
expected := types.GameStatusDefenderWon
if a.agreeWithProposedOutput {
expected = types.GameStatusChallengerWon
}
if expected != status {
a.log.Warn("Game will be lost", "expected", expected, "actual", status)
}
return expected == status
}
// tryResolve resolves the game if it is in a terminal state // tryResolve resolves the game if it is in a terminal state
// and returns true if the game resolves successfully. // and returns true if the game resolves successfully.
func (a *Agent) tryResolve(ctx context.Context) bool { func (a *Agent) tryResolve(ctx context.Context) bool {
if !a.responder.CanResolve(ctx) { status, err := a.responder.CallResolve(ctx)
if err != nil {
return false
}
if !a.shouldResolve(ctx, status) {
return false return false
} }
a.log.Info("Resolving game") a.log.Info("Resolving game")
......
package fault
import (
"context"
"testing"
"github.com/ethereum/go-ethereum/log"
"github.com/stretchr/testify/require"
"github.com/ethereum-optimism/optimism/op-challenger/fault/types"
"github.com/ethereum-optimism/optimism/op-node/testlog"
)
// TestShouldResolve tests the resolution logic.
func TestShouldResolve(t *testing.T) {
log := testlog.Logger(t, log.LvlCrit)
t.Run("AgreeWithProposedOutput", func(t *testing.T) {
agent := NewAgent(nil, 0, nil, nil, nil, true, log)
require.False(t, agent.shouldResolve(context.Background(), types.GameStatusDefenderWon))
require.True(t, agent.shouldResolve(context.Background(), types.GameStatusChallengerWon))
require.False(t, agent.shouldResolve(context.Background(), types.GameStatusInProgress))
})
t.Run("DisagreeWithProposedOutput", func(t *testing.T) {
agent := NewAgent(nil, 0, nil, nil, nil, false, log)
require.True(t, agent.shouldResolve(context.Background(), types.GameStatusDefenderWon))
require.False(t, agent.shouldResolve(context.Background(), types.GameStatusChallengerWon))
require.False(t, agent.shouldResolve(context.Background(), types.GameStatusInProgress))
})
}
...@@ -8,7 +8,6 @@ import ( ...@@ -8,7 +8,6 @@ import (
"github.com/ethereum-optimism/optimism/op-challenger/fault/types" "github.com/ethereum-optimism/optimism/op-challenger/fault/types"
"github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"
) )
type FaultDisputeGameCaller interface { type FaultDisputeGameCaller interface {
...@@ -26,7 +25,7 @@ func NewFaultCaller(caller FaultDisputeGameCaller) *FaultCaller { ...@@ -26,7 +25,7 @@ func NewFaultCaller(caller FaultDisputeGameCaller) *FaultCaller {
} }
} }
func NewFaultCallerFromBindings(fdgAddr common.Address, client *ethclient.Client) (*FaultCaller, error) { func NewFaultCallerFromBindings(fdgAddr common.Address, client bind.ContractCaller) (*FaultCaller, error) {
caller, err := bindings.NewFaultDisputeGameCaller(fdgAddr, client) caller, err := bindings.NewFaultDisputeGameCaller(fdgAddr, client)
if err != nil { if err != nil {
return nil, err return nil, err
......
...@@ -118,6 +118,10 @@ func (p *CannonTraceProvider) AbsolutePreState(ctx context.Context) ([]byte, err ...@@ -118,6 +118,10 @@ func (p *CannonTraceProvider) AbsolutePreState(ctx context.Context) ([]byte, err
return state.EncodeWitness(), nil return state.EncodeWitness(), nil
} }
func (p *CannonTraceProvider) Cleanup() error {
return os.RemoveAll(p.dir)
}
// loadProof will attempt to load or generate the proof data at the specified index // loadProof will attempt to load or generate the proof data at the specified index
// If the requested index is beyond the end of the actual trace it is extended with no-op instructions. // If the requested index is beyond the end of the actual trace it is extended with no-op instructions.
func (p *CannonTraceProvider) loadProof(ctx context.Context, i uint64) (*proofData, error) { func (p *CannonTraceProvider) loadProof(ctx context.Context, i uint64) (*proofData, error) {
......
...@@ -204,6 +204,14 @@ func TestUseGameSpecificSubdir(t *testing.T) { ...@@ -204,6 +204,14 @@ func TestUseGameSpecificSubdir(t *testing.T) {
require.Equal(t, filepath.Join(dataDir, gameDirName), provider.dir, "should use game specific subdir") require.Equal(t, filepath.Join(dataDir, gameDirName), provider.dir, "should use game specific subdir")
} }
func TestCleanup(t *testing.T) {
dataDir, prestate := setupTestData(t)
provider, _ := setupWithTestData(t, dataDir, prestate)
require.NoError(t, provider.Cleanup())
_, err := os.Stat(dataDir)
require.ErrorIs(t, err, os.ErrNotExist)
}
func setupPreState(t *testing.T, dataDir string, filename string) { func setupPreState(t *testing.T, dataDir string, filename string) {
srcDir := filepath.Join("test_data") srcDir := filepath.Join("test_data")
path := filepath.Join(srcDir, filename) path := filepath.Join(srcDir, filename)
......
...@@ -43,7 +43,7 @@ func NewGameLoader(caller MinimalDisputeGameFactoryCaller) *gameLoader { ...@@ -43,7 +43,7 @@ func NewGameLoader(caller MinimalDisputeGameFactoryCaller) *gameLoader {
} }
// FetchAllGamesAtBlock fetches all dispute games from the factory at a given block number. // FetchAllGamesAtBlock fetches all dispute games from the factory at a given block number.
func (l *gameLoader) FetchAllGamesAtBlock(ctx context.Context, blockNumber *big.Int) ([]FaultDisputeGame, error) { func (l *gameLoader) FetchAllGamesAtBlock(ctx context.Context, earliestTimestamp uint64, blockNumber *big.Int) ([]FaultDisputeGame, error) {
if blockNumber == nil { if blockNumber == nil {
return nil, ErrMissingBlockNumber return nil, ErrMissingBlockNumber
} }
...@@ -56,14 +56,19 @@ func (l *gameLoader) FetchAllGamesAtBlock(ctx context.Context, blockNumber *big. ...@@ -56,14 +56,19 @@ func (l *gameLoader) FetchAllGamesAtBlock(ctx context.Context, blockNumber *big.
return nil, fmt.Errorf("failed to fetch game count: %w", err) return nil, fmt.Errorf("failed to fetch game count: %w", err)
} }
games := make([]FaultDisputeGame, gameCount.Uint64()) games := make([]FaultDisputeGame, 0)
for i := uint64(0); i < gameCount.Uint64(); i++ { if gameCount.Uint64() == 0 {
game, err := l.caller.GameAtIndex(callOpts, big.NewInt(int64(i))) return games, nil
}
for i := gameCount.Uint64(); i > 0; i-- {
game, err := l.caller.GameAtIndex(callOpts, big.NewInt(int64(i-1)))
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to fetch game at index %d: %w", i, err) return nil, fmt.Errorf("failed to fetch game at index %d: %w", i, err)
} }
if game.Timestamp < earliestTimestamp {
games[i] = game break
}
games = append(games, game)
} }
return games, nil return games, nil
......
...@@ -25,6 +25,7 @@ func TestGameLoader_FetchAllGames(t *testing.T) { ...@@ -25,6 +25,7 @@ func TestGameLoader_FetchAllGames(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
caller *mockMinimalDisputeGameFactoryCaller caller *mockMinimalDisputeGameFactoryCaller
earliest uint64
blockNumber *big.Int blockNumber *big.Int
expectedErr error expectedErr error
expectedLen int expectedLen int
...@@ -33,35 +34,36 @@ func TestGameLoader_FetchAllGames(t *testing.T) { ...@@ -33,35 +34,36 @@ func TestGameLoader_FetchAllGames(t *testing.T) {
name: "success", name: "success",
caller: newMockMinimalDisputeGameFactoryCaller(10, false, false), caller: newMockMinimalDisputeGameFactoryCaller(10, false, false),
blockNumber: big.NewInt(1), blockNumber: big.NewInt(1),
expectedErr: nil,
expectedLen: 10, expectedLen: 10,
}, },
{
name: "expired game ignored",
caller: newMockMinimalDisputeGameFactoryCaller(10, false, false),
earliest: 500,
blockNumber: big.NewInt(1),
expectedLen: 5,
},
{ {
name: "game count error", name: "game count error",
caller: newMockMinimalDisputeGameFactoryCaller(10, true, false), caller: newMockMinimalDisputeGameFactoryCaller(10, true, false),
blockNumber: big.NewInt(1), blockNumber: big.NewInt(1),
expectedErr: gameCountErr, expectedErr: gameCountErr,
expectedLen: 0,
}, },
{ {
name: "game index error", name: "game index error",
caller: newMockMinimalDisputeGameFactoryCaller(10, false, true), caller: newMockMinimalDisputeGameFactoryCaller(10, false, true),
blockNumber: big.NewInt(1), blockNumber: big.NewInt(1),
expectedErr: gameIndexErr, expectedErr: gameIndexErr,
expectedLen: 0,
}, },
{ {
name: "no games", name: "no games",
caller: newMockMinimalDisputeGameFactoryCaller(0, false, false), caller: newMockMinimalDisputeGameFactoryCaller(0, false, false),
blockNumber: big.NewInt(1), blockNumber: big.NewInt(1),
expectedErr: nil,
expectedLen: 0,
}, },
{ {
name: "missing block number", name: "missing block number",
caller: newMockMinimalDisputeGameFactoryCaller(0, false, false), caller: newMockMinimalDisputeGameFactoryCaller(0, false, false),
expectedErr: ErrMissingBlockNumber, expectedErr: ErrMissingBlockNumber,
expectedLen: 0,
}, },
} }
...@@ -72,10 +74,11 @@ func TestGameLoader_FetchAllGames(t *testing.T) { ...@@ -72,10 +74,11 @@ func TestGameLoader_FetchAllGames(t *testing.T) {
t.Parallel() t.Parallel()
loader := NewGameLoader(test.caller) loader := NewGameLoader(test.caller)
games, err := loader.FetchAllGamesAtBlock(context.Background(), test.blockNumber) games, err := loader.FetchAllGamesAtBlock(context.Background(), test.earliest, test.blockNumber)
require.ErrorIs(t, err, test.expectedErr) require.ErrorIs(t, err, test.expectedErr)
require.Len(t, games, test.expectedLen) require.Len(t, games, test.expectedLen)
expectedGames := test.caller.games expectedGames := test.caller.games
expectedGames = expectedGames[len(expectedGames)-test.expectedLen:]
if test.expectedErr != nil { if test.expectedErr != nil {
expectedGames = make([]FaultDisputeGame, 0) expectedGames = make([]FaultDisputeGame, 0)
} }
...@@ -90,7 +93,7 @@ func generateMockGames(count uint64) []FaultDisputeGame { ...@@ -90,7 +93,7 @@ func generateMockGames(count uint64) []FaultDisputeGame {
for i := uint64(0); i < count; i++ { for i := uint64(0); i < count; i++ {
games[i] = FaultDisputeGame{ games[i] = FaultDisputeGame{
Proxy: common.BigToAddress(big.NewInt(int64(i))), Proxy: common.BigToAddress(big.NewInt(int64(i))),
Timestamp: i, Timestamp: i * 100,
} }
} }
......
...@@ -13,6 +13,7 @@ import ( ...@@ -13,6 +13,7 @@ import (
type gamePlayer interface { type gamePlayer interface {
ProgressGame(ctx context.Context) bool ProgressGame(ctx context.Context) bool
Cleanup() error
} }
type playerCreator func(address common.Address) (gamePlayer, error) type playerCreator func(address common.Address) (gamePlayer, error)
...@@ -20,24 +21,26 @@ type blockNumberFetcher func(ctx context.Context) (uint64, error) ...@@ -20,24 +21,26 @@ type blockNumberFetcher func(ctx context.Context) (uint64, error)
// gameSource loads information about the games available to play // gameSource loads information about the games available to play
type gameSource interface { type gameSource interface {
FetchAllGamesAtBlock(ctx context.Context, blockNumber *big.Int) ([]FaultDisputeGame, error) FetchAllGamesAtBlock(ctx context.Context, earliest uint64, blockNumber *big.Int) ([]FaultDisputeGame, error)
} }
type gameMonitor struct { type gameMonitor struct {
logger log.Logger logger log.Logger
clock clock.Clock clock clock.Clock
source gameSource source gameSource
gameWindow time.Duration
createPlayer playerCreator createPlayer playerCreator
fetchBlockNumber blockNumberFetcher fetchBlockNumber blockNumberFetcher
allowedGames []common.Address allowedGames []common.Address
players map[common.Address]gamePlayer players map[common.Address]gamePlayer
} }
func newGameMonitor(logger log.Logger, cl clock.Clock, fetchBlockNumber blockNumberFetcher, allowedGames []common.Address, source gameSource, createGame playerCreator) *gameMonitor { func newGameMonitor(logger log.Logger, gameWindow time.Duration, cl clock.Clock, fetchBlockNumber blockNumberFetcher, allowedGames []common.Address, source gameSource, createGame playerCreator) *gameMonitor {
return &gameMonitor{ return &gameMonitor{
logger: logger, logger: logger,
clock: cl, clock: cl,
source: source, source: source,
gameWindow: gameWindow,
createPlayer: createGame, createPlayer: createGame,
fetchBlockNumber: fetchBlockNumber, fetchBlockNumber: fetchBlockNumber,
allowedGames: allowedGames, allowedGames: allowedGames,
...@@ -57,26 +60,56 @@ func (m *gameMonitor) allowedGame(game common.Address) bool { ...@@ -57,26 +60,56 @@ func (m *gameMonitor) allowedGame(game common.Address) bool {
return false return false
} }
func (m *gameMonitor) minGameTimestamp() uint64 {
if m.gameWindow.Seconds() == 0 {
return 0
}
// time: "To compute t-d for a duration d, use t.Add(-d)."
// https://pkg.go.dev/time#Time.Sub
if m.clock.Now().Unix() > int64(m.gameWindow.Seconds()) {
return uint64(m.clock.Now().Add(-m.gameWindow).Unix())
}
return 0
}
func (m *gameMonitor) progressGames(ctx context.Context) error { func (m *gameMonitor) progressGames(ctx context.Context) error {
blockNum, err := m.fetchBlockNumber(ctx) blockNum, err := m.fetchBlockNumber(ctx)
if err != nil { if err != nil {
return fmt.Errorf("failed to load current block number: %w", err) return fmt.Errorf("failed to load current block number: %w", err)
} }
games, err := m.source.FetchAllGamesAtBlock(ctx, new(big.Int).SetUint64(blockNum)) games, err := m.source.FetchAllGamesAtBlock(ctx, m.minGameTimestamp(), new(big.Int).SetUint64(blockNum))
if err != nil { if err != nil {
return fmt.Errorf("failed to load games: %w", err) return fmt.Errorf("failed to load games: %w", err)
} }
requiredGames := make(map[common.Address]bool)
for _, game := range games { for _, game := range games {
if !m.allowedGame(game.Proxy) { if !m.allowedGame(game.Proxy) {
m.logger.Debug("Skipping game not on allow list", "game", game.Proxy) m.logger.Debug("Skipping game not on allow list", "game", game.Proxy)
continue continue
} }
requiredGames[game.Proxy] = true
player, err := m.fetchOrCreateGamePlayer(game) player, err := m.fetchOrCreateGamePlayer(game)
if err != nil { if err != nil {
m.logger.Error("Error while progressing game", "game", game.Proxy, "err", err) m.logger.Error("Error while progressing game", "game", game.Proxy, "err", err)
continue continue
} }
player.ProgressGame(ctx) done := player.ProgressGame(ctx)
if done {
// Remove resources on disk as soon as the game is complete to save disk space.
// We keep the player in memory to avoid recreating it on every update but will no longer
// need the resources on disk because there are no further actions required on the game.
if err := player.Cleanup(); err != nil {
m.logger.Error("Unable to cleanup player data", "err", err)
}
}
}
// Remove the player for any game that's no longer being returned from the list of active games
for addr := range m.players {
if _, ok := requiredGames[addr]; ok {
// Game still required
continue
}
delete(m.players, addr)
} }
return nil return nil
} }
......
...@@ -4,6 +4,7 @@ import ( ...@@ -4,6 +4,7 @@ import (
"context" "context"
"math/big" "math/big"
"testing" "testing"
"time"
"github.com/ethereum-optimism/optimism/op-service/clock" "github.com/ethereum-optimism/optimism/op-service/clock"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
...@@ -13,6 +14,32 @@ import ( ...@@ -13,6 +14,32 @@ import (
"github.com/ethereum-optimism/optimism/op-node/testlog" "github.com/ethereum-optimism/optimism/op-node/testlog"
) )
func TestMonitorMinGameTimestamp(t *testing.T) {
t.Parallel()
t.Run("zero game window returns zero", func(t *testing.T) {
monitor, _, _ := setupMonitorTest(t, []common.Address{})
monitor.gameWindow = time.Duration(0)
require.Equal(t, monitor.minGameTimestamp(), uint64(0))
})
t.Run("non-zero game window with zero clock", func(t *testing.T) {
monitor, _, _ := setupMonitorTest(t, []common.Address{})
monitor.gameWindow = time.Minute
monitor.clock = clock.NewDeterministicClock(time.Unix(0, 0))
require.Equal(t, monitor.minGameTimestamp(), uint64(0))
})
t.Run("minimum computed correctly", func(t *testing.T) {
monitor, _, _ := setupMonitorTest(t, []common.Address{})
monitor.gameWindow = time.Minute
frozen := time.Unix(int64(time.Hour.Seconds()), 0)
monitor.clock = clock.NewDeterministicClock(frozen)
expected := uint64(frozen.Add(-time.Minute).Unix())
require.Equal(t, monitor.minGameTimestamp(), expected)
})
}
func TestMonitorExitsWhenContextDone(t *testing.T) { func TestMonitorExitsWhenContextDone(t *testing.T) {
monitor, _, _ := setupMonitorTest(t, []common.Address{common.Address{}}) monitor, _, _ := setupMonitorTest(t, []common.Address{common.Address{}})
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
...@@ -77,6 +104,69 @@ func TestMonitorOnlyCreateSpecifiedGame(t *testing.T) { ...@@ -77,6 +104,69 @@ func TestMonitorOnlyCreateSpecifiedGame(t *testing.T) {
require.Equal(t, 1, games.created[addr2].progressCount) require.Equal(t, 1, games.created[addr2].progressCount)
} }
func TestDeletePlayersWhenNoLongerInListOfGames(t *testing.T) {
addr1 := common.Address{0xaa}
addr2 := common.Address{0xbb}
monitor, source, games := setupMonitorTest(t, nil)
allGames := []FaultDisputeGame{
{
Proxy: addr1,
Timestamp: 9999,
},
{
Proxy: addr2,
Timestamp: 9999,
},
}
source.games = allGames
require.NoError(t, monitor.progressGames(context.Background()))
require.Len(t, games.created, 2)
require.Contains(t, games.created, addr1)
require.Contains(t, games.created, addr2)
// First game is now old enough it's not returned in the list of active games
source.games = source.games[1:]
require.NoError(t, monitor.progressGames(context.Background()))
require.Len(t, games.created, 2)
require.Contains(t, games.created, addr1)
require.Contains(t, games.created, addr2)
// Forget that we created the first game so it can be recreated if needed
delete(games.created, addr1)
// First game now reappears (inexplicably but usefully for our testing)
source.games = allGames
require.NoError(t, monitor.progressGames(context.Background()))
// A new player is created for it because the original was deleted
require.Len(t, games.created, 2)
require.Contains(t, games.created, addr1)
require.Contains(t, games.created, addr2)
require.Equal(t, 1, games.created[addr1].progressCount)
}
func TestCleanupResourcesOfCompletedGames(t *testing.T) {
monitor, source, games := setupMonitorTest(t, []common.Address{})
games.createCompleted = true
addr1 := common.Address{0xaa}
source.games = []FaultDisputeGame{
{
Proxy: addr1,
Timestamp: 9999,
},
}
err := monitor.progressGames(context.Background())
require.NoError(t, err)
require.Len(t, games.created, 1, "should create game agents")
require.Contains(t, games.created, addr1)
require.Equal(t, 1, games.created[addr1].progressCount)
require.Equal(t, 1, games.created[addr1].cleanupCount, "should clean up once game is done")
}
func setupMonitorTest(t *testing.T, allowedGames []common.Address) (*gameMonitor, *stubGameSource, *createdGames) { func setupMonitorTest(t *testing.T, allowedGames []common.Address) (*gameMonitor, *stubGameSource, *createdGames) {
logger := testlog.Logger(t, log.LvlDebug) logger := testlog.Logger(t, log.LvlDebug)
source := &stubGameSource{} source := &stubGameSource{}
...@@ -87,7 +177,7 @@ func setupMonitorTest(t *testing.T, allowedGames []common.Address) (*gameMonitor ...@@ -87,7 +177,7 @@ func setupMonitorTest(t *testing.T, allowedGames []common.Address) (*gameMonitor
fetchBlockNum := func(ctx context.Context) (uint64, error) { fetchBlockNum := func(ctx context.Context) (uint64, error) {
return 1234, nil return 1234, nil
} }
monitor := newGameMonitor(logger, clock.SystemClock, fetchBlockNum, allowedGames, source, games.CreateGame) monitor := newGameMonitor(logger, time.Duration(0), clock.SystemClock, fetchBlockNum, allowedGames, source, games.CreateGame)
return monitor, source, games return monitor, source, games
} }
...@@ -95,13 +185,14 @@ type stubGameSource struct { ...@@ -95,13 +185,14 @@ type stubGameSource struct {
games []FaultDisputeGame games []FaultDisputeGame
} }
func (s *stubGameSource) FetchAllGamesAtBlock(ctx context.Context, blockNumber *big.Int) ([]FaultDisputeGame, error) { func (s *stubGameSource) FetchAllGamesAtBlock(ctx context.Context, earliest uint64, blockNumber *big.Int) ([]FaultDisputeGame, error) {
return s.games, nil return s.games, nil
} }
type stubGame struct { type stubGame struct {
addr common.Address addr common.Address
progressCount int progressCount int
cleanupCount int
done bool done bool
} }
...@@ -110,16 +201,22 @@ func (g *stubGame) ProgressGame(ctx context.Context) bool { ...@@ -110,16 +201,22 @@ func (g *stubGame) ProgressGame(ctx context.Context) bool {
return g.done return g.done
} }
func (g *stubGame) Cleanup() error {
g.cleanupCount++
return nil
}
type createdGames struct { type createdGames struct {
t *testing.T t *testing.T
created map[common.Address]*stubGame createCompleted bool
created map[common.Address]*stubGame
} }
func (c *createdGames) CreateGame(addr common.Address) (gamePlayer, error) { func (c *createdGames) CreateGame(addr common.Address) (gamePlayer, error) {
if _, exists := c.created[addr]; exists { if _, exists := c.created[addr]; exists {
c.t.Fatalf("game %v already exists", addr) c.t.Fatalf("game %v already exists", addr)
} }
game := &stubGame{addr: addr} game := &stubGame{addr: addr, done: c.createCompleted}
c.created[addr] = game c.created[addr] = game
return game, nil return game, nil
} }
...@@ -10,8 +10,8 @@ import ( ...@@ -10,8 +10,8 @@ import (
"github.com/ethereum-optimism/optimism/op-challenger/fault/cannon" "github.com/ethereum-optimism/optimism/op-challenger/fault/cannon"
"github.com/ethereum-optimism/optimism/op-challenger/fault/types" "github.com/ethereum-optimism/optimism/op-challenger/fault/types"
"github.com/ethereum-optimism/optimism/op-service/txmgr" "github.com/ethereum-optimism/optimism/op-service/txmgr"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
) )
...@@ -29,6 +29,9 @@ type GamePlayer struct { ...@@ -29,6 +29,9 @@ type GamePlayer struct {
agreeWithProposedOutput bool agreeWithProposedOutput bool
caller GameInfo caller GameInfo
logger log.Logger logger log.Logger
cleanup func() error
completed bool
} }
func NewGamePlayer( func NewGamePlayer(
...@@ -37,7 +40,7 @@ func NewGamePlayer( ...@@ -37,7 +40,7 @@ func NewGamePlayer(
cfg *config.Config, cfg *config.Config,
addr common.Address, addr common.Address,
txMgr txmgr.TxManager, txMgr txmgr.TxManager,
client *ethclient.Client, client bind.ContractCaller,
) (*GamePlayer, error) { ) (*GamePlayer, error) {
logger = logger.New("game", addr) logger = logger.New("game", addr)
contract, err := bindings.NewFaultDisputeGameCaller(addr, client) contract, err := bindings.NewFaultDisputeGameCaller(addr, client)
...@@ -54,18 +57,22 @@ func NewGamePlayer( ...@@ -54,18 +57,22 @@ func NewGamePlayer(
var provider types.TraceProvider var provider types.TraceProvider
var updater types.OracleUpdater var updater types.OracleUpdater
var cleanup func() error
switch cfg.TraceType { switch cfg.TraceType {
case config.TraceTypeCannon: case config.TraceTypeCannon:
provider, err = cannon.NewTraceProvider(ctx, logger, cfg, client, addr) cannonProvider, err := cannon.NewTraceProvider(ctx, logger, cfg, client, addr)
if err != nil { if err != nil {
return nil, fmt.Errorf("create cannon trace provider: %w", err) return nil, fmt.Errorf("create cannon trace provider: %w", err)
} }
cleanup = cannonProvider.Cleanup
provider = cannonProvider
updater, err = cannon.NewOracleUpdater(ctx, logger, txMgr, addr, client) updater, err = cannon.NewOracleUpdater(ctx, logger, txMgr, addr, client)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to create the cannon updater: %w", err) return nil, fmt.Errorf("failed to create the cannon updater: %w", err)
} }
case config.TraceTypeAlphabet: case config.TraceTypeAlphabet:
provider = alphabet.NewTraceProvider(cfg.AlphabetTrace, gameDepth) provider = alphabet.NewTraceProvider(cfg.AlphabetTrace, gameDepth)
cleanup = func() error { return nil }
updater = alphabet.NewOracleUpdater(logger) updater = alphabet.NewOracleUpdater(logger)
default: default:
return nil, fmt.Errorf("unsupported trace type: %v", cfg.TraceType) return nil, fmt.Errorf("unsupported trace type: %v", cfg.TraceType)
...@@ -90,10 +97,16 @@ func NewGamePlayer( ...@@ -90,10 +97,16 @@ func NewGamePlayer(
agreeWithProposedOutput: cfg.AgreeWithProposedOutput, agreeWithProposedOutput: cfg.AgreeWithProposedOutput,
caller: caller, caller: caller,
logger: logger, logger: logger,
cleanup: cleanup,
}, nil }, nil
} }
func (g *GamePlayer) ProgressGame(ctx context.Context) bool { func (g *GamePlayer) ProgressGame(ctx context.Context) bool {
if g.completed {
// Game is already complete so don't try to perform further actions.
g.logger.Trace("Skipping completed game")
return true
}
g.logger.Trace("Checking if actions are required") g.logger.Trace("Checking if actions are required")
if err := g.agent.Act(ctx); err != nil { if err := g.agent.Act(ctx); err != nil {
g.logger.Error("Error when acting on game", "err", err) g.logger.Error("Error when acting on game", "err", err)
...@@ -102,7 +115,8 @@ func (g *GamePlayer) ProgressGame(ctx context.Context) bool { ...@@ -102,7 +115,8 @@ func (g *GamePlayer) ProgressGame(ctx context.Context) bool {
g.logger.Warn("Unable to retrieve game status", "err", err) g.logger.Warn("Unable to retrieve game status", "err", err)
} else { } else {
g.logGameStatus(ctx, status) g.logGameStatus(ctx, status)
return status != types.GameStatusInProgress g.completed = status != types.GameStatusInProgress
return g.completed
} }
return false return false
} }
...@@ -129,3 +143,7 @@ func (g *GamePlayer) logGameStatus(ctx context.Context, status types.GameStatus) ...@@ -129,3 +143,7 @@ func (g *GamePlayer) logGameStatus(ctx context.Context, status types.GameStatus)
g.logger.Error("Game lost", "status", status) g.logger.Error("Game lost", "status", status)
} }
} }
func (g *GamePlayer) Cleanup() error {
return g.cleanup()
}
...@@ -12,14 +12,14 @@ import ( ...@@ -12,14 +12,14 @@ import (
) )
func TestProgressGame_LogErrorFromAct(t *testing.T) { func TestProgressGame_LogErrorFromAct(t *testing.T) {
handler, game, actor, _ := setupProgressGameTest(t, true) handler, game, actor := setupProgressGameTest(t, true)
actor.err = errors.New("boom") actor.actErr = errors.New("boom")
done := game.ProgressGame(context.Background()) done := game.ProgressGame(context.Background())
require.False(t, done, "should not be done") require.False(t, done, "should not be done")
require.Equal(t, 1, actor.callCount, "should perform next actions") require.Equal(t, 1, actor.callCount, "should perform next actions")
errLog := handler.FindLog(log.LvlError, "Error when acting on game") errLog := handler.FindLog(log.LvlError, "Error when acting on game")
require.NotNil(t, errLog, "should log error") require.NotNil(t, errLog, "should log error")
require.Equal(t, actor.err, errLog.GetContextValue("err")) require.Equal(t, actor.actErr, errLog.GetContextValue("err"))
// Should still log game status // Should still log game status
msg := handler.FindLog(log.LvlInfo, "Game info") msg := handler.FindLog(log.LvlInfo, "Game info")
...@@ -27,6 +27,24 @@ func TestProgressGame_LogErrorFromAct(t *testing.T) { ...@@ -27,6 +27,24 @@ func TestProgressGame_LogErrorFromAct(t *testing.T) {
require.Equal(t, uint64(1), msg.GetContextValue("claims")) require.Equal(t, uint64(1), msg.GetContextValue("claims"))
} }
func TestCleanup(t *testing.T) {
t.Run("default cleanup", func(t *testing.T) {
game := &GamePlayer{
cleanup: func() error { return nil },
}
require.NoError(t, game.Cleanup())
})
t.Run("cleanup bubbles up error", func(t *testing.T) {
err := errors.New("wassie")
game := &GamePlayer{
cleanup: func() error { return err },
}
require.Error(t, err, game.Cleanup())
})
}
func TestProgressGame_LogGameStatus(t *testing.T) { func TestProgressGame_LogGameStatus(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
...@@ -74,11 +92,11 @@ func TestProgressGame_LogGameStatus(t *testing.T) { ...@@ -74,11 +92,11 @@ func TestProgressGame_LogGameStatus(t *testing.T) {
for _, test := range tests { for _, test := range tests {
test := test test := test
t.Run(test.name, func(t *testing.T) { t.Run(test.name, func(t *testing.T) {
handler, game, actor, gameInfo := setupProgressGameTest(t, test.agreeWithOutput) handler, game, gameState := setupProgressGameTest(t, test.agreeWithOutput)
gameInfo.status = test.status gameState.status = test.status
done := game.ProgressGame(context.Background()) done := game.ProgressGame(context.Background())
require.Equal(t, 1, actor.callCount, "should perform next actions") require.Equal(t, 1, gameState.callCount, "should perform next actions")
require.Equal(t, test.status != types.GameStatusInProgress, done, "should be done when not in progress") require.Equal(t, test.status != types.GameStatusInProgress, done, "should be done when not in progress")
errLog := handler.FindLog(test.logLevel, test.logMsg) errLog := handler.FindLog(test.logLevel, test.logMsg)
require.NotNil(t, errLog, "should log game result") require.NotNil(t, errLog, "should log game result")
...@@ -87,43 +105,57 @@ func TestProgressGame_LogGameStatus(t *testing.T) { ...@@ -87,43 +105,57 @@ func TestProgressGame_LogGameStatus(t *testing.T) {
} }
} }
func setupProgressGameTest(t *testing.T, agreeWithProposedRoot bool) (*testlog.CapturingHandler, *GamePlayer, *stubActor, *stubGameInfo) { func TestDoNotActOnCompleteGame(t *testing.T) {
for _, status := range []types.GameStatus{types.GameStatusChallengerWon, types.GameStatusDefenderWon} {
t.Run(status.String(), func(t *testing.T) {
_, game, gameState := setupProgressGameTest(t, true)
gameState.status = status
done := game.ProgressGame(context.Background())
require.Equal(t, 1, gameState.callCount, "acts the first time")
require.True(t, done, "should be done")
// Should not act when it knows the game is already complete
done = game.ProgressGame(context.Background())
require.Equal(t, 1, gameState.callCount, "does not act after game is complete")
require.True(t, done, "should still be done")
})
}
}
func setupProgressGameTest(t *testing.T, agreeWithProposedRoot bool) (*testlog.CapturingHandler, *GamePlayer, *stubGameState) {
logger := testlog.Logger(t, log.LvlDebug) logger := testlog.Logger(t, log.LvlDebug)
handler := &testlog.CapturingHandler{ handler := &testlog.CapturingHandler{
Delegate: logger.GetHandler(), Delegate: logger.GetHandler(),
} }
logger.SetHandler(handler) logger.SetHandler(handler)
actor := &stubActor{} gameState := &stubGameState{claimCount: 1}
gameInfo := &stubGameInfo{claimCount: 1}
game := &GamePlayer{ game := &GamePlayer{
agent: actor, agent: gameState,
agreeWithProposedOutput: agreeWithProposedRoot, agreeWithProposedOutput: agreeWithProposedRoot,
caller: gameInfo, caller: gameState,
logger: logger, logger: logger,
} }
return handler, game, actor, gameInfo return handler, game, gameState
}
type stubActor struct {
callCount int
err error
} }
func (a *stubActor) Act(ctx context.Context) error { type stubGameState struct {
a.callCount++
return a.err
}
type stubGameInfo struct {
status types.GameStatus status types.GameStatus
claimCount uint64 claimCount uint64
err error callCount int
actErr error
Err error
}
func (s *stubGameState) Act(ctx context.Context) error {
s.callCount++
return s.actErr
} }
func (s *stubGameInfo) GetGameStatus(ctx context.Context) (types.GameStatus, error) { func (s *stubGameState) GetGameStatus(ctx context.Context) (types.GameStatus, error) {
return s.status, s.err return s.status, nil
} }
func (s *stubGameInfo) GetClaimCount(ctx context.Context) (uint64, error) { func (s *stubGameState) GetClaimCount(ctx context.Context) (uint64, error) {
return s.claimCount, s.err return s.claimCount, nil
} }
...@@ -79,18 +79,25 @@ func (r *faultResponder) BuildTx(ctx context.Context, response types.Claim) ([]b ...@@ -79,18 +79,25 @@ func (r *faultResponder) BuildTx(ctx context.Context, response types.Claim) ([]b
} }
} }
// CanResolve determines if the resolve function on the fault dispute game contract // CallResolve determines if the resolve function on the fault dispute game contract
// would succeed. Returns true if the game can be resolved, otherwise false. // would succeed. Returns the game status if the call would succeed, errors otherwise.
func (r *faultResponder) CanResolve(ctx context.Context) bool { func (r *faultResponder) CallResolve(ctx context.Context) (types.GameStatus, error) {
txData, err := r.buildResolveData() txData, err := r.buildResolveData()
if err != nil { if err != nil {
return false return types.GameStatusInProgress, err
} }
_, err = r.txMgr.Call(ctx, ethereum.CallMsg{ res, err := r.txMgr.Call(ctx, ethereum.CallMsg{
To: &r.fdgAddr, To: &r.fdgAddr,
Data: txData, Data: txData,
}, nil) }, nil)
return err == nil if err != nil {
return types.GameStatusInProgress, err
}
var status uint8
if err = r.fdgAbi.UnpackIntoInterface(&status, "resolve", res); err != nil {
return types.GameStatusInProgress, err
}
return types.GameStatusFromUint8(status)
} }
// Resolve executes a resolve transaction to resolve a fault dispute game. // Resolve executes a resolve transaction to resolve a fault dispute game.
......
...@@ -22,13 +22,138 @@ import ( ...@@ -22,13 +22,138 @@ import (
var ( var (
mockFdgAddress = common.HexToAddress("0x1234") mockFdgAddress = common.HexToAddress("0x1234")
mockSendError = errors.New("mock send error") mockSendError = errors.New("mock send error")
mockCallError = errors.New("mock call error")
) )
// TestCallResolve tests the [Responder.CallResolve].
func TestCallResolve(t *testing.T) {
t.Run("SendFails", func(t *testing.T) {
responder, mockTxMgr := newTestFaultResponder(t)
mockTxMgr.callFails = true
status, err := responder.CallResolve(context.Background())
require.ErrorIs(t, err, mockCallError)
require.Equal(t, types.GameStatusInProgress, status)
require.Equal(t, 0, mockTxMgr.calls)
})
t.Run("UnpackFails", func(t *testing.T) {
responder, mockTxMgr := newTestFaultResponder(t)
mockTxMgr.callBytes = []byte{0x00, 0x01}
status, err := responder.CallResolve(context.Background())
require.Error(t, err)
require.Equal(t, types.GameStatusInProgress, status)
require.Equal(t, 1, mockTxMgr.calls)
})
t.Run("Success", func(t *testing.T) {
responder, mockTxMgr := newTestFaultResponder(t)
status, err := responder.CallResolve(context.Background())
require.NoError(t, err)
require.Equal(t, types.GameStatusInProgress, status)
require.Equal(t, 1, mockTxMgr.calls)
})
}
// TestResolve tests the [Responder.Resolve] method.
func TestResolve(t *testing.T) {
t.Run("SendFails", func(t *testing.T) {
responder, mockTxMgr := newTestFaultResponder(t)
mockTxMgr.sendFails = true
err := responder.Resolve(context.Background())
require.ErrorIs(t, err, mockSendError)
require.Equal(t, 0, mockTxMgr.sends)
})
t.Run("Success", func(t *testing.T) {
responder, mockTxMgr := newTestFaultResponder(t)
err := responder.Resolve(context.Background())
require.NoError(t, err)
require.Equal(t, 1, mockTxMgr.sends)
})
}
// TestRespond tests the [Responder.Respond] method.
func TestRespond(t *testing.T) {
t.Run("send fails", func(t *testing.T) {
responder, mockTxMgr := newTestFaultResponder(t)
mockTxMgr.sendFails = true
err := responder.Respond(context.Background(), generateMockResponseClaim())
require.ErrorIs(t, err, mockSendError)
require.Equal(t, 0, mockTxMgr.sends)
})
t.Run("sends response", func(t *testing.T) {
responder, mockTxMgr := newTestFaultResponder(t)
err := responder.Respond(context.Background(), generateMockResponseClaim())
require.NoError(t, err)
require.Equal(t, 1, mockTxMgr.sends)
})
}
// TestBuildTx tests the [Responder.BuildTx] method.
func TestBuildTx(t *testing.T) {
t.Run("attack", func(t *testing.T) {
responder, _ := newTestFaultResponder(t)
responseClaim := generateMockResponseClaim()
responseClaim.ParentContractIndex = 7
tx, err := responder.BuildTx(context.Background(), responseClaim)
require.NoError(t, err)
// Pack the tx data manually.
fdgAbi, err := bindings.FaultDisputeGameMetaData.GetAbi()
require.NoError(t, err)
parent := big.NewInt(int64(7))
claim := responseClaim.ValueBytes()
expected, err := fdgAbi.Pack("attack", parent, claim)
require.NoError(t, err)
require.Equal(t, expected, tx)
})
t.Run("defend", func(t *testing.T) {
responder, _ := newTestFaultResponder(t)
responseClaim := types.Claim{
ClaimData: types.ClaimData{
Value: common.Hash{0x01},
Position: types.NewPositionFromGIndex(3),
},
Parent: types.ClaimData{
Value: common.Hash{0x02},
Position: types.NewPositionFromGIndex(6),
},
ContractIndex: 0,
ParentContractIndex: 7,
}
tx, err := responder.BuildTx(context.Background(), responseClaim)
require.NoError(t, err)
// Pack the tx data manually.
fdgAbi, err := bindings.FaultDisputeGameMetaData.GetAbi()
require.NoError(t, err)
parent := big.NewInt(int64(7))
claim := responseClaim.ValueBytes()
expected, err := fdgAbi.Pack("defend", parent, claim)
require.NoError(t, err)
require.Equal(t, expected, tx)
})
}
func newTestFaultResponder(t *testing.T) (*faultResponder, *mockTxManager) {
log := testlog.Logger(t, log.LvlError)
mockTxMgr := &mockTxManager{}
responder, err := NewFaultResponder(log, mockTxMgr, mockFdgAddress)
require.NoError(t, err)
return responder, mockTxMgr
}
type mockTxManager struct { type mockTxManager struct {
from common.Address from common.Address
sends int sends int
calls int calls int
sendFails bool sendFails bool
callFails bool
callBytes []byte
} }
func (m *mockTxManager) Send(ctx context.Context, candidate txmgr.TxCandidate) (*ethtypes.Receipt, error) { func (m *mockTxManager) Send(ctx context.Context, candidate txmgr.TxCandidate) (*ethtypes.Receipt, error) {
...@@ -44,11 +169,16 @@ func (m *mockTxManager) Send(ctx context.Context, candidate txmgr.TxCandidate) ( ...@@ -44,11 +169,16 @@ func (m *mockTxManager) Send(ctx context.Context, candidate txmgr.TxCandidate) (
} }
func (m *mockTxManager) Call(_ context.Context, _ ethereum.CallMsg, _ *big.Int) ([]byte, error) { func (m *mockTxManager) Call(_ context.Context, _ ethereum.CallMsg, _ *big.Int) ([]byte, error) {
if m.sendFails { if m.callFails {
return nil, mockSendError return nil, mockCallError
} }
m.calls++ m.calls++
return []byte{}, nil if m.callBytes != nil {
return m.callBytes, nil
}
return common.Hex2Bytes(
"0000000000000000000000000000000000000000000000000000000000000000",
), nil
} }
func (m *mockTxManager) BlockNumber(ctx context.Context) (uint64, error) { func (m *mockTxManager) BlockNumber(ctx context.Context) (uint64, error) {
...@@ -59,56 +189,8 @@ func (m *mockTxManager) From() common.Address { ...@@ -59,56 +189,8 @@ func (m *mockTxManager) From() common.Address {
return m.from return m.from
} }
func newTestFaultResponder(t *testing.T, sendFails bool) (*faultResponder, *mockTxManager) { func generateMockResponseClaim() types.Claim {
log := testlog.Logger(t, log.LvlError) return types.Claim{
mockTxMgr := &mockTxManager{}
mockTxMgr.sendFails = sendFails
responder, err := NewFaultResponder(log, mockTxMgr, mockFdgAddress)
require.NoError(t, err)
return responder, mockTxMgr
}
// TestResponder_CanResolve_CallFails tests the [Responder.CanResolve] method
// bubbles up the error returned by the [txmgr.Call] method.
func TestResponder_CanResolve_CallFails(t *testing.T) {
responder, mockTxMgr := newTestFaultResponder(t, true)
resolved := responder.CanResolve(context.Background())
require.False(t, resolved)
require.Equal(t, 0, mockTxMgr.sends)
}
// TestResponder_CanResolve_Success tests the [Responder.CanResolve] method
// succeeds when the call message is successfully sent through the txmgr.
func TestResponder_CanResolve_Success(t *testing.T) {
responder, mockTxMgr := newTestFaultResponder(t, false)
resolved := responder.CanResolve(context.Background())
require.True(t, resolved)
require.Equal(t, 1, mockTxMgr.calls)
}
// TestResponder_Resolve_SendFails tests the [Responder.Resolve] method
// bubbles up the error returned by the [txmgr.Send] method.
func TestResponder_Resolve_SendFails(t *testing.T) {
responder, mockTxMgr := newTestFaultResponder(t, true)
err := responder.Resolve(context.Background())
require.ErrorIs(t, err, mockSendError)
require.Equal(t, 0, mockTxMgr.sends)
}
// TestResponder_Resolve_Success tests the [Responder.Resolve] method
// succeeds when the tx candidate is successfully sent through the txmgr.
func TestResponder_Resolve_Success(t *testing.T) {
responder, mockTxMgr := newTestFaultResponder(t, false)
err := responder.Resolve(context.Background())
require.NoError(t, err)
require.Equal(t, 1, mockTxMgr.sends)
}
// TestResponder_Respond_SendFails tests the [Responder.Respond] method
// bubbles up the error returned by the [txmgr.Send] method.
func TestResponder_Respond_SendFails(t *testing.T) {
responder, mockTxMgr := newTestFaultResponder(t, true)
err := responder.Respond(context.Background(), types.Claim{
ClaimData: types.ClaimData{ ClaimData: types.ClaimData{
Value: common.Hash{0x01}, Value: common.Hash{0x01},
Position: types.NewPositionFromGIndex(2), Position: types.NewPositionFromGIndex(2),
...@@ -119,89 +201,5 @@ func TestResponder_Respond_SendFails(t *testing.T) { ...@@ -119,89 +201,5 @@ func TestResponder_Respond_SendFails(t *testing.T) {
}, },
ContractIndex: 0, ContractIndex: 0,
ParentContractIndex: 0, ParentContractIndex: 0,
})
require.ErrorIs(t, err, mockSendError)
require.Equal(t, 0, mockTxMgr.sends)
}
// TestResponder_Respond_Success tests the [Responder.Respond] method
// succeeds when the tx candidate is successfully sent through the txmgr.
func TestResponder_Respond_Success(t *testing.T) {
responder, mockTxMgr := newTestFaultResponder(t, false)
err := responder.Respond(context.Background(), types.Claim{
ClaimData: types.ClaimData{
Value: common.Hash{0x01},
Position: types.NewPositionFromGIndex(2),
},
Parent: types.ClaimData{
Value: common.Hash{0x02},
Position: types.NewPositionFromGIndex(1),
},
ContractIndex: 0,
ParentContractIndex: 0,
})
require.NoError(t, err)
require.Equal(t, 1, mockTxMgr.sends)
}
// TestResponder_BuildTx_Attack tests the [Responder.BuildTx] method
// returns a tx candidate with the correct data for an attack tx.
func TestResponder_BuildTx_Attack(t *testing.T) {
responder, _ := newTestFaultResponder(t, false)
responseClaim := types.Claim{
ClaimData: types.ClaimData{
Value: common.Hash{0x01},
Position: types.NewPositionFromGIndex(2),
},
Parent: types.ClaimData{
Value: common.Hash{0x02},
Position: types.NewPositionFromGIndex(1),
},
ContractIndex: 0,
ParentContractIndex: 7,
} }
tx, err := responder.BuildTx(context.Background(), responseClaim)
require.NoError(t, err)
// Pack the tx data manually.
fdgAbi, err := bindings.FaultDisputeGameMetaData.GetAbi()
require.NoError(t, err)
expected, err := fdgAbi.Pack(
"attack",
big.NewInt(int64(7)),
responseClaim.ValueBytes(),
)
require.NoError(t, err)
require.Equal(t, expected, tx)
}
// TestResponder_BuildTx_Defend tests the [Responder.BuildTx] method
// returns a tx candidate with the correct data for a defend tx.
func TestResponder_BuildTx_Defend(t *testing.T) {
responder, _ := newTestFaultResponder(t, false)
responseClaim := types.Claim{
ClaimData: types.ClaimData{
Value: common.Hash{0x01},
Position: types.NewPositionFromGIndex(3),
},
Parent: types.ClaimData{
Value: common.Hash{0x02},
Position: types.NewPositionFromGIndex(6),
},
ContractIndex: 0,
ParentContractIndex: 7,
}
tx, err := responder.BuildTx(context.Background(), responseClaim)
require.NoError(t, err)
// Pack the tx data manually.
fdgAbi, err := bindings.FaultDisputeGameMetaData.GetAbi()
require.NoError(t, err)
expected, err := fdgAbi.Pack(
"defend",
big.NewInt(int64(7)),
responseClaim.ValueBytes(),
)
require.NoError(t, err)
require.Equal(t, expected, tx)
} }
...@@ -73,7 +73,7 @@ func NewService(ctx context.Context, logger log.Logger, cfg *config.Config) (*se ...@@ -73,7 +73,7 @@ func NewService(ctx context.Context, logger log.Logger, cfg *config.Config) (*se
} }
loader := NewGameLoader(factory) loader := NewGameLoader(factory)
monitor := newGameMonitor(logger, cl, client.BlockNumber, cfg.GameAllowlist, loader, func(addr common.Address) (gamePlayer, error) { monitor := newGameMonitor(logger, cfg.GameWindow, cl, client.BlockNumber, cfg.GameAllowlist, loader, func(addr common.Address) (gamePlayer, error) {
return NewGamePlayer(ctx, logger, cfg, addr, txMgr, client) return NewGamePlayer(ctx, logger, cfg, addr, txMgr, client)
}) })
......
...@@ -3,6 +3,7 @@ package types ...@@ -3,6 +3,7 @@ package types
import ( import (
"context" "context"
"errors" "errors"
"fmt"
"math/big" "math/big"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
...@@ -34,6 +35,14 @@ func (s GameStatus) String() string { ...@@ -34,6 +35,14 @@ func (s GameStatus) String() string {
} }
} }
// GameStatusFromUint8 returns a game status from the uint8 representation.
func GameStatusFromUint8(i uint8) (GameStatus, error) {
if i > 2 {
return GameStatus(i), fmt.Errorf("invalid game status: %d", i)
}
return GameStatus(i), nil
}
// PreimageOracleData encapsulates the preimage oracle data // PreimageOracleData encapsulates the preimage oracle data
// to load into the onchain oracle. // to load into the onchain oracle.
type PreimageOracleData struct { type PreimageOracleData struct {
......
package types package types
import ( import (
"fmt"
"testing" "testing"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
var validGameStatuses = []GameStatus{
GameStatusInProgress,
GameStatusChallengerWon,
GameStatusDefenderWon,
}
func TestGameStatusFromUint8(t *testing.T) {
for _, status := range validGameStatuses {
t.Run(fmt.Sprintf("Valid Game Status %v", status), func(t *testing.T) {
parsed, err := GameStatusFromUint8(uint8(status))
require.NoError(t, err)
require.Equal(t, status, parsed)
})
}
t.Run("Invalid", func(t *testing.T) {
status, err := GameStatusFromUint8(3)
require.Error(t, err)
require.Equal(t, GameStatus(3), status)
})
}
func TestNewPreimageOracleData(t *testing.T) { func TestNewPreimageOracleData(t *testing.T) {
t.Run("LocalData", func(t *testing.T) { t.Run("LocalData", func(t *testing.T) {
data := NewPreimageOracleData([]byte{1, 2, 3}, []byte{4, 5, 6}, 7) data := NewPreimageOracleData([]byte{1, 2, 3}, []byte{4, 5, 6}, 7)
......
...@@ -109,6 +109,12 @@ var ( ...@@ -109,6 +109,12 @@ var (
EnvVars: prefixEnvVars("CANNON_SNAPSHOT_FREQ"), EnvVars: prefixEnvVars("CANNON_SNAPSHOT_FREQ"),
Value: config.DefaultCannonSnapshotFreq, Value: config.DefaultCannonSnapshotFreq,
} }
GameWindowFlag = &cli.DurationFlag{
Name: "game-window",
Usage: "The time window which the challenger will look for games to progress.",
EnvVars: prefixEnvVars("GAME_WINDOW"),
Value: config.DefaultGameWindow,
}
) )
// requiredFlags are checked by [CheckRequired] // requiredFlags are checked by [CheckRequired]
...@@ -132,6 +138,7 @@ var optionalFlags = []cli.Flag{ ...@@ -132,6 +138,7 @@ var optionalFlags = []cli.Flag{
CannonDatadirFlag, CannonDatadirFlag,
CannonL2Flag, CannonL2Flag,
CannonSnapshotFreqFlag, CannonSnapshotFreqFlag,
GameWindowFlag,
} }
func init() { func init() {
...@@ -222,6 +229,7 @@ func NewConfigFromCLI(ctx *cli.Context) (*config.Config, error) { ...@@ -222,6 +229,7 @@ func NewConfigFromCLI(ctx *cli.Context) (*config.Config, error) {
TraceType: traceTypeFlag, TraceType: traceTypeFlag,
GameFactoryAddress: gameFactoryAddress, GameFactoryAddress: gameFactoryAddress,
GameAllowlist: allowedGames, GameAllowlist: allowedGames,
GameWindow: ctx.Duration(GameWindowFlag.Name),
AlphabetTrace: ctx.String(AlphabetFlag.Name), AlphabetTrace: ctx.String(AlphabetFlag.Name),
CannonNetwork: ctx.String(CannonNetworkFlag.Name), CannonNetwork: ctx.String(CannonNetworkFlag.Name),
CannonRollupConfigPath: ctx.String(CannonRollupConfigFlag.Name), CannonRollupConfigPath: ctx.String(CannonRollupConfigFlag.Name),
......
...@@ -68,7 +68,7 @@ ...@@ -68,7 +68,7 @@
"markdownlint-cli2": "0.4.0", "markdownlint-cli2": "0.4.0",
"mkdirp": "^1.0.4", "mkdirp": "^1.0.4",
"mocha": "^10.2.0", "mocha": "^10.2.0",
"nx": "16.7.2", "nx": "16.7.3",
"nyc": "^15.1.0", "nyc": "^15.1.0",
"patch-package": "^8.0.0", "patch-package": "^8.0.0",
"prettier": "^2.8.0", "prettier": "^2.8.0",
......
...@@ -41,7 +41,7 @@ ...@@ -41,7 +41,7 @@
"lint": "pnpm lint:fix && pnpm lint:check" "lint": "pnpm lint:fix && pnpm lint:check"
}, },
"devDependencies": { "devDependencies": {
"@typescript-eslint/eslint-plugin": "^6.4.0", "@typescript-eslint/eslint-plugin": "^5.62.0",
"@typescript-eslint/parser": "^6.4.0", "@typescript-eslint/parser": "^6.4.0",
"tsx": "^3.12.7", "tsx": "^3.12.7",
"typescript": "^5.1.6" "typescript": "^5.1.6"
......
...@@ -38,7 +38,7 @@ importers: ...@@ -38,7 +38,7 @@ importers:
version: 12.20.20 version: 12.20.20
'@typescript-eslint/eslint-plugin': '@typescript-eslint/eslint-plugin':
specifier: ^5.60.1 specifier: ^5.60.1
version: 5.60.1(@typescript-eslint/parser@5.60.1)(eslint@8.47.0)(typescript@5.1.6) version: 5.62.0(@typescript-eslint/parser@5.60.1)(eslint@8.47.0)(typescript@5.1.6)
'@typescript-eslint/parser': '@typescript-eslint/parser':
specifier: ^5.60.1 specifier: ^5.60.1
version: 5.60.1(eslint@8.47.0)(typescript@5.1.6) version: 5.60.1(eslint@8.47.0)(typescript@5.1.6)
...@@ -109,8 +109,8 @@ importers: ...@@ -109,8 +109,8 @@ importers:
specifier: ^10.2.0 specifier: ^10.2.0
version: 10.2.0 version: 10.2.0
nx: nx:
specifier: 16.7.2 specifier: 16.7.3
version: 16.7.2 version: 16.7.3
nyc: nyc:
specifier: ^15.1.0 specifier: ^15.1.0
version: 15.1.0 version: 15.1.0
...@@ -268,8 +268,8 @@ importers: ...@@ -268,8 +268,8 @@ importers:
packages/contracts-bedrock: packages/contracts-bedrock:
devDependencies: devDependencies:
'@typescript-eslint/eslint-plugin': '@typescript-eslint/eslint-plugin':
specifier: ^6.4.0 specifier: ^5.62.0
version: 6.4.0(@typescript-eslint/parser@6.4.0)(eslint@8.47.0)(typescript@5.1.6) version: 5.62.0(@typescript-eslint/parser@6.4.0)(eslint@8.47.0)(typescript@5.1.6)
'@typescript-eslint/parser': '@typescript-eslint/parser':
specifier: ^6.4.0 specifier: ^6.4.0
version: 6.4.0(eslint@8.47.0)(typescript@5.1.6) version: 6.4.0(eslint@8.47.0)(typescript@5.1.6)
...@@ -1005,7 +1005,7 @@ packages: ...@@ -1005,7 +1005,7 @@ packages:
/@changesets/apply-release-plan@6.1.3: /@changesets/apply-release-plan@6.1.3:
resolution: {integrity: sha512-ECDNeoc3nfeAe1jqJb5aFQX7CqzQhD2klXRez2JDb/aVpGUbX673HgKrnrgJRuQR/9f2TtLoYIzrGB9qwD77mg==} resolution: {integrity: sha512-ECDNeoc3nfeAe1jqJb5aFQX7CqzQhD2klXRez2JDb/aVpGUbX673HgKrnrgJRuQR/9f2TtLoYIzrGB9qwD77mg==}
dependencies: dependencies:
'@babel/runtime': 7.20.7 '@babel/runtime': 7.22.6
'@changesets/config': 2.3.0 '@changesets/config': 2.3.0
'@changesets/get-version-range-type': 0.3.2 '@changesets/get-version-range-type': 0.3.2
'@changesets/git': 2.0.0 '@changesets/git': 2.0.0
...@@ -1023,7 +1023,7 @@ packages: ...@@ -1023,7 +1023,7 @@ packages:
/@changesets/assemble-release-plan@5.2.3: /@changesets/assemble-release-plan@5.2.3:
resolution: {integrity: sha512-g7EVZCmnWz3zMBAdrcKhid4hkHT+Ft1n0mLussFMcB1dE2zCuwcvGoy9ec3yOgPGF4hoMtgHaMIk3T3TBdvU9g==} resolution: {integrity: sha512-g7EVZCmnWz3zMBAdrcKhid4hkHT+Ft1n0mLussFMcB1dE2zCuwcvGoy9ec3yOgPGF4hoMtgHaMIk3T3TBdvU9g==}
dependencies: dependencies:
'@babel/runtime': 7.20.7 '@babel/runtime': 7.22.6
'@changesets/errors': 0.1.4 '@changesets/errors': 0.1.4
'@changesets/get-dependents-graph': 1.3.5 '@changesets/get-dependents-graph': 1.3.5
'@changesets/types': 5.2.1 '@changesets/types': 5.2.1
...@@ -1126,7 +1126,7 @@ packages: ...@@ -1126,7 +1126,7 @@ packages:
/@changesets/get-release-plan@3.0.16: /@changesets/get-release-plan@3.0.16:
resolution: {integrity: sha512-OpP9QILpBp1bY2YNIKFzwigKh7Qe9KizRsZomzLe6pK8IUo8onkAAVUD8+JRKSr8R7d4+JRuQrfSSNlEwKyPYg==} resolution: {integrity: sha512-OpP9QILpBp1bY2YNIKFzwigKh7Qe9KizRsZomzLe6pK8IUo8onkAAVUD8+JRKSr8R7d4+JRuQrfSSNlEwKyPYg==}
dependencies: dependencies:
'@babel/runtime': 7.20.7 '@babel/runtime': 7.22.6
'@changesets/assemble-release-plan': 5.2.3 '@changesets/assemble-release-plan': 5.2.3
'@changesets/config': 2.3.0 '@changesets/config': 2.3.0
'@changesets/pre': 1.0.14 '@changesets/pre': 1.0.14
...@@ -1142,7 +1142,7 @@ packages: ...@@ -1142,7 +1142,7 @@ packages:
/@changesets/git@2.0.0: /@changesets/git@2.0.0:
resolution: {integrity: sha512-enUVEWbiqUTxqSnmesyJGWfzd51PY4H7mH9yUw0hPVpZBJ6tQZFMU3F3mT/t9OJ/GjyiM4770i+sehAn6ymx6A==} resolution: {integrity: sha512-enUVEWbiqUTxqSnmesyJGWfzd51PY4H7mH9yUw0hPVpZBJ6tQZFMU3F3mT/t9OJ/GjyiM4770i+sehAn6ymx6A==}
dependencies: dependencies:
'@babel/runtime': 7.20.7 '@babel/runtime': 7.22.6
'@changesets/errors': 0.1.4 '@changesets/errors': 0.1.4
'@changesets/types': 5.2.1 '@changesets/types': 5.2.1
'@manypkg/get-packages': 1.1.3 '@manypkg/get-packages': 1.1.3
...@@ -1167,7 +1167,7 @@ packages: ...@@ -1167,7 +1167,7 @@ packages:
/@changesets/pre@1.0.14: /@changesets/pre@1.0.14:
resolution: {integrity: sha512-dTsHmxQWEQekHYHbg+M1mDVYFvegDh9j/kySNuDKdylwfMEevTeDouR7IfHNyVodxZXu17sXoJuf2D0vi55FHQ==} resolution: {integrity: sha512-dTsHmxQWEQekHYHbg+M1mDVYFvegDh9j/kySNuDKdylwfMEevTeDouR7IfHNyVodxZXu17sXoJuf2D0vi55FHQ==}
dependencies: dependencies:
'@babel/runtime': 7.20.7 '@babel/runtime': 7.22.6
'@changesets/errors': 0.1.4 '@changesets/errors': 0.1.4
'@changesets/types': 5.2.1 '@changesets/types': 5.2.1
'@manypkg/get-packages': 1.1.3 '@manypkg/get-packages': 1.1.3
...@@ -1177,7 +1177,7 @@ packages: ...@@ -1177,7 +1177,7 @@ packages:
/@changesets/read@0.5.9: /@changesets/read@0.5.9:
resolution: {integrity: sha512-T8BJ6JS6j1gfO1HFq50kU3qawYxa4NTbI/ASNVVCBTsKquy2HYwM9r7ZnzkiMe8IEObAJtUVGSrePCOxAK2haQ==} resolution: {integrity: sha512-T8BJ6JS6j1gfO1HFq50kU3qawYxa4NTbI/ASNVVCBTsKquy2HYwM9r7ZnzkiMe8IEObAJtUVGSrePCOxAK2haQ==}
dependencies: dependencies:
'@babel/runtime': 7.20.7 '@babel/runtime': 7.22.6
'@changesets/git': 2.0.0 '@changesets/git': 2.0.0
'@changesets/logger': 0.0.5 '@changesets/logger': 0.0.5
'@changesets/parse': 0.3.16 '@changesets/parse': 0.3.16
...@@ -1197,7 +1197,7 @@ packages: ...@@ -1197,7 +1197,7 @@ packages:
/@changesets/write@0.2.3: /@changesets/write@0.2.3:
resolution: {integrity: sha512-Dbamr7AIMvslKnNYsLFafaVORx4H0pvCA2MHqgtNCySMe1blImEyAEOzDmcgKAkgz4+uwoLz7demIrX+JBr/Xw==} resolution: {integrity: sha512-Dbamr7AIMvslKnNYsLFafaVORx4H0pvCA2MHqgtNCySMe1blImEyAEOzDmcgKAkgz4+uwoLz7demIrX+JBr/Xw==}
dependencies: dependencies:
'@babel/runtime': 7.20.7 '@babel/runtime': 7.22.6
'@changesets/types': 5.2.1 '@changesets/types': 5.2.1
fs-extra: 7.0.1 fs-extra: 7.0.1
human-id: 1.0.2 human-id: 1.0.2
...@@ -1738,11 +1738,6 @@ packages: ...@@ -1738,11 +1738,6 @@ packages:
eslint-visitor-keys: 3.4.3 eslint-visitor-keys: 3.4.3
dev: true dev: true
/@eslint-community/regexpp@4.5.1:
resolution: {integrity: sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ==}
engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0}
dev: true
/@eslint-community/regexpp@4.6.2: /@eslint-community/regexpp@4.6.2:
resolution: {integrity: sha512-pPTNuaAG3QMH+buKyBIGJs3g/S5y0caxw0ygM3YyE6yJFySwiGGSzA+mM3KJ8QQvzeLh3blwgSonkFjgQdxzMw==} resolution: {integrity: sha512-pPTNuaAG3QMH+buKyBIGJs3g/S5y0caxw0ygM3YyE6yJFySwiGGSzA+mM3KJ8QQvzeLh3blwgSonkFjgQdxzMw==}
engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0}
...@@ -2517,7 +2512,7 @@ packages: ...@@ -2517,7 +2512,7 @@ packages:
dependencies: dependencies:
'@lerna/child-process': 7.1.5 '@lerna/child-process': 7.1.5
'@npmcli/run-script': 6.0.2 '@npmcli/run-script': 6.0.2
'@nx/devkit': 16.7.1(nx@16.7.2) '@nx/devkit': 16.7.1(nx@16.7.3)
'@octokit/plugin-enterprise-rest': 6.0.1 '@octokit/plugin-enterprise-rest': 6.0.1
'@octokit/rest': 19.0.11 '@octokit/rest': 19.0.11
byte-size: 8.1.1 byte-size: 8.1.1
...@@ -2553,7 +2548,7 @@ packages: ...@@ -2553,7 +2548,7 @@ packages:
npm-packlist: 5.1.1 npm-packlist: 5.1.1
npm-registry-fetch: 14.0.5 npm-registry-fetch: 14.0.5
npmlog: 6.0.2 npmlog: 6.0.2
nx: 16.7.2 nx: 16.7.3
p-map: 4.0.0 p-map: 4.0.0
p-map-series: 2.1.0 p-map-series: 2.1.0
p-queue: 6.6.2 p-queue: 6.6.2
...@@ -2608,7 +2603,7 @@ packages: ...@@ -2608,7 +2603,7 @@ packages:
/@manypkg/get-packages@1.1.3: /@manypkg/get-packages@1.1.3:
resolution: {integrity: sha512-fo+QhuU3qE/2TQMQmbVMqaQ6EWbMhi4ABWP+O4AM1NqPBuy0OrApV5LO6BrrgnhtAHS2NH6RrVk9OL181tTi8A==} resolution: {integrity: sha512-fo+QhuU3qE/2TQMQmbVMqaQ6EWbMhi4ABWP+O4AM1NqPBuy0OrApV5LO6BrrgnhtAHS2NH6RrVk9OL181tTi8A==}
dependencies: dependencies:
'@babel/runtime': 7.20.7 '@babel/runtime': 7.22.6
'@changesets/types': 4.1.0 '@changesets/types': 4.1.0
'@manypkg/find-root': 1.1.0 '@manypkg/find-root': 1.1.0
fs-extra: 8.1.0 fs-extra: 8.1.0
...@@ -2838,10 +2833,10 @@ packages: ...@@ -2838,10 +2833,10 @@ packages:
- supports-color - supports-color
dev: true dev: true
/@nrwl/devkit@16.7.1(nx@16.7.2): /@nrwl/devkit@16.7.1(nx@16.7.3):
resolution: {integrity: sha512-ysAgNju6o7QjG/ZHW0wIRJ8yWxjhErjqQ8GZ2Smqsb1myrr6UbYsuxaXjoOHI56fMmGyNPK04zzyNXXWQw/UAA==} resolution: {integrity: sha512-ysAgNju6o7QjG/ZHW0wIRJ8yWxjhErjqQ8GZ2Smqsb1myrr6UbYsuxaXjoOHI56fMmGyNPK04zzyNXXWQw/UAA==}
dependencies: dependencies:
'@nx/devkit': 16.7.1(nx@16.7.2) '@nx/devkit': 16.7.1(nx@16.7.3)
transitivePeerDependencies: transitivePeerDependencies:
- nx - nx
dev: true dev: true
...@@ -2854,11 +2849,11 @@ packages: ...@@ -2854,11 +2849,11 @@ packages:
- debug - debug
dev: true dev: true
/@nrwl/tao@16.7.2: /@nrwl/tao@16.7.3:
resolution: {integrity: sha512-4Wc3ic5VtZL3t4qqCMJlEad/wWuFxNUX78U5ohEStN3UFFJIjwJJpKZYZDtxhaOLWUdXbk6CI3KfSIpWgwPdbQ==} resolution: {integrity: sha512-kaH0i7ZuncSW8hGXg6DVlUBG319lUG/ene6aJUeV1spOxEsEqlckCm9HfJPfcVntvh9m1LauW+yk64cw/biVwg==}
hasBin: true hasBin: true
dependencies: dependencies:
nx: 16.7.2 nx: 16.7.3
tslib: 2.6.0 tslib: 2.6.0
transitivePeerDependencies: transitivePeerDependencies:
- '@swc-node/register' - '@swc-node/register'
...@@ -2866,23 +2861,23 @@ packages: ...@@ -2866,23 +2861,23 @@ packages:
- debug - debug
dev: true dev: true
/@nx/devkit@16.7.1(nx@16.7.2): /@nx/devkit@16.7.1(nx@16.7.3):
resolution: {integrity: sha512-PASQGd1YhcAA/hpupCsSakP71Qh1pYle4dtF+wh3KDe2kdeM6BgccClapiGcXAI46JKLUGAbNYJ8pg7GEPY5Nw==} resolution: {integrity: sha512-PASQGd1YhcAA/hpupCsSakP71Qh1pYle4dtF+wh3KDe2kdeM6BgccClapiGcXAI46JKLUGAbNYJ8pg7GEPY5Nw==}
peerDependencies: peerDependencies:
nx: '>= 15 <= 17' nx: '>= 15 <= 17'
dependencies: dependencies:
'@nrwl/devkit': 16.7.1(nx@16.7.2) '@nrwl/devkit': 16.7.1(nx@16.7.3)
ejs: 3.1.9 ejs: 3.1.9
enquirer: 2.3.6 enquirer: 2.3.6
ignore: 5.2.4 ignore: 5.2.4
nx: 16.7.2 nx: 16.7.3
semver: 7.5.3 semver: 7.5.3
tmp: 0.2.1 tmp: 0.2.1
tslib: 2.6.0 tslib: 2.6.0
dev: true dev: true
/@nx/nx-darwin-arm64@16.7.2: /@nx/nx-darwin-arm64@16.7.3:
resolution: {integrity: sha512-dkTHAzOTbqRHUQtnw7knEJq4ll6hew11u+9B0fThs9gC/X0iPK0eDXD4TqbIKEbcWAsxpuGiWPzGoNPo7Gwl9A==} resolution: {integrity: sha512-s1woGSGbNEzDSzNoSIIpaYkVwJmM0D89/1QmccVZIv7jvGGcqx4ONQPsBylWpDco3IeTDhNsOMzMhF3fvqhtgA==}
engines: {node: '>= 10'} engines: {node: '>= 10'}
cpu: [arm64] cpu: [arm64]
os: [darwin] os: [darwin]
...@@ -2890,8 +2885,8 @@ packages: ...@@ -2890,8 +2885,8 @@ packages:
dev: true dev: true
optional: true optional: true
/@nx/nx-darwin-x64@16.7.2: /@nx/nx-darwin-x64@16.7.3:
resolution: {integrity: sha512-EKhjX7DCRIA5U8yAxIgGXeIFaq1dhgLJy8OAG4n1Ud8c21px+bBSrcZvv0ww5VoEulhggQ+c6fW1cjKtGgLknQ==} resolution: {integrity: sha512-J9lE+T7Hm3hD+s33xidxa6Jkq2CCKZwwTrLO+Ff1/A2d4T13d16O/Rf3Y/nuveUjCVEYwwYkk4G5v2FPJ4i3SQ==}
engines: {node: '>= 10'} engines: {node: '>= 10'}
cpu: [x64] cpu: [x64]
os: [darwin] os: [darwin]
...@@ -2899,8 +2894,8 @@ packages: ...@@ -2899,8 +2894,8 @@ packages:
dev: true dev: true
optional: true optional: true
/@nx/nx-freebsd-x64@16.7.2: /@nx/nx-freebsd-x64@16.7.3:
resolution: {integrity: sha512-3QhXZq0wxvi4lg1MJqwq72F7PE/d0Hcl3uwheenYQtwUvAFAmijC/Z4AVPSqbKJ+QaoqASnXRim9z3EIfeD+DQ==} resolution: {integrity: sha512-/1WrplEyxTkoARsCUcI2FjMVy2AFuaH2oS1vFuGtBchWoKbgFZd3Aek8+oYt0wiQ7cfBxs2y92UqvTOhLygxOw==}
engines: {node: '>= 10'} engines: {node: '>= 10'}
cpu: [x64] cpu: [x64]
os: [freebsd] os: [freebsd]
...@@ -2908,8 +2903,8 @@ packages: ...@@ -2908,8 +2903,8 @@ packages:
dev: true dev: true
optional: true optional: true
/@nx/nx-linux-arm-gnueabihf@16.7.2: /@nx/nx-linux-arm-gnueabihf@16.7.3:
resolution: {integrity: sha512-7bny8NvE9iyfwRfq9/mOZjzMNWthT70Ce1N9suB2zdbgbLUEDPQQhBNbg969yT6/LbWMWuWZXeIbz/Fwndf9zA==} resolution: {integrity: sha512-Z3CLZcxBnpra8nlizK97eyohI9x+JPh4wp+87x9WvIiLGd+k3hO42nth/q0xXJs2G5emQN8cSLPscGzbZodVpA==}
engines: {node: '>= 10'} engines: {node: '>= 10'}
cpu: [arm] cpu: [arm]
os: [linux] os: [linux]
...@@ -2917,8 +2912,8 @@ packages: ...@@ -2917,8 +2912,8 @@ packages:
dev: true dev: true
optional: true optional: true
/@nx/nx-linux-arm64-gnu@16.7.2: /@nx/nx-linux-arm64-gnu@16.7.3:
resolution: {integrity: sha512-+UdeFB1HY/3GU2+mflydFWpztghFRQiVzJV6MTcjtOzE3jfgXzz9TP580pDxozTvNSRPlblH07X+iB8DhVcB9w==} resolution: {integrity: sha512-a4E4psBgU0b7ZT99630mylxcrlLObgy4bA6JrT+4XIFAcaHkfCmWLupPyXgBCmSqQN01jsuXSYm/t7EWjKL98Q==}
engines: {node: '>= 10'} engines: {node: '>= 10'}
cpu: [arm64] cpu: [arm64]
os: [linux] os: [linux]
...@@ -2926,8 +2921,8 @@ packages: ...@@ -2926,8 +2921,8 @@ packages:
dev: true dev: true
optional: true optional: true
/@nx/nx-linux-arm64-musl@16.7.2: /@nx/nx-linux-arm64-musl@16.7.3:
resolution: {integrity: sha512-YfkWu+4GKXageuYiH5a77gIDAXnit5SIyfI+RWe/j04uFy171KnUt167DC417fv/fTGxeXY1tzOu112Y+x5ixw==} resolution: {integrity: sha512-vl+WONX6uOS8uGwtcAlb4yiAh2ws/gZSLaIURJaDnf509FrYTb/RsBca5BskOQUYkKSI//6oQu653TRDKYxyWw==}
engines: {node: '>= 10'} engines: {node: '>= 10'}
cpu: [arm64] cpu: [arm64]
os: [linux] os: [linux]
...@@ -2935,8 +2930,8 @@ packages: ...@@ -2935,8 +2930,8 @@ packages:
dev: true dev: true
optional: true optional: true
/@nx/nx-linux-x64-gnu@16.7.2: /@nx/nx-linux-x64-gnu@16.7.3:
resolution: {integrity: sha512-/TtSa2rHR+1gNuALR1yafl4fzBK2/GAhosf+skn00OgwsJ0c8ie9tuuftlMo+2n3LcXY/IaPDaD7t6fln4qsQg==} resolution: {integrity: sha512-udZ+6IOYv0Ra0MRpbAW8TSFdcUxtfuIryRsGVF2767HeWqHzOhLynmJyJPatJ7gXMVFaL7+zfcAoV6fm7My1FQ==}
engines: {node: '>= 10'} engines: {node: '>= 10'}
cpu: [x64] cpu: [x64]
os: [linux] os: [linux]
...@@ -2944,8 +2939,8 @@ packages: ...@@ -2944,8 +2939,8 @@ packages:
dev: true dev: true
optional: true optional: true
/@nx/nx-linux-x64-musl@16.7.2: /@nx/nx-linux-x64-musl@16.7.3:
resolution: {integrity: sha512-VC638hxdWSA8VTDU9rAXjr60mmMP3ZyCUbSkJ+8ydEe83StMDY3PAXS5Hw3n/ouxDfCF9r1kWIGFe4g+emvfBw==} resolution: {integrity: sha512-LQW1ttQWNekHoJTrzXMumaMxfYRcjsuGQP8Ki2pWuw43TFTQyI6Cfgk8/wjKv8ATc772cF9Tadyz4+JEIQlcNw==}
engines: {node: '>= 10'} engines: {node: '>= 10'}
cpu: [x64] cpu: [x64]
os: [linux] os: [linux]
...@@ -2953,8 +2948,8 @@ packages: ...@@ -2953,8 +2948,8 @@ packages:
dev: true dev: true
optional: true optional: true
/@nx/nx-win32-arm64-msvc@16.7.2: /@nx/nx-win32-arm64-msvc@16.7.3:
resolution: {integrity: sha512-sSUqgANLgQFFzKTvyMczh5D6xiqTQnB8daJTLX+QUCv5vO5+ZSwuVDyNfr6g/HV2+ak0M9/wVQUae11TgUIPYw==} resolution: {integrity: sha512-wCrpGqh5fPrlkhHZXVSPBDs9E3L5vIJHtdPrc1QP1uCQiV41mpauey31p6rjvQUWYCC0BGTWJGF+hAY7wYUHdg==}
engines: {node: '>= 10'} engines: {node: '>= 10'}
cpu: [arm64] cpu: [arm64]
os: [win32] os: [win32]
...@@ -2962,8 +2957,8 @@ packages: ...@@ -2962,8 +2957,8 @@ packages:
dev: true dev: true
optional: true optional: true
/@nx/nx-win32-x64-msvc@16.7.2: /@nx/nx-win32-x64-msvc@16.7.3:
resolution: {integrity: sha512-+n01cT9/P3o95x+FlRWYf9sFZ29ooxYD/WLcmxACeXN0V1bdbnZxKVSuJqrXZhmpHe7P+/+IRmniv9cdpkxz7g==} resolution: {integrity: sha512-Ja2+VhMFWiVsZt3mkdsU1MCotQlAxG94zFiJYbXufsERJItWuN4i0mZjeZITiRBosEmkn4SeAUkg+xuiH+q4GA==}
engines: {node: '>= 10'} engines: {node: '>= 10'}
cpu: [x64] cpu: [x64]
os: [win32] os: [win32]
...@@ -3980,10 +3975,6 @@ packages: ...@@ -3980,10 +3975,6 @@ packages:
pretty-format: 29.6.1 pretty-format: 29.6.1
dev: true dev: true
/@types/json-schema@7.0.11:
resolution: {integrity: sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==}
dev: true
/@types/json-schema@7.0.12: /@types/json-schema@7.0.12:
resolution: {integrity: sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==} resolution: {integrity: sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==}
dev: true dev: true
...@@ -4165,10 +4156,6 @@ packages: ...@@ -4165,10 +4156,6 @@ packages:
resolution: {integrity: sha512-KQf+QAMWKMrtBMsB8/24w53tEsxllMj6TuA80TT/5igJalLI/zm0L3oXRbIAl4Ohfc85gyHX/jhMwsVkmhLU4A==} resolution: {integrity: sha512-KQf+QAMWKMrtBMsB8/24w53tEsxllMj6TuA80TT/5igJalLI/zm0L3oXRbIAl4Ohfc85gyHX/jhMwsVkmhLU4A==}
dev: false dev: false
/@types/semver@7.3.13:
resolution: {integrity: sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==}
dev: true
/@types/semver@7.5.0: /@types/semver@7.5.0:
resolution: {integrity: sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==} resolution: {integrity: sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==}
dev: true dev: true
...@@ -4255,8 +4242,8 @@ packages: ...@@ -4255,8 +4242,8 @@ packages:
'@types/yargs-parser': 21.0.0 '@types/yargs-parser': 21.0.0
dev: true dev: true
/@typescript-eslint/eslint-plugin@5.60.1(@typescript-eslint/parser@5.60.1)(eslint@8.47.0)(typescript@5.1.6): /@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@5.60.1)(eslint@8.47.0)(typescript@5.1.6):
resolution: {integrity: sha512-KSWsVvsJsLJv3c4e73y/Bzt7OpqMCADUO846bHcuWYSYM19bldbAeDv7dYyV0jwkbMfJ2XdlzwjhXtuD7OY6bw==} resolution: {integrity: sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies: peerDependencies:
'@typescript-eslint/parser': ^5.0.0 '@typescript-eslint/parser': ^5.0.0
...@@ -4266,29 +4253,29 @@ packages: ...@@ -4266,29 +4253,29 @@ packages:
typescript: typescript:
optional: true optional: true
dependencies: dependencies:
'@eslint-community/regexpp': 4.5.1 '@eslint-community/regexpp': 4.6.2
'@typescript-eslint/parser': 5.60.1(eslint@8.47.0)(typescript@5.1.6) '@typescript-eslint/parser': 5.60.1(eslint@8.47.0)(typescript@5.1.6)
'@typescript-eslint/scope-manager': 5.60.1 '@typescript-eslint/scope-manager': 5.62.0
'@typescript-eslint/type-utils': 5.60.1(eslint@8.47.0)(typescript@5.1.6) '@typescript-eslint/type-utils': 5.62.0(eslint@8.47.0)(typescript@5.1.6)
'@typescript-eslint/utils': 5.60.1(eslint@8.47.0)(typescript@5.1.6) '@typescript-eslint/utils': 5.62.0(eslint@8.47.0)(typescript@5.1.6)
debug: 4.3.4(supports-color@8.1.1) debug: 4.3.4(supports-color@8.1.1)
eslint: 8.47.0 eslint: 8.47.0
grapheme-splitter: 1.0.4 graphemer: 1.4.0
ignore: 5.2.4 ignore: 5.2.4
natural-compare-lite: 1.4.0 natural-compare-lite: 1.4.0
semver: 7.5.3 semver: 7.5.4
tsutils: 3.21.0(typescript@5.1.6) tsutils: 3.21.0(typescript@5.1.6)
typescript: 5.1.6 typescript: 5.1.6
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
dev: true dev: true
/@typescript-eslint/eslint-plugin@6.4.0(@typescript-eslint/parser@6.4.0)(eslint@8.47.0)(typescript@5.1.6): /@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@6.4.0)(eslint@8.47.0)(typescript@5.1.6):
resolution: {integrity: sha512-62o2Hmc7Gs3p8SLfbXcipjWAa6qk2wZGChXG2JbBtYpwSRmti/9KHLqfbLs9uDigOexG+3PaQ9G2g3201FWLKg==} resolution: {integrity: sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==}
engines: {node: ^16.0.0 || >=18.0.0} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies: peerDependencies:
'@typescript-eslint/parser': ^6.0.0 || ^6.0.0-alpha '@typescript-eslint/parser': ^5.0.0
eslint: ^7.0.0 || ^8.0.0 eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
typescript: '*' typescript: '*'
peerDependenciesMeta: peerDependenciesMeta:
typescript: typescript:
...@@ -4296,17 +4283,16 @@ packages: ...@@ -4296,17 +4283,16 @@ packages:
dependencies: dependencies:
'@eslint-community/regexpp': 4.6.2 '@eslint-community/regexpp': 4.6.2
'@typescript-eslint/parser': 6.4.0(eslint@8.47.0)(typescript@5.1.6) '@typescript-eslint/parser': 6.4.0(eslint@8.47.0)(typescript@5.1.6)
'@typescript-eslint/scope-manager': 6.4.0 '@typescript-eslint/scope-manager': 5.62.0
'@typescript-eslint/type-utils': 6.4.0(eslint@8.47.0)(typescript@5.1.6) '@typescript-eslint/type-utils': 5.62.0(eslint@8.47.0)(typescript@5.1.6)
'@typescript-eslint/utils': 6.4.0(eslint@8.47.0)(typescript@5.1.6) '@typescript-eslint/utils': 5.62.0(eslint@8.47.0)(typescript@5.1.6)
'@typescript-eslint/visitor-keys': 6.4.0
debug: 4.3.4(supports-color@8.1.1) debug: 4.3.4(supports-color@8.1.1)
eslint: 8.47.0 eslint: 8.47.0
graphemer: 1.4.0 graphemer: 1.4.0
ignore: 5.2.4 ignore: 5.2.4
natural-compare: 1.4.0 natural-compare-lite: 1.4.0
semver: 7.5.4 semver: 7.5.4
ts-api-utils: 1.0.1(typescript@5.1.6) tsutils: 3.21.0(typescript@5.1.6)
typescript: 5.1.6 typescript: 5.1.6
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
...@@ -4361,6 +4347,14 @@ packages: ...@@ -4361,6 +4347,14 @@ packages:
'@typescript-eslint/visitor-keys': 5.60.1 '@typescript-eslint/visitor-keys': 5.60.1
dev: true dev: true
/@typescript-eslint/scope-manager@5.62.0:
resolution: {integrity: sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
dependencies:
'@typescript-eslint/types': 5.62.0
'@typescript-eslint/visitor-keys': 5.62.0
dev: true
/@typescript-eslint/scope-manager@6.4.0: /@typescript-eslint/scope-manager@6.4.0:
resolution: {integrity: sha512-TUS7vaKkPWDVvl7GDNHFQMsMruD+zhkd3SdVW0d7b+7Zo+bd/hXJQ8nsiUZMi1jloWo6c9qt3B7Sqo+flC1nig==} resolution: {integrity: sha512-TUS7vaKkPWDVvl7GDNHFQMsMruD+zhkd3SdVW0d7b+7Zo+bd/hXJQ8nsiUZMi1jloWo6c9qt3B7Sqo+flC1nig==}
engines: {node: ^16.0.0 || >=18.0.0} engines: {node: ^16.0.0 || >=18.0.0}
...@@ -4369,8 +4363,8 @@ packages: ...@@ -4369,8 +4363,8 @@ packages:
'@typescript-eslint/visitor-keys': 6.4.0 '@typescript-eslint/visitor-keys': 6.4.0
dev: true dev: true
/@typescript-eslint/type-utils@5.60.1(eslint@8.47.0)(typescript@5.1.6): /@typescript-eslint/type-utils@5.62.0(eslint@8.47.0)(typescript@5.1.6):
resolution: {integrity: sha512-vN6UztYqIu05nu7JqwQGzQKUJctzs3/Hg7E2Yx8rz9J+4LgtIDFWjjl1gm3pycH0P3mHAcEUBd23LVgfrsTR8A==} resolution: {integrity: sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies: peerDependencies:
eslint: '*' eslint: '*'
...@@ -4379,8 +4373,8 @@ packages: ...@@ -4379,8 +4373,8 @@ packages:
typescript: typescript:
optional: true optional: true
dependencies: dependencies:
'@typescript-eslint/typescript-estree': 5.60.1(typescript@5.1.6) '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.1.6)
'@typescript-eslint/utils': 5.60.1(eslint@8.47.0)(typescript@5.1.6) '@typescript-eslint/utils': 5.62.0(eslint@8.47.0)(typescript@5.1.6)
debug: 4.3.4(supports-color@8.1.1) debug: 4.3.4(supports-color@8.1.1)
eslint: 8.47.0 eslint: 8.47.0
tsutils: 3.21.0(typescript@5.1.6) tsutils: 3.21.0(typescript@5.1.6)
...@@ -4389,31 +4383,16 @@ packages: ...@@ -4389,31 +4383,16 @@ packages:
- supports-color - supports-color
dev: true dev: true
/@typescript-eslint/type-utils@6.4.0(eslint@8.47.0)(typescript@5.1.6):
resolution: {integrity: sha512-TvqrUFFyGY0cX3WgDHcdl2/mMCWCDv/0thTtx/ODMY1QhEiyFtv/OlLaNIiYLwRpAxAtOLOY9SUf1H3Q3dlwAg==}
engines: {node: ^16.0.0 || >=18.0.0}
peerDependencies:
eslint: ^7.0.0 || ^8.0.0
typescript: '*'
peerDependenciesMeta:
typescript:
optional: true
dependencies:
'@typescript-eslint/typescript-estree': 6.4.0(typescript@5.1.6)
'@typescript-eslint/utils': 6.4.0(eslint@8.47.0)(typescript@5.1.6)
debug: 4.3.4(supports-color@8.1.1)
eslint: 8.47.0
ts-api-utils: 1.0.1(typescript@5.1.6)
typescript: 5.1.6
transitivePeerDependencies:
- supports-color
dev: true
/@typescript-eslint/types@5.60.1: /@typescript-eslint/types@5.60.1:
resolution: {integrity: sha512-zDcDx5fccU8BA0IDZc71bAtYIcG9PowaOwaD8rjYbqwK7dpe/UMQl3inJ4UtUK42nOCT41jTSCwg76E62JpMcg==} resolution: {integrity: sha512-zDcDx5fccU8BA0IDZc71bAtYIcG9PowaOwaD8rjYbqwK7dpe/UMQl3inJ4UtUK42nOCT41jTSCwg76E62JpMcg==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
dev: true dev: true
/@typescript-eslint/types@5.62.0:
resolution: {integrity: sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
dev: true
/@typescript-eslint/types@6.4.0: /@typescript-eslint/types@6.4.0:
resolution: {integrity: sha512-+FV9kVFrS7w78YtzkIsNSoYsnOtrYVnKWSTVXoL1761CsCRv5wpDOINgsXpxD67YCLZtVQekDDyaxfjVWUJmmg==} resolution: {integrity: sha512-+FV9kVFrS7w78YtzkIsNSoYsnOtrYVnKWSTVXoL1761CsCRv5wpDOINgsXpxD67YCLZtVQekDDyaxfjVWUJmmg==}
engines: {node: ^16.0.0 || >=18.0.0} engines: {node: ^16.0.0 || >=18.0.0}
...@@ -4440,6 +4419,27 @@ packages: ...@@ -4440,6 +4419,27 @@ packages:
- supports-color - supports-color
dev: true dev: true
/@typescript-eslint/typescript-estree@5.62.0(typescript@5.1.6):
resolution: {integrity: sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
typescript: '*'
peerDependenciesMeta:
typescript:
optional: true
dependencies:
'@typescript-eslint/types': 5.62.0
'@typescript-eslint/visitor-keys': 5.62.0
debug: 4.3.4(supports-color@8.1.1)
globby: 11.1.0
is-glob: 4.0.3
semver: 7.5.4
tsutils: 3.21.0(typescript@5.1.6)
typescript: 5.1.6
transitivePeerDependencies:
- supports-color
dev: true
/@typescript-eslint/typescript-estree@6.4.0(typescript@5.1.6): /@typescript-eslint/typescript-estree@6.4.0(typescript@5.1.6):
resolution: {integrity: sha512-iDPJArf/K2sxvjOR6skeUCNgHR/tCQXBsa+ee1/clRKr3olZjZ/dSkXPZjG6YkPtnW6p5D1egeEPMCW6Gn4yLA==} resolution: {integrity: sha512-iDPJArf/K2sxvjOR6skeUCNgHR/tCQXBsa+ee1/clRKr3olZjZ/dSkXPZjG6YkPtnW6p5D1egeEPMCW6Gn4yLA==}
engines: {node: ^16.0.0 || >=18.0.0} engines: {node: ^16.0.0 || >=18.0.0}
...@@ -4461,39 +4461,20 @@ packages: ...@@ -4461,39 +4461,20 @@ packages:
- supports-color - supports-color
dev: true dev: true
/@typescript-eslint/utils@5.60.1(eslint@8.47.0)(typescript@5.1.6): /@typescript-eslint/utils@5.62.0(eslint@8.47.0)(typescript@5.1.6):
resolution: {integrity: sha512-tiJ7FFdFQOWssFa3gqb94Ilexyw0JVxj6vBzaSpfN/8IhoKkDuSAenUKvsSHw2A/TMpJb26izIszTXaqygkvpQ==} resolution: {integrity: sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies: peerDependencies:
eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
dependencies:
'@eslint-community/eslint-utils': 4.4.0(eslint@8.47.0)
'@types/json-schema': 7.0.11
'@types/semver': 7.3.13
'@typescript-eslint/scope-manager': 5.60.1
'@typescript-eslint/types': 5.60.1
'@typescript-eslint/typescript-estree': 5.60.1(typescript@5.1.6)
eslint: 8.47.0
eslint-scope: 5.1.1
semver: 7.5.4
transitivePeerDependencies:
- supports-color
- typescript
dev: true
/@typescript-eslint/utils@6.4.0(eslint@8.47.0)(typescript@5.1.6):
resolution: {integrity: sha512-BvvwryBQpECPGo8PwF/y/q+yacg8Hn/2XS+DqL/oRsOPK+RPt29h5Ui5dqOKHDlbXrAeHUTnyG3wZA0KTDxRZw==}
engines: {node: ^16.0.0 || >=18.0.0}
peerDependencies:
eslint: ^7.0.0 || ^8.0.0
dependencies: dependencies:
'@eslint-community/eslint-utils': 4.4.0(eslint@8.47.0) '@eslint-community/eslint-utils': 4.4.0(eslint@8.47.0)
'@types/json-schema': 7.0.12 '@types/json-schema': 7.0.12
'@types/semver': 7.5.0 '@types/semver': 7.5.0
'@typescript-eslint/scope-manager': 6.4.0 '@typescript-eslint/scope-manager': 5.62.0
'@typescript-eslint/types': 6.4.0 '@typescript-eslint/types': 5.62.0
'@typescript-eslint/typescript-estree': 6.4.0(typescript@5.1.6) '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.1.6)
eslint: 8.47.0 eslint: 8.47.0
eslint-scope: 5.1.1
semver: 7.5.4 semver: 7.5.4
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
...@@ -4508,6 +4489,14 @@ packages: ...@@ -4508,6 +4489,14 @@ packages:
eslint-visitor-keys: 3.4.3 eslint-visitor-keys: 3.4.3
dev: true dev: true
/@typescript-eslint/visitor-keys@5.62.0:
resolution: {integrity: sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
dependencies:
'@typescript-eslint/types': 5.62.0
eslint-visitor-keys: 3.4.3
dev: true
/@typescript-eslint/visitor-keys@6.4.0: /@typescript-eslint/visitor-keys@6.4.0:
resolution: {integrity: sha512-yJSfyT+uJm+JRDWYRYdCm2i+pmvXJSMtPR9Cq5/XQs4QIgNoLcoRtDdzsLbLsFM/c6um6ohQkg/MLxWvoIndJA==} resolution: {integrity: sha512-yJSfyT+uJm+JRDWYRYdCm2i+pmvXJSMtPR9Cq5/XQs4QIgNoLcoRtDdzsLbLsFM/c6um6ohQkg/MLxWvoIndJA==}
engines: {node: ^16.0.0 || >=18.0.0} engines: {node: ^16.0.0 || >=18.0.0}
...@@ -9493,6 +9482,7 @@ packages: ...@@ -9493,6 +9482,7 @@ packages:
/grapheme-splitter@1.0.4: /grapheme-splitter@1.0.4:
resolution: {integrity: sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==} resolution: {integrity: sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==}
dev: false
/graphemer@1.4.0: /graphemer@1.4.0:
resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==}
...@@ -10859,7 +10849,7 @@ packages: ...@@ -10859,7 +10849,7 @@ packages:
'@lerna/child-process': 7.1.5 '@lerna/child-process': 7.1.5
'@lerna/create': 7.1.5 '@lerna/create': 7.1.5
'@npmcli/run-script': 6.0.2 '@npmcli/run-script': 6.0.2
'@nx/devkit': 16.7.1(nx@16.7.2) '@nx/devkit': 16.7.1(nx@16.7.3)
'@octokit/plugin-enterprise-rest': 6.0.1 '@octokit/plugin-enterprise-rest': 6.0.1
'@octokit/rest': 19.0.11 '@octokit/rest': 19.0.11
byte-size: 8.1.1 byte-size: 8.1.1
...@@ -10902,7 +10892,7 @@ packages: ...@@ -10902,7 +10892,7 @@ packages:
npm-packlist: 5.1.1 npm-packlist: 5.1.1
npm-registry-fetch: 14.0.5 npm-registry-fetch: 14.0.5
npmlog: 6.0.2 npmlog: 6.0.2
nx: 16.7.2 nx: 16.7.3
p-map: 4.0.0 p-map: 4.0.0
p-map-series: 2.1.0 p-map-series: 2.1.0
p-pipe: 3.1.0 p-pipe: 3.1.0
...@@ -12529,8 +12519,8 @@ packages: ...@@ -12529,8 +12519,8 @@ packages:
- debug - debug
dev: true dev: true
/nx@16.7.2: /nx@16.7.3:
resolution: {integrity: sha512-T7cRC97qJ4H9fg498ZGwFQaTzJdLQaRp6DFUwzFo1B9qzR56A2tA3HBvT/huo85THaDX+/pcgLyeixJKEE5RPg==} resolution: {integrity: sha512-aam+1ZesbCfV9xv5FktsAqHVBObcazrf1MG56SdBTYNuILBVgAztPj8NyIZ87ZHw8IE/JxWDDUtZo7lwaSOFzA==}
hasBin: true hasBin: true
requiresBuild: true requiresBuild: true
peerDependencies: peerDependencies:
...@@ -12542,7 +12532,7 @@ packages: ...@@ -12542,7 +12532,7 @@ packages:
'@swc/core': '@swc/core':
optional: true optional: true
dependencies: dependencies:
'@nrwl/tao': 16.7.2 '@nrwl/tao': 16.7.3
'@parcel/watcher': 2.0.4 '@parcel/watcher': 2.0.4
'@yarnpkg/lockfile': 1.1.0 '@yarnpkg/lockfile': 1.1.0
'@yarnpkg/parsers': 3.0.0-rc.46 '@yarnpkg/parsers': 3.0.0-rc.46
...@@ -12578,16 +12568,16 @@ packages: ...@@ -12578,16 +12568,16 @@ packages:
yargs: 17.7.2 yargs: 17.7.2
yargs-parser: 21.1.1 yargs-parser: 21.1.1
optionalDependencies: optionalDependencies:
'@nx/nx-darwin-arm64': 16.7.2 '@nx/nx-darwin-arm64': 16.7.3
'@nx/nx-darwin-x64': 16.7.2 '@nx/nx-darwin-x64': 16.7.3
'@nx/nx-freebsd-x64': 16.7.2 '@nx/nx-freebsd-x64': 16.7.3
'@nx/nx-linux-arm-gnueabihf': 16.7.2 '@nx/nx-linux-arm-gnueabihf': 16.7.3
'@nx/nx-linux-arm64-gnu': 16.7.2 '@nx/nx-linux-arm64-gnu': 16.7.3
'@nx/nx-linux-arm64-musl': 16.7.2 '@nx/nx-linux-arm64-musl': 16.7.3
'@nx/nx-linux-x64-gnu': 16.7.2 '@nx/nx-linux-x64-gnu': 16.7.3
'@nx/nx-linux-x64-musl': 16.7.2 '@nx/nx-linux-x64-musl': 16.7.3
'@nx/nx-win32-arm64-msvc': 16.7.2 '@nx/nx-win32-arm64-msvc': 16.7.3
'@nx/nx-win32-x64-msvc': 16.7.2 '@nx/nx-win32-x64-msvc': 16.7.3
transitivePeerDependencies: transitivePeerDependencies:
- debug - debug
dev: true dev: true
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment