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
},
From: deposit.L1BridgeDeposit.Tx.FromAddress.String(),
To: deposit.L1BridgeDeposit.Tx.ToAddress.String(),
Amount: deposit.L1BridgeDeposit.Tx.Amount.Int.String(),
Amount: deposit.L1BridgeDeposit.Tx.Amount.String(),
L1Token: TokenInfo{
ChainId: 1,
Address: deposit.L1BridgeDeposit.TokenPair.LocalTokenAddress.String(),
......
......@@ -60,7 +60,7 @@ func newWithdrawalResponse(withdrawals *database.L2BridgeWithdrawalsResponse) Wi
From: withdrawal.L2BridgeWithdrawal.Tx.FromAddress.String(),
To: withdrawal.L2BridgeWithdrawal.Tx.ToAddress.String(),
TransactionHash: withdrawal.L2TransactionHash.String(),
Amount: withdrawal.L2BridgeWithdrawal.Tx.Amount.Int.String(),
Amount: withdrawal.L2BridgeWithdrawal.Tx.Amount.String(),
Proof: Proof{
TransactionHash: withdrawal.ProvenL1TransactionHash.String(),
BlockTimestamp: withdrawal.L2BridgeWithdrawal.Tx.Timestamp,
......
......@@ -20,7 +20,7 @@ import (
type BlockHeader struct {
Hash common.Hash `gorm:"primaryKey;serializer:bytes"`
ParentHash common.Hash `gorm:"serializer:bytes"`
Number U256
Number *big.Int `gorm:"serializer:u256"`
Timestamp uint64
RLPHeader *RLPHeader `gorm:"serializer:rlp;column:rlp_bytes"`
......@@ -30,7 +30,7 @@ func BlockHeaderFromHeader(header *types.Header) BlockHeader {
return BlockHeader{
Hash: header.Hash(),
ParentHash: header.ParentHash,
Number: U256{Int: header.Number},
Number: header.Number,
Timestamp: header.Time,
RLPHeader: (*RLPHeader)(header),
......@@ -58,8 +58,8 @@ type LegacyStateBatch struct {
type OutputProposal struct {
OutputRoot common.Hash `gorm:"primaryKey;serializer:bytes"`
L2OutputIndex U256
L2BlockNumber U256
L2OutputIndex *big.Int `gorm:"serializer:u256"`
L2BlockNumber *big.Int `gorm:"serializer:u256"`
L1ContractEventGUID uuid.UUID
}
......@@ -165,7 +165,7 @@ func (db *blocksDB) LatestCheckpointedOutput() (*OutputProposal, error) {
func (db *blocksDB) OutputProposal(index *big.Int) (*OutputProposal, error) {
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 errors.Is(result.Error, gorm.ErrRecordNotFound) {
return nil, nil
......
......@@ -3,6 +3,7 @@ package database
import (
"errors"
"fmt"
"math/big"
"gorm.io/gorm"
......@@ -17,13 +18,13 @@ import (
type BridgeMessage struct {
MessageHash common.Hash `gorm:"primaryKey;serializer:bytes"`
Nonce U256
Nonce *big.Int `gorm:"serializer:u256"`
SentMessageEventGUID uuid.UUID
RelayedMessageEventGUID *uuid.UUID
Tx Transaction `gorm:"embedded"`
GasLimit U256
GasLimit *big.Int `gorm:"serializer:u256"`
}
type L1BridgeMessage struct {
......
......@@ -3,6 +3,7 @@ package database
import (
"errors"
"fmt"
"math/big"
"github.com/google/uuid"
"gorm.io/gorm"
......@@ -17,8 +18,8 @@ import (
type Transaction struct {
FromAddress common.Address `gorm:"serializer:bytes"`
ToAddress common.Address `gorm:"serializer:bytes"`
Amount U256
Data Bytes `gorm:"serializer:bytes"`
Amount *big.Int `gorm:"serializer:u256"`
Data Bytes `gorm:"serializer:bytes"`
Timestamp uint64
}
......@@ -28,12 +29,12 @@ type L1TransactionDeposit struct {
InitiatedL1EventGUID uuid.UUID
Tx Transaction `gorm:"embedded"`
GasLimit U256
GasLimit *big.Int `gorm:"serializer:u256"`
}
type L2TransactionWithdrawal struct {
WithdrawalHash common.Hash `gorm:"serializer:bytes;primaryKey"`
Nonce U256
Nonce *big.Int `gorm:"serializer:u256"`
InitiatedL2EventGUID uuid.UUID
ProvenL1EventGUID *uuid.UUID
......@@ -41,7 +42,7 @@ type L2TransactionWithdrawal struct {
Succeeded *bool
Tx Transaction `gorm:"embedded"`
GasLimit U256
GasLimit *big.Int `gorm:"serializer:u256"`
}
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
import (
"database/sql/driver"
"errors"
"io"
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/rlp"
"github.com/jackc/pgtype"
)
var u256BigIntOverflow = new(big.Int).Exp(big.NewInt(2), big.NewInt(256), nil)
var big10 = big.NewInt(10)
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()
}
// Wrapper over types.Header such that we can get an RLP
// encoder over it via a `types.Block` wrapper
type RLPHeader types.Header
......@@ -94,6 +37,9 @@ func (h *RLPHeader) Hash() common.Hash {
return h.Header().Hash()
}
// Type definition for []byte to conform to the
// interface expected by the `bytes` serializer
type Bytes []byte
func (b Bytes) Bytes() []byte {
......
......@@ -59,9 +59,9 @@ func TestE2EBridgeL1CrossDomainMessenger(t *testing.T) {
require.NotNil(t, sentMessage)
require.NotNil(t, sentMessage.SentMessageEventGUID)
require.Equal(t, depositInfo.DepositTx.SourceHash, sentMessage.TransactionSourceHash)
require.Equal(t, nonce.Uint64(), sentMessage.Nonce.Int.Uint64())
require.Equal(t, uint64(100_000), sentMessage.GasLimit.Int.Uint64())
require.Equal(t, big.NewInt(params.Ether), sentMessage.Tx.Amount.Int)
require.Equal(t, nonce.Uint64(), sentMessage.Nonce.Uint64())
require.Equal(t, uint64(100_000), sentMessage.GasLimit.Uint64())
require.Equal(t, uint64(params.Ether), sentMessage.Tx.Amount.Uint64())
require.Equal(t, aliceAddr, sentMessage.Tx.FromAddress)
require.Equal(t, aliceAddr, sentMessage.Tx.ToAddress)
require.ElementsMatch(t, calldata, sentMessage.Tx.Data)
......@@ -146,9 +146,9 @@ func TestE2EBridgeL2CrossDomainMessenger(t *testing.T) {
require.NotNil(t, sentMessage)
require.NotNil(t, sentMessage.SentMessageEventGUID)
require.Equal(t, withdrawalHash, sentMessage.TransactionWithdrawalHash)
require.Equal(t, nonce.Uint64(), sentMessage.Nonce.Int.Uint64())
require.Equal(t, uint64(100_000), sentMessage.GasLimit.Int.Uint64())
require.Equal(t, big.NewInt(params.Ether), sentMessage.Tx.Amount.Int)
require.Equal(t, nonce.Uint64(), sentMessage.Nonce.Uint64())
require.Equal(t, uint64(100_000), sentMessage.GasLimit.Uint64())
require.Equal(t, uint64(params.Ether), sentMessage.Tx.Amount.Uint64())
require.Equal(t, aliceAddr, sentMessage.Tx.FromAddress)
require.Equal(t, aliceAddr, sentMessage.Tx.ToAddress)
require.ElementsMatch(t, calldata, sentMessage.Tx.Data)
......
......@@ -54,8 +54,8 @@ func TestE2EBridgeTransactionsOptimismPortalDeposits(t *testing.T) {
require.NoError(t, err)
require.NotNil(t, deposit)
require.Equal(t, depositL2TxHash, deposit.L2TransactionHash)
require.Equal(t, big.NewInt(100_000), deposit.GasLimit.Int)
require.Equal(t, big.NewInt(params.Ether), deposit.Tx.Amount.Int)
require.Equal(t, uint64(100_000), deposit.GasLimit.Uint64())
require.Equal(t, uint64(params.Ether), deposit.Tx.Amount.Uint64())
require.Equal(t, aliceAddr, deposit.Tx.FromAddress)
require.Equal(t, aliceAddr, deposit.Tx.ToAddress)
require.ElementsMatch(t, calldata, deposit.Tx.Data)
......@@ -113,9 +113,9 @@ func TestE2EBridgeTransactionsL2ToL1MessagePasserWithdrawal(t *testing.T) {
withdraw, err := testSuite.DB.BridgeTransactions.L2TransactionWithdrawal(withdrawalHash)
require.NoError(t, err)
require.NotNil(t, withdraw)
require.Equal(t, msgPassed.Nonce.Uint64(), withdraw.Nonce.Int.Uint64())
require.Equal(t, big.NewInt(100_000), withdraw.GasLimit.Int)
require.Equal(t, big.NewInt(params.Ether), withdraw.Tx.Amount.Int)
require.Equal(t, msgPassed.Nonce.Uint64(), withdraw.Nonce.Uint64())
require.Equal(t, uint64(100_000), withdraw.GasLimit.Uint64())
require.Equal(t, uint64(params.Ether), withdraw.Tx.Amount.Uint64())
require.Equal(t, aliceAddr, withdraw.Tx.FromAddress)
require.Equal(t, aliceAddr, withdraw.Tx.ToAddress)
require.ElementsMatch(t, calldata, withdraw.Tx.Data)
......
......@@ -63,7 +63,7 @@ func TestE2EBridgeTransfersStandardBridgeETHDeposit(t *testing.T) {
require.Equal(t, depositInfo.DepositTx.SourceHash, deposit.TransactionSourceHash)
require.Equal(t, predeploys.LegacyERC20ETHAddr, deposit.TokenPair.LocalTokenAddress)
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.ToAddress)
require.Equal(t, byte(1), deposit.Tx.Data[0])
......@@ -235,7 +235,7 @@ func TestE2EBridgeTransfersOptimismPortalETHReceive(t *testing.T) {
require.Equal(t, depositInfo.DepositTx.SourceHash, deposit.TransactionSourceHash)
require.Equal(t, predeploys.LegacyERC20ETHAddr, deposit.TokenPair.LocalTokenAddress)
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.ToAddress)
require.Len(t, deposit.Tx.Data, 0)
......@@ -306,7 +306,7 @@ func TestE2EBridgeTransfersStandardBridgeETHWithdrawal(t *testing.T) {
require.Equal(t, withdrawalHash, withdrawal.TransactionWithdrawalHash)
require.Equal(t, predeploys.LegacyERC20ETHAddr, withdrawal.TokenPair.LocalTokenAddress)
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.ToAddress)
require.Equal(t, byte(1), withdrawal.Tx.Data[0])
......@@ -390,7 +390,7 @@ func TestE2EBridgeTransfersL2ToL1MessagePasserETHReceive(t *testing.T) {
require.Equal(t, withdrawalHash, withdrawal.TransactionWithdrawalHash)
require.Equal(t, predeploys.LegacyERC20ETHAddr, withdrawal.TokenPair.LocalTokenAddress)
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.ToAddress)
require.Len(t, withdrawal.Tx.Data, 0)
......
......@@ -40,19 +40,19 @@ func TestE2EETL(t *testing.T) {
l2Header, err := testSuite.DB.Blocks.L2LatestBlockHeader()
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) {
latestL2Header, err := testSuite.DB.Blocks.L2LatestBlockHeader()
require.NoError(t, err)
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++ {
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.NotNil(t, indexedHeader)
......@@ -60,7 +60,7 @@ func TestE2EETL(t *testing.T) {
require.NoError(t, err)
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.ParentHash, indexedHeader.ParentHash)
require.Equal(t, header.Time, indexedHeader.Timestamp)
......@@ -144,7 +144,7 @@ func TestE2EETL(t *testing.T) {
require.NoError(t, err)
require.Equal(t, block.Hash(), l1BlockHeader.Hash)
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)
// 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
// Determine the starting height for traversal
var fromHeader *types.Header
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()
} else if startHeight.BitLen() > 0 {
......
......@@ -35,7 +35,7 @@ func NewL2ETL(log log.Logger, db *database.DB, client node.EthClient) (*L2ETL, e
var fromHeader *types.Header
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()
} else {
log.Info("no indexed state, starting from genesis")
......
......@@ -107,7 +107,7 @@ func (b *BridgeProcessor) Start(ctx context.Context) error {
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)
if b.LatestL1Header != nil {
// `NewBridgeProcessor` ensures that LatestL2Header must not be nil if LatestL1Header is set
......
......@@ -94,13 +94,13 @@ func CrossDomainMessengerSentMessageEvents(chainSelector string, contractAddress
Event: &sentMessageEvents[i],
BridgeMessage: database.BridgeMessage{
MessageHash: messageHash,
Nonce: database.U256{Int: sentMessage.MessageNonce},
Nonce: sentMessage.MessageNonce,
SentMessageEventGUID: sentMessageEvents[i].GUID,
GasLimit: database.U256{Int: sentMessage.GasLimit},
GasLimit: sentMessage.GasLimit,
Tx: database.Transaction{
FromAddress: sentMessage.Sender,
ToAddress: sentMessage.Target,
Amount: database.U256{Int: sentMessageExtension.Value},
Amount: sentMessageExtension.Value,
Data: sentMessage.Message,
Timestamp: sentMessageEvents[i].Timestamp,
},
......
......@@ -11,8 +11,8 @@ import (
type L2ToL1MessagePasserMessagePassed struct {
Event *database.ContractEvent
WithdrawalHash common.Hash
GasLimit database.U256
Nonce database.U256
GasLimit *big.Int
Nonce *big.Int
Tx database.Transaction
}
......@@ -40,12 +40,12 @@ func L2ToL1MessagePasserMessagePassedEvents(contractAddress common.Address, db *
messagesPassed[i] = L2ToL1MessagePasserMessagePassed{
Event: &messagePassedEvents[i].ContractEvent,
WithdrawalHash: messagePassed.WithdrawalHash,
Nonce: database.U256{Int: messagePassed.Nonce},
GasLimit: database.U256{Int: messagePassed.GasLimit},
Nonce: messagePassed.Nonce,
GasLimit: messagePassed.GasLimit,
Tx: database.Transaction{
FromAddress: messagePassed.Sender,
ToAddress: messagePassed.Target,
Amount: database.U256{Int: messagePassed.Value},
Amount: messagePassed.Value,
Data: messagePassed.Data,
Timestamp: messagePassedEvents[i].Timestamp,
},
......
......@@ -16,7 +16,7 @@ type OptimismPortalTransactionDepositEvent struct {
Event *database.ContractEvent
DepositTx *types.DepositTx
Tx database.Transaction
GasLimit database.U256
GasLimit *big.Int
}
type OptimismPortalWithdrawalProvenEvent struct {
......@@ -67,11 +67,11 @@ func OptimismPortalTransactionDepositEvents(contractAddress common.Address, db *
optimismPortalTxDeposits[i] = OptimismPortalTransactionDepositEvent{
Event: &transactionDepositEvents[i].ContractEvent,
DepositTx: depositTx,
GasLimit: database.U256{Int: new(big.Int).SetUint64(depositTx.Gas)},
GasLimit: new(big.Int).SetUint64(depositTx.Gas),
Tx: database.Transaction{
FromAddress: txDeposit.From,
ToAddress: txDeposit.To,
Amount: database.U256{Int: depositTx.Value},
Amount: depositTx.Value,
Data: depositTx.Data,
Timestamp: transactionDepositEvents[i].Timestamp,
},
......
......@@ -101,7 +101,7 @@ func _standardBridgeInitiatedEvents[BridgeEventType bindings.StandardBridgeETHBr
Tx: database.Transaction{
FromAddress: erc20Bridge.From,
ToAddress: erc20Bridge.To,
Amount: database.U256{Int: erc20Bridge.Amount},
Amount: erc20Bridge.Amount,
Data: erc20Bridge.ExtraData,
Timestamp: initiatedBridgeEvents[i].Timestamp,
},
......@@ -161,7 +161,7 @@ func _standardBridgeFinalizedEvents[BridgeEventType bindings.StandardBridgeETHBr
Tx: database.Transaction{
FromAddress: erc20Bridge.From,
ToAddress: erc20Bridge.To,
Amount: database.U256{Int: erc20Bridge.Amount},
Amount: erc20Bridge.Amount,
Data: erc20Bridge.ExtraData,
Timestamp: bridgeFinalizedEvents[i].Timestamp,
},
......
......@@ -4,6 +4,7 @@ import (
"context"
"fmt"
"testing"
"time"
"github.com/ethereum-optimism/optimism/op-challenger/config"
"github.com/ethereum-optimism/optimism/op-node/chaincfg"
......@@ -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) {
verifyArgsInvalid(
t,
......
......@@ -3,6 +3,7 @@ package config
import (
"errors"
"fmt"
"time"
"github.com/ethereum/go-ethereum/common"
......@@ -73,7 +74,14 @@ func ValidTraceType(value TraceType) bool {
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.
// This also contains config options for auxiliary services.
......@@ -82,9 +90,9 @@ type Config struct {
L1EthRpc string // L1 RPC Url
GameFactoryAddress common.Address // Address of the dispute game factory
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
TraceType TraceType // Type of trace
TraceType TraceType // Type of trace
// Specific to the alphabet trace provider
AlphabetTrace string // String for the AlphabetTraceProvider
......@@ -124,6 +132,7 @@ func NewConfig(
PprofConfig: oppprof.DefaultCLIConfig(),
CannonSnapshotFreq: DefaultCannonSnapshotFreq,
GameWindow: DefaultGameWindow,
}
}
......
......@@ -55,7 +55,7 @@ func TestBuildFaultDefendData(t *testing.T) {
_, opts, _, contract, err := setupFaultDisputeGame()
require.NoError(t, err)
responder, _ := newTestFaultResponder(t, false)
responder, _ := newTestFaultResponder(t)
data, err := responder.buildFaultDefendData(1, [32]byte{0x02, 0x03})
require.NoError(t, err)
......@@ -72,7 +72,7 @@ func TestBuildFaultAttackData(t *testing.T) {
_, opts, _, contract, err := setupFaultDisputeGame()
require.NoError(t, err)
responder, _ := newTestFaultResponder(t, false)
responder, _ := newTestFaultResponder(t)
data, err := responder.buildFaultAttackData(1, [32]byte{0x02, 0x03})
require.NoError(t, err)
......@@ -89,7 +89,7 @@ func TestBuildFaultStepData(t *testing.T) {
_, opts, _, contract, err := setupFaultDisputeGame()
require.NoError(t, err)
responder, _ := newTestFaultResponder(t, false)
responder, _ := newTestFaultResponder(t)
data, err := responder.buildStepTxData(types.StepCallData{
ClaimIndex: 2,
......
......@@ -13,7 +13,7 @@ import (
// Responder takes a response action & executes.
// For full op-challenger this means executing the transaction on chain.
type Responder interface {
CanResolve(ctx context.Context) bool
CallResolve(ctx context.Context) (types.GameStatus, error)
Resolve(ctx context.Context) error
Respond(ctx context.Context, response types.Claim) error
Step(ctx context.Context, stepData types.StepCallData) error
......@@ -65,10 +65,27 @@ func (a *Agent) Act(ctx context.Context) error {
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
// and returns true if the game resolves successfully.
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
}
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 (
"github.com/ethereum-optimism/optimism/op-challenger/fault/types"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"
)
type FaultDisputeGameCaller interface {
......@@ -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)
if err != nil {
return nil, err
......
......@@ -118,6 +118,10 @@ func (p *CannonTraceProvider) AbsolutePreState(ctx context.Context) ([]byte, err
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
// 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) {
......
......@@ -204,6 +204,14 @@ func TestUseGameSpecificSubdir(t *testing.T) {
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) {
srcDir := filepath.Join("test_data")
path := filepath.Join(srcDir, filename)
......
......@@ -43,7 +43,7 @@ func NewGameLoader(caller MinimalDisputeGameFactoryCaller) *gameLoader {
}
// 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 {
return nil, ErrMissingBlockNumber
}
......@@ -56,14 +56,19 @@ func (l *gameLoader) FetchAllGamesAtBlock(ctx context.Context, blockNumber *big.
return nil, fmt.Errorf("failed to fetch game count: %w", err)
}
games := make([]FaultDisputeGame, gameCount.Uint64())
for i := uint64(0); i < gameCount.Uint64(); i++ {
game, err := l.caller.GameAtIndex(callOpts, big.NewInt(int64(i)))
games := make([]FaultDisputeGame, 0)
if gameCount.Uint64() == 0 {
return games, nil
}
for i := gameCount.Uint64(); i > 0; i-- {
game, err := l.caller.GameAtIndex(callOpts, big.NewInt(int64(i-1)))
if err != nil {
return nil, fmt.Errorf("failed to fetch game at index %d: %w", i, err)
}
games[i] = game
if game.Timestamp < earliestTimestamp {
break
}
games = append(games, game)
}
return games, nil
......
......@@ -25,6 +25,7 @@ func TestGameLoader_FetchAllGames(t *testing.T) {
tests := []struct {
name string
caller *mockMinimalDisputeGameFactoryCaller
earliest uint64
blockNumber *big.Int
expectedErr error
expectedLen int
......@@ -33,35 +34,36 @@ func TestGameLoader_FetchAllGames(t *testing.T) {
name: "success",
caller: newMockMinimalDisputeGameFactoryCaller(10, false, false),
blockNumber: big.NewInt(1),
expectedErr: nil,
expectedLen: 10,
},
{
name: "expired game ignored",
caller: newMockMinimalDisputeGameFactoryCaller(10, false, false),
earliest: 500,
blockNumber: big.NewInt(1),
expectedLen: 5,
},
{
name: "game count error",
caller: newMockMinimalDisputeGameFactoryCaller(10, true, false),
blockNumber: big.NewInt(1),
expectedErr: gameCountErr,
expectedLen: 0,
},
{
name: "game index error",
caller: newMockMinimalDisputeGameFactoryCaller(10, false, true),
blockNumber: big.NewInt(1),
expectedErr: gameIndexErr,
expectedLen: 0,
},
{
name: "no games",
caller: newMockMinimalDisputeGameFactoryCaller(0, false, false),
blockNumber: big.NewInt(1),
expectedErr: nil,
expectedLen: 0,
},
{
name: "missing block number",
caller: newMockMinimalDisputeGameFactoryCaller(0, false, false),
expectedErr: ErrMissingBlockNumber,
expectedLen: 0,
},
}
......@@ -72,10 +74,11 @@ func TestGameLoader_FetchAllGames(t *testing.T) {
t.Parallel()
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.Len(t, games, test.expectedLen)
expectedGames := test.caller.games
expectedGames = expectedGames[len(expectedGames)-test.expectedLen:]
if test.expectedErr != nil {
expectedGames = make([]FaultDisputeGame, 0)
}
......@@ -90,7 +93,7 @@ func generateMockGames(count uint64) []FaultDisputeGame {
for i := uint64(0); i < count; i++ {
games[i] = FaultDisputeGame{
Proxy: common.BigToAddress(big.NewInt(int64(i))),
Timestamp: i,
Timestamp: i * 100,
}
}
......
......@@ -13,6 +13,7 @@ import (
type gamePlayer interface {
ProgressGame(ctx context.Context) bool
Cleanup() error
}
type playerCreator func(address common.Address) (gamePlayer, error)
......@@ -20,24 +21,26 @@ type blockNumberFetcher func(ctx context.Context) (uint64, error)
// gameSource loads information about the games available to play
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 {
logger log.Logger
clock clock.Clock
source gameSource
gameWindow time.Duration
createPlayer playerCreator
fetchBlockNumber blockNumberFetcher
allowedGames []common.Address
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{
logger: logger,
clock: cl,
source: source,
gameWindow: gameWindow,
createPlayer: createGame,
fetchBlockNumber: fetchBlockNumber,
allowedGames: allowedGames,
......@@ -57,26 +60,56 @@ func (m *gameMonitor) allowedGame(game common.Address) bool {
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 {
blockNum, err := m.fetchBlockNumber(ctx)
if err != nil {
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 {
return fmt.Errorf("failed to load games: %w", err)
}
requiredGames := make(map[common.Address]bool)
for _, game := range games {
if !m.allowedGame(game.Proxy) {
m.logger.Debug("Skipping game not on allow list", "game", game.Proxy)
continue
}
requiredGames[game.Proxy] = true
player, err := m.fetchOrCreateGamePlayer(game)
if err != nil {
m.logger.Error("Error while progressing game", "game", game.Proxy, "err", err)
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
}
......
......@@ -4,6 +4,7 @@ import (
"context"
"math/big"
"testing"
"time"
"github.com/ethereum-optimism/optimism/op-service/clock"
"github.com/ethereum/go-ethereum/common"
......@@ -13,6 +14,32 @@ import (
"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) {
monitor, _, _ := setupMonitorTest(t, []common.Address{common.Address{}})
ctx, cancel := context.WithCancel(context.Background())
......@@ -77,6 +104,69 @@ func TestMonitorOnlyCreateSpecifiedGame(t *testing.T) {
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) {
logger := testlog.Logger(t, log.LvlDebug)
source := &stubGameSource{}
......@@ -87,7 +177,7 @@ func setupMonitorTest(t *testing.T, allowedGames []common.Address) (*gameMonitor
fetchBlockNum := func(ctx context.Context) (uint64, error) {
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
}
......@@ -95,13 +185,14 @@ type stubGameSource struct {
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
}
type stubGame struct {
addr common.Address
progressCount int
cleanupCount int
done bool
}
......@@ -110,16 +201,22 @@ func (g *stubGame) ProgressGame(ctx context.Context) bool {
return g.done
}
func (g *stubGame) Cleanup() error {
g.cleanupCount++
return nil
}
type createdGames struct {
t *testing.T
created map[common.Address]*stubGame
t *testing.T
createCompleted bool
created map[common.Address]*stubGame
}
func (c *createdGames) CreateGame(addr common.Address) (gamePlayer, error) {
if _, exists := c.created[addr]; exists {
c.t.Fatalf("game %v already exists", addr)
}
game := &stubGame{addr: addr}
game := &stubGame{addr: addr, done: c.createCompleted}
c.created[addr] = game
return game, nil
}
......@@ -10,8 +10,8 @@ import (
"github.com/ethereum-optimism/optimism/op-challenger/fault/cannon"
"github.com/ethereum-optimism/optimism/op-challenger/fault/types"
"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/ethclient"
"github.com/ethereum/go-ethereum/log"
)
......@@ -29,6 +29,9 @@ type GamePlayer struct {
agreeWithProposedOutput bool
caller GameInfo
logger log.Logger
cleanup func() error
completed bool
}
func NewGamePlayer(
......@@ -37,7 +40,7 @@ func NewGamePlayer(
cfg *config.Config,
addr common.Address,
txMgr txmgr.TxManager,
client *ethclient.Client,
client bind.ContractCaller,
) (*GamePlayer, error) {
logger = logger.New("game", addr)
contract, err := bindings.NewFaultDisputeGameCaller(addr, client)
......@@ -54,18 +57,22 @@ func NewGamePlayer(
var provider types.TraceProvider
var updater types.OracleUpdater
var cleanup func() error
switch cfg.TraceType {
case config.TraceTypeCannon:
provider, err = cannon.NewTraceProvider(ctx, logger, cfg, client, addr)
cannonProvider, err := cannon.NewTraceProvider(ctx, logger, cfg, client, addr)
if err != nil {
return nil, fmt.Errorf("create cannon trace provider: %w", err)
}
cleanup = cannonProvider.Cleanup
provider = cannonProvider
updater, err = cannon.NewOracleUpdater(ctx, logger, txMgr, addr, client)
if err != nil {
return nil, fmt.Errorf("failed to create the cannon updater: %w", err)
}
case config.TraceTypeAlphabet:
provider = alphabet.NewTraceProvider(cfg.AlphabetTrace, gameDepth)
cleanup = func() error { return nil }
updater = alphabet.NewOracleUpdater(logger)
default:
return nil, fmt.Errorf("unsupported trace type: %v", cfg.TraceType)
......@@ -90,10 +97,16 @@ func NewGamePlayer(
agreeWithProposedOutput: cfg.AgreeWithProposedOutput,
caller: caller,
logger: logger,
cleanup: cleanup,
}, nil
}
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")
if err := g.agent.Act(ctx); err != nil {
g.logger.Error("Error when acting on game", "err", err)
......@@ -102,7 +115,8 @@ func (g *GamePlayer) ProgressGame(ctx context.Context) bool {
g.logger.Warn("Unable to retrieve game status", "err", err)
} else {
g.logGameStatus(ctx, status)
return status != types.GameStatusInProgress
g.completed = status != types.GameStatusInProgress
return g.completed
}
return false
}
......@@ -129,3 +143,7 @@ func (g *GamePlayer) logGameStatus(ctx context.Context, status types.GameStatus)
g.logger.Error("Game lost", "status", status)
}
}
func (g *GamePlayer) Cleanup() error {
return g.cleanup()
}
......@@ -12,14 +12,14 @@ import (
)
func TestProgressGame_LogErrorFromAct(t *testing.T) {
handler, game, actor, _ := setupProgressGameTest(t, true)
actor.err = errors.New("boom")
handler, game, actor := setupProgressGameTest(t, true)
actor.actErr = errors.New("boom")
done := game.ProgressGame(context.Background())
require.False(t, done, "should not be done")
require.Equal(t, 1, actor.callCount, "should perform next actions")
errLog := handler.FindLog(log.LvlError, "Error when acting on game")
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
msg := handler.FindLog(log.LvlInfo, "Game info")
......@@ -27,6 +27,24 @@ func TestProgressGame_LogErrorFromAct(t *testing.T) {
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) {
tests := []struct {
name string
......@@ -74,11 +92,11 @@ func TestProgressGame_LogGameStatus(t *testing.T) {
for _, test := range tests {
test := test
t.Run(test.name, func(t *testing.T) {
handler, game, actor, gameInfo := setupProgressGameTest(t, test.agreeWithOutput)
gameInfo.status = test.status
handler, game, gameState := setupProgressGameTest(t, test.agreeWithOutput)
gameState.status = test.status
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")
errLog := handler.FindLog(test.logLevel, test.logMsg)
require.NotNil(t, errLog, "should log game result")
......@@ -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)
handler := &testlog.CapturingHandler{
Delegate: logger.GetHandler(),
}
logger.SetHandler(handler)
actor := &stubActor{}
gameInfo := &stubGameInfo{claimCount: 1}
gameState := &stubGameState{claimCount: 1}
game := &GamePlayer{
agent: actor,
agent: gameState,
agreeWithProposedOutput: agreeWithProposedRoot,
caller: gameInfo,
caller: gameState,
logger: logger,
}
return handler, game, actor, gameInfo
}
type stubActor struct {
callCount int
err error
return handler, game, gameState
}
func (a *stubActor) Act(ctx context.Context) error {
a.callCount++
return a.err
}
type stubGameInfo struct {
type stubGameState struct {
status types.GameStatus
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) {
return s.status, s.err
func (s *stubGameState) GetGameStatus(ctx context.Context) (types.GameStatus, error) {
return s.status, nil
}
func (s *stubGameInfo) GetClaimCount(ctx context.Context) (uint64, error) {
return s.claimCount, s.err
func (s *stubGameState) GetClaimCount(ctx context.Context) (uint64, error) {
return s.claimCount, nil
}
......@@ -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
// would succeed. Returns true if the game can be resolved, otherwise false.
func (r *faultResponder) CanResolve(ctx context.Context) bool {
// CallResolve determines if the resolve function on the fault dispute game contract
// would succeed. Returns the game status if the call would succeed, errors otherwise.
func (r *faultResponder) CallResolve(ctx context.Context) (types.GameStatus, error) {
txData, err := r.buildResolveData()
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,
Data: txData,
}, 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.
......
......@@ -22,13 +22,138 @@ import (
var (
mockFdgAddress = common.HexToAddress("0x1234")
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 {
from common.Address
sends int
calls int
sendFails bool
callFails bool
callBytes []byte
}
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) (
}
func (m *mockTxManager) Call(_ context.Context, _ ethereum.CallMsg, _ *big.Int) ([]byte, error) {
if m.sendFails {
return nil, mockSendError
if m.callFails {
return nil, mockCallError
}
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) {
......@@ -59,56 +189,8 @@ func (m *mockTxManager) From() common.Address {
return m.from
}
func newTestFaultResponder(t *testing.T, sendFails bool) (*faultResponder, *mockTxManager) {
log := testlog.Logger(t, log.LvlError)
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{
func generateMockResponseClaim() types.Claim {
return types.Claim{
ClaimData: types.ClaimData{
Value: common.Hash{0x01},
Position: types.NewPositionFromGIndex(2),
......@@ -119,89 +201,5 @@ func TestResponder_Respond_SendFails(t *testing.T) {
},
ContractIndex: 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
}
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)
})
......
......@@ -3,6 +3,7 @@ package types
import (
"context"
"errors"
"fmt"
"math/big"
"github.com/ethereum/go-ethereum/common"
......@@ -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
// to load into the onchain oracle.
type PreimageOracleData struct {
......
package types
import (
"fmt"
"testing"
"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) {
t.Run("LocalData", func(t *testing.T) {
data := NewPreimageOracleData([]byte{1, 2, 3}, []byte{4, 5, 6}, 7)
......
......@@ -109,6 +109,12 @@ var (
EnvVars: prefixEnvVars("CANNON_SNAPSHOT_FREQ"),
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]
......@@ -132,6 +138,7 @@ var optionalFlags = []cli.Flag{
CannonDatadirFlag,
CannonL2Flag,
CannonSnapshotFreqFlag,
GameWindowFlag,
}
func init() {
......@@ -222,6 +229,7 @@ func NewConfigFromCLI(ctx *cli.Context) (*config.Config, error) {
TraceType: traceTypeFlag,
GameFactoryAddress: gameFactoryAddress,
GameAllowlist: allowedGames,
GameWindow: ctx.Duration(GameWindowFlag.Name),
AlphabetTrace: ctx.String(AlphabetFlag.Name),
CannonNetwork: ctx.String(CannonNetworkFlag.Name),
CannonRollupConfigPath: ctx.String(CannonRollupConfigFlag.Name),
......
......@@ -68,7 +68,7 @@
"markdownlint-cli2": "0.4.0",
"mkdirp": "^1.0.4",
"mocha": "^10.2.0",
"nx": "16.7.2",
"nx": "16.7.3",
"nyc": "^15.1.0",
"patch-package": "^8.0.0",
"prettier": "^2.8.0",
......
......@@ -41,7 +41,7 @@
"lint": "pnpm lint:fix && pnpm lint:check"
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^6.4.0",
"@typescript-eslint/eslint-plugin": "^5.62.0",
"@typescript-eslint/parser": "^6.4.0",
"tsx": "^3.12.7",
"typescript": "^5.1.6"
......
......@@ -38,7 +38,7 @@ importers:
version: 12.20.20
'@typescript-eslint/eslint-plugin':
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':
specifier: ^5.60.1
version: 5.60.1(eslint@8.47.0)(typescript@5.1.6)
......@@ -109,8 +109,8 @@ importers:
specifier: ^10.2.0
version: 10.2.0
nx:
specifier: 16.7.2
version: 16.7.2
specifier: 16.7.3
version: 16.7.3
nyc:
specifier: ^15.1.0
version: 15.1.0
......@@ -268,8 +268,8 @@ importers:
packages/contracts-bedrock:
devDependencies:
'@typescript-eslint/eslint-plugin':
specifier: ^6.4.0
version: 6.4.0(@typescript-eslint/parser@6.4.0)(eslint@8.47.0)(typescript@5.1.6)
specifier: ^5.62.0
version: 5.62.0(@typescript-eslint/parser@6.4.0)(eslint@8.47.0)(typescript@5.1.6)
'@typescript-eslint/parser':
specifier: ^6.4.0
version: 6.4.0(eslint@8.47.0)(typescript@5.1.6)
......@@ -1005,7 +1005,7 @@ packages:
/@changesets/apply-release-plan@6.1.3:
resolution: {integrity: sha512-ECDNeoc3nfeAe1jqJb5aFQX7CqzQhD2klXRez2JDb/aVpGUbX673HgKrnrgJRuQR/9f2TtLoYIzrGB9qwD77mg==}
dependencies:
'@babel/runtime': 7.20.7
'@babel/runtime': 7.22.6
'@changesets/config': 2.3.0
'@changesets/get-version-range-type': 0.3.2
'@changesets/git': 2.0.0
......@@ -1023,7 +1023,7 @@ packages:
/@changesets/assemble-release-plan@5.2.3:
resolution: {integrity: sha512-g7EVZCmnWz3zMBAdrcKhid4hkHT+Ft1n0mLussFMcB1dE2zCuwcvGoy9ec3yOgPGF4hoMtgHaMIk3T3TBdvU9g==}
dependencies:
'@babel/runtime': 7.20.7
'@babel/runtime': 7.22.6
'@changesets/errors': 0.1.4
'@changesets/get-dependents-graph': 1.3.5
'@changesets/types': 5.2.1
......@@ -1126,7 +1126,7 @@ packages:
/@changesets/get-release-plan@3.0.16:
resolution: {integrity: sha512-OpP9QILpBp1bY2YNIKFzwigKh7Qe9KizRsZomzLe6pK8IUo8onkAAVUD8+JRKSr8R7d4+JRuQrfSSNlEwKyPYg==}
dependencies:
'@babel/runtime': 7.20.7
'@babel/runtime': 7.22.6
'@changesets/assemble-release-plan': 5.2.3
'@changesets/config': 2.3.0
'@changesets/pre': 1.0.14
......@@ -1142,7 +1142,7 @@ packages:
/@changesets/git@2.0.0:
resolution: {integrity: sha512-enUVEWbiqUTxqSnmesyJGWfzd51PY4H7mH9yUw0hPVpZBJ6tQZFMU3F3mT/t9OJ/GjyiM4770i+sehAn6ymx6A==}
dependencies:
'@babel/runtime': 7.20.7
'@babel/runtime': 7.22.6
'@changesets/errors': 0.1.4
'@changesets/types': 5.2.1
'@manypkg/get-packages': 1.1.3
......@@ -1167,7 +1167,7 @@ packages:
/@changesets/pre@1.0.14:
resolution: {integrity: sha512-dTsHmxQWEQekHYHbg+M1mDVYFvegDh9j/kySNuDKdylwfMEevTeDouR7IfHNyVodxZXu17sXoJuf2D0vi55FHQ==}
dependencies:
'@babel/runtime': 7.20.7
'@babel/runtime': 7.22.6
'@changesets/errors': 0.1.4
'@changesets/types': 5.2.1
'@manypkg/get-packages': 1.1.3
......@@ -1177,7 +1177,7 @@ packages:
/@changesets/read@0.5.9:
resolution: {integrity: sha512-T8BJ6JS6j1gfO1HFq50kU3qawYxa4NTbI/ASNVVCBTsKquy2HYwM9r7ZnzkiMe8IEObAJtUVGSrePCOxAK2haQ==}
dependencies:
'@babel/runtime': 7.20.7
'@babel/runtime': 7.22.6
'@changesets/git': 2.0.0
'@changesets/logger': 0.0.5
'@changesets/parse': 0.3.16
......@@ -1197,7 +1197,7 @@ packages:
/@changesets/write@0.2.3:
resolution: {integrity: sha512-Dbamr7AIMvslKnNYsLFafaVORx4H0pvCA2MHqgtNCySMe1blImEyAEOzDmcgKAkgz4+uwoLz7demIrX+JBr/Xw==}
dependencies:
'@babel/runtime': 7.20.7
'@babel/runtime': 7.22.6
'@changesets/types': 5.2.1
fs-extra: 7.0.1
human-id: 1.0.2
......@@ -1738,11 +1738,6 @@ packages:
eslint-visitor-keys: 3.4.3
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:
resolution: {integrity: sha512-pPTNuaAG3QMH+buKyBIGJs3g/S5y0caxw0ygM3YyE6yJFySwiGGSzA+mM3KJ8QQvzeLh3blwgSonkFjgQdxzMw==}
engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0}
......@@ -2517,7 +2512,7 @@ packages:
dependencies:
'@lerna/child-process': 7.1.5
'@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/rest': 19.0.11
byte-size: 8.1.1
......@@ -2553,7 +2548,7 @@ packages:
npm-packlist: 5.1.1
npm-registry-fetch: 14.0.5
npmlog: 6.0.2
nx: 16.7.2
nx: 16.7.3
p-map: 4.0.0
p-map-series: 2.1.0
p-queue: 6.6.2
......@@ -2608,7 +2603,7 @@ packages:
/@manypkg/get-packages@1.1.3:
resolution: {integrity: sha512-fo+QhuU3qE/2TQMQmbVMqaQ6EWbMhi4ABWP+O4AM1NqPBuy0OrApV5LO6BrrgnhtAHS2NH6RrVk9OL181tTi8A==}
dependencies:
'@babel/runtime': 7.20.7
'@babel/runtime': 7.22.6
'@changesets/types': 4.1.0
'@manypkg/find-root': 1.1.0
fs-extra: 8.1.0
......@@ -2838,10 +2833,10 @@ packages:
- supports-color
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==}
dependencies:
'@nx/devkit': 16.7.1(nx@16.7.2)
'@nx/devkit': 16.7.1(nx@16.7.3)
transitivePeerDependencies:
- nx
dev: true
......@@ -2854,11 +2849,11 @@ packages:
- debug
dev: true
/@nrwl/tao@16.7.2:
resolution: {integrity: sha512-4Wc3ic5VtZL3t4qqCMJlEad/wWuFxNUX78U5ohEStN3UFFJIjwJJpKZYZDtxhaOLWUdXbk6CI3KfSIpWgwPdbQ==}
/@nrwl/tao@16.7.3:
resolution: {integrity: sha512-kaH0i7ZuncSW8hGXg6DVlUBG319lUG/ene6aJUeV1spOxEsEqlckCm9HfJPfcVntvh9m1LauW+yk64cw/biVwg==}
hasBin: true
dependencies:
nx: 16.7.2
nx: 16.7.3
tslib: 2.6.0
transitivePeerDependencies:
- '@swc-node/register'
......@@ -2866,23 +2861,23 @@ packages:
- debug
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==}
peerDependencies:
nx: '>= 15 <= 17'
dependencies:
'@nrwl/devkit': 16.7.1(nx@16.7.2)
'@nrwl/devkit': 16.7.1(nx@16.7.3)
ejs: 3.1.9
enquirer: 2.3.6
ignore: 5.2.4
nx: 16.7.2
nx: 16.7.3
semver: 7.5.3
tmp: 0.2.1
tslib: 2.6.0
dev: true
/@nx/nx-darwin-arm64@16.7.2:
resolution: {integrity: sha512-dkTHAzOTbqRHUQtnw7knEJq4ll6hew11u+9B0fThs9gC/X0iPK0eDXD4TqbIKEbcWAsxpuGiWPzGoNPo7Gwl9A==}
/@nx/nx-darwin-arm64@16.7.3:
resolution: {integrity: sha512-s1woGSGbNEzDSzNoSIIpaYkVwJmM0D89/1QmccVZIv7jvGGcqx4ONQPsBylWpDco3IeTDhNsOMzMhF3fvqhtgA==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [darwin]
......@@ -2890,8 +2885,8 @@ packages:
dev: true
optional: true
/@nx/nx-darwin-x64@16.7.2:
resolution: {integrity: sha512-EKhjX7DCRIA5U8yAxIgGXeIFaq1dhgLJy8OAG4n1Ud8c21px+bBSrcZvv0ww5VoEulhggQ+c6fW1cjKtGgLknQ==}
/@nx/nx-darwin-x64@16.7.3:
resolution: {integrity: sha512-J9lE+T7Hm3hD+s33xidxa6Jkq2CCKZwwTrLO+Ff1/A2d4T13d16O/Rf3Y/nuveUjCVEYwwYkk4G5v2FPJ4i3SQ==}
engines: {node: '>= 10'}
cpu: [x64]
os: [darwin]
......@@ -2899,8 +2894,8 @@ packages:
dev: true
optional: true
/@nx/nx-freebsd-x64@16.7.2:
resolution: {integrity: sha512-3QhXZq0wxvi4lg1MJqwq72F7PE/d0Hcl3uwheenYQtwUvAFAmijC/Z4AVPSqbKJ+QaoqASnXRim9z3EIfeD+DQ==}
/@nx/nx-freebsd-x64@16.7.3:
resolution: {integrity: sha512-/1WrplEyxTkoARsCUcI2FjMVy2AFuaH2oS1vFuGtBchWoKbgFZd3Aek8+oYt0wiQ7cfBxs2y92UqvTOhLygxOw==}
engines: {node: '>= 10'}
cpu: [x64]
os: [freebsd]
......@@ -2908,8 +2903,8 @@ packages:
dev: true
optional: true
/@nx/nx-linux-arm-gnueabihf@16.7.2:
resolution: {integrity: sha512-7bny8NvE9iyfwRfq9/mOZjzMNWthT70Ce1N9suB2zdbgbLUEDPQQhBNbg969yT6/LbWMWuWZXeIbz/Fwndf9zA==}
/@nx/nx-linux-arm-gnueabihf@16.7.3:
resolution: {integrity: sha512-Z3CLZcxBnpra8nlizK97eyohI9x+JPh4wp+87x9WvIiLGd+k3hO42nth/q0xXJs2G5emQN8cSLPscGzbZodVpA==}
engines: {node: '>= 10'}
cpu: [arm]
os: [linux]
......@@ -2917,8 +2912,8 @@ packages:
dev: true
optional: true
/@nx/nx-linux-arm64-gnu@16.7.2:
resolution: {integrity: sha512-+UdeFB1HY/3GU2+mflydFWpztghFRQiVzJV6MTcjtOzE3jfgXzz9TP580pDxozTvNSRPlblH07X+iB8DhVcB9w==}
/@nx/nx-linux-arm64-gnu@16.7.3:
resolution: {integrity: sha512-a4E4psBgU0b7ZT99630mylxcrlLObgy4bA6JrT+4XIFAcaHkfCmWLupPyXgBCmSqQN01jsuXSYm/t7EWjKL98Q==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
......@@ -2926,8 +2921,8 @@ packages:
dev: true
optional: true
/@nx/nx-linux-arm64-musl@16.7.2:
resolution: {integrity: sha512-YfkWu+4GKXageuYiH5a77gIDAXnit5SIyfI+RWe/j04uFy171KnUt167DC417fv/fTGxeXY1tzOu112Y+x5ixw==}
/@nx/nx-linux-arm64-musl@16.7.3:
resolution: {integrity: sha512-vl+WONX6uOS8uGwtcAlb4yiAh2ws/gZSLaIURJaDnf509FrYTb/RsBca5BskOQUYkKSI//6oQu653TRDKYxyWw==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
......@@ -2935,8 +2930,8 @@ packages:
dev: true
optional: true
/@nx/nx-linux-x64-gnu@16.7.2:
resolution: {integrity: sha512-/TtSa2rHR+1gNuALR1yafl4fzBK2/GAhosf+skn00OgwsJ0c8ie9tuuftlMo+2n3LcXY/IaPDaD7t6fln4qsQg==}
/@nx/nx-linux-x64-gnu@16.7.3:
resolution: {integrity: sha512-udZ+6IOYv0Ra0MRpbAW8TSFdcUxtfuIryRsGVF2767HeWqHzOhLynmJyJPatJ7gXMVFaL7+zfcAoV6fm7My1FQ==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
......@@ -2944,8 +2939,8 @@ packages:
dev: true
optional: true
/@nx/nx-linux-x64-musl@16.7.2:
resolution: {integrity: sha512-VC638hxdWSA8VTDU9rAXjr60mmMP3ZyCUbSkJ+8ydEe83StMDY3PAXS5Hw3n/ouxDfCF9r1kWIGFe4g+emvfBw==}
/@nx/nx-linux-x64-musl@16.7.3:
resolution: {integrity: sha512-LQW1ttQWNekHoJTrzXMumaMxfYRcjsuGQP8Ki2pWuw43TFTQyI6Cfgk8/wjKv8ATc772cF9Tadyz4+JEIQlcNw==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
......@@ -2953,8 +2948,8 @@ packages:
dev: true
optional: true
/@nx/nx-win32-arm64-msvc@16.7.2:
resolution: {integrity: sha512-sSUqgANLgQFFzKTvyMczh5D6xiqTQnB8daJTLX+QUCv5vO5+ZSwuVDyNfr6g/HV2+ak0M9/wVQUae11TgUIPYw==}
/@nx/nx-win32-arm64-msvc@16.7.3:
resolution: {integrity: sha512-wCrpGqh5fPrlkhHZXVSPBDs9E3L5vIJHtdPrc1QP1uCQiV41mpauey31p6rjvQUWYCC0BGTWJGF+hAY7wYUHdg==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [win32]
......@@ -2962,8 +2957,8 @@ packages:
dev: true
optional: true
/@nx/nx-win32-x64-msvc@16.7.2:
resolution: {integrity: sha512-+n01cT9/P3o95x+FlRWYf9sFZ29ooxYD/WLcmxACeXN0V1bdbnZxKVSuJqrXZhmpHe7P+/+IRmniv9cdpkxz7g==}
/@nx/nx-win32-x64-msvc@16.7.3:
resolution: {integrity: sha512-Ja2+VhMFWiVsZt3mkdsU1MCotQlAxG94zFiJYbXufsERJItWuN4i0mZjeZITiRBosEmkn4SeAUkg+xuiH+q4GA==}
engines: {node: '>= 10'}
cpu: [x64]
os: [win32]
......@@ -3980,10 +3975,6 @@ packages:
pretty-format: 29.6.1
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:
resolution: {integrity: sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==}
dev: true
......@@ -4165,10 +4156,6 @@ packages:
resolution: {integrity: sha512-KQf+QAMWKMrtBMsB8/24w53tEsxllMj6TuA80TT/5igJalLI/zm0L3oXRbIAl4Ohfc85gyHX/jhMwsVkmhLU4A==}
dev: false
/@types/semver@7.3.13:
resolution: {integrity: sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==}
dev: true
/@types/semver@7.5.0:
resolution: {integrity: sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==}
dev: true
......@@ -4255,8 +4242,8 @@ packages:
'@types/yargs-parser': 21.0.0
dev: true
/@typescript-eslint/eslint-plugin@5.60.1(@typescript-eslint/parser@5.60.1)(eslint@8.47.0)(typescript@5.1.6):
resolution: {integrity: sha512-KSWsVvsJsLJv3c4e73y/Bzt7OpqMCADUO846bHcuWYSYM19bldbAeDv7dYyV0jwkbMfJ2XdlzwjhXtuD7OY6bw==}
/@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@5.60.1)(eslint@8.47.0)(typescript@5.1.6):
resolution: {integrity: sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
'@typescript-eslint/parser': ^5.0.0
......@@ -4266,29 +4253,29 @@ packages:
typescript:
optional: true
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/scope-manager': 5.60.1
'@typescript-eslint/type-utils': 5.60.1(eslint@8.47.0)(typescript@5.1.6)
'@typescript-eslint/utils': 5.60.1(eslint@8.47.0)(typescript@5.1.6)
'@typescript-eslint/scope-manager': 5.62.0
'@typescript-eslint/type-utils': 5.62.0(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)
eslint: 8.47.0
grapheme-splitter: 1.0.4
graphemer: 1.4.0
ignore: 5.2.4
natural-compare-lite: 1.4.0
semver: 7.5.3
semver: 7.5.4
tsutils: 3.21.0(typescript@5.1.6)
typescript: 5.1.6
transitivePeerDependencies:
- supports-color
dev: true
/@typescript-eslint/eslint-plugin@6.4.0(@typescript-eslint/parser@6.4.0)(eslint@8.47.0)(typescript@5.1.6):
resolution: {integrity: sha512-62o2Hmc7Gs3p8SLfbXcipjWAa6qk2wZGChXG2JbBtYpwSRmti/9KHLqfbLs9uDigOexG+3PaQ9G2g3201FWLKg==}
engines: {node: ^16.0.0 || >=18.0.0}
/@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@6.4.0)(eslint@8.47.0)(typescript@5.1.6):
resolution: {integrity: sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
'@typescript-eslint/parser': ^6.0.0 || ^6.0.0-alpha
eslint: ^7.0.0 || ^8.0.0
'@typescript-eslint/parser': ^5.0.0
eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
typescript: '*'
peerDependenciesMeta:
typescript:
......@@ -4296,17 +4283,16 @@ packages:
dependencies:
'@eslint-community/regexpp': 4.6.2
'@typescript-eslint/parser': 6.4.0(eslint@8.47.0)(typescript@5.1.6)
'@typescript-eslint/scope-manager': 6.4.0
'@typescript-eslint/type-utils': 6.4.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/visitor-keys': 6.4.0
'@typescript-eslint/scope-manager': 5.62.0
'@typescript-eslint/type-utils': 5.62.0(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)
eslint: 8.47.0
graphemer: 1.4.0
ignore: 5.2.4
natural-compare: 1.4.0
natural-compare-lite: 1.4.0
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
transitivePeerDependencies:
- supports-color
......@@ -4361,6 +4347,14 @@ packages:
'@typescript-eslint/visitor-keys': 5.60.1
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:
resolution: {integrity: sha512-TUS7vaKkPWDVvl7GDNHFQMsMruD+zhkd3SdVW0d7b+7Zo+bd/hXJQ8nsiUZMi1jloWo6c9qt3B7Sqo+flC1nig==}
engines: {node: ^16.0.0 || >=18.0.0}
......@@ -4369,8 +4363,8 @@ packages:
'@typescript-eslint/visitor-keys': 6.4.0
dev: true
/@typescript-eslint/type-utils@5.60.1(eslint@8.47.0)(typescript@5.1.6):
resolution: {integrity: sha512-vN6UztYqIu05nu7JqwQGzQKUJctzs3/Hg7E2Yx8rz9J+4LgtIDFWjjl1gm3pycH0P3mHAcEUBd23LVgfrsTR8A==}
/@typescript-eslint/type-utils@5.62.0(eslint@8.47.0)(typescript@5.1.6):
resolution: {integrity: sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
eslint: '*'
......@@ -4379,8 +4373,8 @@ packages:
typescript:
optional: true
dependencies:
'@typescript-eslint/typescript-estree': 5.60.1(typescript@5.1.6)
'@typescript-eslint/utils': 5.60.1(eslint@8.47.0)(typescript@5.1.6)
'@typescript-eslint/typescript-estree': 5.62.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)
eslint: 8.47.0
tsutils: 3.21.0(typescript@5.1.6)
......@@ -4389,31 +4383,16 @@ packages:
- supports-color
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:
resolution: {integrity: sha512-zDcDx5fccU8BA0IDZc71bAtYIcG9PowaOwaD8rjYbqwK7dpe/UMQl3inJ4UtUK42nOCT41jTSCwg76E62JpMcg==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
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:
resolution: {integrity: sha512-+FV9kVFrS7w78YtzkIsNSoYsnOtrYVnKWSTVXoL1761CsCRv5wpDOINgsXpxD67YCLZtVQekDDyaxfjVWUJmmg==}
engines: {node: ^16.0.0 || >=18.0.0}
......@@ -4440,6 +4419,27 @@ packages:
- supports-color
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):
resolution: {integrity: sha512-iDPJArf/K2sxvjOR6skeUCNgHR/tCQXBsa+ee1/clRKr3olZjZ/dSkXPZjG6YkPtnW6p5D1egeEPMCW6Gn4yLA==}
engines: {node: ^16.0.0 || >=18.0.0}
......@@ -4461,39 +4461,20 @@ packages:
- supports-color
dev: true
/@typescript-eslint/utils@5.60.1(eslint@8.47.0)(typescript@5.1.6):
resolution: {integrity: sha512-tiJ7FFdFQOWssFa3gqb94Ilexyw0JVxj6vBzaSpfN/8IhoKkDuSAenUKvsSHw2A/TMpJb26izIszTXaqygkvpQ==}
/@typescript-eslint/utils@5.62.0(eslint@8.47.0)(typescript@5.1.6):
resolution: {integrity: sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
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:
'@eslint-community/eslint-utils': 4.4.0(eslint@8.47.0)
'@types/json-schema': 7.0.12
'@types/semver': 7.5.0
'@typescript-eslint/scope-manager': 6.4.0
'@typescript-eslint/types': 6.4.0
'@typescript-eslint/typescript-estree': 6.4.0(typescript@5.1.6)
'@typescript-eslint/scope-manager': 5.62.0
'@typescript-eslint/types': 5.62.0
'@typescript-eslint/typescript-estree': 5.62.0(typescript@5.1.6)
eslint: 8.47.0
eslint-scope: 5.1.1
semver: 7.5.4
transitivePeerDependencies:
- supports-color
......@@ -4508,6 +4489,14 @@ packages:
eslint-visitor-keys: 3.4.3
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:
resolution: {integrity: sha512-yJSfyT+uJm+JRDWYRYdCm2i+pmvXJSMtPR9Cq5/XQs4QIgNoLcoRtDdzsLbLsFM/c6um6ohQkg/MLxWvoIndJA==}
engines: {node: ^16.0.0 || >=18.0.0}
......@@ -9493,6 +9482,7 @@ packages:
/grapheme-splitter@1.0.4:
resolution: {integrity: sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==}
dev: false
/graphemer@1.4.0:
resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==}
......@@ -10859,7 +10849,7 @@ packages:
'@lerna/child-process': 7.1.5
'@lerna/create': 7.1.5
'@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/rest': 19.0.11
byte-size: 8.1.1
......@@ -10902,7 +10892,7 @@ packages:
npm-packlist: 5.1.1
npm-registry-fetch: 14.0.5
npmlog: 6.0.2
nx: 16.7.2
nx: 16.7.3
p-map: 4.0.0
p-map-series: 2.1.0
p-pipe: 3.1.0
......@@ -12529,8 +12519,8 @@ packages:
- debug
dev: true
/nx@16.7.2:
resolution: {integrity: sha512-T7cRC97qJ4H9fg498ZGwFQaTzJdLQaRp6DFUwzFo1B9qzR56A2tA3HBvT/huo85THaDX+/pcgLyeixJKEE5RPg==}
/nx@16.7.3:
resolution: {integrity: sha512-aam+1ZesbCfV9xv5FktsAqHVBObcazrf1MG56SdBTYNuILBVgAztPj8NyIZ87ZHw8IE/JxWDDUtZo7lwaSOFzA==}
hasBin: true
requiresBuild: true
peerDependencies:
......@@ -12542,7 +12532,7 @@ packages:
'@swc/core':
optional: true
dependencies:
'@nrwl/tao': 16.7.2
'@nrwl/tao': 16.7.3
'@parcel/watcher': 2.0.4
'@yarnpkg/lockfile': 1.1.0
'@yarnpkg/parsers': 3.0.0-rc.46
......@@ -12578,16 +12568,16 @@ packages:
yargs: 17.7.2
yargs-parser: 21.1.1
optionalDependencies:
'@nx/nx-darwin-arm64': 16.7.2
'@nx/nx-darwin-x64': 16.7.2
'@nx/nx-freebsd-x64': 16.7.2
'@nx/nx-linux-arm-gnueabihf': 16.7.2
'@nx/nx-linux-arm64-gnu': 16.7.2
'@nx/nx-linux-arm64-musl': 16.7.2
'@nx/nx-linux-x64-gnu': 16.7.2
'@nx/nx-linux-x64-musl': 16.7.2
'@nx/nx-win32-arm64-msvc': 16.7.2
'@nx/nx-win32-x64-msvc': 16.7.2
'@nx/nx-darwin-arm64': 16.7.3
'@nx/nx-darwin-x64': 16.7.3
'@nx/nx-freebsd-x64': 16.7.3
'@nx/nx-linux-arm-gnueabihf': 16.7.3
'@nx/nx-linux-arm64-gnu': 16.7.3
'@nx/nx-linux-arm64-musl': 16.7.3
'@nx/nx-linux-x64-gnu': 16.7.3
'@nx/nx-linux-x64-musl': 16.7.3
'@nx/nx-win32-arm64-msvc': 16.7.3
'@nx/nx-win32-x64-msvc': 16.7.3
transitivePeerDependencies:
- debug
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