diff --git a/_previous/extensions/listeners/eth_deposits/deposits.go b/_previous/extensions/listeners/eth_deposits/deposits.go deleted file mode 100644 index a22a885f5..000000000 --- a/_previous/extensions/listeners/eth_deposits/deposits.go +++ /dev/null @@ -1,338 +0,0 @@ -// package ethdeposits implements an listener that listens to Ethereum events -// and triggers the creation of deposit events in Kwil. -package ethdeposits - -import ( - "context" - "encoding/binary" - "encoding/hex" - "fmt" - "strconv" - "strings" - "time" - - ethcommon "github.com/ethereum/go-ethereum/common" - "github.com/kwilteam/kwil-db/common" - "github.com/kwilteam/kwil-db/core/log" - "github.com/kwilteam/kwil-db/extensions/listeners" - "github.com/kwilteam/kwil-db/extensions/resolutions/credit" -) - -const ListenerName = "eth_deposits" - -// use golang's init function, which runs before main, to register the extension -// see more here: https://www.digitalocean.com/community/tutorials/understanding-init-in-go -func init() { - // register the listener with the name "eth_deposit" - err := listeners.RegisterListener(ListenerName, Start) - if err != nil { - panic(err) - } -} - -// Start starts the eth_deposit listener, which triggers the creation of deposit events in Kwil. -// It can be configured to listen to a certain smart contract address. It will listen for the EVM event signature -// "Credit(address,uint256)" and create a deposit event in Kwil when it sees a matching event. It uses the -// "credit_account" resolution, defined in extensions/resolutions/credit/credit.go, to create the deposit event. -// It will search for a local extension configuration named "eth_deposit". -func Start(ctx context.Context, service *common.Service, eventStore listeners.EventStore) error { - config := &EthDepositConfig{} - listenerConfig, ok := service.LocalConfig.AppConfig.Extensions[ListenerName] - if !ok { - service.Logger.Warn("no eth_deposit configuration found, eth_deposit oracle will not start") - return nil // no configuration, so we don't start the oracle - } - err := config.setConfig(listenerConfig) - if err != nil { - return fmt.Errorf("failed to set eth_deposit configuration: %w", err) - } - - // we need to catch up with the ethereum chain. - // we will get the last seen height from the kv store - // we will either start from the last seen height, or from the configured starting height, - // whichever is greater - lastHeight, err := getLastStoredHeight(ctx, eventStore) - if err != nil { - return fmt.Errorf("failed to get last stored height: %w", err) - } - - if config.StartingHeight > lastHeight { - lastHeight = config.StartingHeight - } - - client, err := newEthClient(ctx, config.RPCProvider, config.MaxRetries, - ethcommon.HexToAddress(config.ContractAddress), service.Logger) - if err != nil { - return fmt.Errorf("failed to create ethereum client: %w", err) - } - defer client.Close() - - // get the current block height from the Ethereum client - currentHeight, err := client.GetLatestBlock(ctx) - if err != nil { - return fmt.Errorf("failed to get current block height: %w", err) - } - service.Logger.S.Infof("ETH best block: %v", currentHeight) - - if lastHeight > currentHeight-config.RequiredConfirmations { - return fmt.Errorf("starting height is greater than the last confirmed eth block height") - } - - // we will now sync all logs from the starting height to the current height, - // in chunks of config.BlockSyncChunkSize - for { - if lastHeight >= currentHeight-config.RequiredConfirmations { - break - } - - // get the next block chunk. if it is greater than the current height - required confirmations, - // we will set it to the current height - required confirmations - toBlock := lastHeight + config.BlockSyncChunkSize - if toBlock > currentHeight-config.RequiredConfirmations { - toBlock = currentHeight - config.RequiredConfirmations - } - - err = processEvents(ctx, lastHeight, toBlock, client, eventStore, service.Logger) - if err != nil { - return fmt.Errorf("failed to process events: %w", err) - } - - lastHeight = toBlock - } - - // ListenToBlocks will listen to new blocks and process the events. - // It only returns when the context is cancelled, or when the client cannot recover - // from an error after the max retries. - outerErr := client.ListenToBlocks(ctx, time.Duration(config.ReconnectionInterval)*time.Second, func(newHeight int64) error { - newHeight = newHeight - config.RequiredConfirmations // account for required confirmations - - // it is possible to receive the same height twice - if newHeight <= lastHeight { - service.Logger.Info("received duplicate block height", "height", newHeight) - return nil - } - - service.Logger.Info("received new block height", "height", newHeight) - - // lastheight + 1 because we have already processed the last height - err = processEvents(ctx, lastHeight+1, newHeight, client, eventStore, service.Logger) - if err != nil { - return fmt.Errorf("failed to process events: %w", err) - } - - lastHeight = newHeight - - return nil - }) - if outerErr != nil { - return fmt.Errorf("ListenToBlocks failure: %w", outerErr) - } - - return nil -} - -// processEvents will process all events from the Ethereum client from the given -// height range. This means inserting any that have not already been processed -// for broadcast in a Kwil vote ID / approval transaction, and then storing the -// processed height. -func processEvents(ctx context.Context, from, to int64, client *ethClient, eventStore listeners.EventStore, logger log.SugaredLogger) error { - logs, err := client.GetCreditEventLogs(ctx, from, to) - if err != nil { - return fmt.Errorf("failed to get credit event logs: %w", err) - } - - for _, log := range logs { - event, err := decodeCreditEvent(&log) - if err != nil { - return fmt.Errorf("failed to decode credit event: %w", err) - } - - bts, err := event.MarshalBinary() - if err != nil { - return fmt.Errorf("failed to marshal event: %w", err) - } - - logger.Info("Flagging new account credit event for approval (to broadcast)", - "account", hex.EncodeToString(event.Account), "amount", event.Amount, "txHash", hex.EncodeToString(event.TxHash)) - err = eventStore.Broadcast(ctx, credit.CreditAccountEventType, bts) - if err != nil { - return fmt.Errorf("failed to mark new event for broadcast: %w", err) - } - } - - logger.Info("processed events", "from", from, "to", to, "events", len(logs)) - - return setLastStoredHeight(ctx, eventStore, to) -} - -// EthDepositConfig is the configuration for the eth_deposit listener. -// It can be read in from a map[string]string, which is passed from -// the node's local configuration. -type EthDepositConfig struct { - // StartingHeight is the Ethereum block height it will start listening from. - // Any events emitted before this height will be ignored. - // If not configured, it will start from block 0. - StartingHeight int64 - // ContractAddress is the Ethereum address of the smart contract it will listen to. - // It is a required configuration. - ContractAddress string - // RequiredConfirmations is the number of Ethereum blocks that must be mined before - // the listener will create a deposit event in Kwil. This is to protect against Ethereum - // network reorgs / soft forks. If not configured, it will default to 12. - // https://www.alchemy.com/overviews/what-is-a-reorg - RequiredConfirmations int64 - // RPCProvider is the URL of the Ethereum RPC endpoint it will connect to. - // This would likely be an Infura / Alchemy endpoint. - // It is a required configuration. - RPCProvider string - // ReconnectionInterval is the amount of time in seconds that the listener - // will wait before resubscribing for new Ethereum Blocks. Reconnects are - // automatically handled, but a subscription may stall, in which case we - // will make a new subscription. If the write or read on the connection to - // the RPC provider errors, the RPC client will reconnect, and we will - // continue to reestablish a new block subscription. If not configured, it - // will default to 60s. - ReconnectionInterval int64 - // MaxRetries is the total number of times the listener will attempt an RPC - // with the provider before giving up. It will exponentially back off after - // each try, starting at 1 second and doubling each time. If not configured, - // it will default to 10. - MaxRetries int64 - // BlockSyncChunkSize is the number of Ethereum blocks the listener will request from the - // Ethereum RPC endpoint at a time while catching up to the network. If not configured, - // it will default to 1,000,000. - BlockSyncChunkSize int64 -} - -// setConfig sets the configuration for the eth_deposit listener. -// If it doesn't find a required configuration, or if it finds an invalid -// configuration, it returns an error -func (e *EthDepositConfig) setConfig(m map[string]string) error { - startingHeight, ok := m["starting_height"] - if !ok { - startingHeight = "0" - } - - var err error - e.StartingHeight, err = strconv.ParseInt(startingHeight, 10, 64) - if err != nil { - return fmt.Errorf("invalid starting_height: %s", startingHeight) - } - if e.StartingHeight < 0 { - return fmt.Errorf("starting_height cannot be negative") - } - - contractAddress, ok := m["contract_address"] - if !ok { - return fmt.Errorf("no contract_address provided") - } - e.ContractAddress = contractAddress - - requiredConfirmations, ok := m["required_confirmations"] - if !ok { - requiredConfirmations = "12" - } - e.RequiredConfirmations, err = strconv.ParseInt(requiredConfirmations, 10, 64) - if err != nil { - return fmt.Errorf("invalid required_confirmations: %s", requiredConfirmations) - } - if e.RequiredConfirmations < 0 { - return fmt.Errorf("required_confirmations cannot be negative") - } - - rpc, ok := m["rpc_provider"] - if !ok { - return fmt.Errorf("no rpc_provider provided") - } - if !strings.HasPrefix(rpc, "ws") { - return fmt.Errorf("rpc_provider must be a websocket URL") - } - e.RPCProvider = rpc - - reconnectionInterval, ok := m["reconnection_interval"] - if !ok { - reconnectionInterval = "60" - } - intervalInt, err := strconv.ParseInt(reconnectionInterval, 10, 64) - if err != nil { - return fmt.Errorf("invalid reconnection_interval: %s", reconnectionInterval) - } - if intervalInt < 5 { - return fmt.Errorf("reconnection_interval must be greater than or equal to 5") - } - e.ReconnectionInterval = intervalInt - - maxRetries, ok := m["max_retries"] - if !ok { - maxRetries = "10" - } - e.MaxRetries, err = strconv.ParseInt(maxRetries, 10, 64) - if err != nil { - return fmt.Errorf("invalid max_retries: %s", maxRetries) - } - if e.MaxRetries < 0 { - return fmt.Errorf("max_retries cannot be negative") - } - - blockSyncChunkSize, ok := m["block_sync_chunk_size"] - if !ok { - blockSyncChunkSize = "1000000" // check this on goerli, it's big - } - e.BlockSyncChunkSize, err = strconv.ParseInt(blockSyncChunkSize, 10, 64) - if err != nil { - return fmt.Errorf("invalid block_sync_chunk_size: %s", blockSyncChunkSize) - } - if e.BlockSyncChunkSize <= 0 { - return fmt.Errorf("block_sync_chunk_size must be greater than 0") - } - - return nil -} - -// Map returns the configuration as a map[string]string. -// This is used for testing -func (e *EthDepositConfig) Map() map[string]string { - - return map[string]string{ - "starting_height": strconv.FormatInt(e.StartingHeight, 10), - "contract_address": e.ContractAddress, - "required_confirmations": strconv.FormatInt(e.RequiredConfirmations, 10), - "rpc_provider": e.RPCProvider, - "reconnection_interval": strconv.FormatInt(e.ReconnectionInterval, 10), - "max_retries": strconv.FormatInt(e.MaxRetries, 10), - "block_sync_chunk_size": strconv.FormatInt(e.BlockSyncChunkSize, 10), - } -} - -var ( - // lastHeightKey is the key used to store the last height processed by the listener - lastHeightKey = []byte("lh") -) - -// getLastStoredHeight gets the last height stored by the KV store -func getLastStoredHeight(ctx context.Context, eventStore listeners.EventStore) (int64, error) { - // get the last confirmed block height processed by the listener - lastHeight, err := eventStore.Get(ctx, lastHeightKey) - if err != nil { - return 0, fmt.Errorf("failed to get last block height: %w", err) - } - - if len(lastHeight) == 0 { - return 0, nil - } - - return int64(binary.LittleEndian.Uint64(lastHeight)), nil -} - -// setLastStoredHeight sets the last height stored by the KV store -func setLastStoredHeight(ctx context.Context, eventStore listeners.EventStore, height int64) error { - heightBts := make([]byte, 8) - binary.LittleEndian.PutUint64(heightBts, uint64(height)) - - // set the last confirmed block height processed by the listener - err := eventStore.Set(ctx, lastHeightKey, heightBts) - if err != nil { - return fmt.Errorf("failed to set last block height: %w", err) - } - return nil -} diff --git a/_previous/extensions/listeners/eth_deposits/deposits_test.go b/_previous/extensions/listeners/eth_deposits/deposits_test.go deleted file mode 100644 index 5e73f8219..000000000 --- a/_previous/extensions/listeners/eth_deposits/deposits_test.go +++ /dev/null @@ -1,28 +0,0 @@ -package ethdeposits - -import ( - "testing" - - "github.com/stretchr/testify/require" -) - -// we could use better tests for this package. -// this would require more abstractions, which would then -// take away from this being an example of a simple event listener. -func Test_Config(t *testing.T) { - cfg := &EthDepositConfig{ - StartingHeight: 45, - ContractAddress: "0x1234", - RequiredConfirmations: 10, - RPCProvider: "ws://localhost:8545", - ReconnectionInterval: 10, - MaxRetries: 5, - BlockSyncChunkSize: 100, - } - m := cfg.Map() - - cfg2 := &EthDepositConfig{} - err := cfg2.setConfig(m) - require.NoError(t, err) - require.Equal(t, cfg, cfg2) -} diff --git a/_previous/extensions/listeners/eth_deposits/ethereum.go b/_previous/extensions/listeners/eth_deposits/ethereum.go deleted file mode 100644 index dc65203ca..000000000 --- a/_previous/extensions/listeners/eth_deposits/ethereum.go +++ /dev/null @@ -1,227 +0,0 @@ -package ethdeposits - -import ( - "context" - "fmt" - "math/big" - "strings" - "time" - - "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/accounts/abi" - ethcommon "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/ethclient" - "github.com/jpillora/backoff" - - "github.com/kwilteam/kwil-db/core/log" - "github.com/kwilteam/kwil-db/extensions/resolutions/credit" -) - -// file contains functionality for subscribing to ethereum and reading logs - -func init() { - // parse the contract ABI - var err error - eventABI, err = abi.JSON(strings.NewReader(contractABIStr)) - if err != nil { - panic(err) - } -} - -// contractABIStr is the ABI of the smart contract the listener listens to. -// It follows the Ethereum ABI JSON format, and matches the `Credit(address,uint256)` event signature. -const contractABIStr = `[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_from","type":"address"},{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"Credit","type":"event"}]` - -// eventABI is the abi for the Credit event -var eventABI abi.ABI - -// creditEventSignature is the EVM event signature the listener listens to. -var creditEventSignature ethcommon.Hash = crypto.Keccak256Hash([]byte("Credit(address,uint256)")) - -// ethClient is a client for interacting with the ethereum blockchain -// it handles retries and resubscribing to the blockchain in case of -// transient errors -type ethClient struct { - targetAddress ethcommon.Address - maxRetries int64 - logger log.SugaredLogger - client *ethclient.Client -} - -// newEthClient creates a new ethereum client -func newEthClient(ctx context.Context, rpcurl string, maxRetries int64, targetAddress ethcommon.Address, logger log.SugaredLogger) (*ethClient, error) { - var client *ethclient.Client - - // I don't set the max retries here because this only gets run on startup - // the max retries are used for resubscribing to the blockchain - // if we fail 3 times here, it is likely a permanent error - err := retry(ctx, 3, func() error { - var innerErr error - client, innerErr = ethclient.DialContext(ctx, rpcurl) - return innerErr - }) - if err != nil { - return nil, err - } - - return ðClient{ - targetAddress: targetAddress, - maxRetries: maxRetries, - logger: logger, - client: client, - }, nil -} - -// GetLatestBlock gets the latest block number from the ethereum blockchain -func (ec *ethClient) GetLatestBlock(ctx context.Context) (int64, error) { - var blockNumber int64 - err := retry(ctx, ec.maxRetries, func() error { - header, err := ec.client.HeaderByNumber(ctx, nil) - if err != nil { - ec.logger.Error("Failed to get latest block", "error", err) - return err - } - blockNumber = header.Number.Int64() - return nil - }) - return blockNumber, err -} - -// GetCreditEventLogs gets the logs for the credit event from the ethereum blockchain. -// It can be given a start range and an end range to filter the logs by block height. -func (ec *ethClient) GetCreditEventLogs(ctx context.Context, fromBlock, toBlock int64) ([]types.Log, error) { - var logs []types.Log - err := retry(ctx, ec.maxRetries, func() error { - var err error - logs, err = ec.client.FilterLogs(ctx, ethereum.FilterQuery{ - ToBlock: big.NewInt(toBlock), - FromBlock: big.NewInt(fromBlock), - Addresses: []ethcommon.Address{ec.targetAddress}, - Topics: [][]ethcommon.Hash{{creditEventSignature}}, - }) - if err != nil { - ec.logger.Error("Failed to get credit event logs", "error", err) - } - - return err - }) - return logs, err -} - -// decodeCreditEvent decodes the credit event from the ethereum log -func decodeCreditEvent(l *types.Log) (*credit.AccountCreditResolution, error) { - data, err := eventABI.Unpack("Credit", l.Data) - if err != nil { - return nil, err - } - - // the first argument is the address, the second is the amount - address, ok := data[0].(ethcommon.Address) - if !ok { - return nil, fmt.Errorf("failed to parse credit event address") - } - amount, ok := data[1].(*big.Int) - if !ok { - return nil, fmt.Errorf("failed to parse credit event amount") - } - - return &credit.AccountCreditResolution{ - Account: address.Bytes(), - Amount: amount, - TxHash: l.TxHash.Bytes(), - }, nil -} - -// ListenToBlocks subscribes to new blocks on the ethereum blockchain. -// It takes a reconnectInterval, which is the amount of time it will wait -// to reconnect to the ethereum client if no new blocks are received. -// It takes a callback function that is called with the new block number. -// It can send duplicates, if that is received from the ethereum client. -// It will block until the context is cancelled, or until an error is -// returned from the callback function. -func (ec *ethClient) ListenToBlocks(ctx context.Context, reconnectInterval time.Duration, cb func(int64) error) error { - headers := make(chan *types.Header, 1) - sub, err := ec.client.SubscribeNewHead(ctx, headers) - if err != nil { - return err - } - - resubscribe := func() error { - var retryCount int - ec.logger.Warn("Resubscribing to Ethereum node", "attempt", retryCount) // anomalous - sub.Unsubscribe() - - return retry(ctx, ec.maxRetries, func() error { - retryCount++ - sub, err = ec.client.SubscribeNewHead(ctx, headers) - return err - }) - } - - reconn := time.NewTicker(reconnectInterval) - defer reconn.Stop() - - for { - select { - case <-ctx.Done(): - ec.logger.Debug("Context cancelled, stopping ethereum client") - return nil - case header := <-headers: - ec.logger.Debug("New block", "height", header.Number.Int64()) - err := cb(header.Number.Int64()) - if err != nil { - return err - } - - reconn.Reset(reconnectInterval) - case err := <-sub.Err(): - ec.logger.Error("Ethereum subscription error", "error", err) - err = resubscribe() - if err != nil { - return err - } - reconn.Reset(reconnectInterval) - case <-reconn.C: - ec.logger.Warn("No new blocks received, resubscribing") - err := resubscribe() - if err != nil { - return err - } - } - } -} - -// Close closes the ethereum client -func (ec *ethClient) Close() { - ec.client.Close() -} - -// retry will retry the function until it is successful, or reached the max retries -func retry(ctx context.Context, maxRetries int64, fn func() error) error { - retrier := &backoff.Backoff{ - Min: 1 * time.Second, - Max: 10 * time.Second, - Factor: 2, - Jitter: true, - } - - for { - err := fn() - if err == nil { - return nil - } - - // fail after maxRetries retries - if retrier.Attempt() > float64(maxRetries) { - return err - } - - select { - case <-ctx.Done(): - return ctx.Err() - case <-time.After(retrier.Duration()): - } - } -} diff --git a/go.mod b/go.mod index 8c2ec14c5..2babadde7 100644 --- a/go.mod +++ b/go.mod @@ -33,18 +33,30 @@ require ( ) require ( + github.com/Microsoft/go-winio v0.6.2 // indirect + github.com/StackExchange/wmi v1.2.1 // indirect github.com/antlr4-go/antlr/v4 v4.13.1 // indirect + github.com/bits-and-blooms/bitset v1.13.0 // indirect + github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect github.com/chzyer/readline v1.5.1 // indirect github.com/cockroachdb/apd/v3 v3.2.1 // indirect + github.com/consensys/bavard v0.1.13 // indirect + github.com/consensys/gnark-crypto v0.12.1 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect + github.com/crate-crypto/go-ipa v0.0.0-20240223125850-b1e8a79f509c // indirect + github.com/crate-crypto/go-kzg-4844 v1.0.0 // indirect + github.com/deckarep/golang-set/v2 v2.6.0 // indirect github.com/decred/dcrd/certgen v1.2.0 // indirect github.com/decred/dcrd/crypto/rand v1.0.0 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect github.com/decred/slog v1.2.0 // indirect + github.com/ethereum/c-kzg-4844 v1.0.0 // indirect + github.com/ethereum/go-verkle v0.1.1-0.20240829091221-dffa7562dbe9 // indirect github.com/fatih/structs v1.1.0 // indirect github.com/fsnotify/fsnotify v1.8.0 // indirect github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-ole/go-ole v1.3.0 // indirect github.com/go-viper/mapstructure/v2 v2.2.1 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect @@ -68,14 +80,20 @@ require ( github.com/mattn/go-runewidth v0.0.16 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect + github.com/mmcloughlin/addchain v0.4.0 // indirect github.com/polydawn/refmt v0.89.0 // indirect github.com/rivo/uniseg v0.4.7 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect + github.com/supranational/blst v0.3.13 // indirect + github.com/tklauser/go-sysconf v0.3.12 // indirect + github.com/tklauser/numcpus v0.6.1 // indirect github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1 // indirect go.opentelemetry.io/otel v1.32.0 // indirect go.opentelemetry.io/otel/metric v1.32.0 // indirect go.opentelemetry.io/otel/trace v1.32.0 // indirect gonum.org/v1/gonum v0.15.1 // indirect + rsc.io/tmplfunc v0.0.3 // indirect ) require ( @@ -90,7 +108,7 @@ require ( github.com/docker/go-units v0.5.0 // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/elastic/gosigar v0.14.3 // indirect - github.com/ethereum/go-ethereum v1.14.11 // indirect + github.com/ethereum/go-ethereum v1.14.11 github.com/flynn/noise v1.1.0 // indirect github.com/francoispqt/gojay v1.2.13 // indirect github.com/go-task/slim-sprig/v3 v3.0.0 // indirect diff --git a/go.sum b/go.sum index 1f8f1c42f..0bab6ea36 100644 --- a/go.sum +++ b/go.sum @@ -8,6 +8,14 @@ dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1 dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU= git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/DataDog/zstd v1.4.5 h1:EndNeuB0l9syBZhut0wns3gV1hL8zX8LIu6ZiVHWLIQ= +github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= +github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= +github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= +github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA= +github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8= +github.com/VictoriaMetrics/fastcache v1.12.2 h1:N0y9ASrJ0F6h0QaC3o6uJb3NIZ9VKLjCM7NQbSmF7WI= +github.com/VictoriaMetrics/fastcache v1.12.2/go.mod h1:AmC+Nzz1+3G2eCPapF6UcsnkThDcMsQicp4xDukwJYI= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/antlr4-go/antlr/v4 v4.13.1 h1:SqQKkuVZ+zWkMMNkjy5FZe5mr5WURWnlpmOuzYWrPrQ= github.com/antlr4-go/antlr/v4 v4.13.1/go.mod h1:GKmUxMtwp6ZgGwZSva4eWPC5mS6vUAmOABFgjdkM7Nw= @@ -18,7 +26,13 @@ github.com/benbjohnson/clock v1.3.5/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZx github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bits-and-blooms/bitset v1.13.0 h1:bAQ9OPNFYbGHV6Nez0tmNI0RiEu7/hxlYJRUA0wFAVE= +github.com/bits-and-blooms/bitset v1.13.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g= +github.com/btcsuite/btcd/btcec/v2 v2.3.4 h1:3EJjcN70HCu/mwqlUsGK8GcNVyLVxFDlWurTXGPFfiQ= +github.com/btcsuite/btcd/btcec/v2 v2.3.4/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= @@ -37,6 +51,22 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cockroachdb/apd/v3 v3.2.1 h1:U+8j7t0axsIgvQUqthuNm82HIrYXodOV2iWLWtEaIwg= github.com/cockroachdb/apd/v3 v3.2.1/go.mod h1:klXJcjp+FffLTHlhIG69tezTDvdP065naDsHzKhYSqc= +github.com/cockroachdb/errors v1.11.3 h1:5bA+k2Y6r+oz/6Z/RFlNeVCesGARKuC6YymtcDrbC/I= +github.com/cockroachdb/errors v1.11.3/go.mod h1:m4UIW4CDjx+R5cybPsNrRbreomiFqt8o1h1wUVazSd8= +github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce h1:giXvy4KSc/6g/esnpM7Geqxka4WSqI1SZc7sMJFd3y4= +github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce/go.mod h1:9/y3cnZ5GKakj/H4y9r9GTjCvAFta7KLgSHPJJYc52M= +github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE= +github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= +github.com/cockroachdb/pebble v1.1.2 h1:CUh2IPtR4swHlEj48Rhfzw6l/d0qA31fItcIszQVIsA= +github.com/cockroachdb/pebble v1.1.2/go.mod h1:4exszw1r40423ZsmkG/09AFEG83I0uDgfujJdbL6kYU= +github.com/cockroachdb/redact v1.1.5 h1:u1PMllDkdFfPWaNGMyLD1+so+aq3uUItthCFqzwPJ30= +github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= +github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= +github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= +github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ= +github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= +github.com/consensys/gnark-crypto v0.12.1 h1:lHH39WuuFgVHONRl3J0LRBtuYdQTumFSDtJF7HpyG8M= +github.com/consensys/gnark-crypto v0.12.1/go.mod h1:v2Gy7L/4ZRosZ7Ivs+9SfUDr0f5UlG+EM5t7MPHiLuY= github.com/containerd/cgroups v0.0.0-20201119153540-4cbc285b3327/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE= github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM= github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw= @@ -48,12 +78,18 @@ github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:ma github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4= github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/crate-crypto/go-ipa v0.0.0-20240223125850-b1e8a79f509c h1:uQYC5Z1mdLRPrZhHjHxufI8+2UG/i25QG92j0Er9p6I= +github.com/crate-crypto/go-ipa v0.0.0-20240223125850-b1e8a79f509c/go.mod h1:geZJZH3SzKCqnz5VT0q/DyIG/tvu/dZk+VIfXicupJs= +github.com/crate-crypto/go-kzg-4844 v1.0.0 h1:TsSgHwrkTKecKJ4kadtHi4b3xHW5dCFUDFnUp1TsawI= +github.com/crate-crypto/go-kzg-4844 v1.0.0/go.mod h1:1kMhvPgI0Ky3yIa+9lFySEBUBXkYxeOi8ZF1sYioxhc= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c h1:pFUpOrbxDR6AkioZ1ySsx5yxlDQZ8stG2b88gTPxgJU= github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c/go.mod h1:6UhI8N9EjYm1c2odKpFpAYeR8dsBeM7PtzQhRgxRr9U= +github.com/deckarep/golang-set/v2 v2.6.0 h1:XfcQbWM1LlMB8BsJ8N9vW5ehnnPVIw0je80NsVHagjM= +github.com/deckarep/golang-set/v2 v2.6.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= github.com/decred/dcrd/certgen v1.2.0 h1:FF6XXV//5q38/c6QbGQdR35ZJz0GPIkejsZZU3oHuBQ= github.com/decred/dcrd/certgen v1.2.0/go.mod h1:LRh6dF2WPQeDA6QQSZE+SfK7AL6FuFtCRDHZf8DyGzg= github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= @@ -83,8 +119,12 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/ethereum/c-kzg-4844 v1.0.0 h1:0X1LBXxaEtYD9xsyj9B9ctQEZIpnvVDeoBx8aHEwTNA= +github.com/ethereum/c-kzg-4844 v1.0.0/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0= github.com/ethereum/go-ethereum v1.14.11 h1:8nFDCUUE67rPc6AKxFj7JKaOa2W/W1Rse3oS6LvvxEY= github.com/ethereum/go-ethereum v1.14.11/go.mod h1:+l/fr42Mma+xBnhefL/+z11/hcmJ2egl+ScIVPjhc7E= +github.com/ethereum/go-verkle v0.1.1-0.20240829091221-dffa7562dbe9 h1:8NfxH2iXvJ60YRB8ChToFTUzl8awsc3cJ8CbLjGIl/A= +github.com/ethereum/go-verkle v0.1.1-0.20240829091221-dffa7562dbe9/go.mod h1:M3b90YRnzqKyyzBEWJGqj8Qff4IDeXnzFw0P9bFw3uk= github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= @@ -97,6 +137,10 @@ github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7z github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M= github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= +github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI= +github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= +github.com/getsentry/sentry-go v0.27.0 h1:Pv98CIbtB3LkMWmXi4Joa5OOcwbmnX88sF5qbK3r3Ps= +github.com/getsentry/sentry-go v0.27.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= github.com/go-chi/chi/v5 v5.1.0 h1:acVI1TYaD+hhedDJ3r54HyA6sExp3HfXq7QWEEY/xMw= @@ -107,6 +151,9 @@ github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= +github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss= @@ -116,10 +163,14 @@ github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5x github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= +github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= +github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= @@ -139,6 +190,8 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk= +github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/flatbuffers v24.3.25+incompatible h1:CX395cjN9Kke9mmalRoL3d81AtFUxJM+yDthflgJGkI= github.com/google/flatbuffers v24.3.25+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= @@ -153,12 +206,15 @@ github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= +github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= +github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8= github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20241017200806-017d972448fc h1:NGyrhhFhwvRAZg02jnYVg3GBQy0qGBKmFQJwaPmpmxs= github.com/google/pprof v0.0.0-20241017200806-017d972448fc/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= +github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= @@ -175,12 +231,18 @@ github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpg github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE= +github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c= github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= +github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4 h1:X4egAf/gcS1zATw6wn4Ej8vjuVGxeHdan+bRb2ebyv4= +github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4/go.mod h1:5GuXa7vkL8u9FkFuWdVvfR5ix8hRB7DbOAaYULamFpc= +github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= +github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA= github.com/holiman/uint256 v1.3.1 h1:JfTzmih28bittyHM8z360dCjIA9dbPIBlcTI6lmctQs= github.com/holiman/uint256 v1.3.1/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXeiRV4ng7E= github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc= @@ -271,6 +333,10 @@ github.com/kwilteam/kwil-db/core v0.3.1-0.20241212163115-7353f2761884 h1:R8nARxa github.com/kwilteam/kwil-db/core v0.3.1-0.20241212163115-7353f2761884/go.mod h1:v3YA0w26s82aSVWoZMFFxFD39Bqvy/8eHKLEZhn6bBQ= github.com/kwilteam/kwil-db/parse v0.3.1-0.20241212163115-7353f2761884 h1:DyPpPyiuO2MwBrQ1QPkILJXgzdmFjVlRlJerICSp6ks= github.com/kwilteam/kwil-db/parse v0.3.1-0.20241212163115-7353f2761884/go.mod h1:REQKF6pOCxTzY6WaZwRU+QWuIWsRmviYcSgqdKa5zfc= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= +github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw= github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8= @@ -311,6 +377,8 @@ github.com/manifoldco/promptui v0.9.0 h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYt github.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GWtQEhdbn6Pgg= github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd h1:br0buuQ854V8u83wA0rVZ8ttrq5CpaPZdvrK0LP2lOk= github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd/go.mod h1:QuCEs1Nt24+FYQEqAAncTDPJIuGs+LxK1MCiFL25pMU= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= @@ -333,8 +401,15 @@ github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dz github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= +github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag= +github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A= +github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY= +github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqkyU72HC5wJ4RlU= +github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFVejUS1/tS/qU= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= @@ -458,11 +533,15 @@ github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= +github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU= +github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY= github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM= github.com/shurcooL/github_flavored_markdown v0.0.0-20181002035957-2122de532470/go.mod h1:2dOwnU2uBioM+SGy2aZoq1f/Sd1l9OkAeAUvjSyvgU0= @@ -499,6 +578,8 @@ github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA= +github.com/status-im/keycard-go v0.2.0/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9+mHxBEeo3Hbg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= @@ -515,9 +596,22 @@ github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXl github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/supranational/blst v0.3.13 h1:AYeSxdOMacwu7FBmpfloBz5pbFXDmJL33RuwnKtmTjk= +github.com/supranational/blst v0.3.13/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= +github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= +github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= +github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= +github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= +github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= +github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= +github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= +github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/urfave/cli v1.22.10 h1:p8Fspmz3iTctJstry1PYS3HVdllxnEzTEsgIgtxTrCk= github.com/urfave/cli v1.22.10/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/urfave/cli/v2 v2.25.7 h1:VAzn5oq403l5pHjc4OhD54+XGO9cdKVL/7lDjF+iKUs= +github.com/urfave/cli/v2 v2.25.7/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ= github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU= github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM= github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0 h1:GDDkbFiaK8jsSDJfjId/PEGEShv6ugrt4kYsC5UIDaQ= @@ -527,6 +621,8 @@ github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1/go.mod h github.com/wlynxg/anet v0.0.3/go.mod h1:eay5PRQr7fIVAMbTbchTnO9gG65Hg/uYGdc7mguHxoA= github.com/wlynxg/anet v0.0.5 h1:J3VJGi1gvo0JwZ/P1/Yc/8p63SoW98B5dHkYDmpgvvU= github.com/wlynxg/anet v0.0.5/go.mod h1:eay5PRQr7fIVAMbTbchTnO9gG65Hg/uYGdc7mguHxoA= +github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= +github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= @@ -639,6 +735,7 @@ golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190316082340-a2f829d7f35f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -651,6 +748,7 @@ golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -744,6 +842,8 @@ gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= +gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -760,5 +860,7 @@ honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= lukechampine.com/blake3 v1.3.0 h1:sJ3XhFINmHSrYCgl958hscfIa3bw8x4DqMP3u1YvoYE= lukechampine.com/blake3 v1.3.0/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k= +rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU= +rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA= sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck= sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0= diff --git a/node/block_processor/transactions.go b/node/block_processor/transactions.go index e754ce5a6..7fad77497 100644 --- a/node/block_processor/transactions.go +++ b/node/block_processor/transactions.go @@ -223,12 +223,6 @@ func (bp *BlockProcessor) prepareValidatorVoteBodyTx(ctx context.Context, nonce return nil, err } - // If gas costs are enabled, ensure that the node has sufficient funds to include this transaction - if !bp.chainCtx.NetworkParameters.DisabledGasCosts && n == 0 && bal.Sign() == 0 { - bp.log.Debug("Leader account has no balance, not allowed to propose any transactions") - return nil, nil - } - events, err := getEvents(ctx, readTx) if err != nil { return nil, err @@ -239,6 +233,12 @@ func (bp *BlockProcessor) prepareValidatorVoteBodyTx(ctx context.Context, nonce return nil, nil } + // If gas costs are enabled, ensure that the node has sufficient funds to include this transaction + if !bp.chainCtx.NetworkParameters.DisabledGasCosts && n == 0 && bal.Sign() == 0 { + bp.log.Debug("Leader account has no balance, not allowed to propose any transactions") + return nil, nil + } + ids := make([]*types.UUID, 0, len(events)) for _, e := range events { ids = append(ids, e.ID()) diff --git a/node/block_processor/transactions_test.go b/node/block_processor/transactions_test.go index 49ebdedf0..68be4b5f3 100644 --- a/node/block_processor/transactions_test.go +++ b/node/block_processor/transactions_test.go @@ -7,10 +7,12 @@ import ( "testing" "github.com/kwilteam/kwil-db/common" + "github.com/kwilteam/kwil-db/config" "github.com/kwilteam/kwil-db/core/crypto" "github.com/kwilteam/kwil-db/core/crypto/auth" "github.com/kwilteam/kwil-db/core/log" "github.com/kwilteam/kwil-db/core/types" + ktypes "github.com/kwilteam/kwil-db/core/types" "github.com/kwilteam/kwil-db/node/txapp" "github.com/kwilteam/kwil-db/node/types/sql" "github.com/stretchr/testify/require" @@ -55,7 +57,7 @@ func secp256k1Signer(t *testing.T) *auth.EthPersonalSigner { return &auth.EthPersonalSigner{Key: *k} } -func Test_prepareMempoolTxns(t *testing.T) { +func TestPrepareMempoolTxns(t *testing.T) { // To make these tests deterministic, we manually craft certain misorderings // and the known expected orderings. Also include some malformed // transactions that fail to unmarshal, which really shouldn't happen if the @@ -226,14 +228,418 @@ func Test_prepareMempoolTxns(t *testing.T) { } } -type mockTxApp struct{} +var ( + evt1 = &types.VotableEvent{ + Type: "test", + Body: []byte("test"), + } + evt2 = &types.VotableEvent{ + Type: "test", + Body: []byte("test2"), + } + evt3 = &types.VotableEvent{ + Type: "test", + Body: []byte("test3"), + } +) + +func TestPrepareVoteIDTx(t *testing.T) { + leader := secp256k1Signer(t) + validator := secp256k1Signer(t) + sentry := secp256k1Signer(t) + valSet := []*ktypes.Validator{ + { + PubKey: validator.Identity(), + Power: 1, + }, + { + PubKey: leader.Identity(), + Power: 1, + }, + } + genCfg := config.DefaultGenesisConfig() + genCfg.Leader = leader.Identity() + + bp := &BlockProcessor{ + db: &mockDB{}, + log: log.DiscardLogger, + signer: secp256k1Signer(t), + chainCtx: &common.ChainContext{ + ChainID: "test", + NetworkParameters: &common.NetworkParameters{ + MaxBlockSize: 6 * 1024 * 1024, + MaxVotesPerTx: 100, + DisabledGasCosts: true, + }, + }, + txapp: &mockTxApp{}, + genesisParams: genCfg, + } + + testcases := []struct { + name string + signer auth.Signer + events []*types.VotableEvent + cleanup func() + fn func(context.Context, *BlockProcessor, sql.DB, *mockEventStore) error + }{ + { + name: "no voteIDs to broadcast", + events: []*types.VotableEvent{}, // no events + signer: validator, + fn: func(ctx context.Context, bp *BlockProcessor, db sql.DB, es *mockEventStore) error { + bp.signer = validator + tx, ids, err := bp.PrepareValidatorVoteIDTx(ctx, db) + require.NoError(t, err) + require.Nil(t, tx) + require.Nil(t, ids) + return nil + }, + }, + { + name: "leader not allowed to broadcast voteIDs", + events: []*types.VotableEvent{evt1, evt2}, + signer: leader, + fn: func(ctx context.Context, bp *BlockProcessor, db sql.DB, es *mockEventStore) error { + tx, ids, err := bp.PrepareValidatorVoteIDTx(ctx, db) + require.NoError(t, err) + require.Nil(t, tx) + require.Nil(t, ids) + return nil + }, + }, + { + name: "sentry node not allowed to broadcast voteIDs", + events: []*types.VotableEvent{evt1, evt2}, + signer: sentry, + fn: func(ctx context.Context, bp *BlockProcessor, db sql.DB, es *mockEventStore) error { + tx, ids, err := bp.PrepareValidatorVoteIDTx(ctx, db) + require.NoError(t, err) + require.Nil(t, tx) + require.Nil(t, ids) + return nil + }, + }, + { + name: "validator broadcasts voteIDs in gasless mode", + signer: validator, + events: []*types.VotableEvent{evt1, evt2}, + fn: func(ctx context.Context, bp *BlockProcessor, db sql.DB, es *mockEventStore) error { + tx, ids, err := bp.PrepareValidatorVoteIDTx(ctx, db) + require.NoError(t, err) + require.NotNil(t, tx) + require.NotNil(t, ids) + require.Len(t, ids, 2) + return nil + }, + }, + { + name: "insufficient gas to broadcast voteIDs", + signer: validator, + events: []*types.VotableEvent{evt1, evt2}, + fn: func(ctx context.Context, bp *BlockProcessor, db sql.DB, es *mockEventStore) error { + bp.chainCtx.NetworkParameters.DisabledGasCosts = false + // set price of tx high: 1000 + price = big.NewInt(1000) + tx, ids, err := bp.PrepareValidatorVoteIDTx(ctx, db) + + require.NoError(t, err) + require.Nil(t, tx) + require.Nil(t, ids) + return nil + }, + cleanup: func() { + price = big.NewInt(0) + bp.chainCtx.NetworkParameters.DisabledGasCosts = true + }, + }, + { + name: "validator has sufficient gas to broadcast voteIDs", + signer: validator, + events: []*types.VotableEvent{evt1, evt2}, + fn: func(ctx context.Context, bp *BlockProcessor, db sql.DB, es *mockEventStore) error { + bp.chainCtx.NetworkParameters.DisabledGasCosts = false + // set price of tx low: 1 + price = big.NewInt(1000) + accountBalance = big.NewInt(1000) + tx, ids, err := bp.PrepareValidatorVoteIDTx(ctx, db) + + require.NoError(t, err) + require.NotNil(t, tx) + require.NotNil(t, ids) + require.Len(t, ids, 2) + return nil + }, + cleanup: func() { + price = big.NewInt(0) + accountBalance = big.NewInt(0) + bp.chainCtx.NetworkParameters.DisabledGasCosts = true + }, + }, + { + name: "mark broadcasted for broadcasted voteIDs", + signer: validator, + events: []*types.VotableEvent{evt1, evt2}, + fn: func(ctx context.Context, bp *BlockProcessor, db sql.DB, es *mockEventStore) error { + tx, ids, err := bp.PrepareValidatorVoteIDTx(ctx, db) + require.NoError(t, err) + require.NotNil(t, tx) + require.NotNil(t, ids) + require.Len(t, ids, 2) + + err = bp.events.MarkBroadcasted(ctx, ids) + require.NoError(t, err) + + // now no more events to broadcast + tx, ids, err = bp.PrepareValidatorVoteIDTx(ctx, db) + require.NoError(t, err) + require.Nil(t, tx) + require.Nil(t, ids) + + // add more events + es.addEvent(evt3) + tx, ids, err = bp.PrepareValidatorVoteIDTx(ctx, db) + require.NoError(t, err) + require.NotNil(t, tx) + require.NotNil(t, ids) + require.Len(t, ids, 1) + + return nil + }, + }, + } + + for _, tc := range testcases { + t.Run(tc.name, func(t *testing.T) { + defer func() { + if tc.cleanup != nil { + tc.cleanup() + } + }() + + db := &mockDB{} + bp.signer = tc.signer + es := newMockEventStore(tc.events) + bp.events = es + bp.validators = newValidatorStore(valSet) + + ctx := context.Background() + err := tc.fn(ctx, bp, db, es) // run the test function + require.NoError(t, err) + }) + } +} + +func TestPrepareVoteBodyTx(t *testing.T) { + signer := secp256k1Signer(t) + genCfg := config.DefaultGenesisConfig() + genCfg.Leader = signer.Identity() + + bp := &BlockProcessor{ + db: &mockDB{}, + log: log.DiscardLogger, + signer: signer, + chainCtx: &common.ChainContext{ + ChainID: "test", + NetworkParameters: &common.NetworkParameters{ + MaxBlockSize: 6 * 1024 * 1024, + MaxVotesPerTx: 100, + DisabledGasCosts: true, + }, + }, + txapp: &mockTxApp{}, + genesisParams: genCfg, + } + + testcases := []struct { + name string + events []*types.VotableEvent + cleanup func() + fn func(context.Context, *BlockProcessor, *mockEventStore) error + }{ + { + name: "No events to broadcast(gasless mode)", + events: []*types.VotableEvent{}, + fn: func(ctx context.Context, bp *BlockProcessor, es *mockEventStore) error { + tx, err := bp.prepareValidatorVoteBodyTx(ctx, 1, bp.chainCtx.NetworkParameters.MaxBlockSize) + require.NoError(t, err) + require.Nil(t, tx) + + return nil + }, + }, + { + name: "No events to broadcast (gas mode)", + events: []*types.VotableEvent{}, + cleanup: func() { + bp.chainCtx.NetworkParameters.DisabledGasCosts = true + }, + fn: func(ctx context.Context, bp *BlockProcessor, es *mockEventStore) error { + bp.chainCtx.NetworkParameters.DisabledGasCosts = false + + tx, err := bp.prepareValidatorVoteBodyTx(ctx, 1, bp.chainCtx.NetworkParameters.MaxBlockSize) + require.NoError(t, err) + require.Nil(t, tx) + + return nil + }, + }, + { + name: "atleast 1 event to broadcast", + events: []*types.VotableEvent{evt1, evt2}, + fn: func(ctx context.Context, bp *BlockProcessor, es *mockEventStore) error { + tx, err := bp.prepareValidatorVoteBodyTx(ctx, 1, bp.chainCtx.NetworkParameters.MaxBlockSize) + require.NoError(t, err) + require.NotNil(t, tx) + + txn := &types.Transaction{} + err = txn.UnmarshalBinary(tx) + require.NoError(t, err) + + var payload = &ktypes.ValidatorVoteBodies{} + err = payload.UnmarshalBinary(txn.Body.Payload) + require.NoError(t, err) + + require.Len(t, payload.Events, 2) + return nil + }, + }, + { + name: "enforce maxVotesPerTx limit", + events: []*types.VotableEvent{evt1, evt2, evt3}, + fn: func(ctx context.Context, bp *BlockProcessor, es *mockEventStore) error { + bp.chainCtx.NetworkParameters.MaxVotesPerTx = 1 + + tx, err := bp.prepareValidatorVoteBodyTx(ctx, 1, bp.chainCtx.NetworkParameters.MaxBlockSize) + require.NoError(t, err) + require.NotNil(t, tx) + + txn := &types.Transaction{} + err = txn.UnmarshalBinary(tx) + require.NoError(t, err) + + var payload = &ktypes.ValidatorVoteBodies{} + err = payload.UnmarshalBinary(txn.Body.Payload) + require.NoError(t, err) + + require.Len(t, payload.Events, 1) + return nil + }, + cleanup: func() { + bp.chainCtx.NetworkParameters.MaxVotesPerTx = 100 + }, + }, + { + name: "enforce maxSizePerTx limit", + events: []*types.VotableEvent{evt1, evt2, evt3}, + fn: func(ctx context.Context, bp *BlockProcessor, es *mockEventStore) error { + + emptyTxSize, err := bp.emptyVodeBodyTxSize() + require.NoError(t, err) + + // support evt1 + txSize := emptyTxSize + int64(len(evt1.Body)+len(evt1.Type)+8) + bp.chainCtx.NetworkParameters.MaxBlockSize = txSize + 10 /* buffer */ + + tx, err := bp.prepareValidatorVoteBodyTx(ctx, 1, bp.chainCtx.NetworkParameters.MaxBlockSize) + require.NoError(t, err) + require.NotNil(t, tx) + + txn := &types.Transaction{} + err = txn.UnmarshalBinary(tx) + require.NoError(t, err) + + var payload = &ktypes.ValidatorVoteBodies{} + err = payload.UnmarshalBinary(txn.Body.Payload) + require.NoError(t, err) + + require.Len(t, payload.Events, 1) + return nil + + }, + cleanup: func() { + bp.chainCtx.NetworkParameters.MaxBlockSize = 6 * 1024 * 1024 + }, + }, + { + name: "insufficient funds", + events: []*types.VotableEvent{evt1, evt2}, + fn: func(ctx context.Context, bp *BlockProcessor, es *mockEventStore) error { + bp.chainCtx.NetworkParameters.DisabledGasCosts = false + accountBalance = big.NewInt(0) + price = big.NewInt(1000) + + tx, err := bp.prepareValidatorVoteBodyTx(ctx, 1, bp.chainCtx.NetworkParameters.MaxBlockSize) + require.NoError(t, err) + require.Nil(t, tx) + + return nil + }, + cleanup: func() { + bp.chainCtx.NetworkParameters.DisabledGasCosts = true + }, + }, + { + name: "have sufficient funds", + events: []*types.VotableEvent{evt1, evt2}, + fn: func(ctx context.Context, bp *BlockProcessor, es *mockEventStore) error { + bp.chainCtx.NetworkParameters.DisabledGasCosts = false + accountBalance = big.NewInt(1000) + price = big.NewInt(1000) + + tx, err := bp.prepareValidatorVoteBodyTx(ctx, 1, bp.chainCtx.NetworkParameters.MaxBlockSize) + require.NoError(t, err) + require.NotNil(t, tx) + + txn := &types.Transaction{} + err = txn.UnmarshalBinary(tx) + require.NoError(t, err) + + var payload = &ktypes.ValidatorVoteBodies{} + err = payload.UnmarshalBinary(txn.Body.Payload) + require.NoError(t, err) + + require.Len(t, payload.Events, 2) + return nil + }, + cleanup: func() { + bp.chainCtx.NetworkParameters.DisabledGasCosts = true + accountBalance = big.NewInt(0) + price = big.NewInt(0) + }, + }, + } + + for _, tc := range testcases { + t.Run(tc.name, func(t *testing.T) { + // cleanup + defer func() { + if tc.cleanup != nil { + tc.cleanup() + } + }() + + es := newMockEventStore(tc.events) + bp.events = es + + getEvents = func(_ context.Context, _ sql.Executor) ([]*types.VotableEvent, error) { + return es.getEvents(), nil + } + + if tc.fn != nil { + tc.fn(context.Background(), bp, es) + } + }) + } -func (m *mockTxApp) MarkBroadcasted(ctx context.Context, ids []types.UUID) error { - return nil } +type mockTxApp struct{} + +var accountBalance = big.NewInt(0) + func (m *mockTxApp) AccountInfo(ctx context.Context, db sql.DB, acctID []byte, getUncommitted bool) (balance *big.Int, nonce int64, err error) { - return big.NewInt(0), 0, nil + return accountBalance, 0, nil } func (m *mockTxApp) ApplyMempool(ctx *common.TxContext, db sql.DB, tx *types.Transaction) error { @@ -279,8 +685,10 @@ func (m *mockTxApp) Reload(ctx context.Context, db sql.DB) error { return nil } +var price = big.NewInt(0) + func (m *mockTxApp) Price(ctx context.Context, db sql.DB, tx *types.Transaction, c *common.ChainContext) (*big.Int, error) { - return big.NewInt(0), nil + return price, nil } type mockDB struct{} @@ -332,3 +740,69 @@ func (m *mockTx) BeginTx(ctx context.Context) (sql.Tx, error) { func (m *mockTx) Precommit(ctx context.Context, changes chan<- any) ([]byte, error) { return nil, nil } + +type event struct { + evt *types.VotableEvent + broadcasted bool +} + +type mockEventStore struct { + events map[string]event +} + +func newMockEventStore(events []*types.VotableEvent) *mockEventStore { + es := &mockEventStore{events: make(map[string]event)} + for _, e := range events { + es.events[e.ID().String()] = event{evt: e, broadcasted: false} + } + return es +} + +func (m *mockEventStore) addEvent(evt *types.VotableEvent) { + m.events[evt.ID().String()] = event{evt: evt, broadcasted: false} +} + +func (m *mockEventStore) getEvents() []*types.VotableEvent { + var events []*types.VotableEvent + for _, e := range m.events { + events = append(events, e.evt) + } + return events +} +func (m *mockEventStore) GetUnbroadcastedEvents(ctx context.Context) ([]*types.UUID, error) { + var ids []*types.UUID + for _, e := range m.events { + if !e.broadcasted { + ids = append(ids, e.evt.ID()) + } + } + return ids, nil +} + +func (m *mockEventStore) MarkBroadcasted(ctx context.Context, ids []*types.UUID) error { + for _, id := range ids { + if e, ok := m.events[id.String()]; ok { + e.broadcasted = true + m.events[id.String()] = e + } + } + return nil +} + +type mockValidatorStore struct { + valSet []*ktypes.Validator +} + +func newValidatorStore(valSet []*ktypes.Validator) *mockValidatorStore { + return &mockValidatorStore{ + valSet: valSet, + } +} + +func (v *mockValidatorStore) GetValidators() []*ktypes.Validator { + return v.valSet +} + +func (v *mockValidatorStore) ValidatorUpdates() map[string]*ktypes.Validator { + return nil +}