diff --git a/.gitignore b/.gitignore index 39e2d3f67..0ef017b38 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,7 @@ yarn-error.log package-lock.json dist +abi artifacts cache @@ -56,5 +57,5 @@ mantle.iml ops/data/** dist/ - +packages/contracts/test/data/ packages/contracts/abi/ diff --git a/batch-submitter/batch_submitter.go b/batch-submitter/batch_submitter.go index 1da162863..8e44f482d 100644 --- a/batch-submitter/batch_submitter.go +++ b/batch-submitter/batch_submitter.go @@ -2,11 +2,7 @@ package batchsubmitter import ( "context" - ethc "github.com/ethereum/go-ethereum/common" - "github.com/mantlenetworkio/mantle/l2geth/common" - "os" - "time" - + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/log" "github.com/getsentry/sentry-go" "github.com/mantlenetworkio/mantle/batch-submitter/drivers/proposer" @@ -17,6 +13,8 @@ import ( "github.com/mantlenetworkio/mantle/bss-core/metrics" "github.com/mantlenetworkio/mantle/bss-core/txmgr" "github.com/urfave/cli" + "os" + "time" ) // Main is the entrypoint into the batch submitter service. This method returns @@ -135,7 +133,7 @@ func Main(gitVersion string) func(ctx *cli.Context) error { MaxTxSize: cfg.MaxL1TxSize, MaxPlaintextBatchSize: cfg.MaxPlaintextBatchSize, DaUpgradeBlock: cfg.DaUpgradeBlock, - DAAddr: ethc.Address(common.HexToAddress(cfg.DAAddress)), + DAAddr: common.Address(common.HexToAddress(cfg.DAAddress)), CTCAddr: ctcAddress, ChainID: chainID, PrivKey: sequencerPrivKey, @@ -166,8 +164,10 @@ func Main(gitVersion string) func(ctx *cli.Context) error { MaxStateRootElements: cfg.MaxStateRootElements, SCCAddr: sccAddress, CTCAddr: ctcAddress, + FPRollupAddr: common.HexToAddress(cfg.FPRollupAddress), ChainID: chainID, PrivKey: proposerPrivKey, + SccRollback: cfg.EnableSccRollback, }) if err != nil { return err diff --git a/batch-submitter/config.go b/batch-submitter/config.go index 2a40bb252..e2409795d 100644 --- a/batch-submitter/config.go +++ b/batch-submitter/config.go @@ -75,6 +75,9 @@ type Config struct { // SCCAddress is the SCC contract address. SCCAddress string + // FPRollupAddress is the fraud proof rollup contract address. + FPRollupAddress string + // MinL1TxSize is the minimum size in bytes of any L1 transactions generated // by the batch submitter. MinL1TxSize uint64 @@ -201,6 +204,8 @@ type Config struct { // DisableHTTP2 disables HTTP2 support. DisableHTTP2 bool + + EnableSccRollback bool } // NewConfig parses the Config from the provided flags or environment variables. @@ -217,6 +222,7 @@ func NewConfig(ctx *cli.Context) (Config, error) { DAAddress: ctx.GlobalString(flags.DaAddressFlag.Name), CTCAddress: ctx.GlobalString(flags.CTCAddressFlag.Name), SCCAddress: ctx.GlobalString(flags.SCCAddressFlag.Name), + FPRollupAddress: ctx.GlobalString(flags.FPRollupAddressFlag.Name), MinL1TxSize: ctx.GlobalUint64(flags.MinL1TxSizeFlag.Name), MaxL1TxSize: ctx.GlobalUint64(flags.MaxL1TxSizeFlag.Name), MaxPlaintextBatchSize: ctx.GlobalUint64(flags.MaxPlaintextBatchSizeFlag.Name), @@ -249,6 +255,7 @@ func NewConfig(ctx *cli.Context) (Config, error) { MetricsHostname: ctx.GlobalString(flags.MetricsHostnameFlag.Name), MetricsPort: ctx.GlobalUint64(flags.MetricsPortFlag.Name), DisableHTTP2: ctx.GlobalBool(flags.HTTP2DisableFlag.Name), + EnableSccRollback: ctx.GlobalBool(flags.SccRollbackFlag.Name), } err := ValidateConfig(&cfg) diff --git a/batch-submitter/drivers/proposer/driver.go b/batch-submitter/drivers/proposer/driver.go index 437f845b6..b3b81027d 100644 --- a/batch-submitter/drivers/proposer/driver.go +++ b/batch-submitter/drivers/proposer/driver.go @@ -10,6 +10,7 @@ import ( "fmt" "math/big" "strings" + "sync" "github.com/ethereum/go-ethereum/log" @@ -25,6 +26,9 @@ import ( "github.com/mantlenetworkio/mantle/bss-core/drivers" "github.com/mantlenetworkio/mantle/bss-core/metrics" "github.com/mantlenetworkio/mantle/bss-core/txmgr" + fpbindings "github.com/mantlenetworkio/mantle/fraud-proof/bindings" + rollupTypes "github.com/mantlenetworkio/mantle/fraud-proof/rollup/types" + l2types "github.com/mantlenetworkio/mantle/l2geth/core/types" l2ethclient "github.com/mantlenetworkio/mantle/l2geth/ethclient" tss_types "github.com/mantlenetworkio/mantle/tss/common" ) @@ -44,8 +48,10 @@ type Config struct { MinStateRootElements uint64 SCCAddr common.Address CTCAddr common.Address + FPRollupAddr common.Address ChainID *big.Int PrivKey *ecdsa.PrivateKey + SccRollback bool } type Driver struct { @@ -53,9 +59,13 @@ type Driver struct { sccContract *scc.StateCommitmentChain rawSccContract *bind.BoundContract ctcContract *ctc.CanonicalTransactionChain + fpRollup *fpbindings.Rollup + rawFPContract *bind.BoundContract + fpAssertion *fpbindings.AssertionMap walletAddr common.Address rollbackEndBlock *big.Int rollbackEndStateRoot [stateRootSize]byte + once sync.Once metrics *metrics.Base } @@ -74,15 +84,44 @@ func NewDriver(cfg Config) (*Driver, error) { return nil, err } - parsed, err := abi.JSON(strings.NewReader( + fpRollup, err := fpbindings.NewRollup( + cfg.FPRollupAddr, cfg.L1Client, + ) + if err != nil { + return nil, err + } + + assertionAddr, err := fpRollup.Assertions(&bind.CallOpts{}) + if err != nil { + return nil, err + } + + assertionMap, err := fpbindings.NewAssertionMap( + assertionAddr, cfg.L1Client, + ) + if err != nil { + return nil, err + } + + parsedSCC, err := abi.JSON(strings.NewReader( scc.StateCommitmentChainABI, )) if err != nil { return nil, err } + parsedFP, err := abi.JSON(strings.NewReader( + fpbindings.RollupABI, + )) + if err != nil { + return nil, err + } rawSccContract := bind.NewBoundContract( - cfg.SCCAddr, parsed, cfg.L1Client, cfg.L1Client, cfg.L1Client, + cfg.SCCAddr, parsedSCC, cfg.L1Client, cfg.L1Client, cfg.L1Client, + ) + + rawFPContract := bind.NewBoundContract( + cfg.FPRollupAddr, parsedFP, cfg.L1Client, cfg.L1Client, cfg.L1Client, ) walletAddr := crypto.PubkeyToAddress(cfg.PrivKey.PublicKey) @@ -92,9 +131,13 @@ func NewDriver(cfg Config) (*Driver, error) { sccContract: sccContract, rawSccContract: rawSccContract, ctcContract: ctcContract, + fpRollup: fpRollup, + rawFPContract: rawFPContract, + fpAssertion: assertionMap, walletAddr: walletAddr, rollbackEndBlock: big.NewInt(0), rollbackEndStateRoot: [stateRootSize]byte{}, + once: sync.Once{}, metrics: metrics.NewBase("batch_submitter", cfg.Name), }, nil } @@ -177,6 +220,7 @@ func (d *Driver) CraftBatchTx( log.Info(name+" crafting batch tx", "start", start, "end", end, "nonce", nonce) + var blocks []*l2types.Block var stateRoots [][stateRootSize]byte for i := new(big.Int).Set(start); i.Cmp(end) < 0; i.Add(i, bigOne) { // Consume state roots until reach our maximum tx size. @@ -191,6 +235,7 @@ func (d *Driver) CraftBatchTx( return nil, err } + blocks = append(blocks, block) stateRoots = append(stateRoots, block.Root()) } @@ -220,23 +265,11 @@ func (d *Driver) CraftBatchTx( blockOffset := new(big.Int).SetUint64(d.cfg.BlockOffset) offsetStartsAtIndex := new(big.Int).Sub(start, blockOffset) // Assembly data request tss node signature - tssReqParams := tss_types.SignStateRequest{ - StartBlock: start.String(), - OffsetStartsAtIndex: offsetStartsAtIndex.String(), - StateRoots: stateRoots, - } - tssReponseBytes, err := d.cfg.TssClient.GetSignStateBatch(tssReqParams) + tssResponse, err := d.RequestTssSignature(0, start, offsetStartsAtIndex, "", stateRoots) if err != nil { log.Error(name+" get tss manager signature fail", "err", err) return nil, err } - var tssResponse tssClient.TssResponse - err = json.Unmarshal(tssReponseBytes, &tssResponse) - if err != nil { - log.Error(name+" failed to unmarshal response from tss", "err", err) - return nil, err - } - log.Info(name+" append log", "stateRoots size ", len(stateRoots), "offsetStartsAtIndex", offsetStartsAtIndex, "signature", hex.EncodeToString(tssResponse.Signature), "rollback", tssResponse.RollBack) log.Info(name+" signature ", "len", len(tssResponse.Signature)) var tx *types.Transaction @@ -253,9 +286,30 @@ func (d *Driver) CraftBatchTx( d.rollbackEndBlock = end tx, err = d.sccContract.RollBackL2Chain(opts, start, offsetStartsAtIndex, tssResponse.Signature) } else { - tx, err = d.sccContract.AppendStateBatch( - opts, stateRoots, offsetStartsAtIndex, tssResponse.Signature, - ) + if len(d.cfg.FPRollupAddr.Bytes()) != 0 { + log.Info("append state with fraud proof") + // ##### FRAUD-PROOF modify ##### + // check stake initialised + owner, _ := d.fpRollup.Owner(&bind.CallOpts{}) + assertionInit, _ := d.fpAssertion.Assertions(&bind.CallOpts{}, new(big.Int).SetUint64(0)) + if !bytes.Equal(owner.Bytes(), opts.From.Bytes()) || bytes.Equal(assertionInit.Deadline.Bytes(), common.Big0.Bytes()) { + log.Error("fraud proof not init", "owner", owner, "expect", opts.From) + return nil, nil + } + // Append state batch + tx, err = d.FraudProofAppendStateBatch( + opts, stateRoots, offsetStartsAtIndex, tssResponse.Signature, blocks, + ) + if err != nil { + log.Error("fraud proof append state batch is failed", "err", err) + } + // ##### FRAUD-PROOF modify ##### // + } else { + log.Info("append state with scc") + tx, err = d.sccContract.AppendStateBatch( + opts, stateRoots, offsetStartsAtIndex, tssResponse.Signature, + ) + } } switch { @@ -276,9 +330,100 @@ func (d *Driver) CraftBatchTx( opts, start, offsetStartsAtIndex, tssResponse.Signature, ) } else { - return d.sccContract.AppendStateBatch( - opts, stateRoots, offsetStartsAtIndex, tssResponse.Signature, - ) + if len(d.cfg.FPRollupAddr.Bytes()) != 0 { + log.Info("append state with fraud proof by gas tip cap") + // ##### FRAUD-PROOF modify ##### + // check stake initialised + // check is in challenge status + challengeContext, err := d.fpRollup.ChallengeCtx(&bind.CallOpts{}) + if err != nil { + return nil, err + } + isInChallenge := challengeContext.DefenderAssertionID.Uint64() != 0 && !challengeContext.Completed + if isInChallenge { + log.Warn("currently in challenge, can't submit new assertion") + return nil, nil + } + // check rollback status + if d.cfg.SccRollback { + fpChallenge, err := fpbindings.NewChallenge( + challengeContext.ChallengeAddress, d.cfg.L1Client, + ) + if err != nil { + return nil, err + } + alreadyRollback, err := fpChallenge.Rollback(&bind.CallOpts{}) + if err != nil { + return nil, err + } + challenger, err := fpChallenge.Challenger(&bind.CallOpts{}) + if err != nil { + return nil, err + } + winner, err := fpChallenge.Winner(&bind.CallOpts{}) + if err != nil { + return nil, err + } + startInboxSize, err := fpChallenge.StartInboxSize(&bind.CallOpts{}) + if err != nil { + return nil, err + } + if challengeContext.Completed && !alreadyRollback && bytes.Equal(challenger[:], winner[:]) { + tssResponse, err = d.RequestTssSignature(1, startInboxSize, offsetStartsAtIndex, challengeContext.ChallengeAddress.String(), nil) + if err != nil { + return nil, err + } + if tssResponse.RollBack { + // delete scc batch states one by one + totalBatches, err := d.sccContract.GetTotalBatches(&bind.CallOpts{}) + if err != nil { + return nil, err + } + + filter, err := d.sccContract.FilterStateBatchAppended(&bind.FilterOpts{}, []*big.Int{totalBatches}) + if err != nil { + return nil, err + } + if filter.Event.PrevTotalElements.Cmp(startInboxSize) <= 0 { + var rollbackTx *types.Transaction + var rollbackErr error + // must ensure all those action done properly until rollback finished + // or RollBackL2Chain will happen multiple times + d.once.Do( + func() { + rollbackTx, rollbackErr = d.sccContract.RollBackL2Chain( + opts, startInboxSize, offsetStartsAtIndex, tssResponse.Signature, + ) + }, + ) + if rollbackTx != nil || rollbackErr != nil { + return rollbackTx, rollbackErr + } else { + return fpChallenge.SetRollback(opts) + } + } + return d.sccContract.DeleteStateBatch(opts, scc.LibBVMCodecChainBatchHeader{ + BatchIndex: filter.Event.BatchIndex, + BatchRoot: filter.Event.BatchRoot, + BatchSize: filter.Event.BatchSize, + PrevTotalElements: filter.Event.PrevTotalElements, + Signature: filter.Event.Signature, + ExtraData: filter.Event.ExtraData, + }) + } + } + } + // rollup assertion + return d.FraudProofAppendStateBatch( + opts, stateRoots, offsetStartsAtIndex, tssResponse.Signature, blocks, + ) + // ##### FRAUD-PROOF modify ##### // + } else { + log.Info("append state with scc by gas tip cap") + return d.sccContract.AppendStateBatch( + opts, stateRoots, offsetStartsAtIndex, tssResponse.Signature, + ) + } } default: return nil, err @@ -293,6 +438,8 @@ func (d *Driver) UpdateGasPrice( ctx context.Context, tx *types.Transaction, ) (*types.Transaction, error) { + var finalTx *types.Transaction + var err error opts, err := bind.NewKeyedTransactorWithChainID( d.cfg.PrivKey, d.cfg.ChainID, @@ -304,7 +451,15 @@ func (d *Driver) UpdateGasPrice( opts.Nonce = new(big.Int).SetUint64(tx.Nonce()) opts.NoSend = true - finalTx, err := d.rawSccContract.RawTransact(opts, tx.Data()) + if len(d.cfg.FPRollupAddr.Bytes()) != 0 { + // ##### FRAUD-PROOF modify ##### + log.Info("get RawTransact from Fraud Proof") + finalTx, err = d.rawFPContract.RawTransact(opts, tx.Data()) + // ##### FRAUD-PROOF modify ##### // + } else { + log.Info("get RawTransact from SCC") + finalTx, err = d.rawSccContract.RawTransact(opts, tx.Data()) + } switch { case err == nil: return finalTx, nil @@ -319,7 +474,16 @@ func (d *Driver) UpdateGasPrice( log.Warn(d.cfg.Name + " eth_maxPriorityFeePerGas is unsupported " + "by current backend, using fallback gasTipCap") opts.GasTipCap = drivers.FallbackGasTipCap - return d.rawSccContract.RawTransact(opts, tx.Data()) + + if len(d.cfg.FPRollupAddr.Bytes()) != 0 { + // ##### FRAUD-PROOF modify ##### + log.Info("get RawTransact from Fraud Proof by gas tip cap") + return d.rawFPContract.RawTransact(opts, tx.Data()) + // ##### FRAUD-PROOF modify ##### // + } else { + log.Info("get RawTransact from SCC by gas tip cap") + return d.rawSccContract.RawTransact(opts, tx.Data()) + } default: return nil, err @@ -334,3 +498,72 @@ func (d *Driver) SendTransaction( ) error { return d.cfg.L1Client.SendTransaction(ctx, tx) } + +func (d *Driver) FraudProofAppendStateBatch(opts *bind.TransactOpts, batch [][32]byte, shouldStartAtElement *big.Int, signature []byte, blocks []*l2types.Block) (*types.Transaction, error) { + var latestAssertion rollupTypes.Assertion + var staker rollupTypes.Staker + if ret, err := d.fpRollup.Stakers(&bind.CallOpts{}, opts.From); err != nil { + return nil, err + } else { + staker.IsStaked = ret.IsStaked + staker.AmountStaked = ret.AmountStaked + staker.AssertionID = ret.AssertionID + staker.CurrentChallenge = ret.CurrentChallenge + } + if ret, err := d.fpAssertion.Assertions(&bind.CallOpts{}, staker.AssertionID); err != nil { + return nil, err + } else { + latestAssertion.ID = staker.AssertionID + latestAssertion.VmHash = ret.StateHash + latestAssertion.InboxSize = ret.InboxSize + latestAssertion.Parent = ret.Parent + latestAssertion.Deadline = ret.Deadline + latestAssertion.ProposalTime = ret.ProposalTime + } + + txBatch := rollupTypes.NewTxBatch(blocks, uint64(len(blocks))) + + // First assertion check + lastCreatedAssertionID, err := d.fpRollup.LastCreatedAssertionID(&bind.CallOpts{}) + if err != nil { + return nil, err + } + if lastCreatedAssertionID.Uint64() != 0 && latestAssertion.InboxSize.Uint64()+uint64(len(txBatch.Txs)) != txBatch.LastBlockNumber() { + log.Error("Online total InboxSize not match with local batch's LatestBlockNumber") + return nil, errors.New("Online total InboxSize not match with local batch's LatestBlockNumber") + } + + assertion := txBatch.ToAssertion(&latestAssertion) + + log.Debug("show assertion", "VmHash", assertion.VmHash.String()) + log.Debug("show assertion", "InboxSize", assertion.InboxSize) + log.Debug("show assertion", "Batch", batch) + log.Debug("show assertion", "ShouldStartAtElement", shouldStartAtElement.String()) + log.Debug("show assertion", "Signature", hex.EncodeToString(signature)) + + // create assertion + return d.fpRollup.CreateAssertionWithStateBatch( + opts, assertion.VmHash, assertion.InboxSize, batch, shouldStartAtElement, signature) +} + +func (d *Driver) RequestTssSignature(requestType uint64, start, offsetStartsAtIndex *big.Int, challenge string, stateRoots [][stateRootSize]byte) (*tssClient.TssResponse, error) { + var tssResponse tssClient.TssResponse + tssReqParams := tss_types.SignStateRequest{ + Type: requestType, + StartBlock: start.String(), + OffsetStartsAtIndex: offsetStartsAtIndex.String(), + Challenge: challenge, + StateRoots: stateRoots, + } + tssReponseBytes, err := d.cfg.TssClient.GetSignStateBatch(tssReqParams) + if err != nil { + log.Error("get tss manager signature fail", "err", err) + return nil, err + } + err = json.Unmarshal(tssReponseBytes, &tssResponse) + if err != nil { + log.Error("failed to unmarshal response from tss", "err", err) + return nil, err + } + return &tssResponse, nil +} diff --git a/batch-submitter/drivers/sequencer/driver.go b/batch-submitter/drivers/sequencer/driver.go index 26d1c4856..27c671ee3 100644 --- a/batch-submitter/drivers/sequencer/driver.go +++ b/batch-submitter/drivers/sequencer/driver.go @@ -15,6 +15,7 @@ import ( "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/log" + "github.com/mantlenetworkio/mantle/batch-submitter/bindings/ctc" "github.com/mantlenetworkio/mantle/batch-submitter/bindings/da" "github.com/mantlenetworkio/mantle/bss-core/drivers" diff --git a/batch-submitter/drivers/sequencer/metrics.go b/batch-submitter/drivers/sequencer/metrics.go index 58fa003d8..ddc4ffc77 100644 --- a/batch-submitter/drivers/sequencer/metrics.go +++ b/batch-submitter/drivers/sequencer/metrics.go @@ -2,6 +2,7 @@ package sequencer import ( "github.com/mantlenetworkio/mantle/bss-core/metrics" + "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" ) diff --git a/batch-submitter/flags/flags.go b/batch-submitter/flags/flags.go index 7f160cbe1..2e27d93f4 100644 --- a/batch-submitter/flags/flags.go +++ b/batch-submitter/flags/flags.go @@ -70,6 +70,12 @@ var ( Required: true, EnvVar: "SCC_ADDRESS", } + FPRollupAddressFlag = cli.StringFlag{ + Name: "fraud-proof-rollup-address", + Usage: "Address of the FraudProof Rollup contract", + Required: true, + EnvVar: "FP_ROLLUP_ADDRESS", + } MinL1TxSizeFlag = cli.Uint64Flag{ Name: "min-l1-tx-size", Usage: "Minimum size in bytes of any L1 transaction that gets " + @@ -268,6 +274,11 @@ var ( Usage: "Whether or not to disable HTTP/2 support.", EnvVar: prefixEnvVar("HTTP2_DISABLE"), } + SccRollbackFlag = cli.BoolFlag{ + Name: "EnableSccRollbackFlag", + Usage: "Whether or not to enable scc rollback.", + EnvVar: prefixEnvVar("SCC_ROLLBACK"), + } ) var requiredFlags = []cli.Flag{ @@ -280,6 +291,7 @@ var requiredFlags = []cli.Flag{ DaUpgradeBlockFlag, CTCAddressFlag, SCCAddressFlag, + FPRollupAddressFlag, MinL1TxSizeFlag, MaxL1TxSizeFlag, MaxPlaintextBatchSizeFlag, diff --git a/datalayr-mantle b/datalayr-mantle index 5f6cdcbbc..7c5c35015 160000 --- a/datalayr-mantle +++ b/datalayr-mantle @@ -1 +1 @@ -Subproject commit 5f6cdcbbcbde680abaae217ca2209666243a18aa +Subproject commit 7c5c350152ef4021dbff649aae5621c4767eae18 diff --git a/eignlayr-contracts-mantle b/eignlayr-contracts-mantle index 15bb22aa2..590abb538 160000 --- a/eignlayr-contracts-mantle +++ b/eignlayr-contracts-mantle @@ -1 +1 @@ -Subproject commit 15bb22aa2d4942fcb0a838eba9853f50db5c319f +Subproject commit 590abb53876a2e00a739bdcf319d4e14173da328 diff --git a/fraud-proof/bindings/AssertionMap.go b/fraud-proof/bindings/AssertionMap.go new file mode 100644 index 000000000..69ee0fa74 --- /dev/null +++ b/fraud-proof/bindings/AssertionMap.go @@ -0,0 +1,737 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package bindings + +import ( + "errors" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" +) + +// Reference imports to suppress errors if they are not otherwise used. +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription +) + +// AssertionMapMetaData contains all meta data concerning the AssertionMap contract. +var AssertionMapMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"ChildInboxSizeMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"rollup\",\"type\":\"address\"}],\"name\":\"NotRollup\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SiblingStateHashExists\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"assertions\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"stateHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"inboxSize\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"parent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"proposalTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"numStakers\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"childInboxSize\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"assertionID\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"stateHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"inboxSize\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"parentID\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"createAssertion\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"assertionID\",\"type\":\"uint256\"}],\"name\":\"deleteAssertion\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"assertionID\",\"type\":\"uint256\"}],\"name\":\"getDeadline\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"assertionID\",\"type\":\"uint256\"}],\"name\":\"getInboxSize\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"assertionID\",\"type\":\"uint256\"}],\"name\":\"getNumStakers\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"assertionID\",\"type\":\"uint256\"}],\"name\":\"getParentID\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"assertionID\",\"type\":\"uint256\"}],\"name\":\"getProposalTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"assertionID\",\"type\":\"uint256\"}],\"name\":\"getStateHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"assertionID\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"stakerAddress\",\"type\":\"address\"}],\"name\":\"isStaker\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"rollupAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_rollupAddress\",\"type\":\"address\"}],\"name\":\"setRollupAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"assertionID\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"stakerAddress\",\"type\":\"address\"}],\"name\":\"stakeOnAssertion\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", +} + +// AssertionMapABI is the input ABI used to generate the binding from. +// Deprecated: Use AssertionMapMetaData.ABI instead. +var AssertionMapABI = AssertionMapMetaData.ABI + +// AssertionMap is an auto generated Go binding around an Ethereum contract. +type AssertionMap struct { + AssertionMapCaller // Read-only binding to the contract + AssertionMapTransactor // Write-only binding to the contract + AssertionMapFilterer // Log filterer for contract events +} + +// AssertionMapCaller is an auto generated read-only Go binding around an Ethereum contract. +type AssertionMapCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// AssertionMapTransactor is an auto generated write-only Go binding around an Ethereum contract. +type AssertionMapTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// AssertionMapFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type AssertionMapFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// AssertionMapSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type AssertionMapSession struct { + Contract *AssertionMap // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// AssertionMapCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type AssertionMapCallerSession struct { + Contract *AssertionMapCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// AssertionMapTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type AssertionMapTransactorSession struct { + Contract *AssertionMapTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// AssertionMapRaw is an auto generated low-level Go binding around an Ethereum contract. +type AssertionMapRaw struct { + Contract *AssertionMap // Generic contract binding to access the raw methods on +} + +// AssertionMapCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type AssertionMapCallerRaw struct { + Contract *AssertionMapCaller // Generic read-only contract binding to access the raw methods on +} + +// AssertionMapTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type AssertionMapTransactorRaw struct { + Contract *AssertionMapTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewAssertionMap creates a new instance of AssertionMap, bound to a specific deployed contract. +func NewAssertionMap(address common.Address, backend bind.ContractBackend) (*AssertionMap, error) { + contract, err := bindAssertionMap(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &AssertionMap{AssertionMapCaller: AssertionMapCaller{contract: contract}, AssertionMapTransactor: AssertionMapTransactor{contract: contract}, AssertionMapFilterer: AssertionMapFilterer{contract: contract}}, nil +} + +// NewAssertionMapCaller creates a new read-only instance of AssertionMap, bound to a specific deployed contract. +func NewAssertionMapCaller(address common.Address, caller bind.ContractCaller) (*AssertionMapCaller, error) { + contract, err := bindAssertionMap(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &AssertionMapCaller{contract: contract}, nil +} + +// NewAssertionMapTransactor creates a new write-only instance of AssertionMap, bound to a specific deployed contract. +func NewAssertionMapTransactor(address common.Address, transactor bind.ContractTransactor) (*AssertionMapTransactor, error) { + contract, err := bindAssertionMap(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &AssertionMapTransactor{contract: contract}, nil +} + +// NewAssertionMapFilterer creates a new log filterer instance of AssertionMap, bound to a specific deployed contract. +func NewAssertionMapFilterer(address common.Address, filterer bind.ContractFilterer) (*AssertionMapFilterer, error) { + contract, err := bindAssertionMap(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &AssertionMapFilterer{contract: contract}, nil +} + +// bindAssertionMap binds a generic wrapper to an already deployed contract. +func bindAssertionMap(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := abi.JSON(strings.NewReader(AssertionMapABI)) + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_AssertionMap *AssertionMapRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _AssertionMap.Contract.AssertionMapCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_AssertionMap *AssertionMapRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _AssertionMap.Contract.AssertionMapTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_AssertionMap *AssertionMapRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _AssertionMap.Contract.AssertionMapTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_AssertionMap *AssertionMapCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _AssertionMap.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_AssertionMap *AssertionMapTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _AssertionMap.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_AssertionMap *AssertionMapTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _AssertionMap.Contract.contract.Transact(opts, method, params...) +} + +// Assertions is a free data retrieval call binding the contract method 0x524232f6. +// +// Solidity: function assertions(uint256 ) view returns(bytes32 stateHash, uint256 inboxSize, uint256 parent, uint256 deadline, uint256 proposalTime, uint256 numStakers, uint256 childInboxSize) +func (_AssertionMap *AssertionMapCaller) Assertions(opts *bind.CallOpts, arg0 *big.Int) (struct { + StateHash [32]byte + InboxSize *big.Int + Parent *big.Int + Deadline *big.Int + ProposalTime *big.Int + NumStakers *big.Int + ChildInboxSize *big.Int +}, error) { + var out []interface{} + err := _AssertionMap.contract.Call(opts, &out, "assertions", arg0) + + outstruct := new(struct { + StateHash [32]byte + InboxSize *big.Int + Parent *big.Int + Deadline *big.Int + ProposalTime *big.Int + NumStakers *big.Int + ChildInboxSize *big.Int + }) + if err != nil { + return *outstruct, err + } + + outstruct.StateHash = *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + outstruct.InboxSize = *abi.ConvertType(out[1], new(*big.Int)).(**big.Int) + outstruct.Parent = *abi.ConvertType(out[2], new(*big.Int)).(**big.Int) + outstruct.Deadline = *abi.ConvertType(out[3], new(*big.Int)).(**big.Int) + outstruct.ProposalTime = *abi.ConvertType(out[4], new(*big.Int)).(**big.Int) + outstruct.NumStakers = *abi.ConvertType(out[5], new(*big.Int)).(**big.Int) + outstruct.ChildInboxSize = *abi.ConvertType(out[6], new(*big.Int)).(**big.Int) + + return *outstruct, err + +} + +// Assertions is a free data retrieval call binding the contract method 0x524232f6. +// +// Solidity: function assertions(uint256 ) view returns(bytes32 stateHash, uint256 inboxSize, uint256 parent, uint256 deadline, uint256 proposalTime, uint256 numStakers, uint256 childInboxSize) +func (_AssertionMap *AssertionMapSession) Assertions(arg0 *big.Int) (struct { + StateHash [32]byte + InboxSize *big.Int + Parent *big.Int + Deadline *big.Int + ProposalTime *big.Int + NumStakers *big.Int + ChildInboxSize *big.Int +}, error) { + return _AssertionMap.Contract.Assertions(&_AssertionMap.CallOpts, arg0) +} + +// Assertions is a free data retrieval call binding the contract method 0x524232f6. +// +// Solidity: function assertions(uint256 ) view returns(bytes32 stateHash, uint256 inboxSize, uint256 parent, uint256 deadline, uint256 proposalTime, uint256 numStakers, uint256 childInboxSize) +func (_AssertionMap *AssertionMapCallerSession) Assertions(arg0 *big.Int) (struct { + StateHash [32]byte + InboxSize *big.Int + Parent *big.Int + Deadline *big.Int + ProposalTime *big.Int + NumStakers *big.Int + ChildInboxSize *big.Int +}, error) { + return _AssertionMap.Contract.Assertions(&_AssertionMap.CallOpts, arg0) +} + +// GetDeadline is a free data retrieval call binding the contract method 0x82862275. +// +// Solidity: function getDeadline(uint256 assertionID) view returns(uint256) +func (_AssertionMap *AssertionMapCaller) GetDeadline(opts *bind.CallOpts, assertionID *big.Int) (*big.Int, error) { + var out []interface{} + err := _AssertionMap.contract.Call(opts, &out, "getDeadline", assertionID) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// GetDeadline is a free data retrieval call binding the contract method 0x82862275. +// +// Solidity: function getDeadline(uint256 assertionID) view returns(uint256) +func (_AssertionMap *AssertionMapSession) GetDeadline(assertionID *big.Int) (*big.Int, error) { + return _AssertionMap.Contract.GetDeadline(&_AssertionMap.CallOpts, assertionID) +} + +// GetDeadline is a free data retrieval call binding the contract method 0x82862275. +// +// Solidity: function getDeadline(uint256 assertionID) view returns(uint256) +func (_AssertionMap *AssertionMapCallerSession) GetDeadline(assertionID *big.Int) (*big.Int, error) { + return _AssertionMap.Contract.GetDeadline(&_AssertionMap.CallOpts, assertionID) +} + +// GetInboxSize is a free data retrieval call binding the contract method 0x2b27e93b. +// +// Solidity: function getInboxSize(uint256 assertionID) view returns(uint256) +func (_AssertionMap *AssertionMapCaller) GetInboxSize(opts *bind.CallOpts, assertionID *big.Int) (*big.Int, error) { + var out []interface{} + err := _AssertionMap.contract.Call(opts, &out, "getInboxSize", assertionID) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// GetInboxSize is a free data retrieval call binding the contract method 0x2b27e93b. +// +// Solidity: function getInboxSize(uint256 assertionID) view returns(uint256) +func (_AssertionMap *AssertionMapSession) GetInboxSize(assertionID *big.Int) (*big.Int, error) { + return _AssertionMap.Contract.GetInboxSize(&_AssertionMap.CallOpts, assertionID) +} + +// GetInboxSize is a free data retrieval call binding the contract method 0x2b27e93b. +// +// Solidity: function getInboxSize(uint256 assertionID) view returns(uint256) +func (_AssertionMap *AssertionMapCallerSession) GetInboxSize(assertionID *big.Int) (*big.Int, error) { + return _AssertionMap.Contract.GetInboxSize(&_AssertionMap.CallOpts, assertionID) +} + +// GetNumStakers is a free data retrieval call binding the contract method 0x366b2b69. +// +// Solidity: function getNumStakers(uint256 assertionID) view returns(uint256) +func (_AssertionMap *AssertionMapCaller) GetNumStakers(opts *bind.CallOpts, assertionID *big.Int) (*big.Int, error) { + var out []interface{} + err := _AssertionMap.contract.Call(opts, &out, "getNumStakers", assertionID) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// GetNumStakers is a free data retrieval call binding the contract method 0x366b2b69. +// +// Solidity: function getNumStakers(uint256 assertionID) view returns(uint256) +func (_AssertionMap *AssertionMapSession) GetNumStakers(assertionID *big.Int) (*big.Int, error) { + return _AssertionMap.Contract.GetNumStakers(&_AssertionMap.CallOpts, assertionID) +} + +// GetNumStakers is a free data retrieval call binding the contract method 0x366b2b69. +// +// Solidity: function getNumStakers(uint256 assertionID) view returns(uint256) +func (_AssertionMap *AssertionMapCallerSession) GetNumStakers(assertionID *big.Int) (*big.Int, error) { + return _AssertionMap.Contract.GetNumStakers(&_AssertionMap.CallOpts, assertionID) +} + +// GetParentID is a free data retrieval call binding the contract method 0x30b94770. +// +// Solidity: function getParentID(uint256 assertionID) view returns(uint256) +func (_AssertionMap *AssertionMapCaller) GetParentID(opts *bind.CallOpts, assertionID *big.Int) (*big.Int, error) { + var out []interface{} + err := _AssertionMap.contract.Call(opts, &out, "getParentID", assertionID) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// GetParentID is a free data retrieval call binding the contract method 0x30b94770. +// +// Solidity: function getParentID(uint256 assertionID) view returns(uint256) +func (_AssertionMap *AssertionMapSession) GetParentID(assertionID *big.Int) (*big.Int, error) { + return _AssertionMap.Contract.GetParentID(&_AssertionMap.CallOpts, assertionID) +} + +// GetParentID is a free data retrieval call binding the contract method 0x30b94770. +// +// Solidity: function getParentID(uint256 assertionID) view returns(uint256) +func (_AssertionMap *AssertionMapCallerSession) GetParentID(assertionID *big.Int) (*big.Int, error) { + return _AssertionMap.Contract.GetParentID(&_AssertionMap.CallOpts, assertionID) +} + +// GetProposalTime is a free data retrieval call binding the contract method 0x4e04886d. +// +// Solidity: function getProposalTime(uint256 assertionID) view returns(uint256) +func (_AssertionMap *AssertionMapCaller) GetProposalTime(opts *bind.CallOpts, assertionID *big.Int) (*big.Int, error) { + var out []interface{} + err := _AssertionMap.contract.Call(opts, &out, "getProposalTime", assertionID) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// GetProposalTime is a free data retrieval call binding the contract method 0x4e04886d. +// +// Solidity: function getProposalTime(uint256 assertionID) view returns(uint256) +func (_AssertionMap *AssertionMapSession) GetProposalTime(assertionID *big.Int) (*big.Int, error) { + return _AssertionMap.Contract.GetProposalTime(&_AssertionMap.CallOpts, assertionID) +} + +// GetProposalTime is a free data retrieval call binding the contract method 0x4e04886d. +// +// Solidity: function getProposalTime(uint256 assertionID) view returns(uint256) +func (_AssertionMap *AssertionMapCallerSession) GetProposalTime(assertionID *big.Int) (*big.Int, error) { + return _AssertionMap.Contract.GetProposalTime(&_AssertionMap.CallOpts, assertionID) +} + +// GetStateHash is a free data retrieval call binding the contract method 0x54823e66. +// +// Solidity: function getStateHash(uint256 assertionID) view returns(bytes32) +func (_AssertionMap *AssertionMapCaller) GetStateHash(opts *bind.CallOpts, assertionID *big.Int) ([32]byte, error) { + var out []interface{} + err := _AssertionMap.contract.Call(opts, &out, "getStateHash", assertionID) + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +// GetStateHash is a free data retrieval call binding the contract method 0x54823e66. +// +// Solidity: function getStateHash(uint256 assertionID) view returns(bytes32) +func (_AssertionMap *AssertionMapSession) GetStateHash(assertionID *big.Int) ([32]byte, error) { + return _AssertionMap.Contract.GetStateHash(&_AssertionMap.CallOpts, assertionID) +} + +// GetStateHash is a free data retrieval call binding the contract method 0x54823e66. +// +// Solidity: function getStateHash(uint256 assertionID) view returns(bytes32) +func (_AssertionMap *AssertionMapCallerSession) GetStateHash(assertionID *big.Int) ([32]byte, error) { + return _AssertionMap.Contract.GetStateHash(&_AssertionMap.CallOpts, assertionID) +} + +// IsStaker is a free data retrieval call binding the contract method 0x873fd089. +// +// Solidity: function isStaker(uint256 assertionID, address stakerAddress) view returns(bool) +func (_AssertionMap *AssertionMapCaller) IsStaker(opts *bind.CallOpts, assertionID *big.Int, stakerAddress common.Address) (bool, error) { + var out []interface{} + err := _AssertionMap.contract.Call(opts, &out, "isStaker", assertionID, stakerAddress) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// IsStaker is a free data retrieval call binding the contract method 0x873fd089. +// +// Solidity: function isStaker(uint256 assertionID, address stakerAddress) view returns(bool) +func (_AssertionMap *AssertionMapSession) IsStaker(assertionID *big.Int, stakerAddress common.Address) (bool, error) { + return _AssertionMap.Contract.IsStaker(&_AssertionMap.CallOpts, assertionID, stakerAddress) +} + +// IsStaker is a free data retrieval call binding the contract method 0x873fd089. +// +// Solidity: function isStaker(uint256 assertionID, address stakerAddress) view returns(bool) +func (_AssertionMap *AssertionMapCallerSession) IsStaker(assertionID *big.Int, stakerAddress common.Address) (bool, error) { + return _AssertionMap.Contract.IsStaker(&_AssertionMap.CallOpts, assertionID, stakerAddress) +} + +// RollupAddress is a free data retrieval call binding the contract method 0x5ec6a8df. +// +// Solidity: function rollupAddress() view returns(address) +func (_AssertionMap *AssertionMapCaller) RollupAddress(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _AssertionMap.contract.Call(opts, &out, "rollupAddress") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// RollupAddress is a free data retrieval call binding the contract method 0x5ec6a8df. +// +// Solidity: function rollupAddress() view returns(address) +func (_AssertionMap *AssertionMapSession) RollupAddress() (common.Address, error) { + return _AssertionMap.Contract.RollupAddress(&_AssertionMap.CallOpts) +} + +// RollupAddress is a free data retrieval call binding the contract method 0x5ec6a8df. +// +// Solidity: function rollupAddress() view returns(address) +func (_AssertionMap *AssertionMapCallerSession) RollupAddress() (common.Address, error) { + return _AssertionMap.Contract.RollupAddress(&_AssertionMap.CallOpts) +} + +// CreateAssertion is a paid mutator transaction binding the contract method 0x42281584. +// +// Solidity: function createAssertion(uint256 assertionID, bytes32 stateHash, uint256 inboxSize, uint256 parentID, uint256 deadline) returns() +func (_AssertionMap *AssertionMapTransactor) CreateAssertion(opts *bind.TransactOpts, assertionID *big.Int, stateHash [32]byte, inboxSize *big.Int, parentID *big.Int, deadline *big.Int) (*types.Transaction, error) { + return _AssertionMap.contract.Transact(opts, "createAssertion", assertionID, stateHash, inboxSize, parentID, deadline) +} + +// CreateAssertion is a paid mutator transaction binding the contract method 0x42281584. +// +// Solidity: function createAssertion(uint256 assertionID, bytes32 stateHash, uint256 inboxSize, uint256 parentID, uint256 deadline) returns() +func (_AssertionMap *AssertionMapSession) CreateAssertion(assertionID *big.Int, stateHash [32]byte, inboxSize *big.Int, parentID *big.Int, deadline *big.Int) (*types.Transaction, error) { + return _AssertionMap.Contract.CreateAssertion(&_AssertionMap.TransactOpts, assertionID, stateHash, inboxSize, parentID, deadline) +} + +// CreateAssertion is a paid mutator transaction binding the contract method 0x42281584. +// +// Solidity: function createAssertion(uint256 assertionID, bytes32 stateHash, uint256 inboxSize, uint256 parentID, uint256 deadline) returns() +func (_AssertionMap *AssertionMapTransactorSession) CreateAssertion(assertionID *big.Int, stateHash [32]byte, inboxSize *big.Int, parentID *big.Int, deadline *big.Int) (*types.Transaction, error) { + return _AssertionMap.Contract.CreateAssertion(&_AssertionMap.TransactOpts, assertionID, stateHash, inboxSize, parentID, deadline) +} + +// DeleteAssertion is a paid mutator transaction binding the contract method 0xd8a4e5af. +// +// Solidity: function deleteAssertion(uint256 assertionID) returns() +func (_AssertionMap *AssertionMapTransactor) DeleteAssertion(opts *bind.TransactOpts, assertionID *big.Int) (*types.Transaction, error) { + return _AssertionMap.contract.Transact(opts, "deleteAssertion", assertionID) +} + +// DeleteAssertion is a paid mutator transaction binding the contract method 0xd8a4e5af. +// +// Solidity: function deleteAssertion(uint256 assertionID) returns() +func (_AssertionMap *AssertionMapSession) DeleteAssertion(assertionID *big.Int) (*types.Transaction, error) { + return _AssertionMap.Contract.DeleteAssertion(&_AssertionMap.TransactOpts, assertionID) +} + +// DeleteAssertion is a paid mutator transaction binding the contract method 0xd8a4e5af. +// +// Solidity: function deleteAssertion(uint256 assertionID) returns() +func (_AssertionMap *AssertionMapTransactorSession) DeleteAssertion(assertionID *big.Int) (*types.Transaction, error) { + return _AssertionMap.Contract.DeleteAssertion(&_AssertionMap.TransactOpts, assertionID) +} + +// Initialize is a paid mutator transaction binding the contract method 0x8129fc1c. +// +// Solidity: function initialize() returns() +func (_AssertionMap *AssertionMapTransactor) Initialize(opts *bind.TransactOpts) (*types.Transaction, error) { + return _AssertionMap.contract.Transact(opts, "initialize") +} + +// Initialize is a paid mutator transaction binding the contract method 0x8129fc1c. +// +// Solidity: function initialize() returns() +func (_AssertionMap *AssertionMapSession) Initialize() (*types.Transaction, error) { + return _AssertionMap.Contract.Initialize(&_AssertionMap.TransactOpts) +} + +// Initialize is a paid mutator transaction binding the contract method 0x8129fc1c. +// +// Solidity: function initialize() returns() +func (_AssertionMap *AssertionMapTransactorSession) Initialize() (*types.Transaction, error) { + return _AssertionMap.Contract.Initialize(&_AssertionMap.TransactOpts) +} + +// SetRollupAddress is a paid mutator transaction binding the contract method 0x07663706. +// +// Solidity: function setRollupAddress(address _rollupAddress) returns() +func (_AssertionMap *AssertionMapTransactor) SetRollupAddress(opts *bind.TransactOpts, _rollupAddress common.Address) (*types.Transaction, error) { + return _AssertionMap.contract.Transact(opts, "setRollupAddress", _rollupAddress) +} + +// SetRollupAddress is a paid mutator transaction binding the contract method 0x07663706. +// +// Solidity: function setRollupAddress(address _rollupAddress) returns() +func (_AssertionMap *AssertionMapSession) SetRollupAddress(_rollupAddress common.Address) (*types.Transaction, error) { + return _AssertionMap.Contract.SetRollupAddress(&_AssertionMap.TransactOpts, _rollupAddress) +} + +// SetRollupAddress is a paid mutator transaction binding the contract method 0x07663706. +// +// Solidity: function setRollupAddress(address _rollupAddress) returns() +func (_AssertionMap *AssertionMapTransactorSession) SetRollupAddress(_rollupAddress common.Address) (*types.Transaction, error) { + return _AssertionMap.Contract.SetRollupAddress(&_AssertionMap.TransactOpts, _rollupAddress) +} + +// StakeOnAssertion is a paid mutator transaction binding the contract method 0xa832c3ae. +// +// Solidity: function stakeOnAssertion(uint256 assertionID, address stakerAddress) returns() +func (_AssertionMap *AssertionMapTransactor) StakeOnAssertion(opts *bind.TransactOpts, assertionID *big.Int, stakerAddress common.Address) (*types.Transaction, error) { + return _AssertionMap.contract.Transact(opts, "stakeOnAssertion", assertionID, stakerAddress) +} + +// StakeOnAssertion is a paid mutator transaction binding the contract method 0xa832c3ae. +// +// Solidity: function stakeOnAssertion(uint256 assertionID, address stakerAddress) returns() +func (_AssertionMap *AssertionMapSession) StakeOnAssertion(assertionID *big.Int, stakerAddress common.Address) (*types.Transaction, error) { + return _AssertionMap.Contract.StakeOnAssertion(&_AssertionMap.TransactOpts, assertionID, stakerAddress) +} + +// StakeOnAssertion is a paid mutator transaction binding the contract method 0xa832c3ae. +// +// Solidity: function stakeOnAssertion(uint256 assertionID, address stakerAddress) returns() +func (_AssertionMap *AssertionMapTransactorSession) StakeOnAssertion(assertionID *big.Int, stakerAddress common.Address) (*types.Transaction, error) { + return _AssertionMap.Contract.StakeOnAssertion(&_AssertionMap.TransactOpts, assertionID, stakerAddress) +} + +// AssertionMapInitializedIterator is returned from FilterInitialized and is used to iterate over the raw logs and unpacked data for Initialized events raised by the AssertionMap contract. +type AssertionMapInitializedIterator struct { + Event *AssertionMapInitialized // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *AssertionMapInitializedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(AssertionMapInitialized) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(AssertionMapInitialized) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *AssertionMapInitializedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *AssertionMapInitializedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// AssertionMapInitialized represents a Initialized event raised by the AssertionMap contract. +type AssertionMapInitialized struct { + Version uint8 + Raw types.Log // Blockchain specific contextual infos +} + +// FilterInitialized is a free log retrieval operation binding the contract event 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498. +// +// Solidity: event Initialized(uint8 version) +func (_AssertionMap *AssertionMapFilterer) FilterInitialized(opts *bind.FilterOpts) (*AssertionMapInitializedIterator, error) { + + logs, sub, err := _AssertionMap.contract.FilterLogs(opts, "Initialized") + if err != nil { + return nil, err + } + return &AssertionMapInitializedIterator{contract: _AssertionMap.contract, event: "Initialized", logs: logs, sub: sub}, nil +} + +// WatchInitialized is a free log subscription operation binding the contract event 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498. +// +// Solidity: event Initialized(uint8 version) +func (_AssertionMap *AssertionMapFilterer) WatchInitialized(opts *bind.WatchOpts, sink chan<- *AssertionMapInitialized) (event.Subscription, error) { + + logs, sub, err := _AssertionMap.contract.WatchLogs(opts, "Initialized") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(AssertionMapInitialized) + if err := _AssertionMap.contract.UnpackLog(event, "Initialized", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseInitialized is a log parse operation binding the contract event 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498. +// +// Solidity: event Initialized(uint8 version) +func (_AssertionMap *AssertionMapFilterer) ParseInitialized(log types.Log) (*AssertionMapInitialized, error) { + event := new(AssertionMapInitialized) + if err := _AssertionMap.contract.UnpackLog(event, "Initialized", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} diff --git a/fraud-proof/bindings/Challenge.go b/fraud-proof/bindings/Challenge.go new file mode 100644 index 000000000..ef9cebc4a --- /dev/null +++ b/fraud-proof/bindings/Challenge.go @@ -0,0 +1,1100 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package bindings + +import ( + "errors" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" +) + +// Reference imports to suppress errors if they are not otherwise used. +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription +) + +// EVMTypesLibTransaction is an auto generated low-level Go binding around an user-defined struct. +type EVMTypesLibTransaction struct { + Nonce uint64 + GasPrice *big.Int + Gas uint64 + To common.Address + Value *big.Int + Data []byte + V *big.Int + R *big.Int + S *big.Int +} + +// VerificationContextContext is an auto generated low-level Go binding around an user-defined struct. +type VerificationContextContext struct { + Coinbase common.Address + Timestamp *big.Int + Number *big.Int + Origin common.Address + Transaction EVMTypesLibTransaction + InputRoot [32]byte + TxHash [32]byte +} + +// ChallengeMetaData contains all meta data concerning the Challenge contract. +var ChallengeMetaData = &bind.MetaData{ + ABI: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"startState\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"midState\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"endState\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"blockNum\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"blockTime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"challengedSegmentStart\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"challengedSegmentLength\",\"type\":\"uint256\"}],\"name\":\"Bisected\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"winner\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"loser\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"enumIChallenge.CompletionReason\",\"name\":\"reason\",\"type\":\"uint8\"}],\"name\":\"ChallengeCompleted\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"bisection\",\"type\":\"bytes32[3]\"},{\"internalType\":\"uint256\",\"name\":\"challengedSegmentIndex\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"challengedSegmentStart\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"challengedSegmentLength\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"prevChallengedSegmentStart\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"prevChallengedSegmentLength\",\"type\":\"uint256\"}],\"name\":\"bisectExecution\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bisectionHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"challenger\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"challengerTimeLeft\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"result\",\"type\":\"bool\"}],\"name\":\"completeChallenge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"currentBisected\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"startState\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"midState\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"endState\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"blockNum\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"blockTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"challengedSegmentStart\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"challengedSegmentLength\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"currentResponder\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"currentResponderTimeLeft\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"defender\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"defenderTimeLeft\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_defender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_challenger\",\"type\":\"address\"},{\"internalType\":\"contractIVerifierEntry\",\"name\":\"_verifier\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_resultReceiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_startInboxSize\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_startStateHash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"_endStateHash\",\"type\":\"bytes32\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"checkStateHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_numSteps\",\"type\":\"uint256\"}],\"name\":\"initializeChallengeLength\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastMoveBlockTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"prevBisection\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"rollback\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"setRollback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"startInboxSize\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"timeout\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"turn\",\"outputs\":[{\"internalType\":\"enumChallenge.Turn\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"coinbase\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"number\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"origin\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"gasPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"gas\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"v\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"r\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"s\",\"type\":\"uint256\"}],\"internalType\":\"structEVMTypesLib.Transaction\",\"name\":\"transaction\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"inputRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"txHash\",\"type\":\"bytes32\"}],\"internalType\":\"structVerificationContext.Context\",\"name\":\"ctx\",\"type\":\"tuple\"},{\"internalType\":\"uint8\",\"name\":\"verifyType\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"proof\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"challengedStepIndex\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"prevChallengedSegmentStart\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"prevChallengedSegmentLength\",\"type\":\"uint256\"}],\"name\":\"verifyOneStepProof\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"winner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", +} + +// ChallengeABI is the input ABI used to generate the binding from. +// Deprecated: Use ChallengeMetaData.ABI instead. +var ChallengeABI = ChallengeMetaData.ABI + +// Challenge is an auto generated Go binding around an Ethereum contract. +type Challenge struct { + ChallengeCaller // Read-only binding to the contract + ChallengeTransactor // Write-only binding to the contract + ChallengeFilterer // Log filterer for contract events +} + +// ChallengeCaller is an auto generated read-only Go binding around an Ethereum contract. +type ChallengeCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ChallengeTransactor is an auto generated write-only Go binding around an Ethereum contract. +type ChallengeTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ChallengeFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type ChallengeFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ChallengeSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type ChallengeSession struct { + Contract *Challenge // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// ChallengeCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type ChallengeCallerSession struct { + Contract *ChallengeCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// ChallengeTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type ChallengeTransactorSession struct { + Contract *ChallengeTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// ChallengeRaw is an auto generated low-level Go binding around an Ethereum contract. +type ChallengeRaw struct { + Contract *Challenge // Generic contract binding to access the raw methods on +} + +// ChallengeCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type ChallengeCallerRaw struct { + Contract *ChallengeCaller // Generic read-only contract binding to access the raw methods on +} + +// ChallengeTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type ChallengeTransactorRaw struct { + Contract *ChallengeTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewChallenge creates a new instance of Challenge, bound to a specific deployed contract. +func NewChallenge(address common.Address, backend bind.ContractBackend) (*Challenge, error) { + contract, err := bindChallenge(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &Challenge{ChallengeCaller: ChallengeCaller{contract: contract}, ChallengeTransactor: ChallengeTransactor{contract: contract}, ChallengeFilterer: ChallengeFilterer{contract: contract}}, nil +} + +// NewChallengeCaller creates a new read-only instance of Challenge, bound to a specific deployed contract. +func NewChallengeCaller(address common.Address, caller bind.ContractCaller) (*ChallengeCaller, error) { + contract, err := bindChallenge(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &ChallengeCaller{contract: contract}, nil +} + +// NewChallengeTransactor creates a new write-only instance of Challenge, bound to a specific deployed contract. +func NewChallengeTransactor(address common.Address, transactor bind.ContractTransactor) (*ChallengeTransactor, error) { + contract, err := bindChallenge(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &ChallengeTransactor{contract: contract}, nil +} + +// NewChallengeFilterer creates a new log filterer instance of Challenge, bound to a specific deployed contract. +func NewChallengeFilterer(address common.Address, filterer bind.ContractFilterer) (*ChallengeFilterer, error) { + contract, err := bindChallenge(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &ChallengeFilterer{contract: contract}, nil +} + +// bindChallenge binds a generic wrapper to an already deployed contract. +func bindChallenge(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := abi.JSON(strings.NewReader(ChallengeABI)) + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Challenge *ChallengeRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Challenge.Contract.ChallengeCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Challenge *ChallengeRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Challenge.Contract.ChallengeTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Challenge *ChallengeRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Challenge.Contract.ChallengeTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Challenge *ChallengeCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Challenge.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Challenge *ChallengeTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Challenge.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Challenge *ChallengeTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Challenge.Contract.contract.Transact(opts, method, params...) +} + +// BisectionHash is a free data retrieval call binding the contract method 0x2a51f6f7. +// +// Solidity: function bisectionHash() view returns(bytes32) +func (_Challenge *ChallengeCaller) BisectionHash(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _Challenge.contract.Call(opts, &out, "bisectionHash") + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +// BisectionHash is a free data retrieval call binding the contract method 0x2a51f6f7. +// +// Solidity: function bisectionHash() view returns(bytes32) +func (_Challenge *ChallengeSession) BisectionHash() ([32]byte, error) { + return _Challenge.Contract.BisectionHash(&_Challenge.CallOpts) +} + +// BisectionHash is a free data retrieval call binding the contract method 0x2a51f6f7. +// +// Solidity: function bisectionHash() view returns(bytes32) +func (_Challenge *ChallengeCallerSession) BisectionHash() ([32]byte, error) { + return _Challenge.Contract.BisectionHash(&_Challenge.CallOpts) +} + +// Challenger is a free data retrieval call binding the contract method 0x534db0e2. +// +// Solidity: function challenger() view returns(address) +func (_Challenge *ChallengeCaller) Challenger(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _Challenge.contract.Call(opts, &out, "challenger") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// Challenger is a free data retrieval call binding the contract method 0x534db0e2. +// +// Solidity: function challenger() view returns(address) +func (_Challenge *ChallengeSession) Challenger() (common.Address, error) { + return _Challenge.Contract.Challenger(&_Challenge.CallOpts) +} + +// Challenger is a free data retrieval call binding the contract method 0x534db0e2. +// +// Solidity: function challenger() view returns(address) +func (_Challenge *ChallengeCallerSession) Challenger() (common.Address, error) { + return _Challenge.Contract.Challenger(&_Challenge.CallOpts) +} + +// ChallengerTimeLeft is a free data retrieval call binding the contract method 0x41e8510c. +// +// Solidity: function challengerTimeLeft() view returns(uint256) +func (_Challenge *ChallengeCaller) ChallengerTimeLeft(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Challenge.contract.Call(opts, &out, "challengerTimeLeft") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// ChallengerTimeLeft is a free data retrieval call binding the contract method 0x41e8510c. +// +// Solidity: function challengerTimeLeft() view returns(uint256) +func (_Challenge *ChallengeSession) ChallengerTimeLeft() (*big.Int, error) { + return _Challenge.Contract.ChallengerTimeLeft(&_Challenge.CallOpts) +} + +// ChallengerTimeLeft is a free data retrieval call binding the contract method 0x41e8510c. +// +// Solidity: function challengerTimeLeft() view returns(uint256) +func (_Challenge *ChallengeCallerSession) ChallengerTimeLeft() (*big.Int, error) { + return _Challenge.Contract.ChallengerTimeLeft(&_Challenge.CallOpts) +} + +// CurrentBisected is a free data retrieval call binding the contract method 0x732e6961. +// +// Solidity: function currentBisected() view returns(bytes32 startState, bytes32 midState, bytes32 endState, uint256 blockNum, uint256 blockTime, uint256 challengedSegmentStart, uint256 challengedSegmentLength) +func (_Challenge *ChallengeCaller) CurrentBisected(opts *bind.CallOpts) (struct { + StartState [32]byte + MidState [32]byte + EndState [32]byte + BlockNum *big.Int + BlockTime *big.Int + ChallengedSegmentStart *big.Int + ChallengedSegmentLength *big.Int +}, error) { + var out []interface{} + err := _Challenge.contract.Call(opts, &out, "currentBisected") + + outstruct := new(struct { + StartState [32]byte + MidState [32]byte + EndState [32]byte + BlockNum *big.Int + BlockTime *big.Int + ChallengedSegmentStart *big.Int + ChallengedSegmentLength *big.Int + }) + if err != nil { + return *outstruct, err + } + + outstruct.StartState = *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + outstruct.MidState = *abi.ConvertType(out[1], new([32]byte)).(*[32]byte) + outstruct.EndState = *abi.ConvertType(out[2], new([32]byte)).(*[32]byte) + outstruct.BlockNum = *abi.ConvertType(out[3], new(*big.Int)).(**big.Int) + outstruct.BlockTime = *abi.ConvertType(out[4], new(*big.Int)).(**big.Int) + outstruct.ChallengedSegmentStart = *abi.ConvertType(out[5], new(*big.Int)).(**big.Int) + outstruct.ChallengedSegmentLength = *abi.ConvertType(out[6], new(*big.Int)).(**big.Int) + + return *outstruct, err + +} + +// CurrentBisected is a free data retrieval call binding the contract method 0x732e6961. +// +// Solidity: function currentBisected() view returns(bytes32 startState, bytes32 midState, bytes32 endState, uint256 blockNum, uint256 blockTime, uint256 challengedSegmentStart, uint256 challengedSegmentLength) +func (_Challenge *ChallengeSession) CurrentBisected() (struct { + StartState [32]byte + MidState [32]byte + EndState [32]byte + BlockNum *big.Int + BlockTime *big.Int + ChallengedSegmentStart *big.Int + ChallengedSegmentLength *big.Int +}, error) { + return _Challenge.Contract.CurrentBisected(&_Challenge.CallOpts) +} + +// CurrentBisected is a free data retrieval call binding the contract method 0x732e6961. +// +// Solidity: function currentBisected() view returns(bytes32 startState, bytes32 midState, bytes32 endState, uint256 blockNum, uint256 blockTime, uint256 challengedSegmentStart, uint256 challengedSegmentLength) +func (_Challenge *ChallengeCallerSession) CurrentBisected() (struct { + StartState [32]byte + MidState [32]byte + EndState [32]byte + BlockNum *big.Int + BlockTime *big.Int + ChallengedSegmentStart *big.Int + ChallengedSegmentLength *big.Int +}, error) { + return _Challenge.Contract.CurrentBisected(&_Challenge.CallOpts) +} + +// CurrentResponder is a free data retrieval call binding the contract method 0x8a8cd218. +// +// Solidity: function currentResponder() view returns(address) +func (_Challenge *ChallengeCaller) CurrentResponder(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _Challenge.contract.Call(opts, &out, "currentResponder") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// CurrentResponder is a free data retrieval call binding the contract method 0x8a8cd218. +// +// Solidity: function currentResponder() view returns(address) +func (_Challenge *ChallengeSession) CurrentResponder() (common.Address, error) { + return _Challenge.Contract.CurrentResponder(&_Challenge.CallOpts) +} + +// CurrentResponder is a free data retrieval call binding the contract method 0x8a8cd218. +// +// Solidity: function currentResponder() view returns(address) +func (_Challenge *ChallengeCallerSession) CurrentResponder() (common.Address, error) { + return _Challenge.Contract.CurrentResponder(&_Challenge.CallOpts) +} + +// CurrentResponderTimeLeft is a free data retrieval call binding the contract method 0xe87e3589. +// +// Solidity: function currentResponderTimeLeft() view returns(uint256) +func (_Challenge *ChallengeCaller) CurrentResponderTimeLeft(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Challenge.contract.Call(opts, &out, "currentResponderTimeLeft") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// CurrentResponderTimeLeft is a free data retrieval call binding the contract method 0xe87e3589. +// +// Solidity: function currentResponderTimeLeft() view returns(uint256) +func (_Challenge *ChallengeSession) CurrentResponderTimeLeft() (*big.Int, error) { + return _Challenge.Contract.CurrentResponderTimeLeft(&_Challenge.CallOpts) +} + +// CurrentResponderTimeLeft is a free data retrieval call binding the contract method 0xe87e3589. +// +// Solidity: function currentResponderTimeLeft() view returns(uint256) +func (_Challenge *ChallengeCallerSession) CurrentResponderTimeLeft() (*big.Int, error) { + return _Challenge.Contract.CurrentResponderTimeLeft(&_Challenge.CallOpts) +} + +// Defender is a free data retrieval call binding the contract method 0x7f4c91c5. +// +// Solidity: function defender() view returns(address) +func (_Challenge *ChallengeCaller) Defender(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _Challenge.contract.Call(opts, &out, "defender") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// Defender is a free data retrieval call binding the contract method 0x7f4c91c5. +// +// Solidity: function defender() view returns(address) +func (_Challenge *ChallengeSession) Defender() (common.Address, error) { + return _Challenge.Contract.Defender(&_Challenge.CallOpts) +} + +// Defender is a free data retrieval call binding the contract method 0x7f4c91c5. +// +// Solidity: function defender() view returns(address) +func (_Challenge *ChallengeCallerSession) Defender() (common.Address, error) { + return _Challenge.Contract.Defender(&_Challenge.CallOpts) +} + +// DefenderTimeLeft is a free data retrieval call binding the contract method 0x5f41e3d6. +// +// Solidity: function defenderTimeLeft() view returns(uint256) +func (_Challenge *ChallengeCaller) DefenderTimeLeft(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Challenge.contract.Call(opts, &out, "defenderTimeLeft") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// DefenderTimeLeft is a free data retrieval call binding the contract method 0x5f41e3d6. +// +// Solidity: function defenderTimeLeft() view returns(uint256) +func (_Challenge *ChallengeSession) DefenderTimeLeft() (*big.Int, error) { + return _Challenge.Contract.DefenderTimeLeft(&_Challenge.CallOpts) +} + +// DefenderTimeLeft is a free data retrieval call binding the contract method 0x5f41e3d6. +// +// Solidity: function defenderTimeLeft() view returns(uint256) +func (_Challenge *ChallengeCallerSession) DefenderTimeLeft() (*big.Int, error) { + return _Challenge.Contract.DefenderTimeLeft(&_Challenge.CallOpts) +} + +// LastMoveBlockTime is a free data retrieval call binding the contract method 0xed5b1303. +// +// Solidity: function lastMoveBlockTime() view returns(uint256) +func (_Challenge *ChallengeCaller) LastMoveBlockTime(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Challenge.contract.Call(opts, &out, "lastMoveBlockTime") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// LastMoveBlockTime is a free data retrieval call binding the contract method 0xed5b1303. +// +// Solidity: function lastMoveBlockTime() view returns(uint256) +func (_Challenge *ChallengeSession) LastMoveBlockTime() (*big.Int, error) { + return _Challenge.Contract.LastMoveBlockTime(&_Challenge.CallOpts) +} + +// LastMoveBlockTime is a free data retrieval call binding the contract method 0xed5b1303. +// +// Solidity: function lastMoveBlockTime() view returns(uint256) +func (_Challenge *ChallengeCallerSession) LastMoveBlockTime() (*big.Int, error) { + return _Challenge.Contract.LastMoveBlockTime(&_Challenge.CallOpts) +} + +// PrevBisection is a free data retrieval call binding the contract method 0xafeae965. +// +// Solidity: function prevBisection(uint256 ) view returns(bytes32) +func (_Challenge *ChallengeCaller) PrevBisection(opts *bind.CallOpts, arg0 *big.Int) ([32]byte, error) { + var out []interface{} + err := _Challenge.contract.Call(opts, &out, "prevBisection", arg0) + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +// PrevBisection is a free data retrieval call binding the contract method 0xafeae965. +// +// Solidity: function prevBisection(uint256 ) view returns(bytes32) +func (_Challenge *ChallengeSession) PrevBisection(arg0 *big.Int) ([32]byte, error) { + return _Challenge.Contract.PrevBisection(&_Challenge.CallOpts, arg0) +} + +// PrevBisection is a free data retrieval call binding the contract method 0xafeae965. +// +// Solidity: function prevBisection(uint256 ) view returns(bytes32) +func (_Challenge *ChallengeCallerSession) PrevBisection(arg0 *big.Int) ([32]byte, error) { + return _Challenge.Contract.PrevBisection(&_Challenge.CallOpts, arg0) +} + +// Rollback is a free data retrieval call binding the contract method 0x9afd9d78. +// +// Solidity: function rollback() view returns(bool) +func (_Challenge *ChallengeCaller) Rollback(opts *bind.CallOpts) (bool, error) { + var out []interface{} + err := _Challenge.contract.Call(opts, &out, "rollback") + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// Rollback is a free data retrieval call binding the contract method 0x9afd9d78. +// +// Solidity: function rollback() view returns(bool) +func (_Challenge *ChallengeSession) Rollback() (bool, error) { + return _Challenge.Contract.Rollback(&_Challenge.CallOpts) +} + +// Rollback is a free data retrieval call binding the contract method 0x9afd9d78. +// +// Solidity: function rollback() view returns(bool) +func (_Challenge *ChallengeCallerSession) Rollback() (bool, error) { + return _Challenge.Contract.Rollback(&_Challenge.CallOpts) +} + +// StartInboxSize is a free data retrieval call binding the contract method 0xfaeff41b. +// +// Solidity: function startInboxSize() view returns(uint256) +func (_Challenge *ChallengeCaller) StartInboxSize(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Challenge.contract.Call(opts, &out, "startInboxSize") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// StartInboxSize is a free data retrieval call binding the contract method 0xfaeff41b. +// +// Solidity: function startInboxSize() view returns(uint256) +func (_Challenge *ChallengeSession) StartInboxSize() (*big.Int, error) { + return _Challenge.Contract.StartInboxSize(&_Challenge.CallOpts) +} + +// StartInboxSize is a free data retrieval call binding the contract method 0xfaeff41b. +// +// Solidity: function startInboxSize() view returns(uint256) +func (_Challenge *ChallengeCallerSession) StartInboxSize() (*big.Int, error) { + return _Challenge.Contract.StartInboxSize(&_Challenge.CallOpts) +} + +// Turn is a free data retrieval call binding the contract method 0x8b299903. +// +// Solidity: function turn() view returns(uint8) +func (_Challenge *ChallengeCaller) Turn(opts *bind.CallOpts) (uint8, error) { + var out []interface{} + err := _Challenge.contract.Call(opts, &out, "turn") + + if err != nil { + return *new(uint8), err + } + + out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8) + + return out0, err + +} + +// Turn is a free data retrieval call binding the contract method 0x8b299903. +// +// Solidity: function turn() view returns(uint8) +func (_Challenge *ChallengeSession) Turn() (uint8, error) { + return _Challenge.Contract.Turn(&_Challenge.CallOpts) +} + +// Turn is a free data retrieval call binding the contract method 0x8b299903. +// +// Solidity: function turn() view returns(uint8) +func (_Challenge *ChallengeCallerSession) Turn() (uint8, error) { + return _Challenge.Contract.Turn(&_Challenge.CallOpts) +} + +// Winner is a free data retrieval call binding the contract method 0xdfbf53ae. +// +// Solidity: function winner() view returns(address) +func (_Challenge *ChallengeCaller) Winner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _Challenge.contract.Call(opts, &out, "winner") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// Winner is a free data retrieval call binding the contract method 0xdfbf53ae. +// +// Solidity: function winner() view returns(address) +func (_Challenge *ChallengeSession) Winner() (common.Address, error) { + return _Challenge.Contract.Winner(&_Challenge.CallOpts) +} + +// Winner is a free data retrieval call binding the contract method 0xdfbf53ae. +// +// Solidity: function winner() view returns(address) +func (_Challenge *ChallengeCallerSession) Winner() (common.Address, error) { + return _Challenge.Contract.Winner(&_Challenge.CallOpts) +} + +// BisectExecution is a paid mutator transaction binding the contract method 0x8f2400a8. +// +// Solidity: function bisectExecution(bytes32[3] bisection, uint256 challengedSegmentIndex, uint256 challengedSegmentStart, uint256 challengedSegmentLength, uint256 prevChallengedSegmentStart, uint256 prevChallengedSegmentLength) returns() +func (_Challenge *ChallengeTransactor) BisectExecution(opts *bind.TransactOpts, bisection [3][32]byte, challengedSegmentIndex *big.Int, challengedSegmentStart *big.Int, challengedSegmentLength *big.Int, prevChallengedSegmentStart *big.Int, prevChallengedSegmentLength *big.Int) (*types.Transaction, error) { + return _Challenge.contract.Transact(opts, "bisectExecution", bisection, challengedSegmentIndex, challengedSegmentStart, challengedSegmentLength, prevChallengedSegmentStart, prevChallengedSegmentLength) +} + +// BisectExecution is a paid mutator transaction binding the contract method 0x8f2400a8. +// +// Solidity: function bisectExecution(bytes32[3] bisection, uint256 challengedSegmentIndex, uint256 challengedSegmentStart, uint256 challengedSegmentLength, uint256 prevChallengedSegmentStart, uint256 prevChallengedSegmentLength) returns() +func (_Challenge *ChallengeSession) BisectExecution(bisection [3][32]byte, challengedSegmentIndex *big.Int, challengedSegmentStart *big.Int, challengedSegmentLength *big.Int, prevChallengedSegmentStart *big.Int, prevChallengedSegmentLength *big.Int) (*types.Transaction, error) { + return _Challenge.Contract.BisectExecution(&_Challenge.TransactOpts, bisection, challengedSegmentIndex, challengedSegmentStart, challengedSegmentLength, prevChallengedSegmentStart, prevChallengedSegmentLength) +} + +// BisectExecution is a paid mutator transaction binding the contract method 0x8f2400a8. +// +// Solidity: function bisectExecution(bytes32[3] bisection, uint256 challengedSegmentIndex, uint256 challengedSegmentStart, uint256 challengedSegmentLength, uint256 prevChallengedSegmentStart, uint256 prevChallengedSegmentLength) returns() +func (_Challenge *ChallengeTransactorSession) BisectExecution(bisection [3][32]byte, challengedSegmentIndex *big.Int, challengedSegmentStart *big.Int, challengedSegmentLength *big.Int, prevChallengedSegmentStart *big.Int, prevChallengedSegmentLength *big.Int) (*types.Transaction, error) { + return _Challenge.Contract.BisectExecution(&_Challenge.TransactOpts, bisection, challengedSegmentIndex, challengedSegmentStart, challengedSegmentLength, prevChallengedSegmentStart, prevChallengedSegmentLength) +} + +// CompleteChallenge is a paid mutator transaction binding the contract method 0xf2858aa3. +// +// Solidity: function completeChallenge(bool result) returns() +func (_Challenge *ChallengeTransactor) CompleteChallenge(opts *bind.TransactOpts, result bool) (*types.Transaction, error) { + return _Challenge.contract.Transact(opts, "completeChallenge", result) +} + +// CompleteChallenge is a paid mutator transaction binding the contract method 0xf2858aa3. +// +// Solidity: function completeChallenge(bool result) returns() +func (_Challenge *ChallengeSession) CompleteChallenge(result bool) (*types.Transaction, error) { + return _Challenge.Contract.CompleteChallenge(&_Challenge.TransactOpts, result) +} + +// CompleteChallenge is a paid mutator transaction binding the contract method 0xf2858aa3. +// +// Solidity: function completeChallenge(bool result) returns() +func (_Challenge *ChallengeTransactorSession) CompleteChallenge(result bool) (*types.Transaction, error) { + return _Challenge.Contract.CompleteChallenge(&_Challenge.TransactOpts, result) +} + +// Initialize is a paid mutator transaction binding the contract method 0xabf48013. +// +// Solidity: function initialize(address _defender, address _challenger, address _verifier, address _resultReceiver, uint256 _startInboxSize, bytes32 _startStateHash, bytes32 _endStateHash) returns() +func (_Challenge *ChallengeTransactor) Initialize(opts *bind.TransactOpts, _defender common.Address, _challenger common.Address, _verifier common.Address, _resultReceiver common.Address, _startInboxSize *big.Int, _startStateHash [32]byte, _endStateHash [32]byte) (*types.Transaction, error) { + return _Challenge.contract.Transact(opts, "initialize", _defender, _challenger, _verifier, _resultReceiver, _startInboxSize, _startStateHash, _endStateHash) +} + +// Initialize is a paid mutator transaction binding the contract method 0xabf48013. +// +// Solidity: function initialize(address _defender, address _challenger, address _verifier, address _resultReceiver, uint256 _startInboxSize, bytes32 _startStateHash, bytes32 _endStateHash) returns() +func (_Challenge *ChallengeSession) Initialize(_defender common.Address, _challenger common.Address, _verifier common.Address, _resultReceiver common.Address, _startInboxSize *big.Int, _startStateHash [32]byte, _endStateHash [32]byte) (*types.Transaction, error) { + return _Challenge.Contract.Initialize(&_Challenge.TransactOpts, _defender, _challenger, _verifier, _resultReceiver, _startInboxSize, _startStateHash, _endStateHash) +} + +// Initialize is a paid mutator transaction binding the contract method 0xabf48013. +// +// Solidity: function initialize(address _defender, address _challenger, address _verifier, address _resultReceiver, uint256 _startInboxSize, bytes32 _startStateHash, bytes32 _endStateHash) returns() +func (_Challenge *ChallengeTransactorSession) Initialize(_defender common.Address, _challenger common.Address, _verifier common.Address, _resultReceiver common.Address, _startInboxSize *big.Int, _startStateHash [32]byte, _endStateHash [32]byte) (*types.Transaction, error) { + return _Challenge.Contract.Initialize(&_Challenge.TransactOpts, _defender, _challenger, _verifier, _resultReceiver, _startInboxSize, _startStateHash, _endStateHash) +} + +// InitializeChallengeLength is a paid mutator transaction binding the contract method 0x18ef160d. +// +// Solidity: function initializeChallengeLength(bytes32 checkStateHash, uint256 _numSteps) returns() +func (_Challenge *ChallengeTransactor) InitializeChallengeLength(opts *bind.TransactOpts, checkStateHash [32]byte, _numSteps *big.Int) (*types.Transaction, error) { + return _Challenge.contract.Transact(opts, "initializeChallengeLength", checkStateHash, _numSteps) +} + +// InitializeChallengeLength is a paid mutator transaction binding the contract method 0x18ef160d. +// +// Solidity: function initializeChallengeLength(bytes32 checkStateHash, uint256 _numSteps) returns() +func (_Challenge *ChallengeSession) InitializeChallengeLength(checkStateHash [32]byte, _numSteps *big.Int) (*types.Transaction, error) { + return _Challenge.Contract.InitializeChallengeLength(&_Challenge.TransactOpts, checkStateHash, _numSteps) +} + +// InitializeChallengeLength is a paid mutator transaction binding the contract method 0x18ef160d. +// +// Solidity: function initializeChallengeLength(bytes32 checkStateHash, uint256 _numSteps) returns() +func (_Challenge *ChallengeTransactorSession) InitializeChallengeLength(checkStateHash [32]byte, _numSteps *big.Int) (*types.Transaction, error) { + return _Challenge.Contract.InitializeChallengeLength(&_Challenge.TransactOpts, checkStateHash, _numSteps) +} + +// SetRollback is a paid mutator transaction binding the contract method 0x631acced. +// +// Solidity: function setRollback() returns() +func (_Challenge *ChallengeTransactor) SetRollback(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Challenge.contract.Transact(opts, "setRollback") +} + +// SetRollback is a paid mutator transaction binding the contract method 0x631acced. +// +// Solidity: function setRollback() returns() +func (_Challenge *ChallengeSession) SetRollback() (*types.Transaction, error) { + return _Challenge.Contract.SetRollback(&_Challenge.TransactOpts) +} + +// SetRollback is a paid mutator transaction binding the contract method 0x631acced. +// +// Solidity: function setRollback() returns() +func (_Challenge *ChallengeTransactorSession) SetRollback() (*types.Transaction, error) { + return _Challenge.Contract.SetRollback(&_Challenge.TransactOpts) +} + +// Timeout is a paid mutator transaction binding the contract method 0x70dea79a. +// +// Solidity: function timeout() returns() +func (_Challenge *ChallengeTransactor) Timeout(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Challenge.contract.Transact(opts, "timeout") +} + +// Timeout is a paid mutator transaction binding the contract method 0x70dea79a. +// +// Solidity: function timeout() returns() +func (_Challenge *ChallengeSession) Timeout() (*types.Transaction, error) { + return _Challenge.Contract.Timeout(&_Challenge.TransactOpts) +} + +// Timeout is a paid mutator transaction binding the contract method 0x70dea79a. +// +// Solidity: function timeout() returns() +func (_Challenge *ChallengeTransactorSession) Timeout() (*types.Transaction, error) { + return _Challenge.Contract.Timeout(&_Challenge.TransactOpts) +} + +// VerifyOneStepProof is a paid mutator transaction binding the contract method 0xf03a7fcb. +// +// Solidity: function verifyOneStepProof((address,uint256,uint256,address,(uint64,uint256,uint64,address,uint256,bytes,uint256,uint256,uint256),bytes32,bytes32) ctx, uint8 verifyType, bytes proof, uint256 challengedStepIndex, uint256 prevChallengedSegmentStart, uint256 prevChallengedSegmentLength) returns() +func (_Challenge *ChallengeTransactor) VerifyOneStepProof(opts *bind.TransactOpts, ctx VerificationContextContext, verifyType uint8, proof []byte, challengedStepIndex *big.Int, prevChallengedSegmentStart *big.Int, prevChallengedSegmentLength *big.Int) (*types.Transaction, error) { + return _Challenge.contract.Transact(opts, "verifyOneStepProof", ctx, verifyType, proof, challengedStepIndex, prevChallengedSegmentStart, prevChallengedSegmentLength) +} + +// VerifyOneStepProof is a paid mutator transaction binding the contract method 0xf03a7fcb. +// +// Solidity: function verifyOneStepProof((address,uint256,uint256,address,(uint64,uint256,uint64,address,uint256,bytes,uint256,uint256,uint256),bytes32,bytes32) ctx, uint8 verifyType, bytes proof, uint256 challengedStepIndex, uint256 prevChallengedSegmentStart, uint256 prevChallengedSegmentLength) returns() +func (_Challenge *ChallengeSession) VerifyOneStepProof(ctx VerificationContextContext, verifyType uint8, proof []byte, challengedStepIndex *big.Int, prevChallengedSegmentStart *big.Int, prevChallengedSegmentLength *big.Int) (*types.Transaction, error) { + return _Challenge.Contract.VerifyOneStepProof(&_Challenge.TransactOpts, ctx, verifyType, proof, challengedStepIndex, prevChallengedSegmentStart, prevChallengedSegmentLength) +} + +// VerifyOneStepProof is a paid mutator transaction binding the contract method 0xf03a7fcb. +// +// Solidity: function verifyOneStepProof((address,uint256,uint256,address,(uint64,uint256,uint64,address,uint256,bytes,uint256,uint256,uint256),bytes32,bytes32) ctx, uint8 verifyType, bytes proof, uint256 challengedStepIndex, uint256 prevChallengedSegmentStart, uint256 prevChallengedSegmentLength) returns() +func (_Challenge *ChallengeTransactorSession) VerifyOneStepProof(ctx VerificationContextContext, verifyType uint8, proof []byte, challengedStepIndex *big.Int, prevChallengedSegmentStart *big.Int, prevChallengedSegmentLength *big.Int) (*types.Transaction, error) { + return _Challenge.Contract.VerifyOneStepProof(&_Challenge.TransactOpts, ctx, verifyType, proof, challengedStepIndex, prevChallengedSegmentStart, prevChallengedSegmentLength) +} + +// ChallengeBisectedIterator is returned from FilterBisected and is used to iterate over the raw logs and unpacked data for Bisected events raised by the Challenge contract. +type ChallengeBisectedIterator struct { + Event *ChallengeBisected // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *ChallengeBisectedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(ChallengeBisected) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(ChallengeBisected) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *ChallengeBisectedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *ChallengeBisectedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// ChallengeBisected represents a Bisected event raised by the Challenge contract. +type ChallengeBisected struct { + StartState [32]byte + MidState [32]byte + EndState [32]byte + BlockNum *big.Int + BlockTime *big.Int + ChallengedSegmentStart *big.Int + ChallengedSegmentLength *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterBisected is a free log retrieval operation binding the contract event 0x71809f4d4f7bf3c208a85ccd3c922c984024f8e3cef51e3d03ae677e4217097d. +// +// Solidity: event Bisected(bytes32 startState, bytes32 midState, bytes32 endState, uint256 blockNum, uint256 blockTime, uint256 challengedSegmentStart, uint256 challengedSegmentLength) +func (_Challenge *ChallengeFilterer) FilterBisected(opts *bind.FilterOpts) (*ChallengeBisectedIterator, error) { + + logs, sub, err := _Challenge.contract.FilterLogs(opts, "Bisected") + if err != nil { + return nil, err + } + return &ChallengeBisectedIterator{contract: _Challenge.contract, event: "Bisected", logs: logs, sub: sub}, nil +} + +// WatchBisected is a free log subscription operation binding the contract event 0x71809f4d4f7bf3c208a85ccd3c922c984024f8e3cef51e3d03ae677e4217097d. +// +// Solidity: event Bisected(bytes32 startState, bytes32 midState, bytes32 endState, uint256 blockNum, uint256 blockTime, uint256 challengedSegmentStart, uint256 challengedSegmentLength) +func (_Challenge *ChallengeFilterer) WatchBisected(opts *bind.WatchOpts, sink chan<- *ChallengeBisected) (event.Subscription, error) { + + logs, sub, err := _Challenge.contract.WatchLogs(opts, "Bisected") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(ChallengeBisected) + if err := _Challenge.contract.UnpackLog(event, "Bisected", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseBisected is a log parse operation binding the contract event 0x71809f4d4f7bf3c208a85ccd3c922c984024f8e3cef51e3d03ae677e4217097d. +// +// Solidity: event Bisected(bytes32 startState, bytes32 midState, bytes32 endState, uint256 blockNum, uint256 blockTime, uint256 challengedSegmentStart, uint256 challengedSegmentLength) +func (_Challenge *ChallengeFilterer) ParseBisected(log types.Log) (*ChallengeBisected, error) { + event := new(ChallengeBisected) + if err := _Challenge.contract.UnpackLog(event, "Bisected", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// ChallengeChallengeCompletedIterator is returned from FilterChallengeCompleted and is used to iterate over the raw logs and unpacked data for ChallengeCompleted events raised by the Challenge contract. +type ChallengeChallengeCompletedIterator struct { + Event *ChallengeChallengeCompleted // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *ChallengeChallengeCompletedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(ChallengeChallengeCompleted) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(ChallengeChallengeCompleted) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *ChallengeChallengeCompletedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *ChallengeChallengeCompletedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// ChallengeChallengeCompleted represents a ChallengeCompleted event raised by the Challenge contract. +type ChallengeChallengeCompleted struct { + Winner common.Address + Loser common.Address + Reason uint8 + Raw types.Log // Blockchain specific contextual infos +} + +// FilterChallengeCompleted is a free log retrieval operation binding the contract event 0x03f929a9a6b1f0aef5e43cb12b56f862da97ec3de3fda02a52e85f9f3974fb6a. +// +// Solidity: event ChallengeCompleted(address winner, address loser, uint8 reason) +func (_Challenge *ChallengeFilterer) FilterChallengeCompleted(opts *bind.FilterOpts) (*ChallengeChallengeCompletedIterator, error) { + + logs, sub, err := _Challenge.contract.FilterLogs(opts, "ChallengeCompleted") + if err != nil { + return nil, err + } + return &ChallengeChallengeCompletedIterator{contract: _Challenge.contract, event: "ChallengeCompleted", logs: logs, sub: sub}, nil +} + +// WatchChallengeCompleted is a free log subscription operation binding the contract event 0x03f929a9a6b1f0aef5e43cb12b56f862da97ec3de3fda02a52e85f9f3974fb6a. +// +// Solidity: event ChallengeCompleted(address winner, address loser, uint8 reason) +func (_Challenge *ChallengeFilterer) WatchChallengeCompleted(opts *bind.WatchOpts, sink chan<- *ChallengeChallengeCompleted) (event.Subscription, error) { + + logs, sub, err := _Challenge.contract.WatchLogs(opts, "ChallengeCompleted") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(ChallengeChallengeCompleted) + if err := _Challenge.contract.UnpackLog(event, "ChallengeCompleted", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseChallengeCompleted is a log parse operation binding the contract event 0x03f929a9a6b1f0aef5e43cb12b56f862da97ec3de3fda02a52e85f9f3974fb6a. +// +// Solidity: event ChallengeCompleted(address winner, address loser, uint8 reason) +func (_Challenge *ChallengeFilterer) ParseChallengeCompleted(log types.Log) (*ChallengeChallengeCompleted, error) { + event := new(ChallengeChallengeCompleted) + if err := _Challenge.contract.UnpackLog(event, "ChallengeCompleted", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} diff --git a/fraud-proof/bindings/Rollup.go b/fraud-proof/bindings/Rollup.go new file mode 100644 index 000000000..d34b3f675 --- /dev/null +++ b/fraud-proof/bindings/Rollup.go @@ -0,0 +1,2058 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package bindings + +import ( + "errors" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" +) + +// Reference imports to suppress errors if they are not otherwise used. +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription +) + +// RollupMetaData contains all meta data concerning the Rollup contract. +var RollupMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"AssertionAlreadyResolved\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AssertionOutOfRange\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ChallengePeriodPending\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ChallengedStaker\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DifferentParent\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyAssertion\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"staker1Challenge\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"staker2Challenge\",\"type\":\"address\"}],\"name\":\"InDifferentChallenge\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InboxReadLimitExceeded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientStake\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidParent\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MinimumAssertionPeriodNotPassed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoStaker\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoUnresolvedAssertion\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotAllStaked\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotInChallenge\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotStaked\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ParentAssertionUnstaked\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PreviousStateHash\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RedundantInitialized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"StakedOnUnconfirmedAssertion\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"StakerStakedOnTarget\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"StakersPresent\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TransferFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnproposedAssertion\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WrongOrder\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddress\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"assertionID\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"challengeAddr\",\"type\":\"address\"}],\"name\":\"AssertionChallenged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"assertionID\",\"type\":\"uint256\"}],\"name\":\"AssertionConfirmed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"assertionID\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"asserterAddr\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"vmHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"inboxSize\",\"type\":\"uint256\"}],\"name\":\"AssertionCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"assertionID\",\"type\":\"uint256\"}],\"name\":\"AssertionRejected\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"stakerAddr\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"assertionID\",\"type\":\"uint256\"}],\"name\":\"StakerStaked\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"toAddAddresses\",\"type\":\"address[]\"}],\"name\":\"addToWhitelist\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"assertionID\",\"type\":\"uint256\"}],\"name\":\"advanceStake\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"assertions\",\"outputs\":[{\"internalType\":\"contractAssertionMap\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"baseStakeAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[2]\",\"name\":\"players\",\"type\":\"address[2]\"},{\"internalType\":\"uint256[2]\",\"name\":\"assertionIDs\",\"type\":\"uint256[2]\"}],\"name\":\"challengeAssertion\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"challengeCtx\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"completed\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"challengeAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"defenderAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"challengerAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"defenderAssertionID\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"challengerAssertionID\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"challengePeriod\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"winner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"loser\",\"type\":\"address\"}],\"name\":\"completeChallenge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"confirmFirstUnresolvedAssertion\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"confirmationPeriod\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"confirmedInboxSize\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"vmHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"inboxSize\",\"type\":\"uint256\"}],\"name\":\"createAssertion\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"vmHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"inboxSize\",\"type\":\"uint256\"},{\"internalType\":\"bytes32[]\",\"name\":\"_batch\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"_shouldStartAtElement\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_signature\",\"type\":\"bytes\"}],\"name\":\"createAssertionWithStateBatch\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"currentRequiredStake\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_verifier\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_stakeToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_libAddressManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_assertionMap\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_confirmationPeriod\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_challengePeriod\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_minimumAssertionPeriod\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_baseStakeAmount\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_initialVMhash\",\"type\":\"bytes32\"},{\"internalType\":\"address[]\",\"name\":\"whitelists\",\"type\":\"address[]\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"isStaked\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastConfirmedAssertionID\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastCreatedAssertionID\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastResolvedAssertionID\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"libAddressManager\",\"outputs\":[{\"internalType\":\"contractLib_AddressManager\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minimumAssertionPeriod\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"numStakers\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"rejectFirstUnresolvedAssertion\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"toRemoveAddresses\",\"type\":\"address[]\"}],\"name\":\"removeFromWhitelist\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"removeOldZombies\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"stakerAddress\",\"type\":\"address\"}],\"name\":\"removeStake\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"}],\"name\":\"resolve\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"stake\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"stakeToken\",\"outputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"stakers\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"isStaked\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"amountStaked\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"assertionID\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"currentChallenge\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"stakeAmount\",\"type\":\"uint256\"}],\"name\":\"unstake\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"verifier\",\"outputs\":[{\"internalType\":\"contractIVerifierEntry\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"whitelist\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"withdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"withdrawableFunds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"zombies\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"stakerAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"lastAssertionID\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", +} + +// RollupABI is the input ABI used to generate the binding from. +// Deprecated: Use RollupMetaData.ABI instead. +var RollupABI = RollupMetaData.ABI + +// Rollup is an auto generated Go binding around an Ethereum contract. +type Rollup struct { + RollupCaller // Read-only binding to the contract + RollupTransactor // Write-only binding to the contract + RollupFilterer // Log filterer for contract events +} + +// RollupCaller is an auto generated read-only Go binding around an Ethereum contract. +type RollupCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// RollupTransactor is an auto generated write-only Go binding around an Ethereum contract. +type RollupTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// RollupFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type RollupFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// RollupSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type RollupSession struct { + Contract *Rollup // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// RollupCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type RollupCallerSession struct { + Contract *RollupCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// RollupTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type RollupTransactorSession struct { + Contract *RollupTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// RollupRaw is an auto generated low-level Go binding around an Ethereum contract. +type RollupRaw struct { + Contract *Rollup // Generic contract binding to access the raw methods on +} + +// RollupCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type RollupCallerRaw struct { + Contract *RollupCaller // Generic read-only contract binding to access the raw methods on +} + +// RollupTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type RollupTransactorRaw struct { + Contract *RollupTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewRollup creates a new instance of Rollup, bound to a specific deployed contract. +func NewRollup(address common.Address, backend bind.ContractBackend) (*Rollup, error) { + contract, err := bindRollup(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &Rollup{RollupCaller: RollupCaller{contract: contract}, RollupTransactor: RollupTransactor{contract: contract}, RollupFilterer: RollupFilterer{contract: contract}}, nil +} + +// NewRollupCaller creates a new read-only instance of Rollup, bound to a specific deployed contract. +func NewRollupCaller(address common.Address, caller bind.ContractCaller) (*RollupCaller, error) { + contract, err := bindRollup(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &RollupCaller{contract: contract}, nil +} + +// NewRollupTransactor creates a new write-only instance of Rollup, bound to a specific deployed contract. +func NewRollupTransactor(address common.Address, transactor bind.ContractTransactor) (*RollupTransactor, error) { + contract, err := bindRollup(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &RollupTransactor{contract: contract}, nil +} + +// NewRollupFilterer creates a new log filterer instance of Rollup, bound to a specific deployed contract. +func NewRollupFilterer(address common.Address, filterer bind.ContractFilterer) (*RollupFilterer, error) { + contract, err := bindRollup(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &RollupFilterer{contract: contract}, nil +} + +// bindRollup binds a generic wrapper to an already deployed contract. +func bindRollup(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := abi.JSON(strings.NewReader(RollupABI)) + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Rollup *RollupRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Rollup.Contract.RollupCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Rollup *RollupRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Rollup.Contract.RollupTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Rollup *RollupRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Rollup.Contract.RollupTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Rollup *RollupCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Rollup.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Rollup *RollupTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Rollup.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Rollup *RollupTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Rollup.Contract.contract.Transact(opts, method, params...) +} + +// Assertions is a free data retrieval call binding the contract method 0x40d9224b. +// +// Solidity: function assertions() view returns(address) +func (_Rollup *RollupCaller) Assertions(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _Rollup.contract.Call(opts, &out, "assertions") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// Assertions is a free data retrieval call binding the contract method 0x40d9224b. +// +// Solidity: function assertions() view returns(address) +func (_Rollup *RollupSession) Assertions() (common.Address, error) { + return _Rollup.Contract.Assertions(&_Rollup.CallOpts) +} + +// Assertions is a free data retrieval call binding the contract method 0x40d9224b. +// +// Solidity: function assertions() view returns(address) +func (_Rollup *RollupCallerSession) Assertions() (common.Address, error) { + return _Rollup.Contract.Assertions(&_Rollup.CallOpts) +} + +// BaseStakeAmount is a free data retrieval call binding the contract method 0x71129559. +// +// Solidity: function baseStakeAmount() view returns(uint256) +func (_Rollup *RollupCaller) BaseStakeAmount(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Rollup.contract.Call(opts, &out, "baseStakeAmount") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// BaseStakeAmount is a free data retrieval call binding the contract method 0x71129559. +// +// Solidity: function baseStakeAmount() view returns(uint256) +func (_Rollup *RollupSession) BaseStakeAmount() (*big.Int, error) { + return _Rollup.Contract.BaseStakeAmount(&_Rollup.CallOpts) +} + +// BaseStakeAmount is a free data retrieval call binding the contract method 0x71129559. +// +// Solidity: function baseStakeAmount() view returns(uint256) +func (_Rollup *RollupCallerSession) BaseStakeAmount() (*big.Int, error) { + return _Rollup.Contract.BaseStakeAmount(&_Rollup.CallOpts) +} + +// ChallengeCtx is a free data retrieval call binding the contract method 0x0e456acf. +// +// Solidity: function challengeCtx() view returns(bool completed, address challengeAddress, address defenderAddress, address challengerAddress, uint256 defenderAssertionID, uint256 challengerAssertionID) +func (_Rollup *RollupCaller) ChallengeCtx(opts *bind.CallOpts) (struct { + Completed bool + ChallengeAddress common.Address + DefenderAddress common.Address + ChallengerAddress common.Address + DefenderAssertionID *big.Int + ChallengerAssertionID *big.Int +}, error) { + var out []interface{} + err := _Rollup.contract.Call(opts, &out, "challengeCtx") + + outstruct := new(struct { + Completed bool + ChallengeAddress common.Address + DefenderAddress common.Address + ChallengerAddress common.Address + DefenderAssertionID *big.Int + ChallengerAssertionID *big.Int + }) + if err != nil { + return *outstruct, err + } + + outstruct.Completed = *abi.ConvertType(out[0], new(bool)).(*bool) + outstruct.ChallengeAddress = *abi.ConvertType(out[1], new(common.Address)).(*common.Address) + outstruct.DefenderAddress = *abi.ConvertType(out[2], new(common.Address)).(*common.Address) + outstruct.ChallengerAddress = *abi.ConvertType(out[3], new(common.Address)).(*common.Address) + outstruct.DefenderAssertionID = *abi.ConvertType(out[4], new(*big.Int)).(**big.Int) + outstruct.ChallengerAssertionID = *abi.ConvertType(out[5], new(*big.Int)).(**big.Int) + + return *outstruct, err + +} + +// ChallengeCtx is a free data retrieval call binding the contract method 0x0e456acf. +// +// Solidity: function challengeCtx() view returns(bool completed, address challengeAddress, address defenderAddress, address challengerAddress, uint256 defenderAssertionID, uint256 challengerAssertionID) +func (_Rollup *RollupSession) ChallengeCtx() (struct { + Completed bool + ChallengeAddress common.Address + DefenderAddress common.Address + ChallengerAddress common.Address + DefenderAssertionID *big.Int + ChallengerAssertionID *big.Int +}, error) { + return _Rollup.Contract.ChallengeCtx(&_Rollup.CallOpts) +} + +// ChallengeCtx is a free data retrieval call binding the contract method 0x0e456acf. +// +// Solidity: function challengeCtx() view returns(bool completed, address challengeAddress, address defenderAddress, address challengerAddress, uint256 defenderAssertionID, uint256 challengerAssertionID) +func (_Rollup *RollupCallerSession) ChallengeCtx() (struct { + Completed bool + ChallengeAddress common.Address + DefenderAddress common.Address + ChallengerAddress common.Address + DefenderAssertionID *big.Int + ChallengerAssertionID *big.Int +}, error) { + return _Rollup.Contract.ChallengeCtx(&_Rollup.CallOpts) +} + +// ChallengePeriod is a free data retrieval call binding the contract method 0xf3f480d9. +// +// Solidity: function challengePeriod() view returns(uint256) +func (_Rollup *RollupCaller) ChallengePeriod(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Rollup.contract.Call(opts, &out, "challengePeriod") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// ChallengePeriod is a free data retrieval call binding the contract method 0xf3f480d9. +// +// Solidity: function challengePeriod() view returns(uint256) +func (_Rollup *RollupSession) ChallengePeriod() (*big.Int, error) { + return _Rollup.Contract.ChallengePeriod(&_Rollup.CallOpts) +} + +// ChallengePeriod is a free data retrieval call binding the contract method 0xf3f480d9. +// +// Solidity: function challengePeriod() view returns(uint256) +func (_Rollup *RollupCallerSession) ChallengePeriod() (*big.Int, error) { + return _Rollup.Contract.ChallengePeriod(&_Rollup.CallOpts) +} + +// ConfirmationPeriod is a free data retrieval call binding the contract method 0x0429b880. +// +// Solidity: function confirmationPeriod() view returns(uint256) +func (_Rollup *RollupCaller) ConfirmationPeriod(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Rollup.contract.Call(opts, &out, "confirmationPeriod") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// ConfirmationPeriod is a free data retrieval call binding the contract method 0x0429b880. +// +// Solidity: function confirmationPeriod() view returns(uint256) +func (_Rollup *RollupSession) ConfirmationPeriod() (*big.Int, error) { + return _Rollup.Contract.ConfirmationPeriod(&_Rollup.CallOpts) +} + +// ConfirmationPeriod is a free data retrieval call binding the contract method 0x0429b880. +// +// Solidity: function confirmationPeriod() view returns(uint256) +func (_Rollup *RollupCallerSession) ConfirmationPeriod() (*big.Int, error) { + return _Rollup.Contract.ConfirmationPeriod(&_Rollup.CallOpts) +} + +// ConfirmedInboxSize is a free data retrieval call binding the contract method 0xc94b5847. +// +// Solidity: function confirmedInboxSize() view returns(uint256) +func (_Rollup *RollupCaller) ConfirmedInboxSize(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Rollup.contract.Call(opts, &out, "confirmedInboxSize") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// ConfirmedInboxSize is a free data retrieval call binding the contract method 0xc94b5847. +// +// Solidity: function confirmedInboxSize() view returns(uint256) +func (_Rollup *RollupSession) ConfirmedInboxSize() (*big.Int, error) { + return _Rollup.Contract.ConfirmedInboxSize(&_Rollup.CallOpts) +} + +// ConfirmedInboxSize is a free data retrieval call binding the contract method 0xc94b5847. +// +// Solidity: function confirmedInboxSize() view returns(uint256) +func (_Rollup *RollupCallerSession) ConfirmedInboxSize() (*big.Int, error) { + return _Rollup.Contract.ConfirmedInboxSize(&_Rollup.CallOpts) +} + +// CurrentRequiredStake is a free data retrieval call binding the contract method 0x4d26732d. +// +// Solidity: function currentRequiredStake() view returns(uint256) +func (_Rollup *RollupCaller) CurrentRequiredStake(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Rollup.contract.Call(opts, &out, "currentRequiredStake") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// CurrentRequiredStake is a free data retrieval call binding the contract method 0x4d26732d. +// +// Solidity: function currentRequiredStake() view returns(uint256) +func (_Rollup *RollupSession) CurrentRequiredStake() (*big.Int, error) { + return _Rollup.Contract.CurrentRequiredStake(&_Rollup.CallOpts) +} + +// CurrentRequiredStake is a free data retrieval call binding the contract method 0x4d26732d. +// +// Solidity: function currentRequiredStake() view returns(uint256) +func (_Rollup *RollupCallerSession) CurrentRequiredStake() (*big.Int, error) { + return _Rollup.Contract.CurrentRequiredStake(&_Rollup.CallOpts) +} + +// IsStaked is a free data retrieval call binding the contract method 0x6177fd18. +// +// Solidity: function isStaked(address addr) view returns(bool) +func (_Rollup *RollupCaller) IsStaked(opts *bind.CallOpts, addr common.Address) (bool, error) { + var out []interface{} + err := _Rollup.contract.Call(opts, &out, "isStaked", addr) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// IsStaked is a free data retrieval call binding the contract method 0x6177fd18. +// +// Solidity: function isStaked(address addr) view returns(bool) +func (_Rollup *RollupSession) IsStaked(addr common.Address) (bool, error) { + return _Rollup.Contract.IsStaked(&_Rollup.CallOpts, addr) +} + +// IsStaked is a free data retrieval call binding the contract method 0x6177fd18. +// +// Solidity: function isStaked(address addr) view returns(bool) +func (_Rollup *RollupCallerSession) IsStaked(addr common.Address) (bool, error) { + return _Rollup.Contract.IsStaked(&_Rollup.CallOpts, addr) +} + +// LastConfirmedAssertionID is a free data retrieval call binding the contract method 0xa56ba93b. +// +// Solidity: function lastConfirmedAssertionID() view returns(uint256) +func (_Rollup *RollupCaller) LastConfirmedAssertionID(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Rollup.contract.Call(opts, &out, "lastConfirmedAssertionID") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// LastConfirmedAssertionID is a free data retrieval call binding the contract method 0xa56ba93b. +// +// Solidity: function lastConfirmedAssertionID() view returns(uint256) +func (_Rollup *RollupSession) LastConfirmedAssertionID() (*big.Int, error) { + return _Rollup.Contract.LastConfirmedAssertionID(&_Rollup.CallOpts) +} + +// LastConfirmedAssertionID is a free data retrieval call binding the contract method 0xa56ba93b. +// +// Solidity: function lastConfirmedAssertionID() view returns(uint256) +func (_Rollup *RollupCallerSession) LastConfirmedAssertionID() (*big.Int, error) { + return _Rollup.Contract.LastConfirmedAssertionID(&_Rollup.CallOpts) +} + +// LastCreatedAssertionID is a free data retrieval call binding the contract method 0x107035a4. +// +// Solidity: function lastCreatedAssertionID() view returns(uint256) +func (_Rollup *RollupCaller) LastCreatedAssertionID(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Rollup.contract.Call(opts, &out, "lastCreatedAssertionID") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// LastCreatedAssertionID is a free data retrieval call binding the contract method 0x107035a4. +// +// Solidity: function lastCreatedAssertionID() view returns(uint256) +func (_Rollup *RollupSession) LastCreatedAssertionID() (*big.Int, error) { + return _Rollup.Contract.LastCreatedAssertionID(&_Rollup.CallOpts) +} + +// LastCreatedAssertionID is a free data retrieval call binding the contract method 0x107035a4. +// +// Solidity: function lastCreatedAssertionID() view returns(uint256) +func (_Rollup *RollupCallerSession) LastCreatedAssertionID() (*big.Int, error) { + return _Rollup.Contract.LastCreatedAssertionID(&_Rollup.CallOpts) +} + +// LastResolvedAssertionID is a free data retrieval call binding the contract method 0xb553ee84. +// +// Solidity: function lastResolvedAssertionID() view returns(uint256) +func (_Rollup *RollupCaller) LastResolvedAssertionID(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Rollup.contract.Call(opts, &out, "lastResolvedAssertionID") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// LastResolvedAssertionID is a free data retrieval call binding the contract method 0xb553ee84. +// +// Solidity: function lastResolvedAssertionID() view returns(uint256) +func (_Rollup *RollupSession) LastResolvedAssertionID() (*big.Int, error) { + return _Rollup.Contract.LastResolvedAssertionID(&_Rollup.CallOpts) +} + +// LastResolvedAssertionID is a free data retrieval call binding the contract method 0xb553ee84. +// +// Solidity: function lastResolvedAssertionID() view returns(uint256) +func (_Rollup *RollupCallerSession) LastResolvedAssertionID() (*big.Int, error) { + return _Rollup.Contract.LastResolvedAssertionID(&_Rollup.CallOpts) +} + +// LibAddressManager is a free data retrieval call binding the contract method 0x299ca478. +// +// Solidity: function libAddressManager() view returns(address) +func (_Rollup *RollupCaller) LibAddressManager(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _Rollup.contract.Call(opts, &out, "libAddressManager") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// LibAddressManager is a free data retrieval call binding the contract method 0x299ca478. +// +// Solidity: function libAddressManager() view returns(address) +func (_Rollup *RollupSession) LibAddressManager() (common.Address, error) { + return _Rollup.Contract.LibAddressManager(&_Rollup.CallOpts) +} + +// LibAddressManager is a free data retrieval call binding the contract method 0x299ca478. +// +// Solidity: function libAddressManager() view returns(address) +func (_Rollup *RollupCallerSession) LibAddressManager() (common.Address, error) { + return _Rollup.Contract.LibAddressManager(&_Rollup.CallOpts) +} + +// MinimumAssertionPeriod is a free data retrieval call binding the contract method 0x45e38b64. +// +// Solidity: function minimumAssertionPeriod() view returns(uint256) +func (_Rollup *RollupCaller) MinimumAssertionPeriod(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Rollup.contract.Call(opts, &out, "minimumAssertionPeriod") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// MinimumAssertionPeriod is a free data retrieval call binding the contract method 0x45e38b64. +// +// Solidity: function minimumAssertionPeriod() view returns(uint256) +func (_Rollup *RollupSession) MinimumAssertionPeriod() (*big.Int, error) { + return _Rollup.Contract.MinimumAssertionPeriod(&_Rollup.CallOpts) +} + +// MinimumAssertionPeriod is a free data retrieval call binding the contract method 0x45e38b64. +// +// Solidity: function minimumAssertionPeriod() view returns(uint256) +func (_Rollup *RollupCallerSession) MinimumAssertionPeriod() (*big.Int, error) { + return _Rollup.Contract.MinimumAssertionPeriod(&_Rollup.CallOpts) +} + +// NumStakers is a free data retrieval call binding the contract method 0x6c8b052a. +// +// Solidity: function numStakers() view returns(uint256) +func (_Rollup *RollupCaller) NumStakers(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Rollup.contract.Call(opts, &out, "numStakers") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// NumStakers is a free data retrieval call binding the contract method 0x6c8b052a. +// +// Solidity: function numStakers() view returns(uint256) +func (_Rollup *RollupSession) NumStakers() (*big.Int, error) { + return _Rollup.Contract.NumStakers(&_Rollup.CallOpts) +} + +// NumStakers is a free data retrieval call binding the contract method 0x6c8b052a. +// +// Solidity: function numStakers() view returns(uint256) +func (_Rollup *RollupCallerSession) NumStakers() (*big.Int, error) { + return _Rollup.Contract.NumStakers(&_Rollup.CallOpts) +} + +// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. +// +// Solidity: function owner() view returns(address) +func (_Rollup *RollupCaller) Owner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _Rollup.contract.Call(opts, &out, "owner") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. +// +// Solidity: function owner() view returns(address) +func (_Rollup *RollupSession) Owner() (common.Address, error) { + return _Rollup.Contract.Owner(&_Rollup.CallOpts) +} + +// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. +// +// Solidity: function owner() view returns(address) +func (_Rollup *RollupCallerSession) Owner() (common.Address, error) { + return _Rollup.Contract.Owner(&_Rollup.CallOpts) +} + +// Resolve is a free data retrieval call binding the contract method 0x461a4478. +// +// Solidity: function resolve(string _name) view returns(address) +func (_Rollup *RollupCaller) Resolve(opts *bind.CallOpts, _name string) (common.Address, error) { + var out []interface{} + err := _Rollup.contract.Call(opts, &out, "resolve", _name) + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// Resolve is a free data retrieval call binding the contract method 0x461a4478. +// +// Solidity: function resolve(string _name) view returns(address) +func (_Rollup *RollupSession) Resolve(_name string) (common.Address, error) { + return _Rollup.Contract.Resolve(&_Rollup.CallOpts, _name) +} + +// Resolve is a free data retrieval call binding the contract method 0x461a4478. +// +// Solidity: function resolve(string _name) view returns(address) +func (_Rollup *RollupCallerSession) Resolve(_name string) (common.Address, error) { + return _Rollup.Contract.Resolve(&_Rollup.CallOpts, _name) +} + +// StakeToken is a free data retrieval call binding the contract method 0x51ed6a30. +// +// Solidity: function stakeToken() view returns(address) +func (_Rollup *RollupCaller) StakeToken(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _Rollup.contract.Call(opts, &out, "stakeToken") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// StakeToken is a free data retrieval call binding the contract method 0x51ed6a30. +// +// Solidity: function stakeToken() view returns(address) +func (_Rollup *RollupSession) StakeToken() (common.Address, error) { + return _Rollup.Contract.StakeToken(&_Rollup.CallOpts) +} + +// StakeToken is a free data retrieval call binding the contract method 0x51ed6a30. +// +// Solidity: function stakeToken() view returns(address) +func (_Rollup *RollupCallerSession) StakeToken() (common.Address, error) { + return _Rollup.Contract.StakeToken(&_Rollup.CallOpts) +} + +// Stakers is a free data retrieval call binding the contract method 0x9168ae72. +// +// Solidity: function stakers(address ) view returns(bool isStaked, uint256 amountStaked, uint256 assertionID, address currentChallenge) +func (_Rollup *RollupCaller) Stakers(opts *bind.CallOpts, arg0 common.Address) (struct { + IsStaked bool + AmountStaked *big.Int + AssertionID *big.Int + CurrentChallenge common.Address +}, error) { + var out []interface{} + err := _Rollup.contract.Call(opts, &out, "stakers", arg0) + + outstruct := new(struct { + IsStaked bool + AmountStaked *big.Int + AssertionID *big.Int + CurrentChallenge common.Address + }) + if err != nil { + return *outstruct, err + } + + outstruct.IsStaked = *abi.ConvertType(out[0], new(bool)).(*bool) + outstruct.AmountStaked = *abi.ConvertType(out[1], new(*big.Int)).(**big.Int) + outstruct.AssertionID = *abi.ConvertType(out[2], new(*big.Int)).(**big.Int) + outstruct.CurrentChallenge = *abi.ConvertType(out[3], new(common.Address)).(*common.Address) + + return *outstruct, err + +} + +// Stakers is a free data retrieval call binding the contract method 0x9168ae72. +// +// Solidity: function stakers(address ) view returns(bool isStaked, uint256 amountStaked, uint256 assertionID, address currentChallenge) +func (_Rollup *RollupSession) Stakers(arg0 common.Address) (struct { + IsStaked bool + AmountStaked *big.Int + AssertionID *big.Int + CurrentChallenge common.Address +}, error) { + return _Rollup.Contract.Stakers(&_Rollup.CallOpts, arg0) +} + +// Stakers is a free data retrieval call binding the contract method 0x9168ae72. +// +// Solidity: function stakers(address ) view returns(bool isStaked, uint256 amountStaked, uint256 assertionID, address currentChallenge) +func (_Rollup *RollupCallerSession) Stakers(arg0 common.Address) (struct { + IsStaked bool + AmountStaked *big.Int + AssertionID *big.Int + CurrentChallenge common.Address +}, error) { + return _Rollup.Contract.Stakers(&_Rollup.CallOpts, arg0) +} + +// Verifier is a free data retrieval call binding the contract method 0x2b7ac3f3. +// +// Solidity: function verifier() view returns(address) +func (_Rollup *RollupCaller) Verifier(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _Rollup.contract.Call(opts, &out, "verifier") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// Verifier is a free data retrieval call binding the contract method 0x2b7ac3f3. +// +// Solidity: function verifier() view returns(address) +func (_Rollup *RollupSession) Verifier() (common.Address, error) { + return _Rollup.Contract.Verifier(&_Rollup.CallOpts) +} + +// Verifier is a free data retrieval call binding the contract method 0x2b7ac3f3. +// +// Solidity: function verifier() view returns(address) +func (_Rollup *RollupCallerSession) Verifier() (common.Address, error) { + return _Rollup.Contract.Verifier(&_Rollup.CallOpts) +} + +// Whitelist is a free data retrieval call binding the contract method 0x9b19251a. +// +// Solidity: function whitelist(address ) view returns(bool) +func (_Rollup *RollupCaller) Whitelist(opts *bind.CallOpts, arg0 common.Address) (bool, error) { + var out []interface{} + err := _Rollup.contract.Call(opts, &out, "whitelist", arg0) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// Whitelist is a free data retrieval call binding the contract method 0x9b19251a. +// +// Solidity: function whitelist(address ) view returns(bool) +func (_Rollup *RollupSession) Whitelist(arg0 common.Address) (bool, error) { + return _Rollup.Contract.Whitelist(&_Rollup.CallOpts, arg0) +} + +// Whitelist is a free data retrieval call binding the contract method 0x9b19251a. +// +// Solidity: function whitelist(address ) view returns(bool) +func (_Rollup *RollupCallerSession) Whitelist(arg0 common.Address) (bool, error) { + return _Rollup.Contract.Whitelist(&_Rollup.CallOpts, arg0) +} + +// WithdrawableFunds is a free data retrieval call binding the contract method 0x2f30cabd. +// +// Solidity: function withdrawableFunds(address ) view returns(uint256) +func (_Rollup *RollupCaller) WithdrawableFunds(opts *bind.CallOpts, arg0 common.Address) (*big.Int, error) { + var out []interface{} + err := _Rollup.contract.Call(opts, &out, "withdrawableFunds", arg0) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// WithdrawableFunds is a free data retrieval call binding the contract method 0x2f30cabd. +// +// Solidity: function withdrawableFunds(address ) view returns(uint256) +func (_Rollup *RollupSession) WithdrawableFunds(arg0 common.Address) (*big.Int, error) { + return _Rollup.Contract.WithdrawableFunds(&_Rollup.CallOpts, arg0) +} + +// WithdrawableFunds is a free data retrieval call binding the contract method 0x2f30cabd. +// +// Solidity: function withdrawableFunds(address ) view returns(uint256) +func (_Rollup *RollupCallerSession) WithdrawableFunds(arg0 common.Address) (*big.Int, error) { + return _Rollup.Contract.WithdrawableFunds(&_Rollup.CallOpts, arg0) +} + +// Zombies is a free data retrieval call binding the contract method 0x2052465e. +// +// Solidity: function zombies(uint256 ) view returns(address stakerAddress, uint256 lastAssertionID) +func (_Rollup *RollupCaller) Zombies(opts *bind.CallOpts, arg0 *big.Int) (struct { + StakerAddress common.Address + LastAssertionID *big.Int +}, error) { + var out []interface{} + err := _Rollup.contract.Call(opts, &out, "zombies", arg0) + + outstruct := new(struct { + StakerAddress common.Address + LastAssertionID *big.Int + }) + if err != nil { + return *outstruct, err + } + + outstruct.StakerAddress = *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + outstruct.LastAssertionID = *abi.ConvertType(out[1], new(*big.Int)).(**big.Int) + + return *outstruct, err + +} + +// Zombies is a free data retrieval call binding the contract method 0x2052465e. +// +// Solidity: function zombies(uint256 ) view returns(address stakerAddress, uint256 lastAssertionID) +func (_Rollup *RollupSession) Zombies(arg0 *big.Int) (struct { + StakerAddress common.Address + LastAssertionID *big.Int +}, error) { + return _Rollup.Contract.Zombies(&_Rollup.CallOpts, arg0) +} + +// Zombies is a free data retrieval call binding the contract method 0x2052465e. +// +// Solidity: function zombies(uint256 ) view returns(address stakerAddress, uint256 lastAssertionID) +func (_Rollup *RollupCallerSession) Zombies(arg0 *big.Int) (struct { + StakerAddress common.Address + LastAssertionID *big.Int +}, error) { + return _Rollup.Contract.Zombies(&_Rollup.CallOpts, arg0) +} + +// AddToWhitelist is a paid mutator transaction binding the contract method 0x7f649783. +// +// Solidity: function addToWhitelist(address[] toAddAddresses) returns() +func (_Rollup *RollupTransactor) AddToWhitelist(opts *bind.TransactOpts, toAddAddresses []common.Address) (*types.Transaction, error) { + return _Rollup.contract.Transact(opts, "addToWhitelist", toAddAddresses) +} + +// AddToWhitelist is a paid mutator transaction binding the contract method 0x7f649783. +// +// Solidity: function addToWhitelist(address[] toAddAddresses) returns() +func (_Rollup *RollupSession) AddToWhitelist(toAddAddresses []common.Address) (*types.Transaction, error) { + return _Rollup.Contract.AddToWhitelist(&_Rollup.TransactOpts, toAddAddresses) +} + +// AddToWhitelist is a paid mutator transaction binding the contract method 0x7f649783. +// +// Solidity: function addToWhitelist(address[] toAddAddresses) returns() +func (_Rollup *RollupTransactorSession) AddToWhitelist(toAddAddresses []common.Address) (*types.Transaction, error) { + return _Rollup.Contract.AddToWhitelist(&_Rollup.TransactOpts, toAddAddresses) +} + +// AdvanceStake is a paid mutator transaction binding the contract method 0x8821b2ae. +// +// Solidity: function advanceStake(uint256 assertionID) returns() +func (_Rollup *RollupTransactor) AdvanceStake(opts *bind.TransactOpts, assertionID *big.Int) (*types.Transaction, error) { + return _Rollup.contract.Transact(opts, "advanceStake", assertionID) +} + +// AdvanceStake is a paid mutator transaction binding the contract method 0x8821b2ae. +// +// Solidity: function advanceStake(uint256 assertionID) returns() +func (_Rollup *RollupSession) AdvanceStake(assertionID *big.Int) (*types.Transaction, error) { + return _Rollup.Contract.AdvanceStake(&_Rollup.TransactOpts, assertionID) +} + +// AdvanceStake is a paid mutator transaction binding the contract method 0x8821b2ae. +// +// Solidity: function advanceStake(uint256 assertionID) returns() +func (_Rollup *RollupTransactorSession) AdvanceStake(assertionID *big.Int) (*types.Transaction, error) { + return _Rollup.Contract.AdvanceStake(&_Rollup.TransactOpts, assertionID) +} + +// ChallengeAssertion is a paid mutator transaction binding the contract method 0x2f06d1b0. +// +// Solidity: function challengeAssertion(address[2] players, uint256[2] assertionIDs) returns(address) +func (_Rollup *RollupTransactor) ChallengeAssertion(opts *bind.TransactOpts, players [2]common.Address, assertionIDs [2]*big.Int) (*types.Transaction, error) { + return _Rollup.contract.Transact(opts, "challengeAssertion", players, assertionIDs) +} + +// ChallengeAssertion is a paid mutator transaction binding the contract method 0x2f06d1b0. +// +// Solidity: function challengeAssertion(address[2] players, uint256[2] assertionIDs) returns(address) +func (_Rollup *RollupSession) ChallengeAssertion(players [2]common.Address, assertionIDs [2]*big.Int) (*types.Transaction, error) { + return _Rollup.Contract.ChallengeAssertion(&_Rollup.TransactOpts, players, assertionIDs) +} + +// ChallengeAssertion is a paid mutator transaction binding the contract method 0x2f06d1b0. +// +// Solidity: function challengeAssertion(address[2] players, uint256[2] assertionIDs) returns(address) +func (_Rollup *RollupTransactorSession) ChallengeAssertion(players [2]common.Address, assertionIDs [2]*big.Int) (*types.Transaction, error) { + return _Rollup.Contract.ChallengeAssertion(&_Rollup.TransactOpts, players, assertionIDs) +} + +// CompleteChallenge is a paid mutator transaction binding the contract method 0xfa7803e6. +// +// Solidity: function completeChallenge(address winner, address loser) returns() +func (_Rollup *RollupTransactor) CompleteChallenge(opts *bind.TransactOpts, winner common.Address, loser common.Address) (*types.Transaction, error) { + return _Rollup.contract.Transact(opts, "completeChallenge", winner, loser) +} + +// CompleteChallenge is a paid mutator transaction binding the contract method 0xfa7803e6. +// +// Solidity: function completeChallenge(address winner, address loser) returns() +func (_Rollup *RollupSession) CompleteChallenge(winner common.Address, loser common.Address) (*types.Transaction, error) { + return _Rollup.Contract.CompleteChallenge(&_Rollup.TransactOpts, winner, loser) +} + +// CompleteChallenge is a paid mutator transaction binding the contract method 0xfa7803e6. +// +// Solidity: function completeChallenge(address winner, address loser) returns() +func (_Rollup *RollupTransactorSession) CompleteChallenge(winner common.Address, loser common.Address) (*types.Transaction, error) { + return _Rollup.Contract.CompleteChallenge(&_Rollup.TransactOpts, winner, loser) +} + +// ConfirmFirstUnresolvedAssertion is a paid mutator transaction binding the contract method 0x2906040e. +// +// Solidity: function confirmFirstUnresolvedAssertion() returns() +func (_Rollup *RollupTransactor) ConfirmFirstUnresolvedAssertion(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Rollup.contract.Transact(opts, "confirmFirstUnresolvedAssertion") +} + +// ConfirmFirstUnresolvedAssertion is a paid mutator transaction binding the contract method 0x2906040e. +// +// Solidity: function confirmFirstUnresolvedAssertion() returns() +func (_Rollup *RollupSession) ConfirmFirstUnresolvedAssertion() (*types.Transaction, error) { + return _Rollup.Contract.ConfirmFirstUnresolvedAssertion(&_Rollup.TransactOpts) +} + +// ConfirmFirstUnresolvedAssertion is a paid mutator transaction binding the contract method 0x2906040e. +// +// Solidity: function confirmFirstUnresolvedAssertion() returns() +func (_Rollup *RollupTransactorSession) ConfirmFirstUnresolvedAssertion() (*types.Transaction, error) { + return _Rollup.Contract.ConfirmFirstUnresolvedAssertion(&_Rollup.TransactOpts) +} + +// CreateAssertion is a paid mutator transaction binding the contract method 0xb6da898f. +// +// Solidity: function createAssertion(bytes32 vmHash, uint256 inboxSize) returns() +func (_Rollup *RollupTransactor) CreateAssertion(opts *bind.TransactOpts, vmHash [32]byte, inboxSize *big.Int) (*types.Transaction, error) { + return _Rollup.contract.Transact(opts, "createAssertion", vmHash, inboxSize) +} + +// CreateAssertion is a paid mutator transaction binding the contract method 0xb6da898f. +// +// Solidity: function createAssertion(bytes32 vmHash, uint256 inboxSize) returns() +func (_Rollup *RollupSession) CreateAssertion(vmHash [32]byte, inboxSize *big.Int) (*types.Transaction, error) { + return _Rollup.Contract.CreateAssertion(&_Rollup.TransactOpts, vmHash, inboxSize) +} + +// CreateAssertion is a paid mutator transaction binding the contract method 0xb6da898f. +// +// Solidity: function createAssertion(bytes32 vmHash, uint256 inboxSize) returns() +func (_Rollup *RollupTransactorSession) CreateAssertion(vmHash [32]byte, inboxSize *big.Int) (*types.Transaction, error) { + return _Rollup.Contract.CreateAssertion(&_Rollup.TransactOpts, vmHash, inboxSize) +} + +// CreateAssertionWithStateBatch is a paid mutator transaction binding the contract method 0x49cd3004. +// +// Solidity: function createAssertionWithStateBatch(bytes32 vmHash, uint256 inboxSize, bytes32[] _batch, uint256 _shouldStartAtElement, bytes _signature) returns() +func (_Rollup *RollupTransactor) CreateAssertionWithStateBatch(opts *bind.TransactOpts, vmHash [32]byte, inboxSize *big.Int, _batch [][32]byte, _shouldStartAtElement *big.Int, _signature []byte) (*types.Transaction, error) { + return _Rollup.contract.Transact(opts, "createAssertionWithStateBatch", vmHash, inboxSize, _batch, _shouldStartAtElement, _signature) +} + +// CreateAssertionWithStateBatch is a paid mutator transaction binding the contract method 0x49cd3004. +// +// Solidity: function createAssertionWithStateBatch(bytes32 vmHash, uint256 inboxSize, bytes32[] _batch, uint256 _shouldStartAtElement, bytes _signature) returns() +func (_Rollup *RollupSession) CreateAssertionWithStateBatch(vmHash [32]byte, inboxSize *big.Int, _batch [][32]byte, _shouldStartAtElement *big.Int, _signature []byte) (*types.Transaction, error) { + return _Rollup.Contract.CreateAssertionWithStateBatch(&_Rollup.TransactOpts, vmHash, inboxSize, _batch, _shouldStartAtElement, _signature) +} + +// CreateAssertionWithStateBatch is a paid mutator transaction binding the contract method 0x49cd3004. +// +// Solidity: function createAssertionWithStateBatch(bytes32 vmHash, uint256 inboxSize, bytes32[] _batch, uint256 _shouldStartAtElement, bytes _signature) returns() +func (_Rollup *RollupTransactorSession) CreateAssertionWithStateBatch(vmHash [32]byte, inboxSize *big.Int, _batch [][32]byte, _shouldStartAtElement *big.Int, _signature []byte) (*types.Transaction, error) { + return _Rollup.Contract.CreateAssertionWithStateBatch(&_Rollup.TransactOpts, vmHash, inboxSize, _batch, _shouldStartAtElement, _signature) +} + +// Initialize is a paid mutator transaction binding the contract method 0x7d6c971f. +// +// Solidity: function initialize(address _owner, address _verifier, address _stakeToken, address _libAddressManager, address _assertionMap, uint256 _confirmationPeriod, uint256 _challengePeriod, uint256 _minimumAssertionPeriod, uint256 _baseStakeAmount, bytes32 _initialVMhash, address[] whitelists) returns() +func (_Rollup *RollupTransactor) Initialize(opts *bind.TransactOpts, _owner common.Address, _verifier common.Address, _stakeToken common.Address, _libAddressManager common.Address, _assertionMap common.Address, _confirmationPeriod *big.Int, _challengePeriod *big.Int, _minimumAssertionPeriod *big.Int, _baseStakeAmount *big.Int, _initialVMhash [32]byte, whitelists []common.Address) (*types.Transaction, error) { + return _Rollup.contract.Transact(opts, "initialize", _owner, _verifier, _stakeToken, _libAddressManager, _assertionMap, _confirmationPeriod, _challengePeriod, _minimumAssertionPeriod, _baseStakeAmount, _initialVMhash, whitelists) +} + +// Initialize is a paid mutator transaction binding the contract method 0x7d6c971f. +// +// Solidity: function initialize(address _owner, address _verifier, address _stakeToken, address _libAddressManager, address _assertionMap, uint256 _confirmationPeriod, uint256 _challengePeriod, uint256 _minimumAssertionPeriod, uint256 _baseStakeAmount, bytes32 _initialVMhash, address[] whitelists) returns() +func (_Rollup *RollupSession) Initialize(_owner common.Address, _verifier common.Address, _stakeToken common.Address, _libAddressManager common.Address, _assertionMap common.Address, _confirmationPeriod *big.Int, _challengePeriod *big.Int, _minimumAssertionPeriod *big.Int, _baseStakeAmount *big.Int, _initialVMhash [32]byte, whitelists []common.Address) (*types.Transaction, error) { + return _Rollup.Contract.Initialize(&_Rollup.TransactOpts, _owner, _verifier, _stakeToken, _libAddressManager, _assertionMap, _confirmationPeriod, _challengePeriod, _minimumAssertionPeriod, _baseStakeAmount, _initialVMhash, whitelists) +} + +// Initialize is a paid mutator transaction binding the contract method 0x7d6c971f. +// +// Solidity: function initialize(address _owner, address _verifier, address _stakeToken, address _libAddressManager, address _assertionMap, uint256 _confirmationPeriod, uint256 _challengePeriod, uint256 _minimumAssertionPeriod, uint256 _baseStakeAmount, bytes32 _initialVMhash, address[] whitelists) returns() +func (_Rollup *RollupTransactorSession) Initialize(_owner common.Address, _verifier common.Address, _stakeToken common.Address, _libAddressManager common.Address, _assertionMap common.Address, _confirmationPeriod *big.Int, _challengePeriod *big.Int, _minimumAssertionPeriod *big.Int, _baseStakeAmount *big.Int, _initialVMhash [32]byte, whitelists []common.Address) (*types.Transaction, error) { + return _Rollup.Contract.Initialize(&_Rollup.TransactOpts, _owner, _verifier, _stakeToken, _libAddressManager, _assertionMap, _confirmationPeriod, _challengePeriod, _minimumAssertionPeriod, _baseStakeAmount, _initialVMhash, whitelists) +} + +// RejectFirstUnresolvedAssertion is a paid mutator transaction binding the contract method 0x30b26075. +// +// Solidity: function rejectFirstUnresolvedAssertion() returns() +func (_Rollup *RollupTransactor) RejectFirstUnresolvedAssertion(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Rollup.contract.Transact(opts, "rejectFirstUnresolvedAssertion") +} + +// RejectFirstUnresolvedAssertion is a paid mutator transaction binding the contract method 0x30b26075. +// +// Solidity: function rejectFirstUnresolvedAssertion() returns() +func (_Rollup *RollupSession) RejectFirstUnresolvedAssertion() (*types.Transaction, error) { + return _Rollup.Contract.RejectFirstUnresolvedAssertion(&_Rollup.TransactOpts) +} + +// RejectFirstUnresolvedAssertion is a paid mutator transaction binding the contract method 0x30b26075. +// +// Solidity: function rejectFirstUnresolvedAssertion() returns() +func (_Rollup *RollupTransactorSession) RejectFirstUnresolvedAssertion() (*types.Transaction, error) { + return _Rollup.Contract.RejectFirstUnresolvedAssertion(&_Rollup.TransactOpts) +} + +// RemoveFromWhitelist is a paid mutator transaction binding the contract method 0x548db174. +// +// Solidity: function removeFromWhitelist(address[] toRemoveAddresses) returns() +func (_Rollup *RollupTransactor) RemoveFromWhitelist(opts *bind.TransactOpts, toRemoveAddresses []common.Address) (*types.Transaction, error) { + return _Rollup.contract.Transact(opts, "removeFromWhitelist", toRemoveAddresses) +} + +// RemoveFromWhitelist is a paid mutator transaction binding the contract method 0x548db174. +// +// Solidity: function removeFromWhitelist(address[] toRemoveAddresses) returns() +func (_Rollup *RollupSession) RemoveFromWhitelist(toRemoveAddresses []common.Address) (*types.Transaction, error) { + return _Rollup.Contract.RemoveFromWhitelist(&_Rollup.TransactOpts, toRemoveAddresses) +} + +// RemoveFromWhitelist is a paid mutator transaction binding the contract method 0x548db174. +// +// Solidity: function removeFromWhitelist(address[] toRemoveAddresses) returns() +func (_Rollup *RollupTransactorSession) RemoveFromWhitelist(toRemoveAddresses []common.Address) (*types.Transaction, error) { + return _Rollup.Contract.RemoveFromWhitelist(&_Rollup.TransactOpts, toRemoveAddresses) +} + +// RemoveOldZombies is a paid mutator transaction binding the contract method 0x8c669739. +// +// Solidity: function removeOldZombies() returns() +func (_Rollup *RollupTransactor) RemoveOldZombies(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Rollup.contract.Transact(opts, "removeOldZombies") +} + +// RemoveOldZombies is a paid mutator transaction binding the contract method 0x8c669739. +// +// Solidity: function removeOldZombies() returns() +func (_Rollup *RollupSession) RemoveOldZombies() (*types.Transaction, error) { + return _Rollup.Contract.RemoveOldZombies(&_Rollup.TransactOpts) +} + +// RemoveOldZombies is a paid mutator transaction binding the contract method 0x8c669739. +// +// Solidity: function removeOldZombies() returns() +func (_Rollup *RollupTransactorSession) RemoveOldZombies() (*types.Transaction, error) { + return _Rollup.Contract.RemoveOldZombies(&_Rollup.TransactOpts) +} + +// RemoveStake is a paid mutator transaction binding the contract method 0xfe2ba848. +// +// Solidity: function removeStake(address stakerAddress) returns() +func (_Rollup *RollupTransactor) RemoveStake(opts *bind.TransactOpts, stakerAddress common.Address) (*types.Transaction, error) { + return _Rollup.contract.Transact(opts, "removeStake", stakerAddress) +} + +// RemoveStake is a paid mutator transaction binding the contract method 0xfe2ba848. +// +// Solidity: function removeStake(address stakerAddress) returns() +func (_Rollup *RollupSession) RemoveStake(stakerAddress common.Address) (*types.Transaction, error) { + return _Rollup.Contract.RemoveStake(&_Rollup.TransactOpts, stakerAddress) +} + +// RemoveStake is a paid mutator transaction binding the contract method 0xfe2ba848. +// +// Solidity: function removeStake(address stakerAddress) returns() +func (_Rollup *RollupTransactorSession) RemoveStake(stakerAddress common.Address) (*types.Transaction, error) { + return _Rollup.Contract.RemoveStake(&_Rollup.TransactOpts, stakerAddress) +} + +// Stake is a paid mutator transaction binding the contract method 0x3a4b66f1. +// +// Solidity: function stake() payable returns() +func (_Rollup *RollupTransactor) Stake(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Rollup.contract.Transact(opts, "stake") +} + +// Stake is a paid mutator transaction binding the contract method 0x3a4b66f1. +// +// Solidity: function stake() payable returns() +func (_Rollup *RollupSession) Stake() (*types.Transaction, error) { + return _Rollup.Contract.Stake(&_Rollup.TransactOpts) +} + +// Stake is a paid mutator transaction binding the contract method 0x3a4b66f1. +// +// Solidity: function stake() payable returns() +func (_Rollup *RollupTransactorSession) Stake() (*types.Transaction, error) { + return _Rollup.Contract.Stake(&_Rollup.TransactOpts) +} + +// Unstake is a paid mutator transaction binding the contract method 0x2e17de78. +// +// Solidity: function unstake(uint256 stakeAmount) returns() +func (_Rollup *RollupTransactor) Unstake(opts *bind.TransactOpts, stakeAmount *big.Int) (*types.Transaction, error) { + return _Rollup.contract.Transact(opts, "unstake", stakeAmount) +} + +// Unstake is a paid mutator transaction binding the contract method 0x2e17de78. +// +// Solidity: function unstake(uint256 stakeAmount) returns() +func (_Rollup *RollupSession) Unstake(stakeAmount *big.Int) (*types.Transaction, error) { + return _Rollup.Contract.Unstake(&_Rollup.TransactOpts, stakeAmount) +} + +// Unstake is a paid mutator transaction binding the contract method 0x2e17de78. +// +// Solidity: function unstake(uint256 stakeAmount) returns() +func (_Rollup *RollupTransactorSession) Unstake(stakeAmount *big.Int) (*types.Transaction, error) { + return _Rollup.Contract.Unstake(&_Rollup.TransactOpts, stakeAmount) +} + +// Withdraw is a paid mutator transaction binding the contract method 0x3ccfd60b. +// +// Solidity: function withdraw() returns() +func (_Rollup *RollupTransactor) Withdraw(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Rollup.contract.Transact(opts, "withdraw") +} + +// Withdraw is a paid mutator transaction binding the contract method 0x3ccfd60b. +// +// Solidity: function withdraw() returns() +func (_Rollup *RollupSession) Withdraw() (*types.Transaction, error) { + return _Rollup.Contract.Withdraw(&_Rollup.TransactOpts) +} + +// Withdraw is a paid mutator transaction binding the contract method 0x3ccfd60b. +// +// Solidity: function withdraw() returns() +func (_Rollup *RollupTransactorSession) Withdraw() (*types.Transaction, error) { + return _Rollup.Contract.Withdraw(&_Rollup.TransactOpts) +} + +// RollupAssertionChallengedIterator is returned from FilterAssertionChallenged and is used to iterate over the raw logs and unpacked data for AssertionChallenged events raised by the Rollup contract. +type RollupAssertionChallengedIterator struct { + Event *RollupAssertionChallenged // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *RollupAssertionChallengedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(RollupAssertionChallenged) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(RollupAssertionChallenged) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *RollupAssertionChallengedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *RollupAssertionChallengedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// RollupAssertionChallenged represents a AssertionChallenged event raised by the Rollup contract. +type RollupAssertionChallenged struct { + AssertionID *big.Int + ChallengeAddr common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterAssertionChallenged is a free log retrieval operation binding the contract event 0xd0ebe74b4f7d89a9b0fdc9d95f887a7b925c6c7300b5c4b2c3304d97925840fa. +// +// Solidity: event AssertionChallenged(uint256 assertionID, address challengeAddr) +func (_Rollup *RollupFilterer) FilterAssertionChallenged(opts *bind.FilterOpts) (*RollupAssertionChallengedIterator, error) { + + logs, sub, err := _Rollup.contract.FilterLogs(opts, "AssertionChallenged") + if err != nil { + return nil, err + } + return &RollupAssertionChallengedIterator{contract: _Rollup.contract, event: "AssertionChallenged", logs: logs, sub: sub}, nil +} + +// WatchAssertionChallenged is a free log subscription operation binding the contract event 0xd0ebe74b4f7d89a9b0fdc9d95f887a7b925c6c7300b5c4b2c3304d97925840fa. +// +// Solidity: event AssertionChallenged(uint256 assertionID, address challengeAddr) +func (_Rollup *RollupFilterer) WatchAssertionChallenged(opts *bind.WatchOpts, sink chan<- *RollupAssertionChallenged) (event.Subscription, error) { + + logs, sub, err := _Rollup.contract.WatchLogs(opts, "AssertionChallenged") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(RollupAssertionChallenged) + if err := _Rollup.contract.UnpackLog(event, "AssertionChallenged", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseAssertionChallenged is a log parse operation binding the contract event 0xd0ebe74b4f7d89a9b0fdc9d95f887a7b925c6c7300b5c4b2c3304d97925840fa. +// +// Solidity: event AssertionChallenged(uint256 assertionID, address challengeAddr) +func (_Rollup *RollupFilterer) ParseAssertionChallenged(log types.Log) (*RollupAssertionChallenged, error) { + event := new(RollupAssertionChallenged) + if err := _Rollup.contract.UnpackLog(event, "AssertionChallenged", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// RollupAssertionConfirmedIterator is returned from FilterAssertionConfirmed and is used to iterate over the raw logs and unpacked data for AssertionConfirmed events raised by the Rollup contract. +type RollupAssertionConfirmedIterator struct { + Event *RollupAssertionConfirmed // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *RollupAssertionConfirmedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(RollupAssertionConfirmed) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(RollupAssertionConfirmed) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *RollupAssertionConfirmedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *RollupAssertionConfirmedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// RollupAssertionConfirmed represents a AssertionConfirmed event raised by the Rollup contract. +type RollupAssertionConfirmed struct { + AssertionID *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterAssertionConfirmed is a free log retrieval operation binding the contract event 0x453430d123684340024ae0a229704bdab39c93dc48bb5a0b4bc83142d95d48ef. +// +// Solidity: event AssertionConfirmed(uint256 assertionID) +func (_Rollup *RollupFilterer) FilterAssertionConfirmed(opts *bind.FilterOpts) (*RollupAssertionConfirmedIterator, error) { + + logs, sub, err := _Rollup.contract.FilterLogs(opts, "AssertionConfirmed") + if err != nil { + return nil, err + } + return &RollupAssertionConfirmedIterator{contract: _Rollup.contract, event: "AssertionConfirmed", logs: logs, sub: sub}, nil +} + +// WatchAssertionConfirmed is a free log subscription operation binding the contract event 0x453430d123684340024ae0a229704bdab39c93dc48bb5a0b4bc83142d95d48ef. +// +// Solidity: event AssertionConfirmed(uint256 assertionID) +func (_Rollup *RollupFilterer) WatchAssertionConfirmed(opts *bind.WatchOpts, sink chan<- *RollupAssertionConfirmed) (event.Subscription, error) { + + logs, sub, err := _Rollup.contract.WatchLogs(opts, "AssertionConfirmed") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(RollupAssertionConfirmed) + if err := _Rollup.contract.UnpackLog(event, "AssertionConfirmed", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseAssertionConfirmed is a log parse operation binding the contract event 0x453430d123684340024ae0a229704bdab39c93dc48bb5a0b4bc83142d95d48ef. +// +// Solidity: event AssertionConfirmed(uint256 assertionID) +func (_Rollup *RollupFilterer) ParseAssertionConfirmed(log types.Log) (*RollupAssertionConfirmed, error) { + event := new(RollupAssertionConfirmed) + if err := _Rollup.contract.UnpackLog(event, "AssertionConfirmed", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// RollupAssertionCreatedIterator is returned from FilterAssertionCreated and is used to iterate over the raw logs and unpacked data for AssertionCreated events raised by the Rollup contract. +type RollupAssertionCreatedIterator struct { + Event *RollupAssertionCreated // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *RollupAssertionCreatedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(RollupAssertionCreated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(RollupAssertionCreated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *RollupAssertionCreatedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *RollupAssertionCreatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// RollupAssertionCreated represents a AssertionCreated event raised by the Rollup contract. +type RollupAssertionCreated struct { + AssertionID *big.Int + AsserterAddr common.Address + VmHash [32]byte + InboxSize *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterAssertionCreated is a free log retrieval operation binding the contract event 0x5c610f28399ecc14b66149012a0197a5e3257a8c397125afee95d1cf4b950734. +// +// Solidity: event AssertionCreated(uint256 assertionID, address asserterAddr, bytes32 vmHash, uint256 inboxSize) +func (_Rollup *RollupFilterer) FilterAssertionCreated(opts *bind.FilterOpts) (*RollupAssertionCreatedIterator, error) { + + logs, sub, err := _Rollup.contract.FilterLogs(opts, "AssertionCreated") + if err != nil { + return nil, err + } + return &RollupAssertionCreatedIterator{contract: _Rollup.contract, event: "AssertionCreated", logs: logs, sub: sub}, nil +} + +// WatchAssertionCreated is a free log subscription operation binding the contract event 0x5c610f28399ecc14b66149012a0197a5e3257a8c397125afee95d1cf4b950734. +// +// Solidity: event AssertionCreated(uint256 assertionID, address asserterAddr, bytes32 vmHash, uint256 inboxSize) +func (_Rollup *RollupFilterer) WatchAssertionCreated(opts *bind.WatchOpts, sink chan<- *RollupAssertionCreated) (event.Subscription, error) { + + logs, sub, err := _Rollup.contract.WatchLogs(opts, "AssertionCreated") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(RollupAssertionCreated) + if err := _Rollup.contract.UnpackLog(event, "AssertionCreated", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseAssertionCreated is a log parse operation binding the contract event 0x5c610f28399ecc14b66149012a0197a5e3257a8c397125afee95d1cf4b950734. +// +// Solidity: event AssertionCreated(uint256 assertionID, address asserterAddr, bytes32 vmHash, uint256 inboxSize) +func (_Rollup *RollupFilterer) ParseAssertionCreated(log types.Log) (*RollupAssertionCreated, error) { + event := new(RollupAssertionCreated) + if err := _Rollup.contract.UnpackLog(event, "AssertionCreated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// RollupAssertionRejectedIterator is returned from FilterAssertionRejected and is used to iterate over the raw logs and unpacked data for AssertionRejected events raised by the Rollup contract. +type RollupAssertionRejectedIterator struct { + Event *RollupAssertionRejected // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *RollupAssertionRejectedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(RollupAssertionRejected) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(RollupAssertionRejected) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *RollupAssertionRejectedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *RollupAssertionRejectedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// RollupAssertionRejected represents a AssertionRejected event raised by the Rollup contract. +type RollupAssertionRejected struct { + AssertionID *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterAssertionRejected is a free log retrieval operation binding the contract event 0x5b24ab8ceb442373727ac5c559a027521cb52db451c74710ebed9faa5fe15a7c. +// +// Solidity: event AssertionRejected(uint256 assertionID) +func (_Rollup *RollupFilterer) FilterAssertionRejected(opts *bind.FilterOpts) (*RollupAssertionRejectedIterator, error) { + + logs, sub, err := _Rollup.contract.FilterLogs(opts, "AssertionRejected") + if err != nil { + return nil, err + } + return &RollupAssertionRejectedIterator{contract: _Rollup.contract, event: "AssertionRejected", logs: logs, sub: sub}, nil +} + +// WatchAssertionRejected is a free log subscription operation binding the contract event 0x5b24ab8ceb442373727ac5c559a027521cb52db451c74710ebed9faa5fe15a7c. +// +// Solidity: event AssertionRejected(uint256 assertionID) +func (_Rollup *RollupFilterer) WatchAssertionRejected(opts *bind.WatchOpts, sink chan<- *RollupAssertionRejected) (event.Subscription, error) { + + logs, sub, err := _Rollup.contract.WatchLogs(opts, "AssertionRejected") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(RollupAssertionRejected) + if err := _Rollup.contract.UnpackLog(event, "AssertionRejected", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseAssertionRejected is a log parse operation binding the contract event 0x5b24ab8ceb442373727ac5c559a027521cb52db451c74710ebed9faa5fe15a7c. +// +// Solidity: event AssertionRejected(uint256 assertionID) +func (_Rollup *RollupFilterer) ParseAssertionRejected(log types.Log) (*RollupAssertionRejected, error) { + event := new(RollupAssertionRejected) + if err := _Rollup.contract.UnpackLog(event, "AssertionRejected", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// RollupInitializedIterator is returned from FilterInitialized and is used to iterate over the raw logs and unpacked data for Initialized events raised by the Rollup contract. +type RollupInitializedIterator struct { + Event *RollupInitialized // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *RollupInitializedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(RollupInitialized) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(RollupInitialized) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *RollupInitializedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *RollupInitializedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// RollupInitialized represents a Initialized event raised by the Rollup contract. +type RollupInitialized struct { + Version uint8 + Raw types.Log // Blockchain specific contextual infos +} + +// FilterInitialized is a free log retrieval operation binding the contract event 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498. +// +// Solidity: event Initialized(uint8 version) +func (_Rollup *RollupFilterer) FilterInitialized(opts *bind.FilterOpts) (*RollupInitializedIterator, error) { + + logs, sub, err := _Rollup.contract.FilterLogs(opts, "Initialized") + if err != nil { + return nil, err + } + return &RollupInitializedIterator{contract: _Rollup.contract, event: "Initialized", logs: logs, sub: sub}, nil +} + +// WatchInitialized is a free log subscription operation binding the contract event 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498. +// +// Solidity: event Initialized(uint8 version) +func (_Rollup *RollupFilterer) WatchInitialized(opts *bind.WatchOpts, sink chan<- *RollupInitialized) (event.Subscription, error) { + + logs, sub, err := _Rollup.contract.WatchLogs(opts, "Initialized") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(RollupInitialized) + if err := _Rollup.contract.UnpackLog(event, "Initialized", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseInitialized is a log parse operation binding the contract event 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498. +// +// Solidity: event Initialized(uint8 version) +func (_Rollup *RollupFilterer) ParseInitialized(log types.Log) (*RollupInitialized, error) { + event := new(RollupInitialized) + if err := _Rollup.contract.UnpackLog(event, "Initialized", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// RollupStakerStakedIterator is returned from FilterStakerStaked and is used to iterate over the raw logs and unpacked data for StakerStaked events raised by the Rollup contract. +type RollupStakerStakedIterator struct { + Event *RollupStakerStaked // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *RollupStakerStakedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(RollupStakerStaked) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(RollupStakerStaked) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *RollupStakerStakedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *RollupStakerStakedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// RollupStakerStaked represents a StakerStaked event raised by the Rollup contract. +type RollupStakerStaked struct { + StakerAddr common.Address + AssertionID *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterStakerStaked is a free log retrieval operation binding the contract event 0x617d31491414a4ab2bd831e566a31837fa7fb6582921c91dffbbe83fbca789f3. +// +// Solidity: event StakerStaked(address stakerAddr, uint256 assertionID) +func (_Rollup *RollupFilterer) FilterStakerStaked(opts *bind.FilterOpts) (*RollupStakerStakedIterator, error) { + + logs, sub, err := _Rollup.contract.FilterLogs(opts, "StakerStaked") + if err != nil { + return nil, err + } + return &RollupStakerStakedIterator{contract: _Rollup.contract, event: "StakerStaked", logs: logs, sub: sub}, nil +} + +// WatchStakerStaked is a free log subscription operation binding the contract event 0x617d31491414a4ab2bd831e566a31837fa7fb6582921c91dffbbe83fbca789f3. +// +// Solidity: event StakerStaked(address stakerAddr, uint256 assertionID) +func (_Rollup *RollupFilterer) WatchStakerStaked(opts *bind.WatchOpts, sink chan<- *RollupStakerStaked) (event.Subscription, error) { + + logs, sub, err := _Rollup.contract.WatchLogs(opts, "StakerStaked") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(RollupStakerStaked) + if err := _Rollup.contract.UnpackLog(event, "StakerStaked", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseStakerStaked is a log parse operation binding the contract event 0x617d31491414a4ab2bd831e566a31837fa7fb6582921c91dffbbe83fbca789f3. +// +// Solidity: event StakerStaked(address stakerAddr, uint256 assertionID) +func (_Rollup *RollupFilterer) ParseStakerStaked(log types.Log) (*RollupStakerStaked, error) { + event := new(RollupStakerStaked) + if err := _Rollup.contract.UnpackLog(event, "StakerStaked", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} diff --git a/fraud-proof/bindings/compile.sh b/fraud-proof/bindings/compile.sh new file mode 100755 index 000000000..6bba86a9f --- /dev/null +++ b/fraud-proof/bindings/compile.sh @@ -0,0 +1,3 @@ +#!/bin/bash +export NODE_OPTIONS="--max-old-space-size=9000" +cd ../../packages/contracts/ && npx hardhat compile diff --git a/fraud-proof/bindings/gen.go b/fraud-proof/bindings/gen.go new file mode 100644 index 000000000..8ee5ec74c --- /dev/null +++ b/fraud-proof/bindings/gen.go @@ -0,0 +1,20 @@ +// Copyright 2022, Specular contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package bindings + +//go:generate ./compile.sh +//go:generate go run github.com/ethereum/go-ethereum/cmd/abigen --abi ../../packages/contracts/abi/contracts/L1/fraud-proof/AssertionMap.sol/AssertionMap.json --pkg bindings --type AssertionMap --out AssertionMap.go +//go:generate go run github.com/ethereum/go-ethereum/cmd/abigen --abi ../../packages/contracts/abi/contracts/L1/fraud-proof/Rollup.sol/Rollup.json --pkg bindings --type Rollup --out Rollup.go +//go:generate go run github.com/ethereum/go-ethereum/cmd/abigen --abi ../../packages/contracts/abi/contracts/L1/fraud-proof/challenge/Challenge.sol/Challenge.json --pkg bindings --type Challenge --out Challenge.go diff --git a/fraud-proof/bindings/tools/tools.go b/fraud-proof/bindings/tools/tools.go new file mode 100644 index 000000000..72449b169 --- /dev/null +++ b/fraud-proof/bindings/tools/tools.go @@ -0,0 +1,21 @@ +// Copyright 2022, Specular contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build tools + +package tools + +import ( + _ "github.com/ethereum/go-ethereum/cmd/abigen" +) diff --git a/fraud-proof/cmd/flags.go b/fraud-proof/cmd/flags.go new file mode 100644 index 000000000..1ebf4b0ed --- /dev/null +++ b/fraud-proof/cmd/flags.go @@ -0,0 +1,110 @@ +package cmd + +import ( + "github.com/mantlenetworkio/mantle/fraud-proof/rollup/services" + "github.com/mantlenetworkio/mantle/l2geth/cmd/utils" + "github.com/mantlenetworkio/mantle/l2geth/common" + + "gopkg.in/urfave/cli.v1" +) + +var ( + // Fraud Proofs Flags + + FraudProofL1EndpointFlag = &cli.StringFlag{ + Name: "fp.l1endpoint", + Usage: "The api endpoint of L1 client", + EnvVar: "L1_ENDPOINT", + Value: "", + } + FraudProofL1ChainIDFlag = &cli.Uint64Flag{ + Name: "fp.l1chainid", + Usage: "The chain ID of L1 client", + EnvVar: "L1_CHAIN_ID", + Value: 31337, + } + FraudProofL1ConfirmationsFlag = &cli.Uint64Flag{ + Name: "fp.l1confirmations", + Usage: "The confirmation block number of L1", + EnvVar: "L1_CONFIRMATIONS", + Value: 0, + } + FraudProofSequencerAddrFlag = &cli.StringFlag{ + Name: "fp.sequencer-addr", + Usage: "The account address of sequencer", + EnvVar: "SEQUENCER_ADDR", + Value: "", + } + // FraudProofRollupAddrFlag rollup contract address + FraudProofRollupAddrFlag = &cli.StringFlag{ + Name: "fp.rollup-addr", + Usage: "The contract address of L1 rollup", + EnvVar: "ROLLUP_ADDR", + Value: "", + } + FraudProofStakeAddrFlag = &cli.StringFlag{ + Name: "fp.stake-addr", + Usage: "The sequencer/validator address to be unlocked (pass passphrash via --password)", + EnvVar: "STAKE_ADDR", + Value: "", + } + FraudProofStakeAmount = &cli.Uint64Flag{ + Name: "fp.stake-amount", + Usage: "Required staking amount", + EnvVar: "STAKE_AMOUNT", + Value: 1000000000000000000, + } + FraudProofChallengeVerify = &cli.BoolTFlag{ + Name: "fp.challenge-verify", + Usage: "Challenge verify", + EnvVar: "CHALLENGE_VERIFY", + } +) + +//// RegisterEthService adds an Ethereum client to the stack. +//// The second return value is the full node instance, which may be nil if the +//// node is running as a light client. +//func RegisterEthService(stack *node.Node, cfg *ethconfig.Config) (ethapi.Backend, *eth.Ethereum) { +// backend, err := eth.New(stack, cfg) +// if err != nil { +// utils.Fatalf("Failed to register the Ethereum service: %v", err) +// } +// //if cfg.LightServ > 0 { +// // _, err := les.NewLesServer(stack, backend, cfg) +// // if err != nil { +// // utils.Fatalf("Failed to create the LES server: %v", err) +// // } +// //} +// if err := ethcatalyst.Register(stack, backend); err != nil { +// utils.Fatalf("Failed to register the Engine API service: %v", err) +// } +// stack.RegisterAPIs(tracers.APIs(backend.APIBackend)) +// // +// stack.RegisterAPIs(proof.APIs(backend.APIBackend)) +// // +// return backend.APIBackend, backend +//} + +func MakeFraudProofConfig(ctx *cli.Context) *services.Config { + //utils.CheckExclusive(ctx, FraudProofNodeFlag, utils.MiningEnabledFlag) + //utils.CheckExclusive(ctx, FraudProofNodeFlag, utils.DeveloperFlag) + var passphrase string + if list := utils.MakePasswordList(ctx); len(list) > 0 { + passphrase = list[0] + } else { + utils.Fatalf("Failed to register the Rollup service: coinbase account locked") + } + cfg := &services.Config{ + Node: ctx.String(utils.RollupRoleFlag.Name), + Passphrase: passphrase, + L1Endpoint: ctx.String(FraudProofL1EndpointFlag.Name), + L1ChainID: ctx.Uint64(FraudProofL1ChainIDFlag.Name), + L1Confirmations: ctx.Uint64(FraudProofL1ConfirmationsFlag.Name), + SequencerAddr: common.HexToAddress(ctx.String(FraudProofSequencerAddrFlag.Name)), + RollupAddr: common.HexToAddress(ctx.String(FraudProofRollupAddrFlag.Name)), + StakeAddr: common.HexToAddress(ctx.String(FraudProofStakeAddrFlag.Name)), + StakeAmount: ctx.Uint64(FraudProofStakeAmount.Name), + ChallengeVerify: ctx.Bool(FraudProofChallengeVerify.Name), + } + return cfg +} diff --git a/fraud-proof/go.mod b/fraud-proof/go.mod new file mode 100644 index 000000000..16e8446c4 --- /dev/null +++ b/fraud-proof/go.mod @@ -0,0 +1,85 @@ +module github.com/mantlenetworkio/mantle/fraud-proof + +go 1.19 + +replace github.com/mantlenetworkio/mantle/fraud-proof v0.0.0 => ./ + +require ( + github.com/cbergoon/merkletree v0.2.0 + github.com/ethereum/go-ethereum v1.10.25 + github.com/holiman/uint256 v1.2.0 + github.com/mantlenetworkio/mantle/l2geth v0.0.0-20221214100001-fb1439a71d5f + github.com/specularl2/specular/clients/geth/specular v0.0.0-20221120100224-5e02437e9455 +) + +require ( + github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 // indirect + github.com/VictoriaMetrics/fastcache v1.9.0 // indirect + github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847 // indirect + github.com/btcsuite/btcd v0.22.1 // indirect + github.com/btcsuite/btcd/btcec/v2 v2.2.0 // indirect + github.com/cespare/xxhash/v2 v2.1.2 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/deckarep/golang-set v1.8.0 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect + github.com/deepmap/oapi-codegen v1.8.2 // indirect + github.com/edsrzf/mmap-go v1.1.0 // indirect + github.com/elastic/gosigar v0.12.0 // indirect + github.com/fjl/memsize v0.0.1 // indirect + github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 // indirect + github.com/go-ole/go-ole v1.2.1 // indirect + github.com/go-stack/stack v1.8.1 // indirect + github.com/golang-jwt/jwt/v4 v4.3.0 // indirect + github.com/golang/protobuf v1.5.2 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/google/uuid v1.3.0 // indirect + github.com/gorilla/websocket v1.5.0 // indirect + github.com/graph-gophers/graphql-go v1.3.0 // indirect + github.com/hashicorp/go-bexpr v0.1.10 // indirect + github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d // indirect + github.com/holiman/bloomfilter/v2 v2.0.3 // indirect + github.com/huin/goupnp v1.0.3 // indirect + github.com/influxdata/influxdb v1.8.3 // indirect + github.com/influxdata/influxdb-client-go/v2 v2.4.0 // indirect + github.com/influxdata/line-protocol v0.0.0-20210311194329-9aa0e372d097 // indirect + github.com/jackpal/go-nat-pmp v1.0.2 // indirect + github.com/karalabe/usb v0.0.2 // indirect + github.com/mattn/go-colorable v0.1.12 // indirect + github.com/mattn/go-isatty v0.0.14 // indirect + github.com/mattn/go-runewidth v0.0.13 // indirect + github.com/mitchellh/mapstructure v1.4.1 // indirect + github.com/mitchellh/pointerstructure v1.2.0 // indirect + github.com/olekukonko/tablewriter v0.0.5 // indirect + github.com/opentracing/opentracing-go v1.2.0 // indirect + github.com/pborman/uuid v1.2.0 // indirect + github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/prometheus/tsdb v0.10.0 // indirect + github.com/rivo/uniseg v0.2.0 // indirect + github.com/rjeczalik/notify v0.9.2 // indirect + github.com/rs/cors v1.8.2 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect + github.com/status-im/keycard-go v0.0.0-20211109104530-b0e0482ba91d // indirect + github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570 // indirect + github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3 // indirect + github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect + github.com/tklauser/go-sysconf v0.3.5 // indirect + github.com/tklauser/numcpus v0.2.2 // indirect + github.com/tyler-smith/go-bip39 v1.1.0 // indirect + github.com/urfave/cli/v2 v2.10.2 // indirect + github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208 // indirect + github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect + golang.org/x/crypto v0.0.0-20220307211146-efcb8507fb70 // indirect + golang.org/x/net v0.2.0 // indirect + golang.org/x/sync v0.1.0 // indirect + golang.org/x/sys v0.2.0 // indirect + golang.org/x/term v0.2.0 // indirect + golang.org/x/text v0.4.0 // indirect + golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 // indirect + google.golang.org/protobuf v1.27.1 // indirect + gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect + gopkg.in/urfave/cli.v1 v1.20.0 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect +) diff --git a/fraud-proof/go.sum b/fraud-proof/go.sum new file mode 100644 index 000000000..ec539487c --- /dev/null +++ b/fraud-proof/go.sum @@ -0,0 +1,950 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.43.0/go.mod h1:BOSR3VbTLkk6FDC/TcffxP4NF/FFBGA5ku+jvKOP7pg= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.51.0/go.mod h1:hWtGJ6gnXH+KgDv+V0zFGDvpi07n3z8ZNj3T1RW0Gcw= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/bigtable v1.2.0/go.mod h1:JcVAOl45lrTmQfLj7T6TxyMzIN/3FGGcFm+2xVAli2o= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +collectd.org v0.3.0/go.mod h1:A/8DzQBkF6abtvrT2j/AU/4tiBgJWYyh0y/oB/4MlWE= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +github.com/Azure/azure-pipeline-go v0.2.1/go.mod h1:UGSo8XybXnIGZ3epmeBw7Jdz+HiUVpqIlpz/HKHylF4= +github.com/Azure/azure-pipeline-go v0.2.2/go.mod h1:4rQ/NZncSvGqNkkOsNpOU1tgoNuIlp9AfUH5G1tvCHc= +github.com/Azure/azure-storage-blob-go v0.7.0/go.mod h1:f9YQKtsG1nMisotuTPpO0tjNuEjKRYAcJU8/ydDI++4= +github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= +github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= +github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= +github.com/Azure/go-autorest/autorest/adal v0.8.0/go.mod h1:Z6vX6WXXuyieHAXwMj0S6HY6e6wcHn37qQMBQlvY3lc= +github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A= +github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= +github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g= +github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= +github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= +github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= +github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM= +github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= +github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= +github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= +github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= +github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= +github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= +github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 h1:fLjPD/aNc3UIOA6tDi6QXUemppXK3P9BI7mr2hd6gx8= +github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= +github.com/VictoriaMetrics/fastcache v1.6.0/go.mod h1:0qHz5QP0GMX4pfmMA/zt5RgfNuXJrTP0zS7DqpHGGTw= +github.com/VictoriaMetrics/fastcache v1.9.0 h1:oMwsS6c8abz98B7ytAewQ7M1ZN/Im/iwKoE1euaFvhs= +github.com/VictoriaMetrics/fastcache v1.9.0/go.mod h1:otoTS3xu+6IzF/qByjqzjp3rTuzM3Qf0ScU1UTj97iU= +github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= +github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= +github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= +github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= +github.com/allegro/bigcache v1.2.1 h1:hg1sY1raCwic3Vnsvje6TT7/pnZba83LeFck5NrFKSc= +github.com/allegro/bigcache v1.2.1/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= +github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= +github.com/apache/arrow/go/arrow v0.0.0-20191024131854-af6fa24be0db/go.mod h1:VTxUBvSJ3s3eHAg65PNgrsn5BtqCRPdmyXh6rAfdxN0= +github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847 h1:rtI0fD4oG/8eVokGVPYJEW1F88p1ZNgXiEIs9thEE4A= +github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ= +github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= +github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= +github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go v1.42.6/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q= +github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= +github.com/aws/aws-sdk-go-v2 v1.2.0/go.mod h1:zEQs02YRBw1DjK0PoJv3ygDYOFTre1ejlJWl8FwAuQo= +github.com/aws/aws-sdk-go-v2/config v1.1.1/go.mod h1:0XsVy9lBI/BCXm+2Tuvt39YmdHwS5unDQmxZOYe8F5Y= +github.com/aws/aws-sdk-go-v2/credentials v1.1.1/go.mod h1:mM2iIjwl7LULWtS6JCACyInboHirisUUdkBPoTHMOUo= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.0.2/go.mod h1:3hGg3PpiEjHnrkrlasTfxFqUsZ2GCk/fMUn4CbKgSkM= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.0.2/go.mod h1:45MfaXZ0cNbeuT0KQ1XJylq8A6+OpVV2E5kvY/Kq+u8= +github.com/aws/aws-sdk-go-v2/service/route53 v1.1.1/go.mod h1:rLiOUrPLW/Er5kRcQ7NkwbjlijluLsrIbu/iyl35RO4= +github.com/aws/aws-sdk-go-v2/service/sso v1.1.1/go.mod h1:SuZJxklHxLAXgLTc1iFXbEWkXs7QRTQpCLGaKIprQW0= +github.com/aws/aws-sdk-go-v2/service/sts v1.1.1/go.mod h1:Wi0EBZwiz/K44YliU0EKxqTCJGUfYTWXrrBwkq736bM= +github.com/aws/smithy-go v1.1.0/go.mod h1:EzMw8dbp/YJL4A5/sbhGddag+NPT7q084agLbB9LgIw= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/bmizerany/pat v0.0.0-20170815010413-6226ea591a40/go.mod h1:8rLXio+WjiTceGBHIoTvn60HIbs7Hm7bcHjyrSqYB9c= +github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= +github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= +github.com/btcsuite/btcd v0.22.0-beta/go.mod h1:9n5ntfhhHQBIhUvlhDvD3Qg6fRUj4jkN0VB8L8svzOA= +github.com/btcsuite/btcd v0.22.1 h1:CnwP9LM/M9xuRrGSCGeMVs9iv09uMqwsVX7EeIpgV2c= +github.com/btcsuite/btcd v0.22.1/go.mod h1:wqgTSL29+50LRkmOVknEdmt8ZojIzhuWvgu/iptuN7Y= +github.com/btcsuite/btcd/btcec/v2 v2.2.0 h1:fzn1qaOt32TuLjFlkzYSsBC35Q3KUjT1SwPxiMSCF5k= +github.com/btcsuite/btcd/btcec/v2 v2.2.0/go.mod h1:U7MHm051Al6XmscBQ0BoNydpOTsFAn707034b5nY8zU= +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/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= +github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= +github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce/go.mod h1:0DVlHczLPewLcPGEIeUEzfOJhqGPQ0mJJRDBtD307+o= +github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= +github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= +github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= +github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= +github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= +github.com/c-bata/go-prompt v0.2.2/go.mod h1:VzqtzE2ksDBcdln8G7mk2RX9QyGjH+OVqOCSiVIqS34= +github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= +github.com/cbergoon/merkletree v0.2.0 h1:Bttqr3OuoiZEo4ed1L7fTasHka9II+BF9fhBfbNEEoQ= +github.com/cbergoon/merkletree v0.2.0/go.mod h1:5c15eckUgiucMGDOCanvalj/yJnD+KAZj1qyJtRW5aM= +github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk= +github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= +github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cloudflare/cloudflare-go v0.14.0/go.mod h1:EnwdgGMaFOruiPZRFSgn+TsQ3hQ7C/YWzIGLeu5c304= +github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= +github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= +github.com/consensys/bavard v0.1.8-0.20210406032232-f3452dc9b572/go.mod h1:Bpd0/3mZuaj6Sj+PqrmIquiOKy397AKGThQPaGzNXAQ= +github.com/consensys/gnark-crypto v0.4.1-0.20210426202927-39ac3d4b3f1f/go.mod h1:815PAHg3wvysy0SyIqanF8gZ0Y1wjk/hrDHD/iT88+Q= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= +github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4= +github.com/dave/jennifer v1.2.0/go.mod h1:fIb+770HOpJ2fmN9EPPKOqm1vMGhB+TwXKMZhrIygKg= +github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ= +github.com/deckarep/golang-set v1.8.0 h1:sk9/l/KqpunDwP7pSjUg0keiOOLEnOBHzykLrsPppp4= +github.com/deckarep/golang-set v1.8.0/go.mod h1:5nI87KwE7wgsBU1F4GKAw2Qod7p5kyS383rP6+o6qqo= +github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= +github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= +github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= +github.com/deepmap/oapi-codegen v1.6.0/go.mod h1:ryDa9AgbELGeB+YEXE1dR53yAjHwFvE9iAUlWl9Al3M= +github.com/deepmap/oapi-codegen v1.8.2 h1:SegyeYGcdi0jLLrpbCMoJxnUUn8GBXHsvr4rbzjuhfU= +github.com/deepmap/oapi-codegen v1.8.2/go.mod h1:YLgSKSDv/bZQB7N4ws6luhozi3cEdRktEqrX88CvjIw= +github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dgryski/go-bitstream v0.0.0-20180413035011-3522498ce2c8/go.mod h1:VMaSuZ+SZcx/wljOQKvp5srsbCiKDEb6K2wC4+PiBmQ= +github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +github.com/dlclark/regexp2 v1.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= +github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= +github.com/docker/docker v1.4.2-0.20180625184442-8e610b2b55bf/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v20.10.10+incompatible h1:GKkP0T7U4ks6X3lmmHKC2QDprnpRJor2Z5a8m62R9ZM= +github.com/docker/docker v20.10.10+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/dop251/goja v0.0.0-20200721192441-a695b0cdd498/go.mod h1:Mw6PkjjMXWbTj+nnj4s3QPXq1jaT0s5pC0iFD4+BOAA= +github.com/dop251/goja v0.0.0-20211011172007-d99e4b8cbf48/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk= +github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA7c8pLvoGndExHudxTDKZ84Pyvv+90pbBjbTz0Y= +github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= +github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= +github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= +github.com/eclipse/paho.mqtt.golang v1.2.0/go.mod h1:H9keYFcgq3Qr5OUJm/JZI/i6U7joQ8SYLhZwfeOo6Ts= +github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= +github.com/edsrzf/mmap-go v1.1.0 h1:6EUwBLQ/Mcr1EYLE4Tn1VdW1A4ckqCQWZBw8Hr0kjpQ= +github.com/edsrzf/mmap-go v1.1.0/go.mod h1:19H/e8pUPLicwkyNgOykDXkJ9F0MHE+Z52B8EIth78Q= +github.com/elastic/gosigar v0.12.0 h1:AsdhYCJlTudhfOYQyFNgx+fIVTfrDO0V1ST0vHgiapU= +github.com/elastic/gosigar v0.12.0/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs= +github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/ethereum/go-ethereum v1.10.4/go.mod h1:nEE0TP5MtxGzOMd7egIrbPJMQBnhVU3ELNxhBglIzhg= +github.com/ethereum/go-ethereum v1.10.16/go.mod h1:Anj6cxczl+AHy63o4X9O8yWNHuN5wMpfb8MAnHkWn7Y= +github.com/ethereum/go-ethereum v1.10.25 h1:5dFrKJDnYf8L6/5o42abCE6a9yJm9cs4EJVRyYMr55s= +github.com/ethereum/go-ethereum v1.10.25/go.mod h1:EYFyF19u3ezGLD4RqOkLq+ZCXzYbLoNDdZlMt7kyKFg= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= +github.com/fjl/memsize v0.0.1 h1:+zhkb+dhUgx0/e+M8sF0QqiouvMQUiKR+QYvdxIOKcQ= +github.com/fjl/memsize v0.0.1/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= +github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= +github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= +github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= +github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= +github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays= +github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= +github.com/getkin/kin-openapi v0.53.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4= +github.com/getkin/kin-openapi v0.61.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/glycerine/go-unsnap-stream v0.0.0-20180323001048-9f0cb55181dd/go.mod h1:/20jfyN9Y5QPEAprSgKAUr+glWDY39ZiUEAYOEv5dsE= +github.com/glycerine/goconvey v0.0.0-20190410193231-58a59202ab31/go.mod h1:Ogl1Tioa0aV7gstGFO7KhffUsb9M4ydbEbbxpcEDc24= +github.com/go-chi/chi/v5 v5.0.0/go.mod h1:BBug9lr0cqtdAhsu6R4AAdvufI0/XBzAQSsUqJpoZOs= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.10.0 h1:dXFJfIHVvUcpSgDOV+Ne6t7jXri8Tfv2uOLHUZ2XNuo= +github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-logfmt/logfmt v0.5.0 h1:TrB8swr/68K7m9CcGut2g3UOihhbcbiMAYiuTXdEih4= +github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-ole/go-ole v1.2.1 h1:2lOsA72HgjxAuMlKpFiCbHTvu44PIVkZ5hqm3RSdI/E= +github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= +github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-resty/resty/v2 v2.4.0/go.mod h1:B88+xCTEwvfD94NOuE6GS1wMlnoKNY8eEiNizfNwOwA= +github.com/go-sourcemap/sourcemap v2.1.2+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= +github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= +github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= +github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= +github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= +github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= +github.com/golang-jwt/jwt/v4 v4.3.0 h1:kHL1vqdqWNfATmA0FNMdmZNMyZI1U6O31X4rlIPoBog= +github.com/golang-jwt/jwt/v4 v4.3.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= +github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= +github.com/golang/geo v0.0.0-20190916061304-5b978397cfec/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golangci/lint-1 v0.0.0-20181222135242-d2cdd8c08219/go.mod h1:/X8TswGSh1pIozq4ZwCfxS0WA5JGXguxk94ar/4c87Y= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/flatbuffers v1.11.0/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= +github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +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-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.5/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= +github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/graph-gophers/graphql-go v0.0.0-20201113091052-beb923fada29/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= +github.com/graph-gophers/graphql-go v1.3.0 h1:Eb9x/q6MFpCLz7jBCiP/WTxjSDrYLR1QY41SORZyNJ0= +github.com/graph-gophers/graphql-go v1.3.0/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= +github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= +github.com/hashicorp/errwrap v1.0.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-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= +github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= +github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d h1:dg1dEPuWpEqDnvIw251EVy4zlP8gWbsGj4BsUKCRpYs= +github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= +github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= +github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= +github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +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.2.0 h1:gpSYcPLWGv4sG43I2mVLiDZCNDh/EpGjSk8tmtxitHM= +github.com/holiman/uint256 v1.2.0/go.mod h1:y4ga/t+u+Xwd7CpDgZESaRcWy0I7XMlTMA25ApIH5Jw= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= +github.com/huin/goupnp v1.0.1-0.20210310174557-0ca763054c88/go.mod h1:nNs7wvRfN1eKaMknBydLNQU6146XQim8t4h+q90biWo= +github.com/huin/goupnp v1.0.2/go.mod h1:0dxJBVBHqTMjIUMkESDTNgOOx/Mw5wYIfyFmdzSamkM= +github.com/huin/goupnp v1.0.3 h1:N8No57ls+MnjlB+JPiCVSOyy/ot7MJTqlo7rn+NYSqQ= +github.com/huin/goupnp v1.0.3/go.mod h1:ZxNlw5WqJj6wSsRK5+YfflQGXYfccj5VgQsMNixHM7Y= +github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/influxdata/flux v0.65.1/go.mod h1:J754/zds0vvpfwuq7Gc2wRdVwEodfpCFM7mYlOw2LqY= +github.com/influxdata/influxdb v1.8.3 h1:WEypI1BQFTT4teLM+1qkEcvUi0dAvopAI/ir0vAiBg8= +github.com/influxdata/influxdb v1.8.3/go.mod h1:JugdFhsvvI8gadxOI6noqNeeBHvWNTbfYGtiAn+2jhI= +github.com/influxdata/influxdb-client-go/v2 v2.4.0 h1:HGBfZYStlx3Kqvsv1h2pJixbCl/jhnFtxpKFAv9Tu5k= +github.com/influxdata/influxdb-client-go/v2 v2.4.0/go.mod h1:vLNHdxTJkIf2mSLvGrpj8TCcISApPoXkaxP8g9uRlW8= +github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= +github.com/influxdata/influxql v1.1.1-0.20200828144457-65d3ef77d385/go.mod h1:gHp9y86a/pxhjJ+zMjNXiQAA197Xk9wLxaz+fGG+kWk= +github.com/influxdata/line-protocol v0.0.0-20180522152040-32c6aa80de5e/go.mod h1:4kt73NQhadE3daL3WhR5EJ/J2ocX0PZzwxQ0gXJ7oFE= +github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839/go.mod h1:xaLFMmpvUxqXtVkUJfg9QmT88cDaCJ3ZKgdZ78oO8Qo= +github.com/influxdata/line-protocol v0.0.0-20210311194329-9aa0e372d097 h1:vilfsDSy7TDxedi9gyBkMvAirat/oRcL0lFdJBf6tdM= +github.com/influxdata/line-protocol v0.0.0-20210311194329-9aa0e372d097/go.mod h1:xaLFMmpvUxqXtVkUJfg9QmT88cDaCJ3ZKgdZ78oO8Qo= +github.com/influxdata/promql/v2 v2.12.0/go.mod h1:fxOPu+DY0bqCTCECchSRtWfc+0X19ybifQhZoQNF5D8= +github.com/influxdata/roaring v0.4.13-0.20180809181101-fc520f41fab6/go.mod h1:bSgUQ7q5ZLSO+bKBGqJiCBGAl+9DxyW63zLTujjUlOE= +github.com/influxdata/tdigest v0.0.0-20181121200506-bf2b5ad3c0a9/go.mod h1:Js0mqiSBE6Ffsg94weZZ2c+v/ciT8QRHFOap7EKDrR0= +github.com/influxdata/usage-client v0.0.0-20160829180054-6d3895376368/go.mod h1:Wbbw6tYNvwa5dlB6304Sd+82Z3f7PmVZHVKU637d4po= +github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= +github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= +github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= +github.com/jarcoal/httpmock v1.0.8/go.mod h1:ATjnClrvW/3tijVmpL/va5Z3aAyGvqU3gCT8nX0Txik= +github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e/go.mod h1:G1CVv03EnqU1wYL2dFwXxW2An0az9JTl/ZsqXQeBlkU= +github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= +github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= +github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/jsternberg/zap-logfmt v1.0.0/go.mod h1:uvPs/4X51zdkcm5jXl5SYoN+4RK21K8mysFmDaM/h+o= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= +github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= +github.com/jwilder/encoding v0.0.0-20170811194829-b4e1701a28ef/go.mod h1:Ct9fl0F6iIOGgxJ5npU/IUOhOhqlVrGjyIZc8/MagT0= +github.com/karalabe/usb v0.0.0-20190919080040-51dc0efba356/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= +github.com/karalabe/usb v0.0.2 h1:M6QQBNxF+CQ8OFvxrT90BA0qBOXymndZnk5q235mFc4= +github.com/karalabe/usb v0.0.2/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= +github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= +github.com/klauspost/compress v1.4.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= +github.com/klauspost/crc32 v0.0.0-20161016154125-cb6bfca970f6/go.mod h1:+ZoRqAPRLkC4NPOvfYeR5KNOrY6TD+/sAC3HXPZgDYg= +github.com/klauspost/pgzip v1.0.2-0.20170402124221-0bf5dcad4ada/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/labstack/echo/v4 v4.2.1/go.mod h1:AA49e0DZ8kk5jTOOCKNuPR6oTnBS0dYiM4FW1e6jwpg= +github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= +github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= +github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= +github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= +github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= +github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mantlenetworkio/mantle/l2geth v0.0.0-20221214100001-fb1439a71d5f h1:n6Gy79+El1e/WKPw7DGPBXaodTh2rajfag9kErM8tNw= +github.com/mantlenetworkio/mantle/l2geth v0.0.0-20221214100001-fb1439a71d5f/go.mod h1:Gb5aIh6+aStBbatHciL8aapFApOgEFaGpIGNfZukgV0= +github.com/matryer/moq v0.0.0-20190312154309-6cfb0558e1bd/go.mod h1:9ELz6aaclSIGnZBoaSLZ3NAl1VTufbOrXBPvtcy6WiQ= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.0/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= +github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= +github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= +github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.5-0.20180830101745-3fb116b82035/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= +github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= +github.com/mattn/go-tty v0.0.0-20180907095812-13ff1204f104/go.mod h1:XPvLUNfbS4fJH25nqRHfWLMa1ONC8Amw+mIA639KxkE= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= +github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= +github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= +github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +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/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae/go.mod h1:qAyveg+e4CE+eKJXWVjKXM4ck2QobLqTDytGJbLLhJg= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/naoina/go-stringutil v0.1.0/go.mod h1:XJ2SJL9jCtBh+P9q5btrd/Ylo8XwT/h1USek5+NqSA0= +github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416/go.mod h1:NBIhNtsFMo3G2szEBne+bO4gS192HuIYRqfvOWb4i1E= +github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= +github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= +github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k= +github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= +github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= +github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= +github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= +github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= +github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= +github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= +github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/onsi/gomega v1.16.0 h1:6gjqkI8iiRHMvdccRJM8rVKjCWk6ZIm6FTm3ddIe4/c= +github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= +github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= +github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= +github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= +github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/opentracing/opentracing-go v1.0.3-0.20180606204148-bd9c31933947/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= +github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= +github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA= +github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= +github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= +github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/paulbellamy/ratecounter v0.2.0/go.mod h1:Hfx1hDpSGoqxkVVpBi/IlYD7kChlfo5C6hzIHwPqfFE= +github.com/pborman/uuid v1.2.0 h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g= +github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= +github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= +github.com/peterh/liner v1.0.1-0.20180619022028-8c1271fcf47f/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc= +github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7 h1:oYW+YCJ1pachXTQmzR3rNLYGGz4g/UgFcjb28p/viDM= +github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0= +github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= +github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= +github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= +github.com/pkg/term v0.0.0-20180730021639-bffc007b7fd5/go.mod h1:eCbImbZ95eXtAUIbLAuAVnBnwf83mjf6QIVH8SHYwqQ= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= +github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= +github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/prometheus/tsdb v0.10.0 h1:If5rVCMTp6W2SiRAQFlbpJNgVlgMEd+U2GZckwK38ic= +github.com/prometheus/tsdb v0.10.0/go.mod h1:oi49uRhEe9dPUTlS3JRZOwJuVi6tmh10QSgwXEyGCt4= +github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/retailnext/hllpp v1.0.1-0.20180308014038-101a6d2f8b52/go.mod h1:RDpi1RftBQPUCDRw6SmxeaREsAaRKnOclghuzp/WRzc= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho= +github.com/rjeczalik/notify v0.9.2 h1:MiTWrPj55mNDHEiIX5YUSKefw/+lCQVoAFmD6oQm5w8= +github.com/rjeczalik/notify v0.9.2/go.mod h1:aErll2f0sUX9PXZnVNyeiObbmTlk5jnMoCa4QEjJeqM= +github.com/robertkrimen/otto v0.0.0-20191219234010-c382bd3c16ff/go.mod h1:xvqspoSXJTIpemEonrMDFq6XzwHYYgToXWj5eRX1OtY= +github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= +github.com/rs/cors v1.8.2 h1:KCooALfAYGs415Cwu5ABvv9n9509fSiG5SQJn/AQo4U= +github.com/rs/cors v1.8.2/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= +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/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= +github.com/segmentio/kafka-go v0.1.0/go.mod h1:X6itGqS9L4jDletMsxZ7Dz+JFWxM6JHfPOCvTvk+EJo= +github.com/segmentio/kafka-go v0.2.0/go.mod h1:X6itGqS9L4jDletMsxZ7Dz+JFWxM6JHfPOCvTvk+EJo= +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/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/specularl2/specular/clients/geth/specular v0.0.0-20221120100224-5e02437e9455 h1:e2SFwBKsMh7PuwHFUh3JeWJvFyXiGzaUDUrKD3mOL10= +github.com/specularl2/specular/clients/geth/specular v0.0.0-20221120100224-5e02437e9455/go.mod h1:F9LmQzX6gPr0ggz9Ez/wnJAAhPLR2voIhYxStD3c+Js= +github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q= +github.com/status-im/keycard-go v0.0.0-20211109104530-b0e0482ba91d h1:vmirMegf1vqPJ+lDBxLQ0MAt3tz+JL57UPxu44JBOjA= +github.com/status-im/keycard-go v0.0.0-20211109104530-b0e0482ba91d/go.mod h1:97vT0Rym0wCnK4B++hNA3nCetr0Mh1KXaVxzSt1arjg= +github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570 h1:gIlAHnH1vJb5vwEjIp5kBj/eu99p/bl0Ay2goiPe5xE= +github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570/go.mod h1:8OR4w3TdeIHIh1g6EMY5p0gVNOovcWC+1vpc7naMuAw= +github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3 h1:njlZPzLwU639dk2kqnCPPv+wNjq7Xb6EfUxe/oX0/NM= +github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3/go.mod h1:hpGUWaI9xL8pRQCTXQgocU38Qw1g0Us7n5PxxTwTCYU= +github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.0/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.2 h1:4jaiDzPyXQvSd7D0EjG45355tLlV3VOECpq10pLC+8s= +github.com/syndtr/goleveldb v1.0.1-0.20210305035536-64b5b1c73954/go.mod h1:u2MKkTVTVJWe5D1rCvame8WqhBd88EuIwODJZ1VHCPM= +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/tinylib/msgp v1.0.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= +github.com/tklauser/go-sysconf v0.3.5 h1:uu3Xl4nkLzQfXNsWn15rPc/HQCJKObbt1dKJeWp3vU4= +github.com/tklauser/go-sysconf v0.3.5/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI= +github.com/tklauser/numcpus v0.2.2 h1:oyhllyrScuYI6g+h/zUvNXNp1wy7x8qQy3t/piefldA= +github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM= +github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= +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.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= +github.com/urfave/cli/v2 v2.10.2 h1:x3p8awjp/2arX+Nl/G2040AZpOCHS/eMJJ1/a+mye4Y= +github.com/urfave/cli/v2 v2.10.2/go.mod h1:f8iq5LtQ/bLxafbdBSLPPNsgaW0l/2fYYEHhAyPlwvo= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= +github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= +github.com/willf/bitset v1.1.3/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= +github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208 h1:1cngl9mPEoITZG8s8cVcUy5CeIBYhEESkOB7m6Gmkrk= +github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208/go.mod h1:IotVbo4F+mw0EzQ08zFqg7pK3FebNXpaMsRy2RT+Ees= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/xlab/treeprint v0.0.0-20180616005107-d6fb6747feb6/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg= +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.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= +go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= +go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= +go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= +golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190909091759-094676da4a83/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20220307211146-efcb8507fb70 h1:syTAU9FwmvzEoIYMqcPHOcVm4H3U5u90WsvuYgwpETU= +golang.org/x/crypto v0.0.0-20220307211146-efcb8507fb70/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210220033124-5f55cee0dc0d/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= +golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.2.0 h1:sZfSu1wtKLGlWI4ZZayP0ck9Y73K1ynO6gqzTdBVdPU= +golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180810173357-98c5dad5d1a0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180926160741-c2ed4eda69e7/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200107162124-548cf772de50/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200826173525-f9321e4c35a6/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210420205809-ac73e9fd8988/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220204135822-1c1b9b1eba6a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A= +golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.2.0 h1:z85xZCsEl7bi/KwbNADeBYoOP0++7W1ipu+aGnpwzRM= +golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg= +golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 h1:M73Iuj3xbbb9Uk1DYhzydthsj6oOd6l9bpuFcNoUvTs= +golang.org/x/time v0.0.0-20220224211638-0e9765cccd65/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200108203644-89082a384178/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= +gonum.org/v1/gonum v0.0.0-20181121035319-3f7ecaa7e8ca/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= +gonum.org/v1/gonum v0.6.0/go.mod h1:9mxDZsDKxgMAuccQkewq682L+0eCu4dCN2yonUJTCLU= +gonum.org/v1/netlib v0.0.0-20181029234149-ec6d1f5cefe6/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= +gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= +gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc= +google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= +google.golang.org/genproto v0.0.0-20190716160619-c506a9f90610/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200108215221-bd8f9a0ef82f/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +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/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= +gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7GC73Ei8pv4MzjDUNPHgQWJdtMAaDU= +gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c= +gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200619000410-60c24ae608a6/go.mod h1:uAJfkITjFhyEEuUfm7bsmCZRbW5WRq8s9EY8HZ6hCns= +gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= +gopkg.in/sourcemap.v1 v1.0.5/go.mod h1:2RlvNNSMglmRrcvhfuzp4hQHwOtjxlbjX7UPY/GXb78= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/urfave/cli.v1 v1.20.0 h1:NdAVW6RYxDif9DhDHaAortIu956m2c0v+09AZBPTbE0= +gopkg.in/urfave/cli.v1 v1.20.0/go.mod h1:vuBzUtMdQeixQj8LVd+/98pzhxNGQoyuPBlsXHOQNO0= +gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= +gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= +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.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= +gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= +honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= +sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= +sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= diff --git a/fraud-proof/interface.go b/fraud-proof/interface.go new file mode 100644 index 000000000..0f6d9da0b --- /dev/null +++ b/fraud-proof/interface.go @@ -0,0 +1,21 @@ +package rollup + +import "math/big" + +type FraudProover interface { + Start() error + + Stop() error + + CreateAssertionWithStateBatch([][32]byte, *big.Int, []byte, interface{}) error + + CreateAssertion(interface{}) error + + GetLatestAssertion() (interface{}, error) + + InChallenge() bool + + RespondChallenge() error + + GenerateState() (interface{}, error) +} diff --git a/fraud-proof/proof/api.go b/fraud-proof/proof/api.go new file mode 100644 index 000000000..59fcda114 --- /dev/null +++ b/fraud-proof/proof/api.go @@ -0,0 +1,136 @@ +// Copyright 2022, Specular contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package proof + +import ( + "context" + "math/big" + + "github.com/mantlenetworkio/mantle/l2geth/common" + "github.com/mantlenetworkio/mantle/l2geth/common/hexutil" + "github.com/mantlenetworkio/mantle/l2geth/consensus" + "github.com/mantlenetworkio/mantle/l2geth/core" + "github.com/mantlenetworkio/mantle/l2geth/core/state" + "github.com/mantlenetworkio/mantle/l2geth/core/types" + "github.com/mantlenetworkio/mantle/l2geth/core/vm" + "github.com/mantlenetworkio/mantle/l2geth/ethdb" + "github.com/mantlenetworkio/mantle/l2geth/log" + "github.com/mantlenetworkio/mantle/l2geth/params" + "github.com/mantlenetworkio/mantle/l2geth/rpc" +) + +// Backend interface provides the common API services (that are provided by +// both full and light clients) with access to necessary functions. +type Backend interface { + HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) + HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error) + BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) + BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error) + GetTransaction(ctx context.Context, txHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error) + GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error) + RPCGasCap() *big.Int + ChainConfig() *params.ChainConfig + Engine() consensus.Engine + ChainDb() ethdb.Database + // StateAtBlock returns the state corresponding to the stateroot of the block. + // N.B: For executing transactions on block N, the required stateRoot is block N-1, + // so this method should be called with the parent. + StateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base *state.StateDB, checkLive, preferDisk bool) (*state.StateDB, error) + StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (core.Message, vm.Context, *state.StateDB, error) +} + +// ProverAPI is the collection of Specular one-step proof APIs. +type ProverAPI struct { + backend Backend +} + +// NewAPI creates a new API definition for the Specular one-step proof services. +func NewAPI(backend Backend) *ProverAPI { + return &ProverAPI{backend: backend} +} + +type chainContext struct { + backend Backend + ctx context.Context +} + +func (context *chainContext) Engine() consensus.Engine { + return context.backend.Engine() +} + +func (context *chainContext) GetHeader(hash common.Hash, number uint64) *types.Header { + header, err := context.backend.HeaderByNumber(context.ctx, rpc.BlockNumber(number)) + if err != nil { + return nil + } + if header.Hash() == hash { + return header + } + header, err = context.backend.HeaderByHash(context.ctx, hash) + if err != nil { + return nil + } + return header +} + +func createChainContext(backend Backend, ctx context.Context) core.ChainContext { + return &chainContext{backend: backend, ctx: ctx} +} + +func (api *ProverAPI) ProveTransaction(ctx context.Context, hash common.Hash, target common.Hash, config *ProverConfig) (hexutil.Bytes, error) { + return hexutil.Bytes{}, nil +} + +func (api *ProverAPI) ProveBlocksForBenchmark(ctx context.Context, startNum, endNum uint64, config *ProverConfig) ([]hexutil.Bytes, error) { + states, err := GenerateStates(api.backend, ctx, startNum, endNum, config) + if err != nil { + return nil, err + } + var proofs []hexutil.Bytes + for _, s := range states { + log.Info("Generate for ", "state", s) + proof, err := GenerateProof(ctx, api.backend, s, config) + if err != nil { + return nil, err + } + proofs = append(proofs, proof.Encode()) + } + return proofs, nil +} + +func (api *ProverAPI) GenerateStateHashes(ctx context.Context, startNum, endNum uint64, config *ProverConfig) ([]common.Hash, error) { + states, err := GenerateStates(api.backend, ctx, startNum, endNum, config) + if err != nil { + return nil, err + } + hashes := make([]common.Hash, len(states)) + for i, state := range states { + hashes[i] = state.Hash() + } + return hashes, nil +} + +// APIs return the collection of RPC services the tracer package offers. +func APIs(backend Backend) []rpc.API { + // Append all the local APIs and return + return []rpc.API{ + { + Namespace: "debug", + Version: "1.0", + Service: NewAPI(backend), + Public: false, + }, + } +} diff --git a/fraud-proof/proof/proof/component_proof.go b/fraud-proof/proof/proof/component_proof.go new file mode 100644 index 000000000..48b38b8ba --- /dev/null +++ b/fraud-proof/proof/proof/component_proof.go @@ -0,0 +1,455 @@ +// Copyright 2022, Specular contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package proof + +import ( + "encoding/binary" + "fmt" + + "github.com/holiman/uint256" + "github.com/mantlenetworkio/mantle/fraud-proof/proof/state" + "github.com/mantlenetworkio/mantle/l2geth/common" + "github.com/mantlenetworkio/mantle/l2geth/core/types" + "github.com/mantlenetworkio/mantle/l2geth/log" + "github.com/mantlenetworkio/mantle/l2geth/rlp" +) + +type StackProof struct { + Pops []uint256.Int + StackHashAfterPops common.Hash +} + +func (s *StackProof) Encode() []byte { + var proofLen int + if len(s.Pops) == 0 { + return []byte{} + } + proofLen = 32 * (len(s.Pops) + 1) + encoded := make([]byte, proofLen) + for idx, val := range s.Pops { + valBytes := val.Bytes32() + copy(encoded[32*idx:], valBytes[:]) + } + copy(encoded[32*len(s.Pops):], s.StackHashAfterPops.Bytes()) + return encoded +} + +type MemoryReadProof struct { + Cells []uint256.Int + Proof []common.Hash +} + +func (m *MemoryReadProof) Encode() []byte { + encoded := make([]byte, 32*len(m.Cells)+8+32*len(m.Proof)) + for idx, cell := range m.Cells { + cellBytes := cell.Bytes32() + copy(encoded[32*idx:], cellBytes[:]) + } + lenBytes := make([]byte, 8) + binary.BigEndian.PutUint64(lenBytes, uint64(len(m.Proof))) + copy(encoded[32*len(m.Cells):], lenBytes) + encodedOffset := 32*len(m.Cells) + 8 + for _, hash := range m.Proof { + copy(encoded[encodedOffset:], hash.Bytes()) + encodedOffset += 32 + } + return encoded +} + +type MemoryWriteProof struct { + Cells []uint256.Int + UpdatedCells []uint256.Int + Proof []common.Hash +} + +func (m *MemoryWriteProof) Encode() []byte { + encoded := make([]byte, 32*len(m.Cells)+32*len(m.UpdatedCells)+8+32*len(m.Proof)) + for idx, cell := range m.Cells { + cellBytes := cell.Bytes32() + copy(encoded[32*idx:], cellBytes[:]) + } + encodedOffset := 32 * len(m.Cells) + for idx, cell := range m.UpdatedCells { + cellBytes := cell.Bytes32() + copy(encoded[32*idx+encodedOffset:], cellBytes[:]) + } + lenBytes := make([]byte, 8) + binary.BigEndian.PutUint64(lenBytes, uint64(len(m.Proof))) + copy(encoded[32*(len(m.Cells)+len(m.UpdatedCells)):], lenBytes) + encodedOffset += 32*len(m.UpdatedCells) + 8 + for _, hash := range m.Proof { + copy(encoded[encodedOffset:], hash.Bytes()) + encodedOffset += 32 + } + return encoded +} + +type MemoryAppendProof struct { + AppendCells []uint256.Int + Proof []common.Hash +} + +func (m *MemoryAppendProof) Encode() []byte { + encoded := make([]byte, 32*len(m.AppendCells)+8+32*len(m.Proof)) + for idx, cell := range m.AppendCells { + cellBytes := cell.Bytes32() + copy(encoded[32*idx:], cellBytes[:]) + } + lenBytes := make([]byte, 8) + binary.BigEndian.PutUint64(lenBytes, uint64(len(m.Proof))) + copy(encoded[32*len(m.AppendCells):], lenBytes) + encodedOffset := 32*len(m.AppendCells) + 8 + for _, hash := range m.Proof { + copy(encoded[encodedOffset:], hash.Bytes()) + encodedOffset += 32 + } + return encoded +} + +type MemoryCombinedReadProof struct { + Cells []uint256.Int + AppendCells []uint256.Int + Proof []common.Hash +} + +func (m *MemoryCombinedReadProof) Encode() []byte { + encoded := make([]byte, 32*len(m.Cells)+32*len(m.AppendCells)+8+32*len(m.Proof)) + for idx, cell := range m.Cells { + cellBytes := cell.Bytes32() + copy(encoded[32*idx:], cellBytes[:]) + } + encodedOffset := 32 * len(m.Cells) + for idx, cell := range m.AppendCells { + cellBytes := cell.Bytes32() + copy(encoded[32*idx+encodedOffset:], cellBytes[:]) + } + lenBytes := make([]byte, 8) + binary.BigEndian.PutUint64(lenBytes, uint64(len(m.Proof))) + copy(encoded[32*(len(m.Cells)+len(m.AppendCells)):], lenBytes) + encodedOffset += 32*len(m.AppendCells) + 8 + for _, hash := range m.Proof { + copy(encoded[encodedOffset:], hash.Bytes()) + encodedOffset += 32 + } + return encoded +} + +type MemoryCombinedWriteProof struct { + Cells []uint256.Int + UpdatedCells []uint256.Int + AppendCells []uint256.Int + Proof []common.Hash +} + +func (m *MemoryCombinedWriteProof) Encode() []byte { + encoded := make([]byte, 32*len(m.Cells)+32*len(m.UpdatedCells)+32*len(m.AppendCells)+8+32*len(m.Proof)) + for idx, cell := range m.Cells { + cellBytes := cell.Bytes32() + copy(encoded[32*idx:], cellBytes[:]) + } + encodedOffset := 32 * len(m.Cells) + for idx, cell := range m.UpdatedCells { + cellBytes := cell.Bytes32() + copy(encoded[32*idx+encodedOffset:], cellBytes[:]) + } + encodedOffset += 32 * len(m.UpdatedCells) + for idx, cell := range m.AppendCells { + cellBytes := cell.Bytes32() + copy(encoded[32*idx+encodedOffset:], cellBytes[:]) + } + lenBytes := make([]byte, 8) + binary.BigEndian.PutUint64(lenBytes, uint64(len(m.Proof))) + copy(encoded[32*(len(m.Cells)+len(m.UpdatedCells)+len(m.AppendCells)):], lenBytes) + encodedOffset += 32*len(m.AppendCells) + 8 + for _, hash := range m.Proof { + copy(encoded[encodedOffset:], hash.Bytes()) + encodedOffset += 32 + } + return encoded +} + +func generateMemoryReadProof(memory *state.Memory, offset uint64, size uint64) (Proof, error) { + if size == 0 { + return nil, nil + } + startCell := offset / 32 + cellNum := calcCellNum(offset, size) + if memory.CellNum() <= startCell { + // The start position pasts the end of the memory + // AppendProof + pf := memory.GetAppendProof() + cellNum += startCell - memory.CellNum() + return &MemoryAppendProof{ + AppendCells: make([]uint256.Int, cellNum), // All empty + Proof: pf, + }, nil + } + if memory.CellNum() >= startCell+cellNum { + // The end position is within the memory + // ReadProof + indices := make([]uint64, cellNum) + for i := uint64(0); i < cellNum; i++ { + indices[i] = startCell + i + } + pf := memory.GetProof(indices) + cells := make([]uint256.Int, cellNum) + for i := uint64(0); i < cellNum; i++ { + cells[i] = *memory.Cell(startCell + i) + } + return &MemoryReadProof{ + Cells: cells, + Proof: pf, + }, nil + } + // The start position is within the memory, but the end position is not + // CombinedReadProof + indices := make([]uint64, memory.CellNum()-startCell) + for i := startCell; i < memory.CellNum(); i++ { + indices[i-startCell] = i + } + pf, err := memory.GetCombinedProof(indices) + if err != nil { + return nil, err + } + cells := make([]uint256.Int, memory.CellNum()-startCell) + for i := startCell; i < memory.CellNum(); i++ { + cells[i-startCell] = *memory.Cell(i) + } + appendCells := make([]uint256.Int, cellNum-(memory.CellNum()-startCell)) + return &MemoryCombinedReadProof{ + Cells: cells, + AppendCells: appendCells, + Proof: pf, + }, nil +} + +func generateMemoryReadProofNoAppend(memory *state.Memory, offset uint64, size uint64) (Proof, error) { + if size == 0 { + return nil, nil + } + startCell := offset / 32 + cellNum := calcCellNum(offset, size) + if memory.CellNum() <= startCell { + // The start position pasts the end of the memory + return nil, nil + } + if memory.CellNum() >= startCell+cellNum { + // The end position is within the memory + indices := make([]uint64, cellNum) + for i := uint64(0); i < cellNum; i++ { + indices[i] = startCell + i + } + pf := memory.GetProof(indices) + cells := make([]uint256.Int, cellNum) + for i := uint64(0); i < cellNum; i++ { + cells[i] = *memory.Cell(startCell + i) + } + return &MemoryReadProof{ + Cells: cells, + Proof: pf, + }, nil + } + // The start position is within the memory, but the end position is not + indices := make([]uint64, memory.CellNum()-startCell) + for i := startCell; i < memory.CellNum(); i++ { + indices[i-startCell] = i + } + pf := memory.GetProof(indices) + cells := make([]uint256.Int, memory.CellNum()-startCell) + for i := startCell; i < memory.CellNum(); i++ { + cells[i-startCell] = *memory.Cell(i) + } + return &MemoryReadProof{ + Cells: cells, + Proof: pf, + }, nil +} + +func generateMemoryWriteProof(memory, memoryAfter *state.Memory, offset uint64, size uint64) (Proof, error) { + if size == 0 { + return nil, nil + } + startCell := offset / 32 + cellNum := calcCellNum(offset, size) + if memory.CellNum() <= startCell { + // The start position pasts the end of the memory + // AppendProof + pf := memory.GetAppendProof() + cellNum += startCell - memory.CellNum() + appendCells := make([]uint256.Int, cellNum) + for i := startCell - memory.CellNum(); i < cellNum; i++ { + appendCells[i] = *memoryAfter.Cell(i + memory.CellNum()) + } + return &MemoryAppendProof{ + AppendCells: appendCells, + Proof: pf, + }, nil + } + if memory.CellNum() >= startCell+cellNum { + // The end position is within the memory + // WriteProof + indices := make([]uint64, cellNum) + for i := uint64(0); i < cellNum; i++ { + indices[i] = startCell + i + } + pf := memory.GetProof(indices) + cells := make([]uint256.Int, cellNum) + updatecCells := make([]uint256.Int, cellNum) + for i := uint64(0); i < cellNum; i++ { + cells[i] = *memory.Cell(startCell + i) + updatecCells[i] = *memoryAfter.Cell(startCell + i) + } + return &MemoryWriteProof{ + Cells: cells, + UpdatedCells: updatecCells, + Proof: pf, + }, nil + } + // The start position is within the memory, but the end position is not + // CombinedWriteProof + existingCellNum := memory.CellNum() - startCell + indices := make([]uint64, existingCellNum) + for i := startCell; i < memory.CellNum(); i++ { + indices[i-startCell] = i + } + pf, err := memory.GetCombinedProof(indices) + if err != nil { + return nil, err + } + cells := make([]uint256.Int, existingCellNum) + updatedCells := make([]uint256.Int, existingCellNum) + for i := startCell; i < memory.CellNum(); i++ { + cells[i-startCell] = *memory.Cell(i) + updatedCells[i-startCell] = *memoryAfter.Cell(i) + } + appendCells := make([]uint256.Int, cellNum-existingCellNum) + for i := existingCellNum; i < cellNum; i++ { + appendCells[i-existingCellNum] = *memoryAfter.Cell(i + startCell) + } + return &MemoryCombinedWriteProof{ + Cells: cells, + UpdatedCells: updatedCells, + AppendCells: appendCells, + Proof: pf, + }, nil +} + +type MPTProof struct { + Proof [][]byte +} + +func (m *MPTProof) Encode() []byte { + data, err := rlp.EncodeToBytes(m.Proof) + if err != nil { + log.Error(fmt.Sprint(err)) + panic(err) + } + dataLen := uint64(len(data)) + encoded := make([]byte, 8+dataLen) + binary.BigEndian.PutUint64(encoded, dataLen) + copy(encoded[8:], data) + return encoded +} + +type CodeProof struct { + Content []byte +} + +func (c *CodeProof) Encode() []byte { + length := make([]byte, 8) + binary.BigEndian.PutUint64(length, uint64(len(c.Content))) + encoded := make([]byte, 8+len(c.Content)) + copy(encoded, length) + copy(encoded[8:], c.Content) + return encoded +} + +type BlockHashProof struct { + BlockHash common.Hash +} + +func (b *BlockHashProof) Encode() []byte { + return b.BlockHash.Bytes() +} + +type BlockHashMerkleProof struct { + MerklePath uint64 + MerkleProof []common.Hash +} + +func GetBlockHashMerkleProof(tree *state.BlockHashTree, blockNum uint64) (*BlockHashMerkleProof, error) { + proof, path, err := tree.GetProof(blockNum) + if err != nil { + return nil, err + } + return &BlockHashMerkleProof{ + MerklePath: path, + MerkleProof: proof, + }, nil +} + +func (p *BlockHashMerkleProof) Encode() []byte { + encoded := make([]byte, 8+1+32*len(p.MerkleProof)) + path := make([]byte, 8) + binary.BigEndian.PutUint64(path, p.MerklePath) + copy(encoded, path) + encoded[8] = byte(len(p.MerkleProof)) + encodedOffset := 9 + for _, hash := range p.MerkleProof { + copy(encoded[encodedOffset:], hash.Bytes()) + encodedOffset += 32 + } + return encoded +} + +type LogProof struct { + AccumulateHash common.Hash + Bloom types.Bloom +} + +func LogProofFromLogSeries(logSeries *state.LogSeries) *LogProof { + return &LogProof{ + AccumulateHash: logSeries.AccumulateHash, + Bloom: logSeries.Bloom, + } +} + +func (p *LogProof) Encode() []byte { + encoded := make([]byte, 32+256) + copy(encoded, p.AccumulateHash.Bytes()) + copy(encoded[32:], p.Bloom.Bytes()) + return encoded +} + +type SelfDestructSetProof struct { + Contracts []common.Address +} + +func SelfDestructSetProofFromSelfDestructSet(selfDestructSet *state.SelfDestructSet) *SelfDestructSetProof { + return &SelfDestructSetProof{ + Contracts: selfDestructSet.Contracts, + } +} + +func (p *SelfDestructSetProof) Encode() []byte { + encoded := make([]byte, 8+20*len(p.Contracts)) + binary.BigEndian.PutUint64(encoded, uint64(len(p.Contracts))) + encodedOffset := 8 + for _, addr := range p.Contracts { + copy(encoded[encodedOffset:], addr.Bytes()) + encodedOffset += 20 + } + return encoded +} diff --git a/fraud-proof/proof/proof/instructions.go b/fraud-proof/proof/proof/instructions.go new file mode 100644 index 000000000..5970e062c --- /dev/null +++ b/fraud-proof/proof/proof/instructions.go @@ -0,0 +1,1290 @@ +// Copyright 2022, Specular contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package proof + +import ( + "errors" + "math/big" + + "github.com/holiman/uint256" + "github.com/mantlenetworkio/mantle/fraud-proof/proof/state" + "github.com/mantlenetworkio/mantle/l2geth/common" + "github.com/mantlenetworkio/mantle/l2geth/core/vm" + "github.com/mantlenetworkio/mantle/l2geth/crypto" + "github.com/mantlenetworkio/mantle/l2geth/log" + "github.com/mantlenetworkio/mantle/l2geth/params" +) + +func (osp *OneStepProof) addStateProof(s *state.IntraState) { + osp.AddProof(StateProofFromState(s)) +} + +func (osp *OneStepProof) addInterStateProof(s *state.InterState) { + osp.AddProof(InterStateProofFromInterState(s)) +} + +func (osp *OneStepProof) addRawCodeProof(code []byte) { + codeProof := &CodeProof{ + Content: code, + } + osp.TotalCodeSize += uint64(len(code)) + osp.AddProof(codeProof) +} + +func (osp *OneStepProof) addCodeProof(currState *state.IntraState, address common.Address) { + osp.addRawCodeProof(currState.GlobalState.GetCode(address)) +} + +func (osp *OneStepProof) addOpCodeProof(ctx ProofGenContext, currState *state.IntraState) { + osp.addRawCodeProof(ctx.actualCode) +} + +func (osp *OneStepProof) addBlockHashProof(num uint64, currState *state.IntraState) error { + if num >= currState.BlockNumber || num < currState.BlockNumber-state.RECENT_BLOCK_HASHES_LENGTH { + return nil + } + pf, err := GetBlockHashMerkleProof(currState.BlockHashTree, num) + if err != nil { + return err + } + osp.AddProof(&BlockHashProof{currState.BlockHashTree.GetBlockHash(num)}) + osp.AddProof(pf) + return nil +} + +func (osp *OneStepProof) addStackProof(popNum int, currState *state.IntraState) { + if popNum == 0 { + return + } + pops := make([]uint256.Int, popNum) + for i := 0; i < popNum; i++ { + pops[i] = *currState.Stack.Back(i) + } + stackProof := &StackProof{ + Pops: pops, + StackHashAfterPops: currState.Stack.HashAfterPops(popNum), + } + osp.AddProof(stackProof) +} + +func (osp *OneStepProof) addMemoryLikeReadProof(offset, size uint64, memoryLike *state.Memory) error { + // We never need Merkle proof is the memory is empty + if memoryLike.CellNum() == 0 { + return nil + } + pf, err := generateMemoryReadProof(memoryLike, offset, size) + if err != nil { + return err + } + if pf != nil { + osp.AddProof(pf) + } + return nil +} + +func (osp *OneStepProof) addMemoryLikeReadProofNoAppend(offset, size uint64, memoryLike *state.Memory) error { + // We never need Merkle proof is the memory is empty + if memoryLike.CellNum() == 0 { + return nil + } + pf, err := generateMemoryReadProofNoAppend(memoryLike, offset, size) + if err != nil { + return err + } + if pf != nil { + osp.AddProof(pf) + } + return nil +} + +func (osp *OneStepProof) addMemoryReadProof(offset, size uint64, currState *state.IntraState) error { + return osp.addMemoryLikeReadProof(offset, size, currState.Memory) +} + +func (osp *OneStepProof) addInputDataReadProof(offset, size uint64, currState *state.IntraState) error { + return osp.addMemoryLikeReadProofNoAppend(offset, size, currState.InputData) +} + +func (osp *OneStepProof) addReturnDataReadProof(offset, size uint64, currState *state.IntraState) error { + return osp.addMemoryLikeReadProofNoAppend(offset, size, currState.ReturnData) +} + +func (osp *OneStepProof) addMemoryWriteProof(offset, size uint64, currState, nextState *state.IntraState) error { + // We never need Merkle proof is the memory is empty + if currState.Memory.CellNum() == 0 { + return nil + } + pf, err := generateMemoryWriteProof(currState.Memory, nextState.Memory, offset, size) + if err != nil { + return err + } + if pf != nil { + osp.AddProof(pf) + } + return nil +} + +func (osp *OneStepProof) addCurrAccountProof(currState *state.IntraState) error { + return osp.addAccountProof(currState, currState.ContractAddress) +} + +func (osp *OneStepProof) addAccountProof(currState *state.IntraState, address common.Address) error { + accPf, err := GetAccountProof(currState.GlobalState, address) + if err != nil { + return err + } + osp.AddProof(accPf) + return nil +} + +func (osp *OneStepProof) addCommittedAccountProof(currState *state.IntraState, address common.Address) error { + accPf, err := GetAccountProof(currState.CommittedGlobalState, address) + if err != nil { + return err + } + osp.AddProof(accPf) + return nil +} + +func (osp *OneStepProof) addStorageLoadProof(key common.Hash, currState *state.IntraState) error { + accPf, stPf, err := GetStorageProof(currState.GlobalState, currState.ContractAddress, key) + if err != nil { + return err + } + osp.AddProof(accPf) + osp.AddProof(stPf) + return nil +} + +func (osp *OneStepProof) addCommittedStorageProof(key common.Hash, currState *state.IntraState) error { + accPf, stPf, err := GetStorageProof(currState.CommittedGlobalState, currState.ContractAddress, key) + if err != nil { + return err + } + osp.AddProof(accPf) + osp.AddProof(stPf) + return nil +} + +func (osp *OneStepProof) addStorageStoreProof(key common.Hash, currState, nextState *state.IntraState) error { + // We need to add 2 storage proofs here + osp.addCommittedStorageProof(key, currState) + osp.addStorageLoadProof(key, currState) + return nil +} + +func (osp *OneStepProof) addLogProof(currState *state.IntraState) error { + logProof := LogProofFromLogSeries(currState.LogSeries) + osp.AddProof(logProof) + return nil +} + +// If a call frame is reverted to its parent call frame, we only need to provide the proof +// of the lastDepthState, which is the state it will revert to +// If the revert is called by opRevert, we also need to provide memory proofs for +// return data reading and writing in memory, but it is handled in [opRevertProof] +func (osp *OneStepProof) addCallRevertProof(currState *state.IntraState) error { + lastDepthState := currState.LastDepthState.(*state.IntraState) + osp.addStateProof(lastDepthState) + return nil +} + +// If a transaction is reverted, nothing changed in the state except the gas tip to the coinbase. +// We need to send the InterStateProof for the verifier to construct the next InterState. +// We also need to send the receipt to help the verifier update the receipt trie. +func (osp *OneStepProof) addTransactionRevertProof(ctx ProofGenContext, currState *state.IntraState, vmerr error) error { + lastDepthState := currState.LastDepthState.(*state.InterState) + osp.addInterStateProof(lastDepthState) + err := osp.addCommittedAccountProof(currState, ctx.coinbase) + if err != nil { + return err + } + osp.AddProof(ReceiptProofFromReceipt(ctx.receipt)) + return nil +} + +func (osp *OneStepProof) addRevertProof(ctx ProofGenContext, currState, nextState *state.IntraState, vmerr error) error { + if nextState == nil { + // We're in the topmost call frame, the entire transaction will be reverted + return osp.addTransactionRevertProof(ctx, currState, vmerr) + } + return osp.addCallRevertProof(currState) +} + +func makeStackOnlyInstructionProof(popNum int) func(ctx ProofGenContext, currState, nextState *state.IntraState, vmerr error) (*OneStepProof, error) { + return func(ctx ProofGenContext, currState, nextState *state.IntraState, vmerr error) (*OneStepProof, error) { + osp := EmptyProof() + if isEnvironmentalOp(currState.OpCode) { + osp.SetVerifierType(VerifierTypeEnvironmentalOp) + } else { + osp.SetVerifierType(VerifierTypeStackOp) + } + osp.addStateProof(currState) + osp.addOpCodeProof(ctx, currState) + if popNum > 0 { + // If the stack validation fails, we don't need to provide stack proofs + if IsStackError(vmerr) { + err := osp.addRevertProof(ctx, currState, nextState, vmerr) + if err != nil { + return nil, err + } + return osp, nil + } + osp.addStackProof(popNum, currState) + } + // If error happens after the stack validation, in most cases we only need the stack proof + // and revert proof + if vmerr != nil { + err := osp.addRevertProof(ctx, currState, nextState, vmerr) + if err != nil { + return nil, err + } + } + return osp, nil + } +} + +func opPushProof(ctx ProofGenContext, currState, nextState *state.IntraState, vmerr error) (*OneStepProof, error) { + // We reuse makeStackOnlyInstructionProof here because the content pushed is covered by the opcode proof + // Note: if we switch to other proof scheme of code, we may need to provide a separate proof for the pushed content + return makeStackOnlyInstructionProof(0)(ctx, currState, nextState, vmerr) +} + +func makeLogProof(topicNum int) func(ctx ProofGenContext, currState, nextState *state.IntraState, vmerr error) (*OneStepProof, error) { + return func(ctx ProofGenContext, currState, nextState *state.IntraState, vmerr error) (*OneStepProof, error) { + osp := EmptyProof() + osp.SetVerifierType(VerifierTypeMemoryOp) + osp.addStateProof(currState) + osp.addOpCodeProof(ctx, currState) + // If the stack validation fails, we don't need to provide stack proofs + if IsStackError(vmerr) { + err := osp.addRevertProof(ctx, currState, nextState, vmerr) + if err != nil { + return nil, err + } + return osp, nil + } + osp.addStackProof(topicNum+2, currState) + // If error happens after the stack validation, in most cases we only need the stack proof + // and revert proof + if vmerr != nil { + err := osp.addRevertProof(ctx, currState, nextState, vmerr) + if err != nil { + return nil, err + } + } + offset := currState.Stack.Peek().Uint64() + size := currState.Stack.Back(1).Uint64() + err := osp.addMemoryReadProof(offset, size, currState) + if err != nil { + return nil, err + } + err = osp.addLogProof(currState) + if err != nil { + return nil, err + } + return osp, nil + } +} + +func opKeccak256Proof(ctx ProofGenContext, currState, nextState *state.IntraState, vmerr error) (*OneStepProof, error) { + osp := EmptyProof() + osp.SetVerifierType(VerifierTypeMemoryOp) + osp.addStateProof(currState) + osp.addOpCodeProof(ctx, currState) + // If the stack validation fails or write protection, we don't need to provide stack proofs + if IsStackError(vmerr) || vmerr == vm.ErrWriteProtection { + err := osp.addRevertProof(ctx, currState, nextState, vmerr) + if err != nil { + return nil, err + } + return osp, nil + } + osp.addStackProof(2, currState) + // If error happens after the stack validation, in most cases we only need the stack proof + // and revert proof + if vmerr != nil { + err := osp.addRevertProof(ctx, currState, nextState, vmerr) + if err != nil { + return nil, err + } + } + offset := currState.Stack.Peek().Uint64() + size := currState.Stack.Back(1).Uint64() + err := osp.addMemoryReadProof(offset, size, currState) + if err != nil { + return nil, err + } + return osp, nil +} + +func opBalanceProof(ctx ProofGenContext, currState, nextState *state.IntraState, vmerr error) (*OneStepProof, error) { + osp := EmptyProof() + osp.SetVerifierType(VerifierTypeStorageOp) + osp.addStateProof(currState) + osp.addOpCodeProof(ctx, currState) + // If the stack validation fails or write protection, we don't need to provide stack proofs + if IsStackError(vmerr) || vmerr == vm.ErrWriteProtection { + err := osp.addRevertProof(ctx, currState, nextState, vmerr) + if err != nil { + return nil, err + } + return osp, nil + } + osp.addStackProof(1, currState) + // If error happens after the stack validation, in most cases we only need the stack proof + // and revert proof + if vmerr != nil { + err := osp.addRevertProof(ctx, currState, nextState, vmerr) + if err != nil { + return nil, err + } + } + addrBytes := currState.Stack.Peek().Bytes32() + address := common.BytesToAddress(addrBytes[:]) + err := osp.addAccountProof(currState, address) + if err != nil { + return nil, err + } + return osp, nil +} + +func opCallDataLoadProof(ctx ProofGenContext, currState, nextState *state.IntraState, vmerr error) (*OneStepProof, error) { + osp := EmptyProof() + osp.SetVerifierType(VerifierTypeMemoryOp) + osp.addStateProof(currState) + osp.addOpCodeProof(ctx, currState) + // If the stack validation fails or write protection, we don't need to provide stack proofs + if IsStackError(vmerr) || vmerr == vm.ErrWriteProtection { + err := osp.addRevertProof(ctx, currState, nextState, vmerr) + if err != nil { + return nil, err + } + return osp, nil + } + osp.addStackProof(1, currState) + // If error happens after the stack validation, in most cases we only need the stack proof + // and revert proof + if vmerr != nil { + err := osp.addRevertProof(ctx, currState, nextState, vmerr) + if err != nil { + return nil, err + } + } + offset := currState.Stack.Peek().Uint64() + err := osp.addInputDataReadProof(offset, 32, currState) + if err != nil { + return nil, err + } + return osp, nil +} + +func opCallDataCopyProof(ctx ProofGenContext, currState, nextState *state.IntraState, vmerr error) (*OneStepProof, error) { + osp := EmptyProof() + osp.SetVerifierType(VerifierTypeMemoryOp) + osp.addStateProof(currState) + osp.addOpCodeProof(ctx, currState) + // If the stack validation fails or write protection, we don't need to provide stack proofs + if IsStackError(vmerr) || vmerr == vm.ErrWriteProtection { + err := osp.addRevertProof(ctx, currState, nextState, vmerr) + if err != nil { + return nil, err + } + return osp, nil + } + osp.addStackProof(3, currState) + // If error happens after the stack validation, in most cases we only need the stack proof + // and revert proof + if vmerr != nil { + err := osp.addRevertProof(ctx, currState, nextState, vmerr) + if err != nil { + return nil, err + } + } + memOffset := currState.Stack.Peek().Uint64() + offset := currState.Stack.Back(1).Uint64() + size := currState.Stack.Back(2).Uint64() + err := osp.addInputDataReadProof(offset, size, currState) + if err != nil { + return nil, err + } + err = osp.addMemoryWriteProof(memOffset, size, currState, nextState) + if err != nil { + return nil, err + } + return osp, nil +} + +func opCodeCopyProof(ctx ProofGenContext, currState, nextState *state.IntraState, vmerr error) (*OneStepProof, error) { + osp := EmptyProof() + osp.SetVerifierType(VerifierTypeMemoryOp) + osp.addStateProof(currState) + osp.addOpCodeProof(ctx, currState) + // If the stack validation fails or write protection, we don't need to provide stack proofs + if IsStackError(vmerr) || vmerr == vm.ErrWriteProtection { + err := osp.addRevertProof(ctx, currState, nextState, vmerr) + if err != nil { + return nil, err + } + return osp, nil + } + osp.addStackProof(3, currState) + // If error happens after the stack validation, in most cases we only need the stack proof + // and revert proof + if vmerr != nil { + err := osp.addRevertProof(ctx, currState, nextState, vmerr) + if err != nil { + return nil, err + } + } + memOffset := currState.Stack.Peek().Uint64() + size := currState.Stack.Back(2).Uint64() + err := osp.addMemoryWriteProof(memOffset, size, currState, nextState) + if err != nil { + return nil, err + } + return osp, nil +} + +func opExtCodeSizeProof(ctx ProofGenContext, currState, nextState *state.IntraState, vmerr error) (*OneStepProof, error) { + osp := EmptyProof() + osp.SetVerifierType(VerifierTypeStorageOp) + osp.addStateProof(currState) + osp.addOpCodeProof(ctx, currState) + // If the stack validation fails or write protection, we don't need to provide stack proofs + if IsStackError(vmerr) || vmerr == vm.ErrWriteProtection { + err := osp.addRevertProof(ctx, currState, nextState, vmerr) + if err != nil { + return nil, err + } + return osp, nil + } + osp.addStackProof(1, currState) + // If error happens after the stack validation, in most cases we only need the stack proof + // and revert proof + if vmerr != nil { + err := osp.addRevertProof(ctx, currState, nextState, vmerr) + if err != nil { + return nil, err + } + } + addrBytes := currState.Stack.Peek().Bytes32() + address := common.BytesToAddress(addrBytes[:]) + err := osp.addAccountProof(currState, address) + if err != nil { + return nil, err + } + osp.addCodeProof(currState, address) + return osp, nil +} + +func opExtCodeCopyProof(ctx ProofGenContext, currState, nextState *state.IntraState, vmerr error) (*OneStepProof, error) { + osp := EmptyProof() + osp.SetVerifierType(VerifierTypeStorageOp) + osp.addStateProof(currState) + osp.addOpCodeProof(ctx, currState) + // If the stack validation fails or write protection, we don't need to provide stack proofs + if IsStackError(vmerr) || vmerr == vm.ErrWriteProtection { + err := osp.addRevertProof(ctx, currState, nextState, vmerr) + if err != nil { + return nil, err + } + return osp, nil + } + osp.addStackProof(4, currState) + // If error happens after the stack validation, in most cases we only need the stack proof + // and revert proof + if vmerr != nil { + err := osp.addRevertProof(ctx, currState, nextState, vmerr) + if err != nil { + return nil, err + } + } + addrBytes := currState.Stack.Peek().Bytes32() + address := common.BytesToAddress(addrBytes[:]) + memOffset := currState.Stack.Back(1).Uint64() + size := currState.Stack.Back(3).Uint64() + err := osp.addAccountProof(currState, address) + if err != nil { + return nil, err + } + osp.addCodeProof(currState, address) + err = osp.addMemoryWriteProof(memOffset, size, currState, nextState) + if err != nil { + return nil, err + } + return osp, nil +} + +func opExtCodeHashProof(ctx ProofGenContext, currState, nextState *state.IntraState, vmerr error) (*OneStepProof, error) { + osp := EmptyProof() + osp.SetVerifierType(VerifierTypeStorageOp) + osp.addStateProof(currState) + osp.addOpCodeProof(ctx, currState) + // If the stack validation fails or write protection, we don't need to provide stack proofs + if IsStackError(vmerr) || vmerr == vm.ErrWriteProtection { + err := osp.addRevertProof(ctx, currState, nextState, vmerr) + if err != nil { + return nil, err + } + return osp, nil + } + osp.addStackProof(1, currState) + // If error happens after the stack validation, in most cases we only need the stack proof + // and revert proof + if vmerr != nil { + err := osp.addRevertProof(ctx, currState, nextState, vmerr) + if err != nil { + return nil, err + } + } + addrBytes := currState.Stack.Peek().Bytes32() + address := common.BytesToAddress(addrBytes[:]) + err := osp.addAccountProof(currState, address) + if err != nil { + return nil, err + } + return osp, nil +} + +func opReturnDataCopyProof(ctx ProofGenContext, currState, nextState *state.IntraState, vmerr error) (*OneStepProof, error) { + osp := EmptyProof() + osp.SetVerifierType(VerifierTypeMemoryOp) + osp.addStateProof(currState) + osp.addOpCodeProof(ctx, currState) + // If the stack validation fails or write protection, we don't need to provide stack proofs + if IsStackError(vmerr) || vmerr == vm.ErrWriteProtection { + err := osp.addRevertProof(ctx, currState, nextState, vmerr) + if err != nil { + return nil, err + } + return osp, nil + } + osp.addStackProof(3, currState) + // If error happens after the stack validation, in most cases we only need the stack proof + // and revert proof + if vmerr != nil { + err := osp.addRevertProof(ctx, currState, nextState, vmerr) + if err != nil { + return nil, err + } + } + memOffset := currState.Stack.Peek().Uint64() + offset := currState.Stack.Back(1).Uint64() + size := currState.Stack.Back(2).Uint64() + err := osp.addReturnDataReadProof(offset, size, currState) + if err != nil { + return nil, err + } + err = osp.addMemoryWriteProof(memOffset, size, currState, nextState) + if err != nil { + return nil, err + } + return osp, nil +} + +func opSelfBalanceProof(ctx ProofGenContext, currState, nextState *state.IntraState, vmerr error) (*OneStepProof, error) { + osp := EmptyProof() + osp.SetVerifierType(VerifierTypeStorageOp) + osp.addStateProof(currState) + osp.addOpCodeProof(ctx, currState) + if vmerr != nil { + err := osp.addRevertProof(ctx, currState, nextState, vmerr) + if err != nil { + return nil, err + } + return osp, nil + } + err := osp.addCurrAccountProof(currState) + if err != nil { + return nil, err + } + return osp, nil +} + +func opBlockHashProof(ctx ProofGenContext, currState, nextState *state.IntraState, vmerr error) (*OneStepProof, error) { + osp := EmptyProof() + osp.SetVerifierType(VerifierTypeEnvironmentalOp) + osp.addStateProof(currState) + osp.addOpCodeProof(ctx, currState) + // If the stack validation fails or write protection, we don't need to provide stack proofs + if IsStackError(vmerr) || vmerr == vm.ErrWriteProtection { + err := osp.addRevertProof(ctx, currState, nextState, vmerr) + if err != nil { + return nil, err + } + return osp, nil + } + osp.addStackProof(1, currState) + num := currState.Stack.Peek().Uint64() + err := osp.addBlockHashProof(num, currState) + if err != nil { + return nil, err + } + return osp, nil +} + +func opMLoadProof(ctx ProofGenContext, currState, nextState *state.IntraState, vmerr error) (*OneStepProof, error) { + osp := EmptyProof() + osp.SetVerifierType(VerifierTypeMemoryOp) + osp.addStateProof(currState) + osp.addOpCodeProof(ctx, currState) + // If the stack validation fails or write protection, we don't need to provide stack proofs + if IsStackError(vmerr) || vmerr == vm.ErrWriteProtection { + err := osp.addRevertProof(ctx, currState, nextState, vmerr) + if err != nil { + return nil, err + } + return osp, nil + } + osp.addStackProof(1, currState) + // If error happens after the stack validation, in most cases we only need the stack proof + // and revert proof + if vmerr != nil { + err := osp.addRevertProof(ctx, currState, nextState, vmerr) + if err != nil { + return nil, err + } + } + offset := currState.Stack.Peek().Uint64() + err := osp.addMemoryReadProof(offset, 32, currState) + if err != nil { + return nil, err + } + return osp, nil +} + +func opMStoreProof(ctx ProofGenContext, currState, nextState *state.IntraState, vmerr error) (*OneStepProof, error) { + osp := EmptyProof() + osp.SetVerifierType(VerifierTypeMemoryOp) + osp.addStateProof(currState) + osp.addOpCodeProof(ctx, currState) + // If the stack validation fails or write protection, we don't need to provide stack proofs + if IsStackError(vmerr) || vmerr == vm.ErrWriteProtection { + err := osp.addRevertProof(ctx, currState, nextState, vmerr) + if err != nil { + return nil, err + } + return osp, nil + } + osp.addStackProof(2, currState) + // If error happens after the stack validation, in most cases we only need the stack proof + // and revert proof + if vmerr != nil { + err := osp.addRevertProof(ctx, currState, nextState, vmerr) + if err != nil { + return nil, err + } + } + offset := currState.Stack.Peek().Uint64() + err := osp.addMemoryWriteProof(offset, 32, currState, nextState) + if err != nil { + return nil, err + } + return osp, nil +} + +func opMStore8Proof(ctx ProofGenContext, currState, nextState *state.IntraState, vmerr error) (*OneStepProof, error) { + osp := EmptyProof() + osp.SetVerifierType(VerifierTypeMemoryOp) + osp.addStateProof(currState) + osp.addOpCodeProof(ctx, currState) + // If the stack validation fails or write protection, we don't need to provide stack proofs + if IsStackError(vmerr) || vmerr == vm.ErrWriteProtection { + err := osp.addRevertProof(ctx, currState, nextState, vmerr) + if err != nil { + return nil, err + } + return osp, nil + } + osp.addStackProof(2, currState) + // If error happens after the stack validation, in most cases we only need the stack proof + // and revert proof + if vmerr != nil { + err := osp.addRevertProof(ctx, currState, nextState, vmerr) + if err != nil { + return nil, err + } + } + offset := currState.Stack.Peek().Uint64() + err := osp.addMemoryWriteProof(offset, 32, currState, nextState) + if err != nil { + return nil, err + } + return osp, nil +} + +func opSLoadProof(ctx ProofGenContext, currState, nextState *state.IntraState, vmerr error) (*OneStepProof, error) { + osp := EmptyProof() + osp.SetVerifierType(VerifierTypeStorageOp) + osp.addStateProof(currState) + osp.addOpCodeProof(ctx, currState) + // If the stack validation fails or write protection, we don't need to provide stack proofs + if IsStackError(vmerr) || vmerr == vm.ErrWriteProtection { + err := osp.addRevertProof(ctx, currState, nextState, vmerr) + if err != nil { + return nil, err + } + return osp, nil + } + osp.addStackProof(1, currState) + // If error happens after the stack validation, in most cases we only need the stack proof + // and revert proof + if vmerr != nil { + err := osp.addRevertProof(ctx, currState, nextState, vmerr) + if err != nil { + return nil, err + } + } + keyBytes := currState.Stack.Peek().Bytes32() + err := osp.addStorageLoadProof(common.BytesToHash(keyBytes[:]), currState) + if err != nil { + return nil, err + } + return osp, nil +} + +func opSStoreProof(ctx ProofGenContext, currState, nextState *state.IntraState, vmerr error) (*OneStepProof, error) { + osp := EmptyProof() + osp.SetVerifierType(VerifierTypeStorageOp) + osp.addStateProof(currState) + osp.addOpCodeProof(ctx, currState) + // If the stack validation fails or write protection, we don't need to provide stack proofs + if IsStackError(vmerr) || vmerr == vm.ErrWriteProtection { + err := osp.addRevertProof(ctx, currState, nextState, vmerr) + if err != nil { + return nil, err + } + return osp, nil + } + osp.addStackProof(2, currState) + // If error happens after the stack validation, in most cases we only need the stack proof + // and revert proof + if vmerr != nil { + err := osp.addRevertProof(ctx, currState, nextState, vmerr) + if err != nil { + return nil, err + } + } + keyBytes := currState.Stack.Peek().Bytes32() + err := osp.addStorageStoreProof(common.BytesToHash(keyBytes[:]), currState, nextState) + if err != nil { + return nil, err + } + return osp, nil +} + +func opJumpDestProof(ctx ProofGenContext, currState, nextState *state.IntraState, vmerr error) (*OneStepProof, error) { + osp := EmptyProof() + osp.SetVerifierType(VerifierTypeStackOp) + osp.addStateProof(currState) + osp.addOpCodeProof(ctx, currState) + if vmerr != nil { + err := osp.addRevertProof(ctx, currState, nextState, vmerr) + if err != nil { + return nil, err + } + } + return osp, nil +} + +// Call opcode proofs + +func (osp *OneStepProof) addCallPostProof(ctx ProofGenContext, currState *state.IntraState) error { + addrBytes := currState.Stack.Back(1).Bytes32() + address := common.BytesToAddress(addrBytes[:]) + var in, inSize uint64 + if currState.OpCode == vm.CALL || currState.OpCode == vm.CALLCODE { + in = currState.Stack.Back(3).Uint64() + inSize = currState.Stack.Back(4).Uint64() + } else if currState.OpCode == vm.DELEGATECALL || currState.OpCode == vm.STATICCALL { + in = currState.Stack.Back(2).Uint64() + inSize = currState.Stack.Back(3).Uint64() + } else { + log.Error("Unreachable") + return errors.New("unreachable") + } + // For input data + err := osp.addMemoryReadProof(in, inSize, currState) + if err != nil { + return err + } + // We don't need to prove the recepient account and the opcode for precompiles + if _, ok := precompile(ctx.rules, address); !ok { + // For recipient address + if currState.OpCode == vm.CALL { + value := currState.Stack.Back(2) + if value.Sign() != 0 && currState.Caller != address { + currState.GlobalState.SubBalance(currState.Caller, value.ToBig()) + currState.GlobalState.CommitForProof() + err = osp.addAccountProof(currState, address) + if err != nil { + return err + } + } + } + // For opcode proof + osp.addCodeProof(currState, address) + } + return nil +} + +func (osp *OneStepProof) addCreatePostProof(currState *state.IntraState, nonce uint64, contractAddr common.Address) error { + value := currState.Stack.Peek() + in := currState.Stack.Back(1).Uint64() + inSize := currState.Stack.Back(2).Uint64() + err := osp.addMemoryReadProof(in, inSize, currState) + if err != nil { + return err + } + currState.GlobalState.SetNonce(currState.Caller, nonce+1) + currState.GlobalState.SubBalance(currState.Caller, value.ToBig()) + currState.GlobalState.CommitForProof() + return osp.addAccountProof(currState, contractAddr) +} + +func opCreateProof(ctx ProofGenContext, currState, nextState *state.IntraState, vmerr error) (*OneStepProof, error) { + osp := EmptyProof() + osp.SetVerifierType(VerifierTypeCallOp) + osp.addStateProof(currState) + osp.addOpCodeProof(ctx, currState) + // If the stack validation fails or write protection or depth, we don't need to provide stack proofs + if IsStackError(vmerr) || vmerr == vm.ErrWriteProtection || vmerr == vm.ErrDepth { + err := osp.addRevertProof(ctx, currState, nextState, vmerr) + if err != nil { + return nil, err + } + return osp, nil + } + osp.addStackProof(3, currState) + if vmerr == vm.ErrOutOfGas || vmerr == vm.ErrGasUintOverflow { + err := osp.addRevertProof(ctx, currState, nextState, vmerr) + if err != nil { + return nil, err + } + } + err := osp.addCurrAccountProof(currState) + if err != nil { + return nil, err + } + if vmerr == vm.ErrInsufficientBalance || vmerr == vm.ErrNonceUintOverflow || vmerr == vm.ErrContractAddressCollision { + err := osp.addRevertProof(ctx, currState, nextState, vmerr) + if err != nil { + return nil, err + } + } + nonce := currState.GlobalState.GetNonce(currState.Caller) + contractAddr := crypto.CreateAddress(currState.Caller, nonce) + err = osp.addCreatePostProof(currState, nonce, contractAddr) + if err != nil { + return nil, err + } + return osp, nil +} + +func opCallProof(ctx ProofGenContext, currState, nextState *state.IntraState, vmerr error) (*OneStepProof, error) { + osp := EmptyProof() + osp.SetVerifierType(VerifierTypeCallOp) + osp.addStateProof(currState) + // If the stack validation fails or write protection or depth, we don't need to provide stack proofs + if IsStackError(vmerr) || vmerr == vm.ErrWriteProtection || vmerr == vm.ErrDepth { + err := osp.addRevertProof(ctx, currState, nextState, vmerr) + if err != nil { + return nil, err + } + return osp, nil + } + osp.addStackProof(7, currState) + if vmerr == vm.ErrOutOfGas || vmerr == vm.ErrGasUintOverflow { + err := osp.addRevertProof(ctx, currState, nextState, vmerr) + if err != nil { + return nil, err + } + } + err := osp.addCurrAccountProof(currState) + if err != nil { + return nil, err + } + if vmerr == vm.ErrInsufficientBalance { + err := osp.addRevertProof(ctx, currState, nextState, vmerr) + if err != nil { + return nil, err + } + } + err = osp.addCallPostProof(ctx, currState) + if err != nil { + return nil, err + } + return osp, nil +} + +func opCallCodeProof(ctx ProofGenContext, currState, nextState *state.IntraState, vmerr error) (*OneStepProof, error) { + osp := EmptyProof() + osp.SetVerifierType(VerifierTypeCallOp) + osp.addStateProof(currState) + // If the stack validation fails or write protection or depth, we don't need to provide stack proofs + if IsStackError(vmerr) || vmerr == vm.ErrWriteProtection || vmerr == vm.ErrDepth { + err := osp.addRevertProof(ctx, currState, nextState, vmerr) + if err != nil { + return nil, err + } + return osp, nil + } + osp.addStackProof(7, currState) + if vmerr == vm.ErrOutOfGas || vmerr == vm.ErrGasUintOverflow { + err := osp.addRevertProof(ctx, currState, nextState, vmerr) + if err != nil { + return nil, err + } + } + err := osp.addCallPostProof(ctx, currState) + if err != nil { + return nil, err + } + return osp, nil +} + +// If a call frame is returned to its parent call frame, we need to provide the proof +// of the lastDepthState. The return data or contract creation is handled in [opReturnProof]. +func (osp *OneStepProof) addCallReturnProof(currState *state.IntraState) error { + lastDepthState := currState.LastDepthState.(*state.IntraState) + osp.addStateProof(lastDepthState) + return nil +} + +func (osp *OneStepProof) addSelfDestructSetProof(currState *state.IntraState) { + osp.AddProof(SelfDestructSetProofFromSelfDestructSet(currState.SelfDestructSet)) +} + +// If a transaction is returned, transaction needs to be finalized. +// 1. refund gas +// 2. tip the coinbase +// 3. delete all suicided contracts +// 4. update the transaction trie and receipt trie +func (osp *OneStepProof) addTransactionReturnProof(ctx ProofGenContext, currState *state.IntraState) error { + lastDepthState := currState.LastDepthState.(*state.InterState) + osp.addInterStateProof(lastDepthState) + + err := osp.addAccountProof(currState, currState.Caller) + if err != nil { + return err + } + refundQuotient := params.RefundQuotient + if ctx.rules.IsLondon { + refundQuotient = params.RefundQuotientEIP3529 + } + initialGas := ctx.transaction.Gas() + gasUsed := ctx.receipt.GasUsed + gasPrice := ctx.transaction.GasPrice() + gasLeft := initialGas - gasUsed + refund := gasUsed / refundQuotient + if refund > currState.Refund { + refund = currState.Refund + } + gasLeft += refund + remaining := new(big.Int).Mul(new(big.Int).SetUint64(gasLeft), gasPrice) + currState.GlobalState.AddBalance(currState.Caller, remaining) + currState.GlobalState.CommitForProof() + + err = osp.addAccountProof(currState, ctx.coinbase) + if err != nil { + return err + } + fee := new(big.Int).Mul(new(big.Int).SetUint64(gasUsed), gasPrice) + currState.GlobalState.AddBalance(ctx.coinbase, fee) + currState.GlobalState.CommitForProof() + + osp.addSelfDestructSetProof(currState) + for _, addr := range currState.SelfDestructSet.Contracts { + err = osp.addAccountProof(currState, addr) + if err != nil { + return err + } + currState.GlobalState.DeleteSuicidedAccountForProof(addr) + currState.GlobalState.CommitForProof() + } + + osp.AddProof(ReceiptProofFromReceipt(ctx.receipt)) + return nil +} + +func (osp *OneStepProof) addReturnProof(ctx ProofGenContext, currState, nextState *state.IntraState) error { + if nextState == nil { + // We're in the topmost call frame, the entire transaction will be finalized + return osp.addTransactionReturnProof(ctx, currState) + } + return osp.addCallReturnProof(currState) +} + +func opStopProof(ctx ProofGenContext, currState, nextState *state.IntraState, vmerr error) (*OneStepProof, error) { + osp := EmptyProof() + osp.SetVerifierType(VerifierTypeCallOp) + osp.addStateProof(currState) + osp.addOpCodeProof(ctx, currState) + // TODO: EIP-3541 invalid code check in London + if vmerr != nil && !IsStopTokenError(vmerr) { + err := osp.addRevertProof(ctx, currState, nextState, vmerr) + if err != nil { + return nil, err + } + return osp, nil + } + err := osp.addReturnProof(ctx, currState, nextState) + if err != nil { + return nil, err + } + return osp, nil +} + +func opReturnProof(ctx ProofGenContext, currState, nextState *state.IntraState, vmerr error) (*OneStepProof, error) { + osp := EmptyProof() + osp.SetVerifierType(VerifierTypeCallOp) + osp.addStateProof(currState) + osp.addOpCodeProof(ctx, currState) + // If the stack validation fails or write protection, we don't need to provide stack proofs + if IsStackError(vmerr) || vmerr == vm.ErrWriteProtection { + err := osp.addRevertProof(ctx, currState, nextState, vmerr) + if err != nil { + return nil, err + } + return osp, nil + } + osp.addStackProof(2, currState) + // TODO: EIP-3541 invalid code check in London + if vmerr != nil && !IsStopTokenError(vmerr) { + err := osp.addRevertProof(ctx, currState, nextState, vmerr) + if err != nil { + return nil, err + } + return osp, nil + } + if currState.Depth > 1 || currState.CallFlag.IsCreate() { + offset := currState.Stack.Peek().Uint64() + size := currState.Stack.Back(1).Uint64() + err := osp.addMemoryReadProof(offset, size, currState) + if err != nil { + return nil, err + } + if currState.CallFlag.IsCreate() { + err = osp.addCurrAccountProof(currState) + if err != nil { + return nil, err + } + // Simulate contract creation + createdCode := currState.Memory.Data()[offset : offset+size] + currState.GlobalState.SetCode(currState.ContractAddress, createdCode) + currState.GlobalState.CommitForProof() + } + } + err := osp.addReturnProof(ctx, currState, nextState) + if currState.Depth > 1 { + if !currState.CallFlag.IsCreate() { + lastDepthState := currState.LastDepthState.(*state.IntraState) + err = osp.addMemoryWriteProof(currState.Out, currState.OutSize, lastDepthState, nextState) + if err != nil { + return nil, err + } + } + } + if err != nil { + return nil, err + } + return osp, nil +} + +func opDelegateCallProof(ctx ProofGenContext, currState, nextState *state.IntraState, vmerr error) (*OneStepProof, error) { + osp := EmptyProof() + osp.SetVerifierType(VerifierTypeCallOp) + osp.addStateProof(currState) + // If the stack validation fails or write protection or depth, we don't need to provide stack proofs + if IsStackError(vmerr) || vmerr == vm.ErrWriteProtection || vmerr == vm.ErrDepth { + err := osp.addRevertProof(ctx, currState, nextState, vmerr) + if err != nil { + return nil, err + } + return osp, nil + } + osp.addStackProof(6, currState) + if vmerr == vm.ErrOutOfGas || vmerr == vm.ErrGasUintOverflow { + err := osp.addRevertProof(ctx, currState, nextState, vmerr) + if err != nil { + return nil, err + } + } + err := osp.addCallPostProof(ctx, currState) + if err != nil { + return nil, err + } + return osp, nil +} + +func opCreate2Proof(ctx ProofGenContext, currState, nextState *state.IntraState, vmerr error) (*OneStepProof, error) { + osp := EmptyProof() + osp.SetVerifierType(VerifierTypeCallOp) + osp.addStateProof(currState) + osp.addOpCodeProof(ctx, currState) + // If the stack validation fails or write protection or depth, we don't need to provide stack proofs + if IsStackError(vmerr) || vmerr == vm.ErrWriteProtection || vmerr == vm.ErrDepth { + err := osp.addRevertProof(ctx, currState, nextState, vmerr) + if err != nil { + return nil, err + } + return osp, nil + } + osp.addStackProof(4, currState) + if vmerr == vm.ErrOutOfGas || vmerr == vm.ErrGasUintOverflow { + err := osp.addRevertProof(ctx, currState, nextState, vmerr) + if err != nil { + return nil, err + } + } + err := osp.addCurrAccountProof(currState) + if err != nil { + return nil, err + } + if vmerr == vm.ErrInsufficientBalance || vmerr == vm.ErrNonceUintOverflow || vmerr == vm.ErrContractAddressCollision { + err := osp.addRevertProof(ctx, currState, nextState, vmerr) + if err != nil { + return nil, err + } + } + nonce := currState.GlobalState.GetNonce(currState.Caller) + // TODO: revise it + contractAddr := nextState.ContractAddress + err = osp.addCreatePostProof(currState, nonce, contractAddr) + if err != nil { + return nil, err + } + return osp, nil +} + +func opStaticCallProof(ctx ProofGenContext, currState, nextState *state.IntraState, vmerr error) (*OneStepProof, error) { + osp := EmptyProof() + osp.SetVerifierType(VerifierTypeCallOp) + osp.addStateProof(currState) + // If the stack validation fails or write protection or depth, we don't need to provide stack proofs + if IsStackError(vmerr) || vmerr == vm.ErrWriteProtection || vmerr == vm.ErrDepth { + err := osp.addRevertProof(ctx, currState, nextState, vmerr) + if err != nil { + return nil, err + } + return osp, nil + } + osp.addStackProof(6, currState) + if vmerr == vm.ErrOutOfGas || vmerr == vm.ErrGasUintOverflow { + err := osp.addRevertProof(ctx, currState, nextState, vmerr) + if err != nil { + return nil, err + } + } + err := osp.addCallPostProof(ctx, currState) + if err != nil { + return nil, err + } + return osp, nil +} + +func opRevertProof(ctx ProofGenContext, currState, nextState *state.IntraState, vmerr error) (*OneStepProof, error) { + osp := EmptyProof() + osp.SetVerifierType(VerifierTypeCallOp) + osp.addStateProof(currState) + osp.addOpCodeProof(ctx, currState) + // If the stack validation fails or write protection, we don't need to provide stack proofs + if IsStackError(vmerr) || vmerr == vm.ErrWriteProtection { + err := osp.addRevertProof(ctx, currState, nextState, vmerr) + if err != nil { + return nil, err + } + return osp, nil + } + osp.addStackProof(2, currState) + if vmerr == vm.ErrOutOfGas || vmerr == vm.ErrGasUintOverflow { + err := osp.addRevertProof(ctx, currState, nextState, vmerr) + if err != nil { + return nil, err + } + } + if currState.Depth > 1 { + lastDepthState := currState.LastDepthState.(*state.IntraState) + offset := currState.Stack.Peek().Uint64() + size := currState.Stack.Back(1).Uint64() + err := osp.addMemoryReadProof(offset, size, currState) + if err != nil { + return nil, err + } + err = osp.addMemoryWriteProof(currState.Out, currState.OutSize, lastDepthState, nextState) + if err != nil { + return nil, err + } + } + err := osp.addRevertProof(ctx, currState, nextState, errors.New("execution reverted")) + if err != nil { + return nil, err + } + return osp, nil +} + +func opInvalidProof(ctx ProofGenContext, currState, nextState *state.IntraState, vmerr error) (*OneStepProof, error) { + osp := EmptyProof() + osp.SetVerifierType(VerifierTypeInvalidOp) + osp.addStateProof(currState) + osp.addOpCodeProof(ctx, currState) + err := osp.addRevertProof(ctx, currState, nextState, vmerr) + if err != nil { + return nil, err + } + return osp, nil +} + +func opSelfDestructProof(ctx ProofGenContext, currState, nextState *state.IntraState, vmerr error) (*OneStepProof, error) { + osp := EmptyProof() + osp.SetVerifierType(VerifierTypeCallOp) + osp.addStateProof(currState) + osp.addOpCodeProof(ctx, currState) + // If the stack validation fails or write protection, we don't need to provide stack proofs + if IsStackError(vmerr) || vmerr == vm.ErrWriteProtection { + err := osp.addRevertProof(ctx, currState, nextState, vmerr) + if err != nil { + return nil, err + } + return osp, nil + } + osp.addStackProof(1, currState) + if vmerr == vm.ErrOutOfGas || vmerr == vm.ErrGasUintOverflow { + err := osp.addRevertProof(ctx, currState, nextState, vmerr) + if err != nil { + return nil, err + } + } + beneficiary := common.Address(currState.Stack.Back(0).Bytes20()) + contract := currState.ContractAddress + err := osp.addAccountProof(currState, contract) + if err != nil { + return nil, err + } + if currState.GlobalState.GetBalance(contract).Sign() > 0 && beneficiary != contract { + currState.GlobalState.SubBalance(contract, currState.GlobalState.GetBalance(contract)) + currState.GlobalState.CommitForProof() + err = osp.addAccountProof(currState, beneficiary) + if err != nil { + return nil, err + } + } + err = osp.addReturnProof(ctx, currState, nextState) + if err != nil { + return nil, err + } + return osp, nil +} diff --git a/fraud-proof/proof/proof/jump_table.go b/fraud-proof/proof/proof/jump_table.go new file mode 100644 index 000000000..9a52975e8 --- /dev/null +++ b/fraud-proof/proof/proof/jump_table.go @@ -0,0 +1,469 @@ +// Copyright 2022, Specular contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package proof + +import ( + "github.com/mantlenetworkio/mantle/fraud-proof/proof/state" + "github.com/mantlenetworkio/mantle/l2geth/core/vm" +) + +type genProofFunc func(ctx ProofGenContext, currState, nextState *state.IntraState, vmerr error) (*OneStepProof, error) + +type proofGen struct { + genProof genProofFunc +} + +type jumpTable [256]*proofGen + +var proofJumpTable = newProofJumpTable() + +func newProofJumpTable() jumpTable { + tbl := jumpTable{ + vm.STOP: { + genProof: opStopProof, + }, + vm.ADD: { + genProof: makeStackOnlyInstructionProof(2), + }, + vm.MUL: { + genProof: makeStackOnlyInstructionProof(2), + }, + vm.SUB: { + genProof: makeStackOnlyInstructionProof(2), + }, + vm.DIV: { + genProof: makeStackOnlyInstructionProof(2), + }, + vm.SDIV: { + genProof: makeStackOnlyInstructionProof(2), + }, + vm.MOD: { + genProof: makeStackOnlyInstructionProof(2), + }, + vm.SMOD: { + genProof: makeStackOnlyInstructionProof(2), + }, + vm.ADDMOD: { + genProof: makeStackOnlyInstructionProof(3), + }, + vm.MULMOD: { + genProof: makeStackOnlyInstructionProof(3), + }, + vm.EXP: { + genProof: makeStackOnlyInstructionProof(2), + }, + vm.SIGNEXTEND: { + genProof: makeStackOnlyInstructionProof(2), + }, + vm.LT: { + genProof: makeStackOnlyInstructionProof(2), + }, + vm.GT: { + genProof: makeStackOnlyInstructionProof(2), + }, + vm.SLT: { + genProof: makeStackOnlyInstructionProof(2), + }, + vm.SGT: { + genProof: makeStackOnlyInstructionProof(2), + }, + vm.EQ: { + genProof: makeStackOnlyInstructionProof(2), + }, + vm.ISZERO: { + genProof: makeStackOnlyInstructionProof(1), + }, + vm.AND: { + genProof: makeStackOnlyInstructionProof(2), + }, + vm.OR: { + genProof: makeStackOnlyInstructionProof(2), + }, + vm.XOR: { + genProof: makeStackOnlyInstructionProof(2), + }, + vm.NOT: { + genProof: makeStackOnlyInstructionProof(1), + }, + vm.BYTE: { + genProof: makeStackOnlyInstructionProof(2), + }, + vm.SHL: { + genProof: makeStackOnlyInstructionProof(2), + }, + vm.SHR: { + genProof: makeStackOnlyInstructionProof(2), + }, + vm.SAR: { + genProof: makeStackOnlyInstructionProof(2), + }, + vm.SHA3: { + genProof: opKeccak256Proof, + }, + vm.ADDRESS: { + genProof: makeStackOnlyInstructionProof(0), + }, + vm.BALANCE: { + genProof: opBalanceProof, + }, + vm.ORIGIN: { + genProof: makeStackOnlyInstructionProof(0), + }, + vm.CALLER: { + genProof: makeStackOnlyInstructionProof(0), + }, + vm.CALLVALUE: { + genProof: makeStackOnlyInstructionProof(0), + }, + vm.CALLDATALOAD: { + genProof: opCallDataLoadProof, + }, + vm.CALLDATASIZE: { + genProof: makeStackOnlyInstructionProof(0), + }, + vm.CALLDATACOPY: { + genProof: opCallDataCopyProof, + }, + vm.CODESIZE: { + genProof: makeStackOnlyInstructionProof(0), + }, + vm.CODECOPY: { + genProof: opCodeCopyProof, + }, + vm.GASPRICE: { + genProof: makeStackOnlyInstructionProof(0), + }, + vm.EXTCODESIZE: { + genProof: opExtCodeSizeProof, + }, + vm.EXTCODECOPY: { + genProof: opExtCodeCopyProof, + }, + vm.RETURNDATASIZE: { + genProof: makeStackOnlyInstructionProof(0), + }, + vm.RETURNDATACOPY: { + genProof: opReturnDataCopyProof, + }, + vm.EXTCODEHASH: { + genProof: opExtCodeHashProof, + }, + vm.BLOCKHASH: { + genProof: opBlockHashProof, + }, + vm.COINBASE: { + genProof: makeStackOnlyInstructionProof(0), + }, + vm.TIMESTAMP: { + genProof: makeStackOnlyInstructionProof(0), + }, + vm.NUMBER: { + genProof: makeStackOnlyInstructionProof(0), + }, + vm.DIFFICULTY: { + genProof: makeStackOnlyInstructionProof(0), + }, + vm.GASLIMIT: { + genProof: makeStackOnlyInstructionProof(0), + }, + vm.CHAINID: { + genProof: makeStackOnlyInstructionProof(0), + }, + vm.SELFBALANCE: { + genProof: opSelfBalanceProof, + }, + // vm.BASEFEE: { + // genProof: makeStackOnlyInstructionProof(0), + // }, + vm.POP: { + genProof: makeStackOnlyInstructionProof(1), + }, + vm.MLOAD: { + genProof: opMLoadProof, + }, + vm.MSTORE: { + genProof: opMStoreProof, + }, + vm.MSTORE8: { + genProof: opMStore8Proof, + }, + vm.SLOAD: { + genProof: opSLoadProof, + }, + vm.SSTORE: { + genProof: opSStoreProof, + }, + vm.JUMP: { + genProof: makeStackOnlyInstructionProof(1), + }, + vm.JUMPI: { + genProof: makeStackOnlyInstructionProof(2), + }, + vm.PC: { + genProof: makeStackOnlyInstructionProof(0), + }, + vm.MSIZE: { + genProof: makeStackOnlyInstructionProof(0), + }, + vm.GAS: { + genProof: makeStackOnlyInstructionProof(0), + }, + vm.JUMPDEST: { + genProof: opJumpDestProof, + }, + vm.PUSH1: { + genProof: opPushProof, + }, + vm.PUSH2: { + genProof: opPushProof, + }, + vm.PUSH3: { + genProof: opPushProof, + }, + vm.PUSH4: { + genProof: opPushProof, + }, + vm.PUSH5: { + genProof: opPushProof, + }, + vm.PUSH6: { + genProof: opPushProof, + }, + vm.PUSH7: { + genProof: opPushProof, + }, + vm.PUSH8: { + genProof: opPushProof, + }, + vm.PUSH9: { + genProof: opPushProof, + }, + vm.PUSH10: { + genProof: opPushProof, + }, + vm.PUSH11: { + genProof: opPushProof, + }, + vm.PUSH12: { + genProof: opPushProof, + }, + vm.PUSH13: { + genProof: opPushProof, + }, + vm.PUSH14: { + genProof: opPushProof, + }, + vm.PUSH15: { + genProof: opPushProof, + }, + vm.PUSH16: { + genProof: opPushProof, + }, + vm.PUSH17: { + genProof: opPushProof, + }, + vm.PUSH18: { + genProof: opPushProof, + }, + vm.PUSH19: { + genProof: opPushProof, + }, + vm.PUSH20: { + genProof: opPushProof, + }, + vm.PUSH21: { + genProof: opPushProof, + }, + vm.PUSH22: { + genProof: opPushProof, + }, + vm.PUSH23: { + genProof: opPushProof, + }, + vm.PUSH24: { + genProof: opPushProof, + }, + vm.PUSH25: { + genProof: opPushProof, + }, + vm.PUSH26: { + genProof: opPushProof, + }, + vm.PUSH27: { + genProof: opPushProof, + }, + vm.PUSH28: { + genProof: opPushProof, + }, + vm.PUSH29: { + genProof: opPushProof, + }, + vm.PUSH30: { + genProof: opPushProof, + }, + vm.PUSH31: { + genProof: opPushProof, + }, + vm.PUSH32: { + genProof: opPushProof, + }, + vm.DUP1: { + genProof: makeStackOnlyInstructionProof(1), + }, + vm.DUP2: { + genProof: makeStackOnlyInstructionProof(2), + }, + vm.DUP3: { + genProof: makeStackOnlyInstructionProof(3), + }, + vm.DUP4: { + genProof: makeStackOnlyInstructionProof(4), + }, + vm.DUP5: { + genProof: makeStackOnlyInstructionProof(5), + }, + vm.DUP6: { + genProof: makeStackOnlyInstructionProof(6), + }, + vm.DUP7: { + genProof: makeStackOnlyInstructionProof(7), + }, + vm.DUP8: { + genProof: makeStackOnlyInstructionProof(8), + }, + vm.DUP9: { + genProof: makeStackOnlyInstructionProof(9), + }, + vm.DUP10: { + genProof: makeStackOnlyInstructionProof(10), + }, + vm.DUP11: { + genProof: makeStackOnlyInstructionProof(11), + }, + vm.DUP12: { + genProof: makeStackOnlyInstructionProof(12), + }, + vm.DUP13: { + genProof: makeStackOnlyInstructionProof(13), + }, + vm.DUP14: { + genProof: makeStackOnlyInstructionProof(14), + }, + vm.DUP15: { + genProof: makeStackOnlyInstructionProof(15), + }, + vm.DUP16: { + genProof: makeStackOnlyInstructionProof(16), + }, + vm.SWAP1: { + genProof: makeStackOnlyInstructionProof(2), + }, + vm.SWAP2: { + genProof: makeStackOnlyInstructionProof(3), + }, + vm.SWAP3: { + genProof: makeStackOnlyInstructionProof(4), + }, + vm.SWAP4: { + genProof: makeStackOnlyInstructionProof(5), + }, + vm.SWAP5: { + genProof: makeStackOnlyInstructionProof(6), + }, + vm.SWAP6: { + genProof: makeStackOnlyInstructionProof(7), + }, + vm.SWAP7: { + genProof: makeStackOnlyInstructionProof(8), + }, + vm.SWAP8: { + genProof: makeStackOnlyInstructionProof(9), + }, + vm.SWAP9: { + genProof: makeStackOnlyInstructionProof(10), + }, + vm.SWAP10: { + genProof: makeStackOnlyInstructionProof(11), + }, + vm.SWAP11: { + genProof: makeStackOnlyInstructionProof(12), + }, + vm.SWAP12: { + genProof: makeStackOnlyInstructionProof(13), + }, + vm.SWAP13: { + genProof: makeStackOnlyInstructionProof(14), + }, + vm.SWAP14: { + genProof: makeStackOnlyInstructionProof(15), + }, + vm.SWAP15: { + genProof: makeStackOnlyInstructionProof(16), + }, + vm.SWAP16: { + genProof: makeStackOnlyInstructionProof(17), + }, + vm.LOG0: { + genProof: makeLogProof(0), + }, + vm.LOG1: { + genProof: makeLogProof(1), + }, + vm.LOG2: { + genProof: makeLogProof(2), + }, + vm.LOG3: { + genProof: makeLogProof(3), + }, + vm.LOG4: { + genProof: makeLogProof(4), + }, + vm.CREATE: { + genProof: opCreateProof, + }, + vm.CALL: { + genProof: opCallProof, + }, + vm.CALLCODE: { + genProof: opCallCodeProof, + }, + vm.RETURN: { + genProof: opReturnProof, + }, + vm.DELEGATECALL: { + genProof: opDelegateCallProof, + }, + vm.CREATE2: { + genProof: opCreate2Proof, + }, + vm.STATICCALL: { + genProof: opStaticCallProof, + }, + vm.REVERT: { + genProof: opRevertProof, + }, + vm.SELFDESTRUCT: { + genProof: opSelfDestructProof, + }, + } + + for i, entry := range tbl { + if entry == nil { + tbl[i] = &proofGen{genProof: opInvalidProof} + } + } + + return tbl +} diff --git a/fraud-proof/proof/proof/proof.go b/fraud-proof/proof/proof/proof.go new file mode 100644 index 000000000..439a5da89 --- /dev/null +++ b/fraud-proof/proof/proof/proof.go @@ -0,0 +1,297 @@ +// Copyright 2022, Specular contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package proof + +import ( + "math/big" + + "github.com/mantlenetworkio/mantle/fraud-proof/proof/state" + "github.com/mantlenetworkio/mantle/l2geth/common" + "github.com/mantlenetworkio/mantle/l2geth/core" + "github.com/mantlenetworkio/mantle/l2geth/core/types" + "github.com/mantlenetworkio/mantle/l2geth/core/vm" + "github.com/mantlenetworkio/mantle/l2geth/crypto" + "github.com/mantlenetworkio/mantle/l2geth/log" + "github.com/mantlenetworkio/mantle/l2geth/params" +) + +type ProofGenContext struct { + rules params.Rules + coinbase common.Address + transaction *types.Transaction + receipt *types.Receipt + actualCode []byte // For opcode proof when in CALLCODE/DELEGATECALL/STATICCALL +} + +func NewProofGenContext(rules params.Rules, coinbase common.Address, transaction *types.Transaction, receipt *types.Receipt, actualCode []byte) ProofGenContext { + return ProofGenContext{ + rules: rules, + coinbase: coinbase, + receipt: receipt, + transaction: transaction, + actualCode: actualCode, + } +} + +type Proof interface { + Encode() []byte +} + +type OneStepProof struct { + VerifierType VerifierType + Proofs []Proof + + TotalCodeSize uint64 // for statistics +} + +func EmptyProof() *OneStepProof { + return &OneStepProof{} +} + +func (p *OneStepProof) AddProof(proof Proof) { + p.Proofs = append(p.Proofs, proof) +} + +func (p *OneStepProof) SetVerifierType(ty VerifierType) { + p.VerifierType = ty +} + +func (p *OneStepProof) Encode() []byte { + if len(p.Proofs) == 0 { + // Empty proof! + return []byte{} + } + encodedLen := 0 + encodedProofs := make([][]byte, len(p.Proofs)) + for idx, proof := range p.Proofs { + encodedProofs[idx] = proof.Encode() + encodedLen += len(encodedProofs[idx]) + } + encoded := make([]byte, encodedLen) + offset := 0 + for _, encodedProof := range encodedProofs { + copy(encoded[offset:], encodedProof) + offset += len(encodedProof) + } + return encoded +} + +// Type 1 BlockState -> InterState: block initiation +// A BlockStateProof suffices to prove this state transition. +// +// The verifier can generate the first InterState by setting the transaction trie root +// and receipt trie root to the empty trie root, logs bloom to empty, and setting the +// block gas used to 0. +func GetBlockInitiationProof(blockState *state.BlockState) (*OneStepProof, error) { + osp := EmptyProof() + osp.SetVerifierType(VerifierTypeBlockInit) + osp.AddProof(BlockStateProofFromBlockState(blockState)) + return osp, nil +} + +// Type 6 InterState -> BlockState: block finalization +// The verifier needs to first pack the block header and calculate the block hash; +// then, the verifier can simulate changing the block hash in the block hash tree +// using the plain Merkle tree proof. +func GetBlockFinalizationProof(interState *state.InterState) (*OneStepProof, error) { + osp := EmptyProof() + osp.SetVerifierType(VerifierTypeBlockFinal) + // This proof reveals the transaction trie root, receipt trie root, logs bloom, + // and block gas used. Verifier can calculate the block hash from these values. + osp.AddProof(InterStateProofFromInterState(interState)) + // Prove the parent block hash + osp.AddProof(&BlockHashProof{interState.BlockHashTree.GetBlockHash(interState.BlockNumber - 1)}) + // This proof provides the block hash tree Merkle proof of the parent block. + blockHashMerkleProof, err := GetBlockHashMerkleProof(interState.BlockHashTree, interState.BlockNumber-1) + if err != nil { + return nil, err + } + osp.AddProof(blockHashMerkleProof) + // Prove the current block hash to be updated + osp.AddProof(&BlockHashProof{interState.BlockHashTree.GetBlockHash(interState.BlockNumber)}) + // This proof provides the block hash tree Merkle proof at the designated index. + blockHashMerkleProof, err = GetBlockHashMerkleProof(interState.BlockHashTree, interState.BlockNumber) + if err != nil { + return nil, err + } + osp.AddProof(blockHashMerkleProof) + return osp, nil +} + +// Type 2 InterState -> IntraState: transaction initiation +// Type 3 InterState -> InterState: EOA transfer transaction +// See go-ethereum/core/state_transition.go for the full state transition logic. +// 1. Provide the inter state proof. +// 2. Provide the MPT proof for the sender account. Verifier can perform nonce +// check and balance check through the MPT proof. +// 3. Simulate the transaction initation including nonce increment, gas buying, +// and balance transfer. If error, stop. +// Note: sadly EVM does not expose methods for these so we have to implement +// them by ourselves. +// 4. Provide the MPT proof for the recipient account, based on the simulated +// state. Verifier can construct the state trie root after transfer. +// 5. If EOA transfer, also provde the MPT proof for both transaction trie, receipt +// trie, and account proof of coinbase so verifier can finalize the transaction. +func GetTransactionInitaitionProof( + chainConfig *params.ChainConfig, + vmctx *vm.BlockContext, + tx *types.Transaction, + txctx *vm.Context, + interState *state.InterState, + statedb vm.StateDB, +) (*OneStepProof, error) { + osp := EmptyProof() + osp.SetVerifierType(VerifierTypeInterTx) + osp.AddProof(InterStateProofFromInterState(interState)) + + // MPT proof of the sender account + senderProof, err := statedb.GetProof(txctx.Origin) + if err != nil { + return nil, err + } + osp.AddProof(&MPTProof{senderProof}) + + // Simulate the transaction initiation + success := true + // 1. Nonce check + stNonce := statedb.GetNonce(txctx.Origin) + msgNonce := tx.Nonce() + if stNonce < msgNonce || stNonce > msgNonce || stNonce+1 < stNonce { + // Nonce check failed + success = false + } + // 2. Sender EOA check + if success && len(statedb.GetCode(txctx.Origin)) != 0 { + // Sender is a contract + success = false + } + // 3. Gas buying + if success { + requiredBalance := new(big.Int).SetUint64(tx.Gas()) + requiredBalance = requiredBalance.Mul(requiredBalance, tx.GasPrice()) + stBalance := statedb.GetBalance(txctx.Origin) + if stBalance.Cmp(requiredBalance) < 0 { + success = false + } + // Here we don't check if there is enough gas left in the block for the transaction. + // Only happens when the sequencer is malicious. + // TODO: reason it or check + if success { + statedb.SubBalance(txctx.Origin, requiredBalance) + } + } + var rules params.Rules + // 4. Instrinsic gas deduction + if success { + rules = chainConfig.Rules(vmctx.BlockNumber) + // TODO: can we just hard-code the consensus rules here? + gas, err := core.IntrinsicGas(tx.Data(), tx.To() == nil, rules.IsHomestead, rules.IsIstanbul) + if err != nil { + // Gas overflow + // TODO: reason it + success = false + } else if tx.Gas() < gas { + // ErrIntrinsicGas + success = false + } + } + // 5. Balance transfer check + if success { + if tx.Value().Sign() > 0 && !vmctx.CanTransfer(statedb, txctx.Origin, tx.Value()) { + // ErrInsufficientFunds + success = false + } + } + // 6. Simulate the transaction initiation on the sender account + if success { + // Increment nonce + statedb.SetNonce(txctx.Origin, stNonce+1) + // Deduct sender's balance + statedb.SubBalance(txctx.Origin, tx.Value()) + // Commit for new trie root after sender account changes + statedb.CommitForProof() + // Generate proof for the recipient account + if tx.To() != nil { + // Call or EOA transfer + recipientProof, err := statedb.GetProof(*tx.To()) + if err != nil { + return nil, err + } + osp.AddProof(&MPTProof{recipientProof}) + // Add recipient's balance + statedb.AddBalance(*tx.To(), tx.Value()) + } else { + // Contract creation + contractAddr := crypto.CreateAddress(txctx.Origin, stNonce) // stNonce is the nonce before increment + recipientProof, err := statedb.GetProof(contractAddr) + if err != nil { + return nil, err + } + osp.AddProof(&MPTProof{recipientProof}) + // Add contract's balance only if no address collision + if statedb.GetNonce(contractAddr) != 0 || len(statedb.GetCode(contractAddr)) != 0 { + success = false + } else { + // Set contract nonce + if rules.IsEIP158 { + statedb.SetNonce(contractAddr, 1) + } + // Add recipient's balance + statedb.AddBalance(contractAddr, tx.Value()) + } + } + } + // 7. Commit statedb for the recipient account changes + if success { + // TODO: EOA transfer can't be contract creation, refactor + statedb.CommitForProof() + } + + // Determine if the transaction is an EOA transfer + // 1. The transaction canot be a contract creation + // 2. The recipient's code length should be 0 + if tx.To() != nil && len(statedb.GetCode(*tx.To())) == 0 { + // This is an EOA transfer, provide proofs for finalization here + // Note: transaction/receipt trie does not contain the current transaction + // so it is acutally proofs of exclusions. The verifier can perform + // insertions based on the proof. + txProof, err := interState.TransactionTrie.Prove(int(interState.TransactionIdx)) + if err != nil { + return nil, err + } + osp.AddProof(&MPTProof{txProof}) + receiptProof, err := interState.ReceiptTrie.Prove(int(interState.TransactionIdx)) + if err != nil { + return nil, err + } + osp.AddProof(&MPTProof{receiptProof}) + if success { + // Only provide the coinbase proof if the transaction is successful started + coinbaseProof, err := statedb.GetProof(vmctx.Coinbase) + if err != nil { + return nil, err + } + osp.AddProof(&MPTProof{coinbaseProof}) + } + } + return osp, nil +} + +// Type 4 IntraState -> IntraState: one-step EVM execution +// Type 5 IntraState -> InterState: transaction finalization +func GetIntraProof(ctx ProofGenContext, currState, nextState *state.IntraState, vmerr error) (*OneStepProof, error) { + log.Debug("Generating intra proof", "op", currState.OpCode, "gen", proofJumpTable[currState.OpCode]) + return proofJumpTable[currState.OpCode].genProof(ctx, currState, nextState, vmerr) +} diff --git a/fraud-proof/proof/proof/state_proof.go b/fraud-proof/proof/proof/state_proof.go new file mode 100644 index 000000000..4f29c08f7 --- /dev/null +++ b/fraud-proof/proof/proof/state_proof.go @@ -0,0 +1,280 @@ +// Copyright 2022, Specular contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package proof + +import ( + "encoding/binary" + + "github.com/holiman/uint256" + "github.com/mantlenetworkio/mantle/fraud-proof/proof/state" + "github.com/mantlenetworkio/mantle/l2geth/common" + "github.com/mantlenetworkio/mantle/l2geth/core/types" + "github.com/mantlenetworkio/mantle/l2geth/core/vm" + "github.com/mantlenetworkio/mantle/l2geth/crypto" + "github.com/mantlenetworkio/mantle/l2geth/rlp" +) + +type IntraStateProof struct { + BlockNumber uint64 + TransactionIdx uint64 + Depth uint16 + Gas uint64 + Refund uint64 + LastDepthHash common.Hash + ContractAddress common.Address + Caller common.Address + Value uint256.Int + CallFlag state.CallFlag + Out uint64 + OutSize uint64 + Pc uint64 + OpCode vm.OpCode + CodeHash common.Hash + StackHash common.Hash + StackSize uint64 + MemorySize uint64 + MemoryRoot common.Hash + InputDataSize uint64 + InputDataRoot common.Hash + ReturnDataSize uint64 + ReturnDataRoot common.Hash + CommittedGlobalStateRoot common.Hash + GlobalStateRoot common.Hash + SelfDestructAcc common.Hash + LogAcc common.Hash + BlockHashRoot common.Hash + AccesslistRoot common.Hash +} + +func StateProofFromState(s *state.IntraState) *IntraStateProof { + var lastDepthHash common.Hash + if s.LastDepthState != nil { + lastDepthHash = s.LastDepthState.Hash() + } + return &IntraStateProof{ + BlockNumber: s.BlockNumber, + TransactionIdx: s.TransactionIdx, + Depth: s.Depth, + Gas: s.Gas, + Refund: s.Refund, + LastDepthHash: lastDepthHash, + ContractAddress: s.ContractAddress, + Caller: s.Caller, + Value: s.Value, + CallFlag: s.CallFlag, + Out: s.Out, + OutSize: s.OutSize, + Pc: s.Pc, + OpCode: s.OpCode, + CodeHash: s.CodeHash, + StackSize: uint64(s.Stack.Len()), + StackHash: s.Stack.Hash(), + MemorySize: s.Memory.Size(), + MemoryRoot: s.Memory.Root(), + InputDataSize: s.InputData.Size(), + InputDataRoot: s.InputData.Root(), + ReturnDataSize: s.ReturnData.Size(), + ReturnDataRoot: s.ReturnData.Root(), + CommittedGlobalStateRoot: s.CommittedGlobalState.GetRootForProof(), + GlobalStateRoot: s.GlobalState.GetRootForProof(), + SelfDestructAcc: s.SelfDestructSet.Hash, + LogAcc: s.LogSeries.Hash(), + BlockHashRoot: s.BlockHashTree.Root(), + AccesslistRoot: s.AccessListTrie.Root(), + } +} + +func (s *IntraStateProof) Encode() []byte { + proofLen := 8 + 8 + 2 + 8 + 8 + 32 + 8 + 1 + 32 + 8 + 8 + 8 + 32 + 32 + 32 + 32 + 32 + 32 // BlockNumber, TransactionIdx, Depth, Gas, Refund, LastDepthHash, Pc, OpCode, CodeMerkle, StackSize, MemorySize, ReturnDataSize, CommittedGlobalStateRoot, GlobalStateRoot, SelfDestructAcc, LogAcc, BlockHashRoot, AccesslistRoot + if s.Depth != 1 { + proofLen += 20 + 20 + 32 + 8 + 1 + 8 + 8 // ContractAddress, Caller, Value, CallFlag, Out, OutSize, InputDataSize + if s.InputDataSize != 0 { + proofLen += 32 // InputDataRoot + } + } + if s.StackSize != 0 { + proofLen += 32 // StackHash + } + if s.MemorySize != 0 { + proofLen += 32 // MemoryRoot + } + if s.ReturnDataSize != 0 { + proofLen += 32 // ReturnDataRoot + } + encoded := make([]byte, proofLen) + blockNumber := make([]byte, 8) + binary.BigEndian.PutUint64(blockNumber, s.BlockNumber) + transactionIdx := make([]byte, 8) + binary.BigEndian.PutUint64(transactionIdx, s.TransactionIdx) + depth := make([]byte, 2) + binary.BigEndian.PutUint16(depth, s.Depth) + gas := make([]byte, 8) + binary.BigEndian.PutUint64(gas, s.Gas) + refund := make([]byte, 8) + binary.BigEndian.PutUint64(refund, s.Refund) + pc := make([]byte, 8) + binary.BigEndian.PutUint64(pc, s.Pc) + stackSize := make([]byte, 8) + binary.BigEndian.PutUint64(stackSize, s.StackSize) + memSize := make([]byte, 8) + binary.BigEndian.PutUint64(memSize, s.MemorySize) + var inputDataSize []byte + if s.Depth != 1 { + inputDataSize = make([]byte, 8) + binary.BigEndian.PutUint64(inputDataSize, s.InputDataSize) + } + returnDataSize := make([]byte, 8) + binary.BigEndian.PutUint64(returnDataSize, s.ReturnDataSize) + copy(encoded, blockNumber) + copy(encoded[8:], transactionIdx) + copy(encoded[16:], depth) + copy(encoded[18:], gas) + copy(encoded[26:], refund) + copy(encoded[34:], s.LastDepthHash.Bytes()) + offset := 66 + if s.Depth != 1 { + copy(encoded[offset:], s.ContractAddress.Bytes()) + copy(encoded[offset+20:], s.Caller.Bytes()) + valueBytes := s.Value.Bytes32() + copy(encoded[offset+20+20:], valueBytes[:]) + out := make([]byte, 8) + binary.BigEndian.PutUint64(out, s.Out) + outSize := make([]byte, 8) + binary.BigEndian.PutUint64(outSize, s.OutSize) + encoded[offset+20+20+32] = byte(s.CallFlag) + copy(encoded[offset+20+20+32+1:], out) + copy(encoded[offset+20+20+32+1+8:], outSize) + offset += 20 + 20 + 32 + 1 + 8 + 8 + } + copy(encoded[offset:], pc) + encoded[offset+8] = byte(s.OpCode) + copy(encoded[offset+8+1:], s.CodeHash.Bytes()) + copy(encoded[offset+8+1+32:], stackSize) + offset += 8 + 1 + 32 + 8 + if s.StackSize != 0 { + copy(encoded[offset:], s.StackHash.Bytes()) + offset += 32 + } + copy(encoded[offset:], memSize) + offset += 8 + if s.MemorySize != 0 { + copy(encoded[offset:], s.MemoryRoot.Bytes()) + offset += 32 + } + if s.Depth != 1 { + copy(encoded[offset:], inputDataSize) + offset += 8 + if s.InputDataSize != 0 { + copy(encoded[offset:], s.InputDataRoot.Bytes()) + offset += 32 + } + } + copy(encoded[offset:], returnDataSize) + offset += 8 + if s.ReturnDataSize != 0 { + copy(encoded[offset:], s.ReturnDataRoot.Bytes()) + offset += 32 + } + copy(encoded[offset:], s.CommittedGlobalStateRoot.Bytes()) + copy(encoded[offset+32:], s.GlobalStateRoot.Bytes()) + copy(encoded[offset+64:], s.SelfDestructAcc.Bytes()) + copy(encoded[offset+96:], s.LogAcc.Bytes()) + copy(encoded[offset+128:], s.BlockHashRoot.Bytes()) + copy(encoded[offset+160:], s.AccesslistRoot.Bytes()) + return encoded +} + +func (s *IntraStateProof) Hash() common.Hash { + return crypto.Keccak256Hash(s.Encode()) +} + +type InterStateProof struct { + BlockNumber uint64 + TransactionIdx uint64 + GlobalStateRoot common.Hash + BlockGasUsed uint256.Int + BlockHashRoot common.Hash + TransactionTireRoot common.Hash + ReceiptTrieRoot common.Hash + LogsBloom types.Bloom +} + +func InterStateProofFromInterState(s *state.InterState) *InterStateProof { + return &InterStateProof{ + BlockNumber: s.BlockNumber, + TransactionIdx: s.TransactionIdx, + GlobalStateRoot: s.GlobalState.GetRootForProof(), + BlockGasUsed: *s.BlockGasUsed, + BlockHashRoot: s.BlockHashTree.Root(), + TransactionTireRoot: s.TransactionTrie.Root(), + ReceiptTrieRoot: s.ReceiptTrie.Root(), + LogsBloom: s.ReceiptTrie.Bloom(), + } +} + +func (s *InterStateProof) Encode() []byte { + encoded := make([]byte, 464) + binary.BigEndian.PutUint64(encoded, s.BlockNumber) + binary.BigEndian.PutUint64(encoded[8:], s.TransactionIdx) + copy(encoded[16:], s.GlobalStateRoot.Bytes()) + blockGasBytes := s.BlockGasUsed.Bytes32() + copy(encoded[80:], blockGasBytes[:]) + copy(encoded[112:], s.BlockHashRoot.Bytes()) + copy(encoded[144:], s.TransactionTireRoot.Bytes()) + copy(encoded[176:], s.ReceiptTrieRoot.Bytes()) + copy(encoded[208:], s.LogsBloom.Bytes()) + return encoded +} + +type BlockStateProof struct { + BlockNumber uint64 + GlobalStateRoot common.Hash + BlockHashRoot common.Hash +} + +func BlockStateProofFromBlockState(s *state.BlockState) *BlockStateProof { + return &BlockStateProof{ + BlockNumber: s.BlockNumber, + GlobalStateRoot: s.GlobalState.GetRootForProof(), + BlockHashRoot: s.BlockHashTree.Root(), + } +} + +func (s *BlockStateProof) Encode() []byte { + encoded := make([]byte, 104) + binary.BigEndian.PutUint64(encoded, s.BlockNumber) + copy(encoded[8:], s.GlobalStateRoot.Bytes()) + copy(encoded[72:], s.BlockHashRoot.Bytes()) + return encoded +} + +type ReceiptProof struct { + RLPEncodedReceipt []byte +} + +func ReceiptProofFromReceipt(r *types.Receipt) *ReceiptProof { + encoded, _ := rlp.EncodeToBytes(r) + return &ReceiptProof{ + RLPEncodedReceipt: encoded, + } +} + +func (s *ReceiptProof) Encode() []byte { + length := len(s.RLPEncodedReceipt) + encoded := make([]byte, 8+length) + binary.BigEndian.PutUint64(encoded, uint64(length)) + copy(encoded[8:], s.RLPEncodedReceipt) + return encoded +} diff --git a/fraud-proof/proof/proof/utils.go b/fraud-proof/proof/proof/utils.go new file mode 100644 index 000000000..64812dada --- /dev/null +++ b/fraud-proof/proof/proof/utils.go @@ -0,0 +1,101 @@ +// Copyright 2022, Specular contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package proof + +import ( + "strings" + + "github.com/mantlenetworkio/mantle/l2geth/common" + "github.com/mantlenetworkio/mantle/l2geth/core/vm" + "github.com/mantlenetworkio/mantle/l2geth/params" +) + +func GetAccountProof( + db vm.StateDB, + address common.Address, +) (*MPTProof, error) { + accountProof, err := db.GetProof(address) + if err != nil { + return nil, err + } + return &MPTProof{accountProof}, nil +} + +func GetStorageProof( + db vm.StateDB, + address common.Address, + key common.Hash, +) (*MPTProof, *MPTProof, error) { + accountProof, err := db.GetProof(address) + if err != nil { + return nil, nil, err + } + storageProof, err := db.GetStorageProof(address, key) + if err != nil { + return nil, nil, err + } + return &MPTProof{accountProof}, &MPTProof{storageProof}, nil +} + +func calcCellNum(offset, size uint64) uint64 { + return (offset+size+31)/32 - offset/32 +} + +func IsStackError(err error) bool { + if err == nil { + return false + } + return strings.HasPrefix(err.Error(), "stack") +} + +func IsStopTokenError(err error) bool { + if err == nil { + return false + } + return err.Error() == "stop token" +} + +func precompile(rules params.Rules, addr common.Address) (vm.PrecompiledContract, bool) { + var precompiles map[common.Address]vm.PrecompiledContract + switch { + case rules.IsBerlin: + precompiles = vm.PrecompiledContractsBerlin + case rules.IsIstanbul: + precompiles = vm.PrecompiledContractsIstanbul + case rules.IsByzantium: + precompiles = vm.PrecompiledContractsByzantium + default: + precompiles = vm.PrecompiledContractsHomestead + } + p, ok := precompiles[addr] + return p, ok +} + +func isEnvironmentalOp(opcode vm.OpCode) bool { + return opcode == vm.ADDRESS || + opcode == vm.ORIGIN || + opcode == vm.CALLER || + opcode == vm.CALLVALUE || + opcode == vm.CODESIZE || + opcode == vm.CALLDATASIZE || + opcode == vm.GASPRICE || + opcode == vm.BLOCKHASH || + opcode == vm.COINBASE || + opcode == vm.TIMESTAMP || + opcode == vm.NUMBER || + opcode == vm.DIFFICULTY || + opcode == vm.GASLIMIT || + opcode == vm.CHAINID +} diff --git a/fraud-proof/proof/proof/verifier_type.go b/fraud-proof/proof/proof/verifier_type.go new file mode 100644 index 000000000..90250390a --- /dev/null +++ b/fraud-proof/proof/proof/verifier_type.go @@ -0,0 +1,29 @@ +// Copyright 2022, Specular contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package proof + +type VerifierType int + +const ( + VerifierTypeStackOp VerifierType = 0 + VerifierTypeEnvironmentalOp VerifierType = 1 + VerifierTypeMemoryOp VerifierType = 2 + VerifierTypeStorageOp VerifierType = 3 + VerifierTypeCallOp VerifierType = 4 + VerifierTypeInvalidOp VerifierType = 5 + VerifierTypeInterTx VerifierType = 6 + VerifierTypeBlockInit VerifierType = 7 + VerifierTypeBlockFinal VerifierType = 8 +) diff --git a/fraud-proof/proof/prover.go b/fraud-proof/proof/prover.go new file mode 100644 index 000000000..22e49f007 --- /dev/null +++ b/fraud-proof/proof/prover.go @@ -0,0 +1,422 @@ +// Copyright 2022, Specular contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package proof + +import ( + "context" + "encoding/json" + "fmt" + "math/big" + + "github.com/mantlenetworkio/mantle/fraud-proof/proof/proof" + "github.com/mantlenetworkio/mantle/fraud-proof/proof/prover" + proofState "github.com/mantlenetworkio/mantle/fraud-proof/proof/state" + "github.com/mantlenetworkio/mantle/l2geth/common" + "github.com/mantlenetworkio/mantle/l2geth/core" + "github.com/mantlenetworkio/mantle/l2geth/core/state" + "github.com/mantlenetworkio/mantle/l2geth/core/types" + "github.com/mantlenetworkio/mantle/l2geth/core/vm" + "github.com/mantlenetworkio/mantle/l2geth/log" + "github.com/mantlenetworkio/mantle/l2geth/rpc" +) + +const ( + // defaultProveReexec is the number of blocks the prover is willing to go back + // and reexecute to produce missing historical state necessary to run a specific + // trace. + defaultProveReexec = uint64(128) +) + +type ProverConfig struct { + Reexec *uint64 +} + +type ExecutionState struct { + VMHash common.Hash + BlockGasUsed *big.Int + StateType proofState.StateType + Block *types.Block + TransactionIdx uint64 + StepIdx uint64 +} + +func (s *ExecutionState) MarshalJson() ([]byte, error) { + return json.Marshal(&struct { + VMHash common.Hash `json:"vmHash"` + BlockGasUsed *big.Int `json:"blockGasUsed"` + StateType string `json:"stateType"` + BlockHash common.Hash `json:"blockHash"` + TransactionIdx uint64 `json:"txnIdx"` + StepIdx uint64 `json:"stepIdx"` + }{ + VMHash: s.VMHash, + BlockGasUsed: s.BlockGasUsed, + StateType: string(s.StateType), + BlockHash: s.Block.Hash(), + TransactionIdx: s.TransactionIdx, + StepIdx: s.StepIdx, + }) +} + +func (s *ExecutionState) Hash() common.Hash { + return s.VMHash +} + +// [GenerateStates] generates execution states across blocks [startNum, endNum) +// +// For example there are 2 blocks: block A with transactions A1, A2; block B without transactions. +// +// The states are (in order): +// 1. the BlockState of the block right before A +// 2. the InterState before A1 +// 3. the IntraStates of A1 if A1 is not an EOA transfer +// 4. the InterState before A2 (after A1) +// 5. the IntraStates of A2 if A2 is not an EOA transfer +// 6. the InterState after A2 +// 7. the BlockState of the block A +// 8. a dummy InterState +// 9. the BlockState of the block B +func GenerateStates(backend Backend, ctx context.Context, startNum, endNum uint64, config *ProverConfig) ([]*ExecutionState, error) { + var states []*ExecutionState + var msg types.Message + var block *types.Block + var err error + + chainCtx := createChainContext(backend, ctx) + startParent, err := backend.BlockByNumber(ctx, rpc.BlockNumber(startNum-1)) + if err != nil { + return nil, err + } + bs, statedb, err := generateStartBlockState(backend, ctx, startParent, config) + if err != nil { + return nil, err + } + + //states = append(states, &ExecutionState{ + // VMHash: bs.Hash(), + // BlockGasUsed: common.Big0, + // StateType: proofState.BlockStateType, + // Block: startParent, + // TransactionIdx: 0, + // StepIdx: 0, + //}) + // append start vmHash + startHeader, err := backend.HeaderByNumber(ctx, rpc.BlockNumber(startNum)) + if err != nil { + return nil, err + } + states = append(states, &ExecutionState{ + VMHash: startHeader.Root, + BlockGasUsed: common.Big0, + StateType: proofState.BlockStateType, + Block: startParent, + TransactionIdx: 0, + StepIdx: 0, + }) + log.Info("Get start state", "startNum", startNum, "VMHash", startHeader.Root.String()) + + for num := startNum; num < endNum; num++ { + // Preparation of block context + if block, err = backend.BlockByNumber(ctx, rpc.BlockNumber(num)); err != nil { + return nil, err + } + if block == nil { + return nil, fmt.Errorf("block #%d not found", num) + } + blockCtx := core.NewEVMBlockContext(block.Header(), chainCtx, nil) + blockHashTree, err := proofState.BlockHashTreeFromBlockContext(&blockCtx) + if err != nil { + return nil, err + } + + transactions := block.Transactions() + receipts, _ := backend.GetReceipts(ctx, block.Hash()) + + blockGasUsed := new(big.Int).SetUint64(block.GasUsed()) + localBlockGasUsed := new(big.Int) + // Trace all the transactions contained within + for i, tx := range transactions { + // Call Prepare to clear out the statedb access list + statedb.Prepare(tx.Hash(), block.Hash(), i) + // Push the interstate before transaction i + its := proofState.InterStateFromCaptured( + block.NumberU64(), + uint64(i), + statedb, + blockGasUsed, + transactions, + receipts, + blockHashTree, + ) + states = append(states, &ExecutionState{ + VMHash: its.Hash(), + BlockGasUsed: blockGasUsed, + StateType: proofState.InterStateType, + Block: block, + TransactionIdx: uint64(i), + StepIdx: 0, + }) + + // Execute transaction i with intra state generator enabled. + stateGenerator := prover.NewIntraStateGenerator(block.NumberU64(), uint64(i), statedb, *its, blockHashTree) + txCtx, err := generateTxCtx(backend, ctx, block, tx) + if err != nil { + return nil, err + } + vmenv := vm.NewEVM(*txCtx, statedb, backend.ChainConfig(), vm.Config{Debug: true, Tracer: stateGenerator}) + signer := types.MakeSigner(backend.ChainConfig(), block.Number()) + if msg, err = tx.AsMessage(signer); err != nil { + return nil, err + } + _, usedGas, _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.Gas())) + if err != nil { + return nil, fmt.Errorf("tracing failed: %w", err) + } + generatedStates, err := stateGenerator.GetGeneratedStates() + if err != nil { + return nil, fmt.Errorf("tracing failed: %w", err) + } + for idx, s := range generatedStates { + states = append(states, &ExecutionState{ + VMHash: s.VMHash, + BlockGasUsed: new(big.Int).Add(blockGasUsed, new(big.Int).SetUint64(tx.Gas()-s.Gas)), + StateType: proofState.IntraStateType, + Block: block, + TransactionIdx: uint64(i), + StepIdx: uint64(idx + 1), + }) + } + // Include refund + localBlockGasUsed.Add(localBlockGasUsed, new(big.Int).SetUint64(usedGas)) + } + + // Push the inter state after all transactions + its := proofState.InterStateFromCaptured( + block.NumberU64(), + uint64(len(transactions)), + statedb, + localBlockGasUsed, + transactions, + receipts, + blockHashTree, + ) + states = append(states, &ExecutionState{ + VMHash: its.Hash(), + BlockGasUsed: localBlockGasUsed, + StateType: proofState.InterStateType, + Block: block, + TransactionIdx: uint64(len(block.Transactions())), + StepIdx: 0, + }) + + // Get next statedb to skip simulating block finalization + // Here the statedb is the state at the end of the current block + // (i.e. start of the new block) + if bs, statedb, err = generateStartBlockState(backend, ctx, block, config); err != nil { + return nil, err + } + states = append(states, &ExecutionState{ + VMHash: bs.Hash(), + BlockGasUsed: common.Big0, + StateType: proofState.BlockStateType, + Block: block, + TransactionIdx: 0, + StepIdx: 0, + }) + } + + // append end vmHash + endParent, err := backend.BlockByNumber(ctx, rpc.BlockNumber(endNum-1)) + if err != nil { + return nil, err + } + endHeader, err := backend.HeaderByNumber(ctx, rpc.BlockNumber(endNum)) + if err != nil { + return nil, err + } + + states = append(states, &ExecutionState{ + VMHash: endHeader.Root, + BlockGasUsed: common.Big0, + StateType: proofState.BlockStateType, + Block: endParent, + TransactionIdx: 0, + StepIdx: 0, + }) + + log.Info("Get end state", "endNum", endNum, "VMHash", endHeader.Root.String()) + return states, nil +} + +// [GenerateProof] serves as an entrypoint for one-step proof generation. +// There are 6 types of one-step proofs: +// 1. BlockState -> InterState: block initiation +// 2. InterState -> IntraState: transaction initiation (contract call or creation) +// 3. InterState -> InterState: EOA transfer transaction +// 4. IntraState -> IntraState: one-step EVM execution (require tracing) +// 5. IntraState -> InterState: transaction finalization (require tracing) +// 6. InterState -> BlockState: block finalization +func GenerateProof(ctx context.Context, backend Backend, startState *ExecutionState, config *ProverConfig) (*proof.OneStepProof, error) { + if startState.Block == nil { + return nil, fmt.Errorf("bad start state") + } + transactions := startState.Block.Transactions() + if startState.TransactionIdx > uint64(len(transactions)) { + return nil, fmt.Errorf("bad start state") + } + + reexec := defaultProveReexec + if config != nil && config.Reexec != nil { + reexec = *config.Reexec + } + + // Type 1: block initiation or Type 6: block finalization + if startState.StateType == proofState.BlockStateType || (startState.StateType == proofState.InterStateType && startState.TransactionIdx == uint64(len(transactions))) { + statedb, err := backend.StateAtBlock(ctx, startState.Block, reexec, nil, true, false) + if err != nil { + return nil, err + } + chainCtx := createChainContext(backend, ctx) + vmctx := core.NewEVMBlockContext(startState.Block.Header(), chainCtx, nil) + blockHashTree, err := proofState.BlockHashTreeFromBlockContext(&vmctx) + if err != nil { + return nil, err + } + if startState.StateType == proofState.BlockStateType { + // Type 1: block initiation + bs, err := proofState.BlockStateFromBlock(startState.Block.NumberU64(), statedb, blockHashTree) + if err != nil { + return nil, err + } + return proof.GetBlockInitiationProof(bs) + } else { + // Type 6: block finalization + receipts, _ := backend.GetReceipts(ctx, startState.Block.Hash()) + its := proofState.InterStateFromCaptured( + startState.Block.NumberU64(), + startState.TransactionIdx, + statedb, + startState.BlockGasUsed, + transactions, + receipts, + blockHashTree, + ) + return proof.GetBlockFinalizationProof(its) + } + } + + // Prepare block and transaction context + msg, txCtx, statedb, err := backend.StateAtTransaction(ctx, startState.Block, int(startState.TransactionIdx), reexec) + if err != nil { + return nil, err + } + chainCtx := createChainContext(backend, ctx) + vmctx := core.NewEVMBlockContext(startState.Block.Header(), chainCtx, nil) + receipts, err := backend.GetReceipts(ctx, startState.Block.Hash()) + if err != nil { + return nil, err + } + blockHashTree, err := proofState.BlockHashTreeFromBlockContext(&vmctx) + if err != nil { + return nil, err + } + + // Prepare the inter state before transaction for the prover + its := proofState.InterStateFromCaptured( + startState.Block.NumberU64(), + startState.TransactionIdx, + statedb, + startState.BlockGasUsed, + transactions, + receipts, + blockHashTree, + ) + + transaction := transactions[startState.TransactionIdx] + + if startState.StateType == proofState.InterStateType { + // Type 2: transaction initiation or Type 3: EOA transfer transaction + return proof.GetTransactionInitaitionProof(backend.ChainConfig(), &vmctx, transaction, &txCtx, its, statedb) + } + // Type 4: one-step EVM execution or Type 5: transaction finalization. Both require tracing. + + // Set up the prover + prover := prover.NewProver( + startState.VMHash, + startState.StepIdx, + backend.ChainConfig().Rules(vmctx.BlockNumber), + startState.Block.NumberU64(), + startState.TransactionIdx, + statedb, + *its, + blockHashTree, + transaction, + receipts[startState.TransactionIdx], + ) + // Run the transaction with prover enabled. + vmenv := vm.NewEVM(txCtx, statedb, backend.ChainConfig(), vm.Config{Debug: true, Tracer: prover}) + // Call Prepare to clear out the statedb access list + txHash := transactions[startState.TransactionIdx].Hash() + statedb.Prepare(txHash, startState.Block.Hash(), int(startState.TransactionIdx)) + _, _, _, err = core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.Gas())) + if err != nil { + return nil, fmt.Errorf("tracing failed: %w", err) + } + return prover.GetProof() +} + +func generateTxCtx(backend Backend, ctx context.Context, block *types.Block, tx *types.Transaction) (*vm.Context, error) { + signer := types.MakeSigner(backend.ChainConfig(), block.Number()) + msg, err := tx.AsMessage(signer) + if err != nil { + return nil, err + } + chainCtx := createChainContext(backend, ctx) + blockCtx := core.NewEVMContext(msg, block.Header(), chainCtx, nil) + return &blockCtx, nil +} + +func generateStartBlockState(backend Backend, ctx context.Context, startBlock *types.Block, config *ProverConfig) (*proofState.BlockState, *state.StateDB, error) { + reexec := defaultProveReexec + if config != nil && config.Reexec != nil { + reexec = *config.Reexec + } + // The statedb here is the state at the end of the parent blcok + statedb, err := backend.StateAtBlock(ctx, startBlock, reexec, nil, true, false) + if err != nil { + return nil, nil, err + } + chainCtx := createChainContext(backend, ctx) + + parentBlockCtx := core.NewEVMBlockContext(startBlock.Header(), chainCtx, nil) + blockHashTree, err := proofState.BlockHashTreeFromBlockContext(&parentBlockCtx) + if err != nil { + return nil, nil, err + } + bs, err := proofState.BlockStateFromBlock(parentBlockCtx.BlockNumber.Uint64(), statedb, blockHashTree) + if err != nil { + return nil, nil, err + } + return bs, statedb, nil +} + +func transactionToMessage(tx types.Transaction, backend Backend, startBlockNum *big.Int) (core.Message, error) { + signer := types.MakeSigner(backend.ChainConfig(), startBlockNum) + msg, err := tx.AsMessage(signer) + if err != nil { + return nil, err + } + return msg, nil +} diff --git a/fraud-proof/proof/prover/intra_state_generator.go b/fraud-proof/proof/prover/intra_state_generator.go new file mode 100644 index 000000000..d34455c5f --- /dev/null +++ b/fraud-proof/proof/prover/intra_state_generator.go @@ -0,0 +1,207 @@ +// Copyright 2022, Specular contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package prover + +import ( + "fmt" + "math/big" + "time" + + "github.com/mantlenetworkio/mantle/fraud-proof/proof/state" + "github.com/mantlenetworkio/mantle/l2geth/common" + "github.com/mantlenetworkio/mantle/l2geth/core/vm" + "github.com/mantlenetworkio/mantle/l2geth/log" +) + +type GeneratedIntraState struct { + VMHash common.Hash + Gas uint64 +} + +type IntraStateGenerator struct { + // Context (read-only) + blockNumber uint64 + transactionIdx uint64 + committedGlobalState vm.StateDB + startInterState *state.InterState + blockHashTree *state.BlockHashTree + + // Global + env *vm.EVM + counter int + states []GeneratedIntraState + err error + done bool + selfDestructSet *state.SelfDestructSet + accessListTrie *state.AccessListTrie + + // Current Call Frame + callFlag state.CallFlag + lastState *state.IntraState + lastCost uint64 + lastDepthState state.OneStepState + input *state.Memory + out uint64 + outSize uint64 + selfDestructed bool +} + +func NewIntraStateGenerator( + blockNumber, transactionIdx uint64, + committedGlobalState vm.StateDB, + interState state.InterState, + blockHashTree *state.BlockHashTree, +) *IntraStateGenerator { + return &IntraStateGenerator{ + blockNumber: blockNumber, + transactionIdx: transactionIdx, + committedGlobalState: committedGlobalState, + startInterState: &interState, + blockHashTree: blockHashTree, + } +} + +func (l *IntraStateGenerator) CaptureTxStart(gasLimit uint64) {} + +func (l *IntraStateGenerator) CaptureTxEnd(restGas uint64) {} + +func (l *IntraStateGenerator) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) error { + l.env = env + // To be consistent with stepIdx, but not necessary for state generation + l.counter = 1 + if create { + l.callFlag = state.CALLFLAG_CREATE + } else { + l.callFlag = state.CALLFLAG_CALL + } + l.input = state.NewMemoryFromBytes(input) + l.accessListTrie = state.NewAccessListTrie() + // We manually accumulate the selfdestruct set during tracing to preserve order + l.selfDestructSet = state.NewSelfDestructSet() + l.startInterState.GlobalState = l.env.StateDB.Copy() // This state includes gas-buying and nonce-increment + l.lastDepthState = l.startInterState + log.Debug("Capture Start", "from", from, "to", to) + return nil +} + +// CaptureState will be called before the opcode execution +// vmerr is for stack validation and gas validation +// the execution error is captured in CaptureFault +func (l *IntraStateGenerator) CaptureState(env *vm.EVM, pc uint64, op vm.OpCode, gas, cost uint64, memory *vm.Memory, stack *vm.Stack, contract *vm.Contract, rData []byte, depth int, vmerr error) error { + if l.done { + // Something went wrong during tracing, exit early + return nil + } + // Construct intra state + s := state.StateFromCaptured( + l.blockNumber, + l.transactionIdx, + l.committedGlobalState, + l.selfDestructSet, + l.blockHashTree, + l.accessListTrie, + env, + l.lastDepthState, + l.callFlag, + l.input, + l.out, l.outSize, pc, + op, + gas, cost, + memory, + stack, + contract, + rData, + depth, + ) + l.states = append(l.states, GeneratedIntraState{s.Hash(), gas}) + l.lastState = s + l.lastCost = cost + l.counter += 1 + return nil +} + +func (l *IntraStateGenerator) CaptureEnter(typ vm.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) { + if l.done { + // Something went wrong during tracing, exit early + return + } + if typ == vm.SELFDESTRUCT { + // This enter is for the selfdestruct, record the address + l.selfDestructed = true + l.selfDestructSet = l.selfDestructSet.Add(from) + return + } + // Since CaptureState is called before the opcode execution, here l.lastState is exactly + // the state before call, so update out and outSize by l.lastState + // Note: we don't want to update out and outSize in CaptureState because the call opcode + // might fail before entering the call frame + if typ == vm.CALL || typ == vm.CALLCODE { + l.out = l.lastState.Stack.Back(5).Uint64() + l.outSize = l.lastState.Stack.Back(6).Uint64() + } else if typ == vm.DELEGATECALL || typ == vm.STATICCALL { + l.out = l.lastState.Stack.Back(4).Uint64() + l.outSize = l.lastState.Stack.Back(5).Uint64() + } + l.callFlag = state.OpCodeToCallFlag(typ) + l.lastDepthState = l.lastState.StateAsLastDepth(l.callFlag, l.lastCost) + l.input = state.NewMemoryFromBytes(input) +} + +func (l *IntraStateGenerator) CaptureExit(output []byte, gasUsed uint64, vmerr error) { + if l.done { + // Something went wrong during tracing, exit early + return + } + if l.selfDestructed { + // This exit is for selfdestruct + l.selfDestructed = false + return + } + // TODO: next line seems unnecessary because CaptureEnd will be instantly called + // if depth of the last state is 1 + if l.lastState.Depth > 1 { + lastDepthState := l.lastDepthState.(*state.IntraState) + l.callFlag = lastDepthState.CallFlag + l.out = lastDepthState.Out + l.outSize = lastDepthState.OutSize + l.input = lastDepthState.InputData + l.lastDepthState = lastDepthState.LastDepthState + if vmerr != nil { + // Call reverted, so revert the selfdestructs and access list changes + l.selfDestructSet = lastDepthState.SelfDestructSet + l.accessListTrie = lastDepthState.AccessListTrie + } + } +} + +// CaptureFault will be called when the stack/gas validation is passed but +// the execution failed. The current call will immediately be reverted. +// The error is handled in CaptureExit so nothing to do here. +func (l *IntraStateGenerator) CaptureFault(env *vm.EVM, pc uint64, op vm.OpCode, gas, cost uint64, memory *vm.Memory, stack *vm.Stack, contract *vm.Contract, depth int, err error) error { + return nil +} + +func (l *IntraStateGenerator) CaptureEnd(output []byte, gasUsed uint64, t time.Duration, err error) error { + // State generation finished, mark it as done + l.done = true + return nil +} + +func (l *IntraStateGenerator) GetGeneratedStates() ([]GeneratedIntraState, error) { + if !l.done { + return nil, fmt.Errorf("states generation not finished") + } + return l.states, l.err +} diff --git a/fraud-proof/proof/prover/one_step_prover.go b/fraud-proof/proof/prover/one_step_prover.go new file mode 100644 index 000000000..bc802f29e --- /dev/null +++ b/fraud-proof/proof/prover/one_step_prover.go @@ -0,0 +1,298 @@ +// Copyright 2022, Specular contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package prover + +import ( + "errors" + "fmt" + "math/big" + "time" + + "github.com/mantlenetworkio/mantle/fraud-proof/proof/proof" + "github.com/mantlenetworkio/mantle/fraud-proof/proof/state" + "github.com/mantlenetworkio/mantle/l2geth/common" + "github.com/mantlenetworkio/mantle/l2geth/common/hexutil" + "github.com/mantlenetworkio/mantle/l2geth/core/types" + "github.com/mantlenetworkio/mantle/l2geth/core/vm" + "github.com/mantlenetworkio/mantle/l2geth/log" + "github.com/mantlenetworkio/mantle/l2geth/params" +) + +var ErrStepIdxAndHashMismatch = errors.New("step index and hash mismatch") + +type OneStepProver struct { + // Config + target common.Hash + step uint64 + + // Context (read-only) + rules params.Rules + blockNumber uint64 + transactionIdx uint64 + committedGlobalState vm.StateDB + startInterState *state.InterState + blockHashTree *state.BlockHashTree + transaction *types.Transaction + receipt *types.Receipt + + // Global + env *vm.EVM + counter uint64 + proof *proof.OneStepProof + vmerr error // Error from EVM execution + err error // Error from the tracer + done bool + selfDestructSet *state.SelfDestructSet + accessListTrie *state.AccessListTrie + + // Current Call Frame + callFlag state.CallFlag + lastState *state.IntraState + lastCost uint64 + lastCode []byte + lastDepthState state.OneStepState + input *state.Memory + out uint64 + outSize uint64 + selfDestructed bool +} + +// [NewProver] creates a new tracer that generates proofs for: +// - Type 4 IntraState -> IntraState: one-step EVM execution +// - Type 5 IntraState -> InterState: transaction finalization +// +// target is the hash of the start state that we want to prove +// step is the step number of the start state (step 0 is the InterState before the transaction) +// The target hash and step should be matched, otherwise [ErrStepIdxAndHashMismatch] will be returned +// receipt is the receipt of the *current* transaction traced +func NewProver( + target common.Hash, + step uint64, + rules params.Rules, + blockNumber uint64, + transactionIdx uint64, + committedGlobalState vm.StateDB, + interState state.InterState, + blockHashTree *state.BlockHashTree, + transaction *types.Transaction, + receipt *types.Receipt, +) *OneStepProver { + return &OneStepProver{ + target: target, + step: step, + rules: rules, + blockNumber: blockNumber, + transactionIdx: transactionIdx, + committedGlobalState: committedGlobalState, + startInterState: &interState, + blockHashTree: blockHashTree, + transaction: transaction, + receipt: receipt, + } +} + +func (l *OneStepProver) CaptureTxStart(gasLimit uint64) {} + +func (l *OneStepProver) CaptureTxEnd(restGas uint64) {} + +func (l *OneStepProver) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) error { + // We won't handle transaction initiation proof here, it should be handled outside tracing + l.env = env + l.counter = 1 + if create { + l.callFlag = state.CALLFLAG_CREATE + } else { + l.callFlag = state.CALLFLAG_CALL + } + l.input = state.NewMemoryFromBytes(input) + l.accessListTrie = state.NewAccessListTrie() + l.selfDestructSet = state.NewSelfDestructSet() + l.startInterState.GlobalState = l.env.StateDB.Copy() // This state includes gas-buying and nonce-increment + l.lastDepthState = l.startInterState + log.Debug("Capture Start", "from", from, "to", to) + return nil +} + +// CaptureState will be called before the opcode execution +// vmerr is for stack validation and gas validation +// the execution error is captured in CaptureFault +func (l *OneStepProver) CaptureState(env *vm.EVM, pc uint64, op vm.OpCode, gas, cost uint64, memory *vm.Memory, stack *vm.Stack, contract *vm.Contract, rData []byte, depth int, vmerr error) error { + if l.done { + // Something went wrong during tracing, exit early + return nil + } + + defer func() { + l.counter += 1 + }() + + // Construct the IntraState before the opcode execution + s := state.StateFromCaptured( + l.blockNumber, + l.transactionIdx, + l.committedGlobalState, + l.selfDestructSet, + l.blockHashTree, + l.accessListTrie, + l.env, + l.lastDepthState, + l.callFlag, + l.input, + l.out, l.outSize, pc, + op, + gas, cost, + memory, + stack, + contract, + rData, + depth, + ) + + log.Debug("Generated state", "idx", l.counter, "hash", hexutil.Encode(s.Hash().Bytes()), "op", op) + log.Debug("State", "state", fmt.Sprintf("%+v", s)) + log.Debug("State", "stack", fmt.Sprintf("%+v", s.Stack)) + log.Debug("State", "memory", fmt.Sprintf("%+v", s.Memory)) + log.Debug("State", "input", fmt.Sprintf("%+v", s.InputData)) + log.Debug("State", "output", fmt.Sprintf("%+v", s.ReturnData)) + + // The target state is found, generate the one-step proof + if l.counter-1 == l.step { + l.done = true + if l.lastState == nil || l.lastState.Hash() != l.target { + l.err = ErrStepIdxAndHashMismatch + return nil + } + // l.vmerr is the error of l.lastState, either before/during the opcode execution + // if l.vmerr is not nil, the current state s must be in the parent call frame of l.lastState + ctx := proof.NewProofGenContext(l.rules, l.env.Context.Coinbase, l.transaction, l.receipt, l.lastCode) + osp, err := proof.GetIntraProof(ctx, l.lastState, s, l.vmerr) + if err != nil { + l.err = err + } else { + l.proof = osp + } + return nil + } + l.lastState = s + l.lastCode = contract.Code + // vmerr is not nil means the gas/stack validation failed, the opcode execution will + // not happen and the current call frame will be immediately reverted. This is the + // last CaptureState call for this call frame and there won't be any CaptureFault call. + // Otherwise, vmerr should be cleared. + l.vmerr = vmerr + return nil +} + +func (l *OneStepProver) CaptureEnter(typ vm.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) { + if l.done { + // Something went wrong during tracing, exit early + return + } + if typ == vm.SELFDESTRUCT { + // This enter is for the selfdestruct, record the address + l.selfDestructed = true + l.selfDestructSet = l.selfDestructSet.Add(from) + return + } + if l.lastDepthState == nil { + // Strange error, should not happen + l.err = errors.New("lastDepthState is nil") + l.done = true + return + } + // Since CaptureState is called before the opcode execution, here l.lastState is exactly + // the state before call, so update out and outSize by l.lastState + // Note: we don't want to update out and outSize in CaptureState because the call opcode + // might fail before entering the call frame + if typ == vm.CALL || typ == vm.CALLCODE { + l.out = l.lastState.Stack.Back(5).Uint64() + l.outSize = l.lastState.Stack.Back(6).Uint64() + } else if typ == vm.DELEGATECALL || typ == vm.STATICCALL { + l.out = l.lastState.Stack.Back(4).Uint64() + l.outSize = l.lastState.Stack.Back(5).Uint64() + } + l.callFlag = state.OpCodeToCallFlag(typ) + l.lastDepthState = l.lastState.StateAsLastDepth(l.callFlag, l.lastCost) + l.input = state.NewMemoryFromBytes(input) +} + +func (l *OneStepProver) CaptureExit(output []byte, gasUsed uint64, vmerr error) { + if l.done { + // Something went wrong during tracing, exit early + return + } + if l.selfDestructed { + // This exit is for selfdestruct + l.selfDestructed = false + return + } + // TODO: next line seems unnecessary because CaptureEnd will be instantly called + // if depth of the last state is 1 + if l.lastState.Depth > 1 { + lastDepthState := l.lastDepthState.(*state.IntraState) + l.callFlag = lastDepthState.CallFlag + l.out = lastDepthState.Out + l.outSize = lastDepthState.OutSize + l.input = lastDepthState.InputData + l.lastDepthState = lastDepthState.LastDepthState + if vmerr != nil { + // Call reverted, so revert the selfdestructs and access list changes + l.selfDestructSet = lastDepthState.SelfDestructSet + l.accessListTrie = lastDepthState.AccessListTrie + } + } +} + +// CaptureFault will be called when the stack/gas validation is passed but +// the execution failed. The current call will immediately be reverted. +func (l *OneStepProver) CaptureFault(env *vm.EVM, pc uint64, op vm.OpCode, gas, cost uint64, memory *vm.Memory, stack *vm.Stack, contract *vm.Contract, depth int, vmerr error) error { + l.vmerr = vmerr + // The next CaptureState or CaptureEnd will handle the proof generation if needed + return nil +} + +func (l *OneStepProver) CaptureEnd(output []byte, gasUsed uint64, t time.Duration, err error) error { + log.Debug("Capture End", "output", output) + if l.done { + // Something went wrong during tracing, exit early + return nil + } + + // If the last state is the target state, generate the transaction finalization proof + if l.counter-1 == l.step { + l.done = true + if l.lastState.Hash() != l.target { + l.err = ErrStepIdxAndHashMismatch + return nil + } + // If l.vmerr is not nil, the entire transaction execution will be reverted. + // Otherwise, the execution ended through STOP or RETURN opcode. + ctx := proof.NewProofGenContext(l.rules, l.env.Context.Coinbase, l.transaction, l.receipt, l.lastCode) + osp, err := proof.GetIntraProof(ctx, l.lastState, nil, l.vmerr) + if err != nil { + l.err = err + } else { + l.proof = osp + } + } + return nil +} + +func (l *OneStepProver) GetProof() (*proof.OneStepProof, error) { + if !l.done { + return nil, errors.New("proof not generated") + } + return l.proof, l.err +} diff --git a/fraud-proof/proof/prover/test_prover.go b/fraud-proof/proof/prover/test_prover.go new file mode 100644 index 000000000..1965df47e --- /dev/null +++ b/fraud-proof/proof/prover/test_prover.go @@ -0,0 +1,395 @@ +// Copyright 2022, Specular contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package prover + +import ( + "encoding/json" + "errors" + "math/big" + "strconv" + "strings" + "time" + + "github.com/mantlenetworkio/mantle/fraud-proof/proof/proof" + "github.com/mantlenetworkio/mantle/fraud-proof/proof/state" + "github.com/mantlenetworkio/mantle/l2geth/common" + "github.com/mantlenetworkio/mantle/l2geth/common/hexutil" + "github.com/mantlenetworkio/mantle/l2geth/core/types" + "github.com/mantlenetworkio/mantle/l2geth/core/vm" + "github.com/mantlenetworkio/mantle/l2geth/crypto" + "github.com/mantlenetworkio/mantle/l2geth/log" + "github.com/mantlenetworkio/mantle/l2geth/params" +) + +func bytesToHex(s []byte) string { + return "0x" + common.Bytes2Hex(s) +} + +func bigToHex(n *big.Int) string { + if n == nil { + return "0x0" + } + return "0x" + n.Text(16) +} + +func uintToHex(n uint64) string { + return "0x" + strconv.FormatUint(n, 16) +} + +func addrToHex(a common.Address) string { + return strings.ToLower(a.Hex()) +} + +type OspTestResult struct { + Ctx OspTestGeneratedCtx `json:"ctx"` + Proof OspTestProof `json:"proof"` +} + +type OspTestGeneratedCtx struct { + TxnHash string `json:"txnHash"` + TxNonce string `json:"txNonce"` + TxV string `json:"txV"` + TxR string `json:"txR"` + TxS string `json:"txS"` + Coinbase string `json:"coinbase"` + Timestamp string `json:"timestamp"` + BlockNumber string `json:"blockNumber"` + Difficulty string `json:"difficulty"` + GasLimit string `json:"gasLimit"` + ChainID string `json:"chainID"` + BaseFee string `json:"baseFee"` + Origin string `json:"origin"` + Recipient string `json:"recipient"` + Value string `json:"value"` + Gas string `json:"gas"` + GasPrice string `json:"gasPrice"` + Input string `json:"input"` + InputSize string `json:"inputSize"` +} + +type OspTestProof struct { + Opcode string `json:"opcode"` + Verifier uint64 `json:"verifier"` + CurrHash string `json:"currHash"` + NextHash string `json:"nextHash"` + ProofSize string `json:"proofSize"` + CodeSize string `json:"codeSize"` + Proof string `json:"proof"` + Idx uint64 `json:"idx"` +} + +type TestProver struct { + // Config + step int64 + opcode int64 + // Context (read-only) + transaction *types.Transaction + txctx *vm.Context + receipt *types.Receipt + rules params.Rules + blockNumber uint64 + transactionIdx uint64 + committedGlobalState vm.StateDB + startInterState *state.InterState + blockHashTree *state.BlockHashTree + + // Global + env *vm.EVM + counter uint64 + vmerr error // Error from EVM execution + err error // Error from the tracer + done bool + ctx OspTestGeneratedCtx + proof OspTestProof + selfDestructSet *state.SelfDestructSet + accessListTrie *state.AccessListTrie + + // Current Call Frame + callFlag state.CallFlag + lastState *state.IntraState + lastCost uint64 + lastCode []byte + lastOpcode byte + lastDepthState state.OneStepState + input *state.Memory + out uint64 + outSize uint64 + selfDestructed bool +} + +func NewTestProver( + step int64, + opcode int64, + transaction *types.Transaction, + txctx *vm.Context, + receipt *types.Receipt, + rules params.Rules, + blockNumber uint64, + transactionIdx uint64, + committedGlobalState vm.StateDB, + interState state.InterState, + blockHashTree *state.BlockHashTree, +) *TestProver { + return &TestProver{ + step: step, + opcode: opcode, + transaction: transaction, + txctx: txctx, + receipt: receipt, + rules: rules, + blockNumber: blockNumber, + transactionIdx: transactionIdx, + committedGlobalState: committedGlobalState, + startInterState: &interState, + blockHashTree: blockHashTree, + } +} + +func (l *TestProver) CaptureTxStart(gasLimit uint64) {} + +func (l *TestProver) CaptureTxEnd(restGas uint64) {} + +func (l *TestProver) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) error { + l.env = env + l.counter = 1 + if create { + l.callFlag = state.CALLFLAG_CREATE + } else { + l.callFlag = state.CALLFLAG_CALL + } + l.input = state.NewMemoryFromBytes(input) + l.accessListTrie = state.NewAccessListTrie() + l.selfDestructSet = state.NewSelfDestructSet() + l.startInterState.GlobalState = l.env.StateDB.Copy() // This state includes gas-buying and nonce-increment + l.lastDepthState = l.startInterState + vmctx := l.env.Context + recipient := common.Address{} + if l.transaction.To() != nil { + recipient = *l.transaction.To() + } + v, r, s := l.transaction.RawSignatureValues() + l.ctx = OspTestGeneratedCtx{ + TxnHash: bytesToHex(l.transaction.Hash().Bytes()), + TxNonce: uintToHex(l.transaction.Nonce()), + TxV: bigToHex(v), + TxR: bigToHex(r), + TxS: bigToHex(s), + Coinbase: addrToHex(vmctx.Coinbase), + Timestamp: bigToHex(vmctx.Time), + BlockNumber: bigToHex(vmctx.BlockNumber), + Difficulty: bigToHex(vmctx.Difficulty), + GasLimit: uintToHex(vmctx.GasLimit), + ChainID: bigToHex(l.transaction.ChainId()), + //BaseFee: bigToHex(vmctx.BaseFee), + Origin: addrToHex(l.txctx.Origin), + Recipient: addrToHex(recipient), + Value: bigToHex(l.transaction.Value()), + Gas: uintToHex(l.transaction.Gas()), + GasPrice: bigToHex(l.txctx.GasPrice), + Input: bytesToHex(input), + InputSize: uintToHex(l.input.Size()), + } + log.Debug("Capture Start", "from", from, "to", to) + return nil +} + +func (l *TestProver) CaptureState(env *vm.EVM, pc uint64, op vm.OpCode, gas, cost uint64, memory *vm.Memory, stack *vm.Stack, contract *vm.Contract, rData []byte, depth int, vmerr error) error { + if l.done { + return vmerr + } + + defer func() { + l.counter += 1 + }() + + // Construct the IntraState before the opcode execution + s := state.StateFromCaptured( + l.blockNumber, + l.transactionIdx, + l.committedGlobalState, + l.selfDestructSet, + l.blockHashTree, + l.accessListTrie, + l.env, + l.lastDepthState, + l.callFlag, + l.input, + l.out, l.outSize, pc, + op, + gas, cost, + memory, + stack, + contract, + rData, + depth, + ) + + log.Debug("Generated state", "idx", l.counter, "hash", hexutil.Encode(s.Hash().Bytes()), "op", op) + // The target state is found, generate the one-step proof + if int64(l.counter-1) == l.step || int64(l.lastOpcode) == l.opcode { + l.done = true + if l.lastState == nil { + l.err = ErrStepIdxAndHashMismatch + return vmerr + } + // l.vmerr is the error of l.lastState, either before/during the opcode execution + // if l.vmerr is not nil, the current state s must be in the parent call frame of l.lastState + ctx := proof.NewProofGenContext(l.rules, l.env.Context.Coinbase, l.transaction, l.receipt, l.lastCode) + osp, err := proof.GetIntraProof(ctx, l.lastState, s, l.vmerr) + if err != nil { + l.err = err + } else { + encoded := osp.Encode() + l.proof = OspTestProof{ + Opcode: l.lastState.OpCode.String(), + Verifier: uint64(osp.VerifierType), + CurrHash: bytesToHex(l.lastState.Hash().Bytes()), + NextHash: bytesToHex(s.Hash().Bytes()), + ProofSize: uintToHex(uint64(len(encoded))), + CodeSize: uintToHex(osp.TotalCodeSize), + Proof: bytesToHex(encoded), + Idx: l.counter - 1, + } + log.Debug("SHOW STATE", "length of lastState", len(l.lastState.Encode())) + log.Debug("SHOW STATE", "length of encoded", len(encoded)) + + log.Debug("SHOW STATE", "hash of lastState", l.lastState.Hash().String()) + log.Debug("SHOW STATE", "hash of encoded", crypto.Keccak256Hash(encoded[:len(l.lastState.Encode())]).String()) + } + return vmerr + } + l.lastState = s + l.lastCode = contract.Code + l.lastCost = cost + l.lastOpcode = byte(op) + // vmerr is not nil means the gas/stack validation failed, the opcode execution will + // not happen and the current call frame will be immediately reverted. This is the + // last CaptureState call for this call frame and there won't be any CaptureFault call. + // Otherwise, vmerr should be cleared. + l.vmerr = vmerr + return vmerr +} + +func (l *TestProver) CaptureEnter(typ vm.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) { + if l.done { + // Something went wrong during tracing, exit early + return + } + if typ == vm.SELFDESTRUCT { + // This enter is for the selfdestruct, record the address + l.selfDestructed = true + l.selfDestructSet = l.selfDestructSet.Add(from) + return + } + if l.lastDepthState == nil { + // Strange error, should not happen + l.err = errors.New("lastDepthState is nil") + l.done = true + return + } + // Since CaptureState is called before the opcode execution, here l.lastState is exactly + // the state before call, so update out and outSize by l.lastState + // Note: we don't want to update out and outSize in CaptureState because the call opcode + // might fail before entering the call frame + if typ == vm.CALL || typ == vm.CALLCODE { + l.out = l.lastState.Stack.Back(5).Uint64() + l.outSize = l.lastState.Stack.Back(6).Uint64() + } else if typ == vm.DELEGATECALL || typ == vm.STATICCALL { + l.out = l.lastState.Stack.Back(4).Uint64() + l.outSize = l.lastState.Stack.Back(5).Uint64() + } + l.callFlag = state.OpCodeToCallFlag(typ) + l.lastDepthState = l.lastState.StateAsLastDepth(l.callFlag, l.lastCost) + l.input = state.NewMemoryFromBytes(input) +} + +func (l *TestProver) CaptureExit(output []byte, gasUsed uint64, vmerr error) { + if l.done { + // Something went wrong during tracing, exit early + return + } + if l.selfDestructed { + // This exit is for selfdestruct + l.selfDestructed = false + return + } + // TODO: next line seems unnecessary because CaptureEnd will be instantly called + // if depth of the last state is 1 + if l.lastState.Depth > 1 { + lastDepthState := l.lastDepthState.(*state.IntraState) + l.callFlag = lastDepthState.CallFlag + l.out = lastDepthState.Out + l.outSize = lastDepthState.OutSize + l.input = lastDepthState.InputData + l.lastDepthState = lastDepthState.LastDepthState + if vmerr != nil { + // Call reverted, so revert the selfdestructs and access list changes + l.selfDestructSet = lastDepthState.SelfDestructSet + l.accessListTrie = lastDepthState.AccessListTrie + } + } +} +func (l *TestProver) CaptureFault(env *vm.EVM, pc uint64, op vm.OpCode, gas, cost uint64, memory *vm.Memory, stack *vm.Stack, contract *vm.Contract, depth int, vmerr error) error { + l.vmerr = vmerr + // The next CaptureState or CaptureEnd will handle the proof generation if needed + return vmerr +} + +func (l *TestProver) CaptureEnd(output []byte, gasUsed uint64, t time.Duration, vmerr error) error { + log.Debug("Capture End", "output", output) + if l.done { + // Something went wrong during tracing, exit early + return vmerr + } + + if int64(l.counter-1) == l.step { + l.done = true + // If l.vmerr is not nil, the entire transaction execution will be reverted. + // Otherwise, the execution ended through STOP or RETURN opcode. + ctx := proof.NewProofGenContext(l.rules, l.env.Context.Coinbase, l.transaction, l.receipt, l.lastCode) + osp, err := proof.GetIntraProof(ctx, l.lastState, nil, l.vmerr) + if err != nil { + l.err = err + } else { + encoded := osp.Encode() + l.proof = OspTestProof{ + Opcode: l.lastState.OpCode.String(), + CurrHash: bytesToHex(l.lastState.Hash().Bytes()), + NextHash: bytesToHex(common.Hash{}.Bytes()), // TODO: get the hash of next InterState + ProofSize: uintToHex(uint64(len(encoded))), + Proof: bytesToHex(encoded), + CodeSize: uintToHex(osp.TotalCodeSize), + Idx: l.counter - 1, + } + } + } + return vmerr +} + +func (l *TestProver) GetResult() (json.RawMessage, error) { + if l.err != nil { + return nil, l.err + } + result := OspTestResult{ + Ctx: l.ctx, + Proof: l.proof, + } + res, err := json.Marshal(result) + if err != nil { + log.Error("Err", "err", err) + return nil, err + } + return json.RawMessage(res), nil +} diff --git a/fraud-proof/proof/prover_test.go b/fraud-proof/proof/prover_test.go new file mode 100644 index 000000000..12994859c --- /dev/null +++ b/fraud-proof/proof/prover_test.go @@ -0,0 +1,19 @@ +package proof + +import ( + "math/big" + "testing" + + "github.com/mantlenetworkio/mantle/l2geth/common" + "github.com/stretchr/testify/require" +) + +func TestExecutionStateHash(t *testing.T) { + gasUsed, ok := new(big.Int).SetString("1eaed", 16) + require.True(t, ok) + es := ExecutionState{ + VMHash: common.HexToHash("0x73ea1d2ee379cd800d4006953888d2e23a57675dfc44de09e1d0194fcd866b1f"), + BlockGasUsed: gasUsed, + } + t.Log(es.Hash().String()) +} diff --git a/fraud-proof/proof/state/access_list_trie.go b/fraud-proof/proof/state/access_list_trie.go new file mode 100644 index 000000000..ba5abe14c --- /dev/null +++ b/fraud-proof/proof/state/access_list_trie.go @@ -0,0 +1,32 @@ +// Copyright 2022, Specular contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package state + +import "github.com/mantlenetworkio/mantle/l2geth/common" + +type AccessListTrie struct { +} + +func NewAccessListTrie() *AccessListTrie { + return &AccessListTrie{} +} + +func (s *AccessListTrie) Root() common.Hash { + return common.Hash{} +} + +func (s *AccessListTrie) EncodeState() []byte { + return s.Root().Bytes() +} diff --git a/fraud-proof/proof/state/account.go b/fraud-proof/proof/state/account.go new file mode 100644 index 000000000..7e18527e6 --- /dev/null +++ b/fraud-proof/proof/state/account.go @@ -0,0 +1,56 @@ +// Copyright 2022, Specular contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package state + +import ( + "encoding/binary" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/holiman/uint256" +) + +type Account struct { + Nonce uint64 + Balance uint256.Int + StorageRoot common.Hash + CodeHash common.Hash +} + +func AccountFromEVM(acc types.StateAccount) *Account { + balance, _ := uint256.FromBig(acc.Balance) + codeHash := common.Hash{} + if acc.CodeHash != nil && len(acc.CodeHash) >= 0 { + codeHash = common.BytesToHash(acc.CodeHash) + } + return &Account{ + Nonce: acc.Nonce, + Balance: *balance, + StorageRoot: acc.Root, + CodeHash: codeHash, + } +} + +func (acc *Account) Encode() []byte { + encLen := 8 + 32 + 32 + 32 + encoded := make([]byte, encLen) + nonce := make([]byte, 8) + binary.BigEndian.PutUint64(nonce, acc.Nonce) + copy(encoded, nonce) + copy(encoded[8:], acc.Balance.Bytes()) + copy(encoded[8+32:], acc.StorageRoot.Bytes()) + copy(encoded[8+32+32:], acc.CodeHash.Bytes()) + return encoded +} diff --git a/fraud-proof/proof/state/block_hash_tree.go b/fraud-proof/proof/state/block_hash_tree.go new file mode 100644 index 000000000..aca48b0b8 --- /dev/null +++ b/fraud-proof/proof/state/block_hash_tree.go @@ -0,0 +1,143 @@ +// Copyright 2022, Specular contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package state + +import ( + basic_merkletree "github.com/cbergoon/merkletree" + "github.com/holiman/uint256" + "github.com/mantlenetworkio/mantle/l2geth/common" + "github.com/mantlenetworkio/mantle/l2geth/core/vm" +) + +const RECENT_BLOCK_HASHES_LENGTH = 256 + +type BlockHash common.Hash +type BlockHashes [RECENT_BLOCK_HASHES_LENGTH]BlockHash + +func (b BlockHash) CalculateHash() ([]byte, error) { + return b[:], nil +} + +func (b BlockHash) Equals(other basic_merkletree.Content) (bool, error) { + return b == other.(BlockHash), nil +} + +type BlockHashTree struct { + Hashes BlockHashes + tree *basic_merkletree.MerkleTree +} + +func NewBlockHashTree(hashes *BlockHashes) (*BlockHashTree, error) { + contents := make([]basic_merkletree.Content, RECENT_BLOCK_HASHES_LENGTH) + for i, h := range hashes { + contents[i] = h + } + tree, err := basic_merkletree.NewTreeWithHashStrategy(contents, newHash) + if err != nil { + return nil, err + } + return &BlockHashTree{ + Hashes: *hashes, + tree: tree, + }, nil +} + +func BlockHashTreeFromBlockContext(blockCtx *vm.BlockContext) (*BlockHashTree, error) { + // Get BlockHashes of block [current-255, current] + blockHashes := BlockHashes{} + currentBlockNum := blockCtx.BlockNumber.Uint64() + start := uint64(0) + if currentBlockNum >= RECENT_BLOCK_HASHES_LENGTH { + start = currentBlockNum - RECENT_BLOCK_HASHES_LENGTH + 1 + } + for i := start; i <= currentBlockNum; i++ { + blockHashes[(currentBlockNum-i)%RECENT_BLOCK_HASHES_LENGTH] = BlockHash(blockCtx.GetHash(currentBlockNum - i)) + } + tree, err := NewBlockHashTree(&blockHashes) + if err != nil { + return nil, err + } + return tree, nil +} + +func BlockHashTreeFromContext(blockCtx *vm.Context) (*BlockHashTree, error) { + // Get BlockHashes of block [current-255, current] + blockHashes := BlockHashes{} + currentBlockNum := blockCtx.BlockNumber.Uint64() + start := uint64(0) + if currentBlockNum >= RECENT_BLOCK_HASHES_LENGTH { + start = currentBlockNum - RECENT_BLOCK_HASHES_LENGTH + 1 + } + for i := start; i <= currentBlockNum; i++ { + blockHashes[(currentBlockNum-i)%RECENT_BLOCK_HASHES_LENGTH] = BlockHash(blockCtx.GetHash(currentBlockNum - i)) + } + tree, err := NewBlockHashTree(&blockHashes) + if err != nil { + return nil, err + } + return tree, nil +} + +func (b *BlockHashTree) Copy() *BlockHashTree { + tree, _ := NewBlockHashTree(&b.Hashes) + return tree +} + +func (b *BlockHashTree) Root() common.Hash { + return common.BytesToHash(b.tree.MerkleRoot()) +} + +func (b *BlockHashTree) EncodeState() []byte { + return b.tree.MerkleRoot() +} + +func (b *BlockHashTree) SetBlockHash(number *uint256.Int, hash common.Hash) error { + index := number.Mod(number, uint256.NewInt(RECENT_BLOCK_HASHES_LENGTH)).Uint64() + b.Hashes[index] = BlockHash(hash) + contents := make([]basic_merkletree.Content, len(b.Hashes)) + for i, h := range b.Hashes { + contents[i] = h + } + tree, err := basic_merkletree.NewTreeWithHashStrategy(contents, newHash) + if err != nil { + return err + } + b.tree = tree + return nil +} + +func (b *BlockHashTree) GetBlockHash(number uint64) common.Hash { + index := number % RECENT_BLOCK_HASHES_LENGTH + return common.Hash(b.Hashes[index]) +} + +func (b *BlockHashTree) GetProof(number uint64) ([]common.Hash, uint64, error) { + index := number % RECENT_BLOCK_HASHES_LENGTH + proofs, indices, err := b.tree.GetMerklePath(b.Hashes[index]) + if err != nil { + return nil, 0, err + } + hashes := make([]common.Hash, len(proofs)) + for idx, proofItem := range proofs { + hashes[idx] = common.BytesToHash(proofItem) + } + path := uint64(0) + // Path is reversed + for i := range indices { + path *= 2 + path += uint64(indices[len(indices)-i-1]) + } + return hashes, path, nil +} diff --git a/fraud-proof/proof/state/call_flag.go b/fraud-proof/proof/state/call_flag.go new file mode 100644 index 000000000..b9c9292c9 --- /dev/null +++ b/fraud-proof/proof/state/call_flag.go @@ -0,0 +1,55 @@ +// Copyright 2022, Specular contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package state + +import ( + "fmt" + + "github.com/mantlenetworkio/mantle/l2geth/core/vm" + "github.com/mantlenetworkio/mantle/l2geth/log" +) + +type CallFlag byte + +const ( + CALLFLAG_CALL = 0 + CALLFLAG_CALLCODE = 1 + CALLFLAG_DELEGATECALL = 2 + CALLFLAG_STATICCALL = 3 + CALLFLAG_CREATE = 4 + CALLFLAG_CREATE2 = 5 +) + +func (f CallFlag) IsCreate() bool { + return f == CALLFLAG_CREATE || f == CALLFLAG_CREATE2 +} + +func OpCodeToCallFlag(op vm.OpCode) CallFlag { + if op == vm.CALL { + return CALLFLAG_CALL + } else if op == vm.CALLCODE { + return CALLFLAG_CALLCODE + } else if op == vm.DELEGATECALL { + return CALLFLAG_DELEGATECALL + } else if op == vm.STATICCALL { + return CALLFLAG_STATICCALL + } else if op == vm.CREATE { + return CALLFLAG_CREATE + } else if op == vm.CREATE2 { + return CALLFLAG_CREATE2 + } + log.Error(fmt.Sprintf("Opcode %s is not call", op)) + panic(fmt.Sprintf("Opcode %s is not call", op)) +} diff --git a/fraud-proof/proof/state/log_series.go b/fraud-proof/proof/state/log_series.go new file mode 100644 index 000000000..d855a96a8 --- /dev/null +++ b/fraud-proof/proof/state/log_series.go @@ -0,0 +1,53 @@ +// Copyright 2022, Specular contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package state + +import ( + "github.com/mantlenetworkio/mantle/l2geth/common" + "github.com/mantlenetworkio/mantle/l2geth/core/types" + "github.com/mantlenetworkio/mantle/l2geth/crypto" + "github.com/mantlenetworkio/mantle/l2geth/rlp" +) + +type LogSeries struct { + Logs []*types.Log + AccumulateHash common.Hash + Bloom types.Bloom +} + +func LogSeriesFromLogs(logs []*types.Log) *LogSeries { + ls := make([]*types.Log, len(logs)) + copy(ls, logs) + h := common.Hash{} + for _, l := range ls { + // TODO: should we check rlp encode error here? + logBytes, _ := rlp.EncodeToBytes(l) + h = crypto.Keccak256Hash(h.Bytes(), logBytes) + } + bin := types.LogsBloom(ls) + return &LogSeries{ + Logs: ls, + AccumulateHash: h, + Bloom: types.BytesToBloom(bin.Bytes()), + } +} + +func (l *LogSeries) Hash() common.Hash { + return common.BytesToHash(l.EncodeState()) +} + +func (l *LogSeries) EncodeState() []byte { + return crypto.Keccak256(l.AccumulateHash.Bytes(), l.Bloom.Bytes()) +} diff --git a/fraud-proof/proof/state/memory.go b/fraud-proof/proof/state/memory.go new file mode 100644 index 000000000..47422fd76 --- /dev/null +++ b/fraud-proof/proof/state/memory.go @@ -0,0 +1,115 @@ +// Copyright 2022, Specular contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package state + +import ( + "encoding/binary" + + "github.com/holiman/uint256" + "github.com/mantlenetworkio/mantle/l2geth/common" + "github.com/mantlenetworkio/mantle/l2geth/core/vm" + "github.com/specularl2/specular/clients/geth/specular/merkletree" +) + +type Memory struct { + content []byte + size uint64 + tree *merkletree.MerkleTree +} + +func NewMemoryFromBytes(values []byte) *Memory { + if len(values) == 0 { + return &Memory{tree: merkletree.New([]*uint256.Int{})} + } + size := len(values) + bytesToPad := 32 - size%32 + if bytesToPad != 32 { + values = append(values, make([]byte, bytesToPad)...) + } + elements := make([]*uint256.Int, len(values)/32) + for idx := range elements { + elements[idx] = new(uint256.Int).SetBytes(values[idx*32 : (idx+1)*32]) + } + return &Memory{ + content: values, + size: uint64(size), + tree: merkletree.New(elements), + } +} + +func MemoryFromEVMMemory(mem *vm.Memory) *Memory { + return NewMemoryFromBytes(mem.Data()) +} + +func (m *Memory) Size() uint64 { + return m.size +} + +func (m *Memory) Data() []byte { + return m.content[:m.size] +} + +func (m *Memory) CellNum() uint64 { + return m.tree.ElementCount() +} + +func (m *Memory) Empty() bool { + return m.size == 0 +} + +func (m *Memory) Cell(i uint64) *uint256.Int { + return m.tree.Element(i) +} + +func (m *Memory) Root() common.Hash { + return common.Hash(m.tree.Root()) +} + +func (m *Memory) GetProof(indices []uint64) []common.Hash { + var hashes []common.Hash + for _, hash := range m.tree.GenerateProof(indices) { + hashes = append(hashes, common.Hash(hash)) + } + return hashes +} + +func (m *Memory) GetAppendProof() []common.Hash { + var hashes []common.Hash + for _, hash := range m.tree.GenerateAppendProof() { + hashes = append(hashes, common.Hash(hash)) + } + return hashes +} + +func (m *Memory) GetCombinedProof(indices []uint64) ([]common.Hash, error) { + var hashes []common.Hash + results, err := m.tree.GenerateCombinedProof(indices) + if err != nil { + return nil, err + } + for _, hash := range results { + hashes = append(hashes, common.Hash(hash)) + } + return hashes, nil +} + +func (m *Memory) EncodeState() []byte { + encoded := make([]byte, 8) + binary.BigEndian.PutUint64(encoded, m.size) + if m.size != 0 { + encoded = append(encoded, m.Root().Bytes()...) + } + return encoded +} diff --git a/fraud-proof/proof/state/receipt_trie.go b/fraud-proof/proof/state/receipt_trie.go new file mode 100644 index 000000000..b625daf60 --- /dev/null +++ b/fraud-proof/proof/state/receipt_trie.go @@ -0,0 +1,72 @@ +// Copyright 2022, Specular contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package state + +import ( + "bytes" + + "github.com/ethereum/go-ethereum/rlp" + "github.com/mantlenetworkio/mantle/l2geth/common" + "github.com/mantlenetworkio/mantle/l2geth/core/types" + "github.com/mantlenetworkio/mantle/l2geth/ethdb/memorydb" + "github.com/mantlenetworkio/mantle/l2geth/trie" +) + +type ReceiptTrie struct { + receipts types.Receipts + trie *trie.Trie +} + +func NewReceiptTrie(receipts types.Receipts) *ReceiptTrie { + t, _ := trie.New(common.Hash{}, trie.NewDatabase(memorydb.New())) + valueBuf := new(bytes.Buffer) + var indexBuf []byte + for i := 0; i < receipts.Len(); i++ { + indexBuf = rlp.AppendUint64(indexBuf[:0], uint64(i)) + valueBuf.Reset() + valueBuf.Write(receipts.GetRlp(i)) + t.Update(indexBuf, common.CopyBytes(valueBuf.Bytes())) + } + return &ReceiptTrie{ + receipts: receipts, + trie: t, + } +} + +func (r *ReceiptTrie) Root() common.Hash { + return r.trie.Hash() +} + +func (r *ReceiptTrie) Bloom() types.Bloom { + return types.CreateBloom(r.receipts) +} + +func (r *ReceiptTrie) EncodeState() []byte { + encoded := r.Root().Bytes() + encoded = append(encoded, r.Bloom().Bytes()...) + return encoded +} + +func (r *ReceiptTrie) GetReceipt(index int) *types.Receipt { + return r.receipts[index] +} + +func (r *ReceiptTrie) Prove(index int) ([][]byte, error) { + var proof mptProofList + var indexBuf []byte + indexBuf = rlp.AppendUint64(indexBuf[:0], uint64(index)) + err := r.trie.Prove(indexBuf, 0, &proof) + return proof, err +} diff --git a/fraud-proof/proof/state/self_destruct_set.go b/fraud-proof/proof/state/self_destruct_set.go new file mode 100644 index 000000000..e34c8630e --- /dev/null +++ b/fraud-proof/proof/state/self_destruct_set.go @@ -0,0 +1,46 @@ +// Copyright 2022, Specular contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package state + +import ( + "github.com/mantlenetworkio/mantle/l2geth/common" + "github.com/mantlenetworkio/mantle/l2geth/crypto" +) + +type SelfDestructSet struct { + Contracts []common.Address + Hash common.Hash +} + +func NewSelfDestructSet() *SelfDestructSet { + return &SelfDestructSet{ + Contracts: make([]common.Address, 0), + Hash: common.Hash{}, + } +} + +func (s *SelfDestructSet) Add(addr common.Address) *SelfDestructSet { + contracts := make([]common.Address, len(s.Contracts)+1) + copy(contracts, s.Contracts) + h := crypto.Keccak256Hash(s.Hash.Bytes(), addr.Bytes()) + return &SelfDestructSet{ + Contracts: append(contracts, addr), + Hash: h, + } +} + +func (s *SelfDestructSet) EncodeState() []byte { + return s.Hash.Bytes() +} diff --git a/fraud-proof/proof/state/stack.go b/fraud-proof/proof/state/stack.go new file mode 100644 index 000000000..96ac21e7a --- /dev/null +++ b/fraud-proof/proof/state/stack.go @@ -0,0 +1,103 @@ +// Copyright 2022, Specular contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package state + +import ( + "encoding/binary" + + "github.com/holiman/uint256" + "github.com/mantlenetworkio/mantle/l2geth/common" + "github.com/mantlenetworkio/mantle/l2geth/core/vm" + "github.com/mantlenetworkio/mantle/l2geth/crypto" +) + +type Stack struct { + data []uint256.Int + hash []common.Hash +} + +func EmptyStack() *Stack { + stack := Stack{ + data: make([]uint256.Int, 0), + hash: []common.Hash{{}}, + } + return &stack +} + +func NewStack(values []uint256.Int) *Stack { + stack := EmptyStack() + stack.data = append(stack.data, values...) + for _, val := range stack.data { + valueBytes := val.Bytes32() + h := crypto.Keccak256Hash(stack.Hash().Bytes(), valueBytes[:]) + stack.hash = append(stack.hash, h) + } + return stack +} + +func StackFromEVMStack(s *vm.Stack) *Stack { + var values []uint256.Int + for _, v := range s.Data() { + value, _ := uint256.FromBig(v) + values = append(values, *value) + } + return NewStack(values) +} + +func (st *Stack) Copy() *Stack { + data := make([]uint256.Int, len(st.data)) + copy(data, st.data) + hash := make([]common.Hash, len(st.hash)) + copy(hash, st.hash) + return &Stack{data, hash} +} + +func (st *Stack) Data() []uint256.Int { + return st.data +} + +func (st *Stack) Hash() common.Hash { + return st.hash[len(st.hash)-1] +} + +func (st *Stack) PopN(n int) { + st.data = st.data[:len(st.data)-n] + st.hash = st.hash[:len(st.hash)-n] +} + +func (st *Stack) Len() int { + return len(st.data) +} + +func (st *Stack) Peek() *uint256.Int { + return &st.data[st.Len()-1] +} + +func (st *Stack) Back(n int) *uint256.Int { + return &st.data[st.Len()-n-1] +} + +func (st *Stack) HashAfterPops(n int) common.Hash { + return st.hash[st.Len()-n] +} + +func (st *Stack) EncodeState() []byte { + encoded := make([]byte, 8) + binary.BigEndian.PutUint64(encoded, uint64(st.Len())) + if st.Len() != 0 { + encoded = append(encoded, st.Hash().Bytes()...) + } + return encoded +} diff --git a/fraud-proof/proof/state/state.go b/fraud-proof/proof/state/state.go new file mode 100644 index 000000000..65d6a8b74 --- /dev/null +++ b/fraud-proof/proof/state/state.go @@ -0,0 +1,287 @@ +// Copyright 2022, Specular contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package state + +import ( + "encoding/binary" + "math/big" + + "github.com/holiman/uint256" + "github.com/mantlenetworkio/mantle/l2geth/common" + "github.com/mantlenetworkio/mantle/l2geth/core/types" + "github.com/mantlenetworkio/mantle/l2geth/core/vm" + "github.com/mantlenetworkio/mantle/l2geth/crypto" +) + +type OneStepState interface { + Hash() common.Hash + IsInter() bool +} + +type StateType string + +const ( + BlockStateType StateType = "BlockState" + InterStateType StateType = "InterState" + IntraStateType StateType = "IntraState" +) + +type IntraState struct { + BlockNumber uint64 + TransactionIdx uint64 + Depth uint16 + Gas uint64 + Refund uint64 + LastDepthState OneStepState + ContractAddress common.Address + Caller common.Address + Value uint256.Int + CallFlag CallFlag + Out uint64 + OutSize uint64 + Pc uint64 + OpCode vm.OpCode + CodeHash common.Hash + Stack *Stack + Memory *Memory + InputData *Memory + ReturnData *Memory + CommittedGlobalState vm.StateDB + GlobalState vm.StateDB + SelfDestructSet *SelfDestructSet + LogSeries *LogSeries + BlockHashTree *BlockHashTree + AccessListTrie *AccessListTrie +} + +func (s *IntraState) Encode() []byte { + items := []byte{} + blockNumBytes := make([]byte, 8) + binary.BigEndian.PutUint64(blockNumBytes, s.BlockNumber) + items = append(items, blockNumBytes...) + txIdxBytes := make([]byte, 8) + binary.BigEndian.PutUint64(txIdxBytes, s.TransactionIdx) + items = append(items, txIdxBytes...) + depth := make([]byte, 2) + binary.BigEndian.PutUint16(depth, s.Depth) + items = append(items, depth...) + gas := make([]byte, 8) + binary.BigEndian.PutUint64(gas, s.Gas) + items = append(items, gas...) + refund := make([]byte, 8) + binary.BigEndian.PutUint64(refund, s.Refund) + items = append(items, refund...) + items = append(items, s.LastDepthState.Hash().Bytes()...) + if s.Depth != 1 { + items = append(items, s.ContractAddress.Bytes()...) + items = append(items, s.Caller.Bytes()...) + valueBytes := s.Value.Bytes32() + items = append(items, valueBytes[:]...) + out := make([]byte, 8) + binary.BigEndian.PutUint64(out, s.Out) + outSize := make([]byte, 8) + binary.BigEndian.PutUint64(outSize, s.OutSize) + items = append(items, []byte{byte(s.CallFlag)}...) + items = append(items, out...) + items = append(items, outSize...) + } + pc := make([]byte, 8) + binary.BigEndian.PutUint64(pc, s.Pc) + items = append(items, pc...) + items = append(items, []byte{byte(s.OpCode)}...) + items = append(items, s.CodeHash.Bytes()...) + items = append(items, s.Stack.EncodeState()...) + items = append(items, s.Memory.EncodeState()...) + if s.Depth != 1 { + items = append(items, s.InputData.EncodeState()...) + } + items = append(items, s.ReturnData.EncodeState()...) + items = append(items, s.CommittedGlobalState.GetRootForProof().Bytes()...) + items = append(items, s.GlobalState.GetRootForProof().Bytes()...) + items = append(items, s.SelfDestructSet.EncodeState()...) + items = append(items, s.LogSeries.EncodeState()...) + items = append(items, s.BlockHashTree.EncodeState()...) + items = append(items, s.AccessListTrie.EncodeState()...) + return items +} + +func (s *IntraState) Hash() common.Hash { + return crypto.Keccak256Hash(s.Encode()) +} + +func (s *IntraState) IsInter() bool { + return false +} + +// Make sure the cost is less than the current gas +func (s *IntraState) StateAsLastDepth(callFlag CallFlag, cost uint64) *IntraState { + s_ := *s + s_.Gas -= cost + s_.Stack = s.Stack.Copy() + if callFlag == CALLFLAG_CALL || callFlag == CALLFLAG_CALLCODE { + s_.Stack.PopN(7) + } else if callFlag == CALLFLAG_DELEGATECALL || callFlag == CALLFLAG_STATICCALL { + s_.Stack.PopN(6) + } else if callFlag == CALLFLAG_CREATE { + s_.Stack.PopN(3) + } else { + s_.Stack.PopN(4) + } + return &s_ +} + +func (s *IntraState) HashAsLastDepth(callFlag CallFlag, cost uint64) common.Hash { + return s.StateAsLastDepth(callFlag, cost).Hash() +} + +func StateFromCaptured( + blockNumber, transactionIdx uint64, + committedGlobalState vm.StateDB, + selfDestructSet *SelfDestructSet, + blockHashTree *BlockHashTree, + accessListTrie *AccessListTrie, + evm *vm.EVM, + lastDepthState OneStepState, + callFlag CallFlag, + inputData *Memory, + out, outSize, pc uint64, + op vm.OpCode, + gas, cost uint64, + memory *vm.Memory, + stack *vm.Stack, + contract *vm.Contract, + rData []byte, + depth int, +) *IntraState { + value, _ := uint256.FromBig(contract.Value()) + contractAddress := contract.Address() + pstack := StackFromEVMStack(stack) + pmemory := MemoryFromEVMMemory(memory) + returnData := NewMemoryFromBytes(rData) + globalState := evm.StateDB.Copy() + refund := globalState.GetRefund() + // All pending changes must be committed before getting the root + globalState.CommitForProof() + logSeries := LogSeriesFromLogs(globalState.GetCurrentLogs()) + return &IntraState{ + BlockNumber: blockNumber, + TransactionIdx: transactionIdx, + Depth: uint16(depth), + Gas: gas, + Refund: refund, + LastDepthState: lastDepthState, + ContractAddress: contractAddress, + Caller: contract.Caller(), + Value: *value, + CallFlag: callFlag, + Out: out, + OutSize: outSize, + Pc: pc, + OpCode: op, + CodeHash: evm.StateDB.GetCodeHash(contractAddress), + Stack: pstack, + Memory: pmemory, + InputData: inputData, + ReturnData: returnData, + CommittedGlobalState: committedGlobalState, + GlobalState: globalState, + SelfDestructSet: selfDestructSet, + LogSeries: logSeries, + BlockHashTree: blockHashTree, + AccessListTrie: accessListTrie, + } +} + +type InterState struct { + BlockNumber uint64 + TransactionIdx uint64 + GlobalState vm.StateDB + BlockGasUsed *uint256.Int + BlockHashTree *BlockHashTree + TransactionTrie *TransactionTrie + ReceiptTrie *ReceiptTrie +} + +func (s *InterState) Hash() common.Hash { + items := [][]byte{} + blockNumber := make([]byte, 8) + binary.BigEndian.PutUint64(blockNumber, s.BlockNumber) + items = append(items, blockNumber) + transactionIdx := make([]byte, 8) + binary.BigEndian.PutUint64(transactionIdx, s.TransactionIdx) + items = append(items, transactionIdx) + items = append(items, s.GlobalState.GetRootForProof().Bytes()) + blockGasBytes := s.BlockGasUsed.Bytes32() + items = append(items, blockGasBytes[:]) + items = append(items, s.BlockHashTree.EncodeState()) + items = append(items, s.TransactionTrie.EncodeState()) + items = append(items, s.ReceiptTrie.EncodeState()) + return crypto.Keccak256Hash(items...) +} + +func (s *InterState) IsInter() bool { + return true +} + +func InterStateFromCaptured( + blockNumber, transactionIdx uint64, + statedb vm.StateDB, + blockGasUsed *big.Int, + transactions types.Transactions, + receipts types.Receipts, + blockHashTree *BlockHashTree, +) *InterState { + bg, _ := uint256.FromBig(blockGasUsed) + transactionTrie := NewTransactionTrie(transactions[:transactionIdx]) + receiptTrie := NewReceiptTrie(receipts[:transactionIdx]) + return &InterState{ + BlockNumber: blockNumber, + TransactionIdx: transactionIdx, + GlobalState: statedb.Copy(), + BlockGasUsed: bg, + TransactionTrie: transactionTrie, + ReceiptTrie: receiptTrie, + BlockHashTree: blockHashTree, + } +} + +// Represent the state at the end of a finalized block +type BlockState struct { + BlockNumber uint64 + GlobalState vm.StateDB + BlockHashTree *BlockHashTree +} + +func (s *BlockState) Hash() common.Hash { + items := [][]byte{} + blockNumBytes := make([]byte, 8) + binary.BigEndian.PutUint64(blockNumBytes, s.BlockNumber) + items = append(items, blockNumBytes) + items = append(items, s.GlobalState.GetRootForProof().Bytes()) + items = append(items, s.BlockHashTree.EncodeState()) + return crypto.Keccak256Hash(items...) +} + +func (s *BlockState) IsInter() bool { + return true +} + +func BlockStateFromBlock(blockNumber uint64, stateDB vm.StateDB, blockHashTree *BlockHashTree) (*BlockState, error) { + return &BlockState{ + BlockNumber: blockNumber, + GlobalState: stateDB.Copy(), + BlockHashTree: blockHashTree, + }, nil +} diff --git a/fraud-proof/proof/state/transaction_trie.go b/fraud-proof/proof/state/transaction_trie.go new file mode 100644 index 000000000..1288cfcba --- /dev/null +++ b/fraud-proof/proof/state/transaction_trie.go @@ -0,0 +1,66 @@ +// Copyright 2022, Specular contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package state + +import ( + "bytes" + + "github.com/ethereum/go-ethereum/rlp" + "github.com/mantlenetworkio/mantle/l2geth/common" + "github.com/mantlenetworkio/mantle/l2geth/core/types" + "github.com/mantlenetworkio/mantle/l2geth/ethdb/memorydb" + "github.com/mantlenetworkio/mantle/l2geth/trie" +) + +type TransactionTrie struct { + transactions types.Transactions + trie *trie.Trie +} + +func NewTransactionTrie(txs types.Transactions) *TransactionTrie { + t, _ := trie.New(common.Hash{}, trie.NewDatabase(memorydb.New())) + valueBuf := new(bytes.Buffer) + var indexBuf []byte + for i := 0; i < txs.Len(); i++ { + indexBuf = rlp.AppendUint64(indexBuf[:0], uint64(i)) + valueBuf.Reset() + valueBuf.Write(txs.GetRlp(i)) + t.Update(indexBuf, common.CopyBytes(valueBuf.Bytes())) + } + return &TransactionTrie{ + transactions: txs, + trie: t, + } +} + +func (t *TransactionTrie) Root() common.Hash { + return t.trie.Hash() +} + +func (t *TransactionTrie) EncodeState() []byte { + return t.Root().Bytes() +} + +func (t *TransactionTrie) GetTransaction(index int) *types.Transaction { + return t.transactions[index] +} + +func (t *TransactionTrie) Prove(index int) ([][]byte, error) { + var proof mptProofList + var indexBuf []byte + indexBuf = rlp.AppendUint64(indexBuf[:0], uint64(index)) + err := t.trie.Prove(indexBuf, 0, &proof) + return proof, err +} diff --git a/fraud-proof/proof/state/utils.go b/fraud-proof/proof/state/utils.go new file mode 100644 index 000000000..33b200506 --- /dev/null +++ b/fraud-proof/proof/state/utils.go @@ -0,0 +1,36 @@ +// Copyright 2022, Specular contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package state + +import ( + "hash" + + "github.com/ethereum/go-ethereum/crypto" +) + +type mptProofList [][]byte + +func (n *mptProofList) Put(key []byte, value []byte) error { + *n = append(*n, value) + return nil +} + +func (n *mptProofList) Delete(key []byte) error { + panic("not supported") +} + +func newHash() hash.Hash { + return crypto.NewKeccakState() +} diff --git a/fraud-proof/proof/test_api.go b/fraud-proof/proof/test_api.go new file mode 100644 index 000000000..4d660a291 --- /dev/null +++ b/fraud-proof/proof/test_api.go @@ -0,0 +1,210 @@ +// Copyright 2022, Specular contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package proof + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "math/big" + "os" + "strconv" + + "github.com/mantlenetworkio/mantle/fraud-proof/proof/prover" + oss "github.com/mantlenetworkio/mantle/fraud-proof/proof/state" + "github.com/mantlenetworkio/mantle/l2geth/common" + "github.com/mantlenetworkio/mantle/l2geth/core" + "github.com/mantlenetworkio/mantle/l2geth/core/vm" + "github.com/mantlenetworkio/mantle/l2geth/rpc" +) + +func (api *ProverAPI) GenerateProofForStep(ctx context.Context, fraud bool, hash common.Hash, step int64, config *ProverConfig) (json.RawMessage, error) { + transaction, blockHash, blockNumber, index, err := api.backend.GetTransaction(ctx, hash) + if err != nil { + return nil, err + } + // It shouldn't happen in practice. + if blockNumber == 0 { + return nil, errors.New("genesis is not traceable") + } + reexec := defaultProveReexec + if config != nil && config.Reexec != nil { + reexec = *config.Reexec + } + block, err := api.backend.BlockByNumber(ctx, rpc.BlockNumber(blockNumber)) + if err != nil { + return nil, err + } + if block == nil { + return nil, fmt.Errorf("block #%d not found", blockNumber) + } + + // get tx ctx + msg, txContext, statedb, err := api.backend.StateAtTransaction(ctx, block, int(index), reexec) + if err != nil { + return nil, err + } + // get block ctx + chainCtx := createChainContext(api.backend, ctx) + vmctx := core.NewEVMBlockContext(block.Header(), chainCtx, nil) + + receipts, err := api.backend.GetReceipts(ctx, blockHash) + if err != nil { + return nil, err + } + // calc block state hash + blockHashTree, err := oss.BlockHashTreeFromBlockContext(&vmctx) + if err != nil { + return nil, err + } + // calc its + its := oss.InterStateFromCaptured( + blockNumber, + index, + statedb, + new(big.Int).SetUint64(block.Header().GasUsed), + block.Transactions(), + receipts, + blockHashTree, + ) + // new test prover + testProver := prover.NewTestProver( + step, + -1, // none exist opcode + transaction, + &txContext, + receipts[index], + api.backend.ChainConfig().Rules(vmctx.BlockNumber), + blockNumber, + index, + statedb, + *its, + blockHashTree, + ) + // set fraud proof status + api.SetFraudProof(ctx, fraud, step, -1, config) + defer api.SetFraudProof(ctx, false, -1, -1, config) + // new evm + vmenv := vm.NewEVM(txContext, statedb, api.backend.ChainConfig(), vm.Config{Debug: true, Tracer: testProver}) + statedb.Prepare(hash, block.Hash(), int(index)) + _, _, _, err = core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.Gas())) + if err != nil { + return nil, fmt.Errorf("tracing failed: %w", err) + } + return testProver.GetResult() +} + +func (api *ProverAPI) GenerateProofForOpcode(ctx context.Context, fraud bool, hash common.Hash, opcode int64, config *ProverConfig) (json.RawMessage, error) { + transaction, blockHash, blockNumber, index, err := api.backend.GetTransaction(ctx, hash) + if err != nil { + return nil, err + } + // It shouldn't happen in practice. + if blockNumber == 0 { + return nil, errors.New("genesis is not traceable") + } + reexec := defaultProveReexec + if config != nil && config.Reexec != nil { + reexec = *config.Reexec + } + block, err := api.backend.BlockByNumber(ctx, rpc.BlockNumber(blockNumber)) + if err != nil { + return nil, err + } + if block == nil { + return nil, fmt.Errorf("block #%d not found", blockNumber) + } + + // get tx ctx + msg, txContext, statedb, err := api.backend.StateAtTransaction(ctx, block, int(index), reexec) + if err != nil { + return nil, err + } + // get block ctx + chainCtx := createChainContext(api.backend, ctx) + vmctx := core.NewEVMBlockContext(block.Header(), chainCtx, nil) + + receipts, err := api.backend.GetReceipts(ctx, blockHash) + if err != nil { + return nil, err + } + // calc block state hash + blockHashTree, err := oss.BlockHashTreeFromBlockContext(&vmctx) + if err != nil { + return nil, err + } + // calc its + its := oss.InterStateFromCaptured( + blockNumber, + index, + statedb, + new(big.Int).SetUint64(block.Header().GasUsed), + block.Transactions(), + receipts, + blockHashTree, + ) + // new test prover + testProver := prover.NewTestProver( + -1, + opcode, + transaction, + &txContext, + receipts[index], + api.backend.ChainConfig().Rules(vmctx.BlockNumber), + blockNumber, + index, + statedb, + *its, + blockHashTree, + ) + // set fraud proof status + api.SetFraudProof(ctx, fraud, -1, opcode, config) + defer api.SetFraudProof(ctx, false, -1, -1, config) + // new evm + vmenv := vm.NewEVM(txContext, statedb, api.backend.ChainConfig(), vm.Config{Debug: true, Tracer: testProver}) + statedb.Prepare(hash, block.Hash(), int(index)) + _, _, _, err = core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.Gas())) + if err != nil { + return nil, fmt.Errorf("tracing failed: %w", err) + } + return testProver.GetResult() +} + +func (api *ProverAPI) SetFraudProof(ctx context.Context, fraud bool, step, opcode int64, config *ProverConfig) (json.RawMessage, error) { + if api.backend.ChainConfig().ChainID.Cmp(big.NewInt(17)) != 0 { + return nil, nil + } + // It shouldn't happen in practice. + // set fraud proof + if fraud { + os.Setenv("Fraud", "true") + } else { + os.Setenv("Fraud", "false") + } + if step >= 0 { + os.Setenv("Step", strconv.Itoa(int(step))) + } else { + os.Setenv("Step", "-1") + } + if opcode >= 0 { + os.Setenv("Opcode", strconv.Itoa(int(opcode))) + } else { + os.Setenv("Opcode", "-1") + } + + res, _ := json.Marshal(os.Getenv("Fraud")) + return json.RawMessage(res), nil +} diff --git a/fraud-proof/rollup/services/backend.go b/fraud-proof/rollup/services/backend.go new file mode 100644 index 000000000..5a067decf --- /dev/null +++ b/fraud-proof/rollup/services/backend.go @@ -0,0 +1,14 @@ +package services + +import ( + "github.com/mantlenetworkio/mantle/l2geth/core" + "github.com/mantlenetworkio/mantle/l2geth/core/state" + "github.com/mantlenetworkio/mantle/l2geth/core/types" +) + +// Required interface for interacting with Ethereum instance +type Backend interface { + BlockChain() *core.BlockChain + TxPool() *core.TxPool + StateAtBlock(block *types.Block, reexec uint64, base *state.StateDB, checkLive bool, preferDisk bool) (statedb *state.StateDB, err error) +} diff --git a/fraud-proof/rollup/services/base.go b/fraud-proof/rollup/services/base.go new file mode 100644 index 000000000..1ff89b07e --- /dev/null +++ b/fraud-proof/rollup/services/base.go @@ -0,0 +1,115 @@ +package services + +import ( + "context" + "math/big" + "sync" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/mantlenetworkio/mantle/fraud-proof/bindings" + "github.com/mantlenetworkio/mantle/fraud-proof/proof" + "github.com/mantlenetworkio/mantle/l2geth/core" + "github.com/mantlenetworkio/mantle/l2geth/core/types" + "github.com/mantlenetworkio/mantle/l2geth/log" +) + +type BaseService struct { + Config *Config + + Eth Backend + ProofBackend proof.Backend + Chain *core.BlockChain + L1 *ethclient.Client + TransactOpts *bind.TransactOpts + Rollup *bindings.RollupSession + AssertionMap *bindings.AssertionMapCallerSession + + Ctx context.Context + Cancel context.CancelFunc + Wg sync.WaitGroup +} + +func NewBaseService(eth Backend, proofBackend proof.Backend, cfg *Config, auth *bind.TransactOpts) (*BaseService, error) { + ctx, cancel := context.WithCancel(context.Background()) + l1, err := ethclient.DialContext(ctx, cfg.L1Endpoint) + if err != nil { + cancel() + return nil, err + } + callOpts := bind.CallOpts{ + Pending: true, + Context: ctx, + } + transactOpts := bind.TransactOpts{ + From: auth.From, + Signer: auth.Signer, + GasPrice: big.NewInt(800000000), + Context: ctx, + } + rollup, err := bindings.NewRollup(common.Address(cfg.RollupAddr), l1) + if err != nil { + cancel() + return nil, err + } + rollupSession := &bindings.RollupSession{ + Contract: rollup, + CallOpts: callOpts, + TransactOpts: transactOpts, + } + assertionMapAddr, err := rollupSession.Assertions() + if err != nil { + cancel() + return nil, err + } + assertionMap, err := bindings.NewAssertionMapCaller(assertionMapAddr, l1) + if err != nil { + cancel() + return nil, err + } + assertionMapSession := &bindings.AssertionMapCallerSession{ + Contract: assertionMap, + CallOpts: callOpts, + } + b := &BaseService{ + Config: cfg, + Eth: eth, + ProofBackend: proofBackend, + L1: l1, + TransactOpts: &transactOpts, + Rollup: rollupSession, + AssertionMap: assertionMapSession, + Ctx: ctx, + Cancel: cancel, + } + if eth != nil { + b.Chain = eth.BlockChain() + } + return b, nil +} + +func (b *BaseService) Start(cleanL1, stake bool) *types.Block { + // Check if we are at genesis + // TODO: if not, sync from L1 + genesis := b.Eth.BlockChain().CurrentBlock() + log.Info("Genesis root", "root", genesis.Root()) + + if stake { + // Initial staking + // TODO: sync L1 staking status + stakeOpts := b.Rollup.TransactOpts + isStaked, err := b.Rollup.Contract.IsStaked(&bind.CallOpts{}, stakeOpts.From) + if err != nil { + log.Crit("Failed to query stake", "err", err) + } + if !isStaked { + stakeOpts.Value = big.NewInt(int64(b.Config.StakeAmount)) + _, err = b.Rollup.Contract.Stake(&stakeOpts) + if err != nil { + log.Crit("Failed to stake", "from", stakeOpts.From.String(), "amount", stakeOpts.Value, "err", err) + } + } + } + return genesis +} diff --git a/fraud-proof/rollup/services/config.go b/fraud-proof/rollup/services/config.go new file mode 100644 index 000000000..ed7905754 --- /dev/null +++ b/fraud-proof/rollup/services/config.go @@ -0,0 +1,24 @@ +package services + +import ( + "github.com/mantlenetworkio/mantle/l2geth/common" +) + +const ( + NODE_SCHEDULER = "scheduler" + NODE_VERIFIER = "verifier" +) + +// Config is the configuration of rollup services +type Config struct { + Node string // Rollup node type, either sequencer or validator + Passphrase string // The passphrase of the coinbase account + L1Endpoint string // L1 API endpoint + L1ChainID uint64 // L1 chain ID + L1Confirmations uint64 // L1 confirmation block number + SequencerAddr common.Address // Validator only + RollupAddr common.Address // L1 Rollup contract address + StakeAddr common.Address // The account used for rollup assertion stake + StakeAmount uint64 // Amount of stake + ChallengeVerify bool +} diff --git a/fraud-proof/rollup/services/sequencer/sequencer.go b/fraud-proof/rollup/services/sequencer/sequencer.go new file mode 100644 index 000000000..346c8626a --- /dev/null +++ b/fraud-proof/rollup/services/sequencer/sequencer.go @@ -0,0 +1,483 @@ +package sequencer + +import ( + "bytes" + "math/big" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + ethc "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" + "github.com/ethereum/go-ethereum/rpc" + + "github.com/mantlenetworkio/mantle/fraud-proof/bindings" + "github.com/mantlenetworkio/mantle/fraud-proof/proof" + "github.com/mantlenetworkio/mantle/fraud-proof/rollup/services" + rollupTypes "github.com/mantlenetworkio/mantle/fraud-proof/rollup/types" + "github.com/mantlenetworkio/mantle/l2geth/common" + "github.com/mantlenetworkio/mantle/l2geth/log" + "github.com/mantlenetworkio/mantle/l2geth/p2p" +) + +func RegisterService(eth services.Backend, proofBackend proof.Backend, cfg *services.Config, auth *bind.TransactOpts) { + sequencer, err := New(eth, proofBackend, cfg, auth) + if err != nil { + log.Crit("Failed to register the Rollup service", "err", err) + } + sequencer.Start() + log.Info("Sequencer registered") +} + +type ChallengeCtx struct { + ChallengeAddr common.Address + Assertion *rollupTypes.Assertion + Parent *rollupTypes.Assertion +} + +// Sequencer run confirming loop and respond challenge, assumes no Berlin+London fork on L2 +type Sequencer struct { + *services.BaseService + + confirmedIDCh chan *big.Int + challengeCh chan *ChallengeCtx + challengeResolutionCh chan struct{} + + confirmations uint64 +} + +func New(eth services.Backend, proofBackend proof.Backend, cfg *services.Config, auth *bind.TransactOpts) (*Sequencer, error) { + base, err := services.NewBaseService(eth, proofBackend, cfg, auth) + if err != nil { + return nil, err + } + s := &Sequencer{ + BaseService: base, + confirmedIDCh: make(chan *big.Int, 4096), + challengeCh: make(chan *ChallengeCtx), + challengeResolutionCh: make(chan struct{}), + confirmations: cfg.L1Confirmations, + } + return s, nil +} + +// This goroutine tries to confirm created assertions +func (s *Sequencer) confirmationLoop() { + defer s.Wg.Done() + + // Watch AssertionCreated event + var createdCh = make(chan *bindings.RollupAssertionCreated, 4096) + createdSub, err := s.Rollup.Contract.WatchAssertionCreated(&bind.WatchOpts{Context: s.Ctx}, createdCh) + if err != nil { + log.Error("Failed to watch rollup event", "err", err) + } + defer createdSub.Unsubscribe() + + // Watch AssertionConfirmed event + var confirmedCh = make(chan *bindings.RollupAssertionConfirmed, 4096) + confirmedSub, err := s.Rollup.Contract.WatchAssertionConfirmed(&bind.WatchOpts{Context: s.Ctx}, confirmedCh) + if err != nil { + log.Error("Failed to watch rollup event", "err", err) + } + defer confirmedSub.Unsubscribe() + + // Watch L1 blockchain for confirmation period + var headCh = make(chan *types.Header, 4096) + headSub, err := s.L1.SubscribeNewHead(s.Ctx, headCh) + if err != nil { + log.Error("Failed to watch l1 chain head", "err", err) + } + defer headSub.Unsubscribe() + + var challengedCh = make(chan *bindings.RollupAssertionChallenged, 4096) + challengedSub, err := s.Rollup.Contract.WatchAssertionChallenged(&bind.WatchOpts{Context: s.Ctx}, challengedCh) + if err != nil { + log.Error("Failed to watch rollup event", "err", err) + } + defer challengedSub.Unsubscribe() + + challengeAssertions := make(map[uint64]bool) + + challengeContext, _ := s.Rollup.ChallengeCtx() + isInChallenge := challengeContext.DefenderAssertionID.Uint64() != 0 && !challengeContext.Completed + // restart with challengeCtx + if isInChallenge { + defenderAssertion, _ := s.AssertionMap.Assertions(challengeContext.DefenderAssertionID) + parentAssertionID, _ := s.AssertionMap.GetParentID(challengeContext.DefenderAssertionID) + parentAssertion, _ := s.AssertionMap.Assertions(parentAssertionID) + + challengeCtx := ChallengeCtx{ + ChallengeAddr: common.Address(challengeContext.ChallengeAddress), + Assertion: &rollupTypes.Assertion{ + ID: challengeContext.DefenderAssertionID, + VmHash: defenderAssertion.StateHash, + InboxSize: defenderAssertion.InboxSize, + Parent: defenderAssertion.Parent, + Deadline: defenderAssertion.Deadline, + ProposalTime: defenderAssertion.ProposalTime, + }, + Parent: &rollupTypes.Assertion{ + ID: parentAssertionID, + VmHash: parentAssertion.StateHash, + InboxSize: parentAssertion.InboxSize, + Parent: parentAssertion.Parent, + Deadline: parentAssertion.Deadline, + ProposalTime: parentAssertion.ProposalTime, + }, + } + s.challengeCh <- &challengeCtx + } + + for { + if isInChallenge { + // Waif for the challenge resolved + select { + case <-s.challengeResolutionCh: + log.Info("Sequencer finished challenge, reset isInChallenge status") + isInChallenge = false + case <-s.Ctx.Done(): + log.Error("Scheduler confirmationLoop ctx done") + return + } + } else { + select { + case ev := <-createdCh: + // New assertion created on L1 Rollup + log.Info("Get New Assertion...", "AssertionID", ev.AssertionID, + "AsserterAddr", ev.AsserterAddr, "VmHash", ev.VmHash, "InboxSize", ev.InboxSize) + if !bytes.Equal(ev.AsserterAddr.Bytes(), s.Config.StakeAddr.Bytes()) { + log.Info("Get Assertion for challenge,store it") + challengeAssertions[ev.AssertionID.Uint64()] = true + } + case header := <-headCh: + // todo : optimization the check with block height + // Get confirm block header + if s.confirmations != 0 { + num := new(big.Int) + num.SetUint64(s.confirmations) + num.Sub(header.Number, num) + header, err = s.L1.HeaderByNumber(s.Ctx, num) + if err != nil { + log.Error("Failed to get confirmed header", "err", err) + continue + } + } + // Get first unresolved confirm assertion and check deadline + lastRSAID, err := s.Rollup.LastResolvedAssertionID() + if err != nil { + log.Error("Failed to get last resolved assertion ID", "err", err) + continue + } + lastCAID, err := s.Rollup.LastCreatedAssertionID() + if err != nil { + log.Error("Failed to get last created assertion ID", "err", err) + continue + } + if lastCAID.Uint64() <= lastRSAID.Uint64() { + continue + } + // New block mined on L1 + log.Info("Sequencer sync new layer1 block", "height", header.Number) + firstUnresolvedID := lastRSAID.Uint64() + 1 + firstUnresolvedAssertion, err := s.AssertionMap.Assertions(new(big.Int).SetUint64(firstUnresolvedID)) + if err != nil { + log.Error("Failed to get first unresolved Assertion", "err", err, "ID", firstUnresolvedID) + continue + } + if header.Time >= firstUnresolvedAssertion.Deadline.Uint64() { + log.Info("Current assertion", "id", firstUnresolvedID) + if !challengeAssertions[firstUnresolvedID] { + // Confirmation period has past, confirm it + log.Info("Sequencer call ConfirmFirstUnresolvedAssertion...") + _, err := s.Rollup.ConfirmFirstUnresolvedAssertion() + if err != nil { + if err.Error() == "execution reverted: InvalidParent" { + challengeAssertions[firstUnresolvedID] = true + } + log.Error("Failed to confirm DA", "err", err) + } + continue + } + log.Info("Sequencer call RejectFirstUnresolvedAssertion...") + // reject challenge assertion + _, err := s.Rollup.RejectFirstUnresolvedAssertion() + if err != nil { + log.Error("Failed to reject DA", "err", err) + continue + } + _, err = s.Rollup.RemoveOldZombies() + if err != nil { + log.Error("Failed to remove zombies", "err", err) + continue + } + delete(challengeAssertions, firstUnresolvedID) + } + + case ev := <-confirmedCh: + log.Info("New confirmed assertion", "id", ev.AssertionID) + case ev := <-challengedCh: + log.Warn("New challenge rise!!!!!!", "ev", ev) + // todo when interrupt at this moment, check staker`s status + challengeAssertion := new(rollupTypes.Assertion) + parent := new(rollupTypes.Assertion) + if ret, err := s.AssertionMap.Assertions(ev.AssertionID); err != nil { + log.Error("Get assertion failed", "id", ev.AssertionID, "err", err) + challengedCh <- ev + continue + } else { + challengeAssertion.ID = ev.AssertionID + challengeAssertion.VmHash = ret.StateHash + challengeAssertion.InboxSize = ret.InboxSize + challengeAssertion.Parent = ret.Parent + challengeAssertion.Deadline = ret.Deadline + challengeAssertion.ProposalTime = ret.ProposalTime + } + if ret, err := s.AssertionMap.Assertions(challengeAssertion.Parent); err != nil { + log.Error("Get assertion failed", "id", challengeAssertion.Parent, "err", err) + challengedCh <- ev + continue + } else { + parent.ID = ev.AssertionID + parent.VmHash = ret.StateHash + parent.InboxSize = ret.InboxSize + parent.Parent = ret.Parent + parent.Deadline = ret.Deadline + parent.ProposalTime = ret.ProposalTime + } + + challengeCtx := ChallengeCtx{ + common.Address(ev.ChallengeAddr), + challengeAssertion, + parent, + } + + s.challengeCh <- &challengeCtx + isInChallenge = true + + case <-s.Ctx.Done(): + return + } + } + } +} + +func (s *Sequencer) challengeLoop() { + defer s.Wg.Done() + + // Watch L1 blockchain for challenge timeout + var headCh = make(chan *types.Header, 4096) + headSub, err := s.L1.SubscribeNewHead(s.Ctx, headCh) + if err != nil { + log.Error("Failed to watch l1 chain head", "err", err) + } + defer headSub.Unsubscribe() + + var challengeSession *bindings.ChallengeSession + var states []*proof.ExecutionState + + var bisectedCh = make(chan *bindings.ChallengeBisected, 4096) + var bisectedSub event.Subscription + var challengeCompletedCh = make(chan *bindings.ChallengeChallengeCompleted, 4096) + var challengeCompletedSub event.Subscription + + inChallenge := false + var opponentTimeout uint64 + + for { + if inChallenge { + select { + case ev := <-bisectedCh: + // case get bisection, if is our turn + // if in single step, submit proof + // if multiple step, track current segment, update + responder, err := challengeSession.CurrentResponder() + if err != nil { + // TODO: error handling + log.Error("Can not get current responder", "error", err) + continue + } + log.Info("Responder info...", "responder", responder, "staker", s.Config.StakeAddr) + if common.Address(responder) == s.Config.StakeAddr { + log.Info("Sequencer start to respond new bisection...") + // If it's our turn + //err := services.RespondBisection(s.BaseService, abi, challengeSession, ev, states, common.Hash{}, false) + err := services.RespondBisection(s.BaseService, challengeSession, ev, states) + if err != nil { + // TODO: error handling + log.Error("Can not respond to bisection", "error", err) + continue + } + } else { + opponentTimeLeft, err := challengeSession.CurrentResponderTimeLeft() + if err != nil { + // TODO: error handling + log.Error("Can not get current responder left time", "error", err) + continue + } + log.Info("[Sequencer] Opponent time left", "blockTime", ev.BlockTime.Uint64(), "timeLeft", opponentTimeLeft) + opponentTimeout = ev.BlockTime.Uint64() + opponentTimeLeft.Uint64() + } + case header := <-headCh: + if opponentTimeout == 0 { + continue + } + // TODO: can we use >= here? + log.Info("New header incoming...", "header.Number", header.Number, "header.Time", header.Time, "opponentTimeout", opponentTimeout) + if header.Time > opponentTimeout { + _, err = challengeSession.Timeout() + if err != nil { + log.Error("Can not timeout opponent", "error", err) + continue + // TODO: wait some time before retry + // TODO: fix race condition + } + log.Info("Timeout challenge...") + } + case ev := <-challengeCompletedCh: + log.Info("[challenge] Try to challenge completed", "winner", ev.Winner) + _, err = challengeSession.CompleteChallenge(s.Config.ChallengeVerify) + if err != nil { + log.Error("Can not complete challenge", "error", err) + continue + } + bisectedSub.Unsubscribe() + challengeCompletedSub.Unsubscribe() + states = []*proof.ExecutionState{} + inChallenge = false + challengeSession = nil + s.challengeResolutionCh <- struct{}{} + log.Info("[challenge] Challenge completed", "winner", ev.Winner) + case <-s.Ctx.Done(): + bisectedSub.Unsubscribe() + challengeCompletedSub.Unsubscribe() + return + } + } else { + select { + case ctx := <-s.challengeCh: + log.Warn("Sequencer receive new challenge!!!", "handle it", ctx) + challenge, err := bindings.NewChallenge(ethc.Address(ctx.ChallengeAddr), s.L1) + if err != nil { + log.Error("Failed to access ongoing challenge", "address", ctx.ChallengeAddr, "err", err) + s.challengeCh <- ctx + continue + } + challengeSession = &bindings.ChallengeSession{ + Contract: challenge, + CallOpts: bind.CallOpts{Pending: true, Context: s.Ctx}, + TransactOpts: *s.TransactOpts, + } + // use staker status to check challenge status + // 1. challenge contract not exist + // 2. challenge exist and already completed + stakeStatus, _ := s.Rollup.Stakers(s.Rollup.TransactOpts.From) + if bytes.Equal(stakeStatus.CurrentChallenge.Bytes(), common.BigToAddress(common.Big0).Bytes()) { + winner, err := challengeSession.Winner() + if err != nil || bytes.Equal(winner.Bytes(), common.BigToAddress(common.Big0).Bytes()) { + // challenge not exit or winner not exist + log.Info("Challenge not exist", "err", err) + } + challengeCompletedCh <- &bindings.ChallengeChallengeCompleted{ + Winner: winner, + } + continue + } + bisectedSub, err = challenge.WatchBisected(&bind.WatchOpts{Context: s.Ctx}, bisectedCh) + if err != nil { + log.Error("Failed to watch challenge event", "err", err) + s.challengeCh <- ctx + continue + } + challengeCompletedSub, err = challenge.WatchChallengeCompleted(&bind.WatchOpts{Context: s.Ctx}, challengeCompletedCh) + if err != nil { + log.Error("Failed to watch challenge event", "err", err) + s.challengeCh <- ctx + continue + } + log.Info("Sequencer generate state...") + states, err = proof.GenerateStates( + s.ProofBackend, + s.Ctx, + ctx.Parent.InboxSize.Uint64(), + ctx.Assertion.InboxSize.Uint64(), + nil, + ) + if err != nil { + log.Error("Failed to generate states", "err", err) + s.challengeCh <- ctx + continue + } + log.Info("Sequencer generate state end...") + + // initialized: get current bisectedCh; + // not initialized: InitializeChallengeLength; + if bytes.Equal(stakeStatus.CurrentChallenge.Bytes(), ctx.ChallengeAddr.Bytes()) { + bisectionHash, _ := challengeSession.BisectionHash() + if bytes.Equal(bisectionHash[:], common.BigToHash(common.Big0).Bytes()) { + // when not init + numSteps := uint64(len(states)) - 1 + log.Info("Print generated states", "states[0]", states[0].Hash().String(), "states[numSteps]", states[numSteps].Hash().String(), "numSteps", numSteps) + _, err = challengeSession.InitializeChallengeLength(services.MidState(states, 0, numSteps), new(big.Int).SetUint64(numSteps)) + if err != nil { + log.Error("Failed to initialize challenge", "err", err) + s.challengeCh <- ctx + continue + } + } else { + //bisectedCh chan *bindings.ChallengeBisected + curr, err := challengeSession.CurrentBisected() + if err != nil { + log.Error("Failed to get current bisected", "err", err) + s.challengeCh <- ctx + continue + } + bisectedCh <- &bindings.ChallengeBisected{ + StartState: curr.StartState, + MidState: curr.MidState, + EndState: curr.EndState, + BlockNum: curr.BlockNum, + BlockTime: curr.BlockTime, + ChallengedSegmentStart: curr.ChallengedSegmentStart, + ChallengedSegmentLength: curr.ChallengedSegmentLength, + } + } + inChallenge = true + } else { + log.Error("Unrecognized challenge", "StakerChallenge", stakeStatus.CurrentChallenge.String(), "ChallengeAddr", ctx.ChallengeAddr.String()) + s.challengeCh <- ctx + continue + } + case <-headCh: + continue // consume channel values + case <-s.Ctx.Done(): + return + } + } + } +} + +func (s *Sequencer) Protocols() []p2p.Protocol { + // TODO: sequencer APIs + return []p2p.Protocol{} +} + +func (s *Sequencer) APIs() []rpc.API { + // TODO: sequencer APIs + return []rpc.API{} +} + +func (s *Sequencer) Start() error { + _ = s.BaseService.Start(true, true) + + s.Wg.Add(2) + go s.confirmationLoop() + go s.challengeLoop() + log.Info("fraud-proof defender started") + return nil +} + +func (s *Sequencer) Stop() error { + log.Info("fraud-proof defender stopped") + s.Cancel() + s.Wg.Wait() + return nil +} diff --git a/fraud-proof/rollup/services/sequencer/sequencer_test.go b/fraud-proof/rollup/services/sequencer/sequencer_test.go new file mode 100644 index 000000000..5f9da75d0 --- /dev/null +++ b/fraud-proof/rollup/services/sequencer/sequencer_test.go @@ -0,0 +1 @@ +package sequencer diff --git a/fraud-proof/rollup/services/utils.go b/fraud-proof/rollup/services/utils.go new file mode 100644 index 000000000..2cc8d58ba --- /dev/null +++ b/fraud-proof/rollup/services/utils.go @@ -0,0 +1,223 @@ +package services + +import ( + "bytes" + "context" + "encoding/hex" + "errors" + "fmt" + "math/big" + + ethc "github.com/ethereum/go-ethereum/common" + "github.com/mantlenetworkio/mantle/fraud-proof/bindings" + "github.com/mantlenetworkio/mantle/fraud-proof/proof" + "github.com/mantlenetworkio/mantle/l2geth/common" + "github.com/mantlenetworkio/mantle/l2geth/core/types" + "github.com/mantlenetworkio/mantle/l2geth/log" +) + +func SubmitOneStepProof( + challengeSession *bindings.ChallengeSession, + proofBackend proof.Backend, + ctx context.Context, + state *proof.ExecutionState, + challengedStepIndex *big.Int, + prevChallengedSegmentStart *big.Int, + prevChallengedSegmentLength *big.Int, +) error { + log.Info("OSP GenerateProof...") + osp, err := proof.GenerateProof(ctx, proofBackend, state, nil) + if err != nil { + log.Error("UNHANDELED: osp generation failed", "err", err) + return err + } + log.Info("OSP GenerateProof success") + log.Info("OSP BuildVerificationContext...") + verificationContext, err := BuildVerificationContext(ctx, proofBackend, state) + if err != nil { + log.Error("UNHANDELED: osp build verification context failed", "err", err) + return err + } + + log.Info("OSP BuildVerificationContext success") + log.Debug("OSP VerifyOneStepProof...") + log.Debug("OSP verificationContext: ", "verificationContext", verificationContext) + log.Debug("OSP VerifierType: ", "VerifierType", uint8(osp.VerifierType)) + log.Debug("OSP encode: ", "osp", osp.Encode()) + log.Debug("challengedStepIndex: ", "challengedStepIndex", challengedStepIndex) + log.Debug("prevChallengedSegmentStart: ", "prevChallengedSegmentStart", prevChallengedSegmentStart) + log.Debug("prevChallengedSegmentLength: ", "prevChallengedSegmentLength", prevChallengedSegmentLength) + _, err = challengeSession.VerifyOneStepProof( + *verificationContext, + uint8(osp.VerifierType), + osp.Encode(), + challengedStepIndex, + prevChallengedSegmentStart, + prevChallengedSegmentLength, + ) + if err != nil { + log.Error("OSP verification failed") + return err + } + log.Info("OSP VerifyOneStepProof submitted") + return nil +} + +// Responder -> startStateHash, endStateHash +func RespondBisection( + b *BaseService, + challengeSession *bindings.ChallengeSession, + ev *bindings.ChallengeBisected, + states []*proof.ExecutionState, +) error { + var challengedStepIndex = new(big.Int) + var bisection [3][32]byte + var challengeIdx uint64 + var newStart uint64 + var newLen uint64 // New segment length + + // Get bisection info from event + segStart := ev.ChallengedSegmentStart.Uint64() + segLen := ev.ChallengedSegmentLength.Uint64() + + if segStart+segLen >= uint64(len(states)) { + log.Error("RespondBisection out of range", "segStart", segStart, "segLen", segLen, "len(states)", len(states)) + return errors.New("RespondBisection out of range") + } + + startState := states[segStart].Hash() + midState := MidState(states, segStart, segLen) + endState := states[segStart+segLen].Hash() + if segLen >= 3 { + if !bytes.Equal(midState[:], ev.MidState[:]) { + newLen = MidLen(segLen) + newStart = segStart + bisection[0] = startState + bisection[1] = MidState(states, newStart, newLen) + bisection[2] = midState + challengeIdx = 1 + } else { + newLen = MidLen(segLen) + newStart = segStart + MidLenWithMod(segLen) + bisection[0] = midState + bisection[1] = MidState(states, newStart, newLen) + bisection[2] = endState + challengeIdx = 2 + } + } else if segLen <= 2 && segLen > 0 { + var state *proof.ExecutionState + if !bytes.Equal(startState[:], ev.StartState[:]) { + log.Error("bisection find different start state") + state = states[segStart] + challengedStepIndex.SetUint64(0) + } else if !bytes.Equal(midState[:], ev.MidState[:]) { + state = states[segStart+segLen/2+segLen%2] + challengedStepIndex.SetUint64(1) + } else if !bytes.Equal(endState[:], ev.EndState[:]) { + state = states[segStart+segLen] + challengedStepIndex.SetUint64(2) + } else { + return errors.New("RespondBisection can't find state difference") + } + + // We've reached one step + err := SubmitOneStepProof( + challengeSession, + b.ProofBackend, + b.Ctx, + state, + challengedStepIndex, + ev.ChallengedSegmentStart, + ev.ChallengedSegmentLength, + ) + if err != nil { + log.Error("UNHANDELED: osp failed", "err", err) + return err + } + return nil + } else { + log.Error("RespondBisection segLen in event is illegal") + return errors.New("RespondBisection segLen in event is illegal") + } + log.Info("BisectExecution", "bisection[0]", hex.EncodeToString(bisection[0][:]), "bisection[1]", hex.EncodeToString(bisection[1][:]), "bisection[2]", hex.EncodeToString(bisection[2][:]), "cidx", challengeIdx, "segStart", segStart, "segLen", segLen) + _, err := challengeSession.BisectExecution( + bisection, + new(big.Int).SetUint64(challengeIdx), + new(big.Int).SetUint64(newStart), + new(big.Int).SetUint64(newLen), + ev.ChallengedSegmentStart, + ev.ChallengedSegmentLength, + ) + if err != nil { + log.Error("UNHANDELED: bisection excution failed", "err", err) + return err + } + return nil +} + +// MidLen middle index with ceil +func MidLen(segLen uint64) uint64 { + return segLen / 2 +} + +// MidLenWithMod middle index with ceil +func MidLenWithMod(segLen uint64) uint64 { + return segLen/2 + segLen%2 +} + +// MidState mid-states with floor index +func MidState(states []*proof.ExecutionState, segStart, segLen uint64) common.Hash { + return states[segStart+MidLenWithMod(segLen)].Hash() +} + +func BuildVerificationContext(ctx context.Context, proofBackend proof.Backend, state *proof.ExecutionState) (*bindings.VerificationContextContext, error) { + var evmTx bindings.EVMTypesLibTransaction + var tx *types.Transaction + var header *types.Header + var err error + // get block + if state != nil && state.Block != nil { + header = state.Block.Header() + } else { + return nil, fmt.Errorf("get nil block from ExecutionState status") + } + // get transaction + if state != nil && state.Block.Transactions() != nil { + txs := state.Block.Transactions() + if uint64(len(txs)) < state.TransactionIdx+1 { + return nil, fmt.Errorf("get transaction index from ExecutionState out of range") + } + tx = state.Block.Transactions()[state.TransactionIdx] + } else { + return nil, fmt.Errorf("get nil transactions from ExecutionState status") + } + // build EVMTypesLibTransaction + var txOrigin common.Address + evmTx.Nonce = tx.Nonce() + evmTx.GasPrice = tx.GasPrice() + evmTx.To = ethc.Address(*tx.To()) + evmTx.Value = tx.Value() + evmTx.Data = tx.Data() + if tx.QueueOrigin() == types.QueueOriginSequencer { + evmTx.V, evmTx.R, evmTx.S = tx.RawSignatureValues() + signer := types.NewEIP155Signer(tx.ChainId()) + txOrigin, err = types.Sender(signer, tx) + if err != nil { + return nil, err + } + } else { + evmTx.V = big.NewInt(0) + evmTx.R = big.NewInt(0) + evmTx.S = big.NewInt(0) + txOrigin = common.BigToAddress(common.Big0) + } + return &bindings.VerificationContextContext{ + Coinbase: ethc.Address(header.Coinbase), + Timestamp: new(big.Int).SetUint64(tx.L1Timestamp()), + Number: header.Number, + Origin: ethc.Address(txOrigin), + Transaction: evmTx, + InputRoot: [32]byte{0}, + TxHash: tx.Hash(), + }, nil +} diff --git a/fraud-proof/rollup/services/validator/validator.go b/fraud-proof/rollup/services/validator/validator.go new file mode 100644 index 000000000..95c3bba3d --- /dev/null +++ b/fraud-proof/rollup/services/validator/validator.go @@ -0,0 +1,486 @@ +package validator + +import ( + "bytes" + "math/big" + "time" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + ethcommon "github.com/ethereum/go-ethereum/common" + ethtypes "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" + "github.com/ethereum/go-ethereum/rpc" + + "github.com/mantlenetworkio/mantle/fraud-proof/bindings" + "github.com/mantlenetworkio/mantle/fraud-proof/proof" + "github.com/mantlenetworkio/mantle/fraud-proof/rollup/services" + rollupTypes "github.com/mantlenetworkio/mantle/fraud-proof/rollup/types" + "github.com/mantlenetworkio/mantle/l2geth/common" + "github.com/mantlenetworkio/mantle/l2geth/core/rawdb" + "github.com/mantlenetworkio/mantle/l2geth/log" + "github.com/mantlenetworkio/mantle/l2geth/rlp" + rpc2 "github.com/mantlenetworkio/mantle/l2geth/rpc" +) + +func RegisterService(eth services.Backend, proofBackend proof.Backend, cfg *services.Config, auth *bind.TransactOpts) { + validator, err := New(eth, proofBackend, cfg, auth) + if err != nil { + log.Crit("Failed to register the Rollup service", "err", err) + } + validator.Start() + log.Info("Validator registered") +} + +type ChallengeCtx struct { + OpponentAssertion *rollupTypes.Assertion + OurAssertion *rollupTypes.Assertion +} + +type Validator struct { + *services.BaseService + + batchCh chan *rollupTypes.TxBatch + challengeCh chan *ChallengeCtx + challengeResoutionCh chan struct{} +} + +func New(eth services.Backend, proofBackend proof.Backend, cfg *services.Config, auth *bind.TransactOpts) (*Validator, error) { + base, err := services.NewBaseService(eth, proofBackend, cfg, auth) + if err != nil { + return nil, err + } + v := &Validator{ + BaseService: base, + batchCh: make(chan *rollupTypes.TxBatch, 4096), + challengeCh: make(chan *ChallengeCtx), + challengeResoutionCh: make(chan struct{}), + } + return v, nil +} + +// This goroutine validates the assertion posted to L1 Rollup, advances +// stake if validated, or challenges if not +func (v *Validator) validationLoop(genesisRoot common.Hash) { + defer v.Wg.Done() + + db := v.ProofBackend.ChainDb() + + // Listen to AssertionCreated event + var assertionEventCh = make(chan *bindings.RollupAssertionCreated, 4096) + assertionEventSub, err := v.Rollup.Contract.WatchAssertionCreated(&bind.WatchOpts{Context: v.Ctx}, assertionEventCh) + if err != nil { + log.Crit("Failed to watch rollup event", "err", err) + } + defer assertionEventSub.Unsubscribe() + + isInChallenge := false + challengeCtxEnc := rawdb.ReadFPValidatorChallengeCtx(db) + if challengeCtxEnc != nil { + isInChallenge = true + } + + for { + stakerStatus, err := v.Rollup.Stakers(v.Rollup.TransactOpts.From) + if err != nil { + log.Error("UNHANDELED: Can't find stake, validator state corrupted", "err", err) + time.Sleep(5 * time.Second) + continue + } + + if isInChallenge { + // Wait for the challenge resolution + select { + case <-v.challengeResoutionCh: + log.Info("Validator finished challenge, reset isInChallenge status") + isInChallenge = false + rawdb.DeleteFPValidatorChallengeCtx(db) + case <-v.Ctx.Done(): + return + } + } else { + select { + case ev := <-assertionEventCh: + // only one verifier and check it + // re-stake check + if !stakerStatus.IsStaked { + stakeOpts := v.Rollup.TransactOpts + stakeOpts.Value = big.NewInt(int64(v.Config.StakeAmount)) + _, err = v.Rollup.Contract.Stake(&stakeOpts) + if err != nil { + log.Error("Failed to stake", "from", stakeOpts.From.String(), "amount", stakeOpts.Value, "err", err) + continue + } + } + // check challenge status + if !bytes.Equal(stakerStatus.CurrentChallenge.Bytes(), common.BigToAddress(common.Big0).Bytes()) { + continue + } + // check staker status + zombies, _ := v.Rollup.Zombies(big.NewInt(0)) + if !bytes.Equal(zombies.StakerAddress.Bytes(), common.BigToAddress(common.Big0).Bytes()) { + continue + } + + if common.Address(ev.AsserterAddr) == v.Config.StakeAddr { + log.Info("Stake address", "address", v.Config.StakeAddr) + // Create by our own for challenge + continue + } + // New assertion created on Rollup + log.Info("Validator get new assertion, check it with local block....") + log.Info("check ev.AssertionID....", "id", ev.AssertionID) + + startID := stakerStatus.AssertionID.Uint64() + // advance the assertion that has fallen behind + for ; startID < ev.AssertionID.Uint64(); startID++ { + checkID := startID + 1 + assertion, err := v.AssertionMap.Assertions(new(big.Int).SetUint64(checkID)) + if err != nil { + log.Error("Validator get block failed", "err", err) + } + if assertion.InboxSize.Uint64() == 0 { + // Skip assertions that have been deleted + continue + } + checkAssertion := &rollupTypes.Assertion{ + ID: new(big.Int).SetUint64(checkID), + VmHash: assertion.StateHash, + InboxSize: assertion.InboxSize, + Parent: assertion.Parent, + } + block, err := v.BaseService.ProofBackend.BlockByNumber(v.Ctx, rpc2.BlockNumber(checkAssertion.InboxSize.Int64())) + if err != nil { + log.Error("Validator get block failed", "err", err) + } + if bytes.Compare(checkAssertion.VmHash.Bytes(), block.Root().Bytes()) != 0 { + // Validation failed + log.Info("Validator check assertion vmHash failed, start challenge assertion....") + ourAssertion := &rollupTypes.Assertion{ + VmHash: block.Root(), + InboxSize: checkAssertion.InboxSize, + Parent: assertion.Parent, + } + challengeCtx := ChallengeCtx{checkAssertion, ourAssertion} + data, _ := rlp.EncodeToBytes(challengeCtx) + rawdb.WriteFPValidatorChallengeCtx(db, data) + + v.challengeCh <- &challengeCtx + isInChallenge = true + break + } else { + // Validation succeeded, confirm assertion and advance stake + log.Info("Validator advance stake into assertion", "ID", ev.AssertionID, "now", startID) + // todo :During frequent interactions, it is necessary to check the results of the previous interaction + _, err = v.Rollup.AdvanceStake(new(big.Int).SetUint64(startID + 1)) + if err != nil { + log.Error("UNHANDELED: Can't advance stake, validator state corrupted", "err", err) + break + } + } + } + case <-v.Ctx.Done(): + return + } + } + } +} + +func (v *Validator) challengeLoop() { + defer v.Wg.Done() + + // challenge position + // 1.Assertion create + // 1.1 already created and now at correct assertion position + // 1.2 need create new assertion then create challenge by ctx.inboxSize and ctx.vmHash + + // 2.Challenge create + // 2.1 already created challenge + // 2.2 challenge need create by seq.assertionID and val.assertion. + + // 3.Bisected execute + // 3.1 sub channels and get current bisected + // 3.2 already finished challenge + + // Watch AssertionCreated event + var createdCh = make(chan *bindings.RollupAssertionCreated, 4096) + createdSub, err := v.Rollup.Contract.WatchAssertionCreated(&bind.WatchOpts{Context: v.Ctx}, createdCh) + if err != nil { + log.Crit("Failed to watch rollup event", "err", err) + } + defer createdSub.Unsubscribe() + + var challengedCh = make(chan *bindings.RollupAssertionChallenged, 4096) + challengedSub, err := v.Rollup.Contract.WatchAssertionChallenged(&bind.WatchOpts{Context: v.Ctx}, challengedCh) + if err != nil { + log.Crit("Failed to watch rollup event", "err", err) + } + defer challengedSub.Unsubscribe() + + // Watch L1 blockchain for challenge timeout + var headCh = make(chan *ethtypes.Header, 4096) + headSub, err := v.L1.SubscribeNewHead(v.Ctx, headCh) + if err != nil { + log.Crit("Failed to watch l1 chain head", "err", err) + } + defer headSub.Unsubscribe() + + var challengeSession *bindings.ChallengeSession + var states []*proof.ExecutionState + + var bisectedCh = make(chan *bindings.ChallengeBisected, 4096) + var bisectedSub event.Subscription + var challengeCompletedCh = make(chan *bindings.ChallengeChallengeCompleted, 4096) + var challengeCompletedSub event.Subscription + + restart := false + inChallenge := false + var ctx *ChallengeCtx + var opponentTimeoutBlock uint64 + + db := v.ProofBackend.ChainDb() + + go func() { + // The necessity of local storage: + // Can't judge whether the interruption has just entered the challenge process and did not create assertions + challengeCtxEnc := rawdb.ReadFPValidatorChallengeCtx(db) + if challengeCtxEnc != nil { + // Before the program was exited last time, it had + // entered the challenge state and did not execute it to challenge complete. + // we need to re-enter in the challenge process. + // Find the entry point through the state of the L1. + stakeStatus, _ := v.Rollup.Stakers(v.Rollup.TransactOpts.From) + currentAssertion, _ := v.AssertionMap.Assertions(stakeStatus.AssertionID) + var challengeCtx ChallengeCtx + if err = rlp.DecodeBytes(challengeCtxEnc, &challengeCtx); err != nil { + return + } + ctx = &challengeCtx + challengeContext, _ := v.Rollup.ChallengeCtx() + + if currentAssertion.InboxSize.Cmp(challengeCtx.OurAssertion.InboxSize) < 0 && + !bytes.Equal(currentAssertion.StateHash[:], challengeCtx.OurAssertion.VmHash[:]) { + // did not create assertion + v.challengeCh <- &challengeCtx + log.Info("Did not create assertion") + } else if bytes.Equal(stakeStatus.CurrentChallenge.Bytes(), common.BigToAddress(common.Big0).Bytes()) { + // did not create challenge + createdCh <- &bindings.RollupAssertionCreated{ + AssertionID: stakeStatus.AssertionID, + AsserterAddr: v.Rollup.TransactOpts.From, + VmHash: currentAssertion.StateHash, + InboxSize: currentAssertion.InboxSize, + } + } else if challengeContext.Completed { + // already challenged do nothing + v.challengeResoutionCh <- struct{}{} + log.Info("Challenge already completed") + } else { + // in bisectedCh + challengedCh <- &bindings.RollupAssertionChallenged{ + AssertionID: ctx.OpponentAssertion.ID, + ChallengeAddr: stakeStatus.CurrentChallenge, + } + restart = true + } + } + }() + + for { + if inChallenge { + select { + case ev := <-bisectedCh: + // case get bisection, if is our turn + // 1. In single step, submit proof + // 2. In multiple step, track current segment, update + log.Info("Validator saw new bisection coming...") + responder, err := challengeSession.CurrentResponder() + if err != nil { + // TODO: error handling + log.Error("Can not get current responder", "error", err) + continue + } + // If it's our turn + log.Info("Responder info...", "responder", responder, "staker", v.Config.StakeAddr) + if common.Address(responder) == v.Config.StakeAddr { + log.Info("Validator start to respond new bisection...") + err := services.RespondBisection(v.BaseService, challengeSession, ev, states) + if err != nil { + // TODO: error handling + log.Error("Can not respond to bisection", "error", err) + continue + } + } else { + log.Info("Validator check bisection respond time left...") + opponentTimeLeft, err := challengeSession.CurrentResponderTimeLeft() + if err != nil { + // TODO: error handling + log.Error("Can not get current responder left time", "error", err) + continue + } + log.Info("[challenge] Opponent time left", "time", opponentTimeLeft) + opponentTimeoutBlock = ev.Raw.BlockNumber + opponentTimeLeft.Uint64() + } + case header := <-headCh: + if opponentTimeoutBlock == 0 { + continue + } + // TODO: can we use >= here? + if header.Number.Uint64() > opponentTimeoutBlock { + _, err := challengeSession.Timeout() + if err != nil { + log.Error("Can not timeout opponent", "error", err) + continue + // TODO: wait some time before retry + // TODO: fix race condition + } + } + case ev := <-challengeCompletedCh: + // TODO: handle if we are not winner --> state corrupted + log.Info("[challenge] Challenge completed", "winner", ev.Winner) + bisectedSub.Unsubscribe() + challengeCompletedSub.Unsubscribe() + states = []*proof.ExecutionState{} + inChallenge = false + v.challengeResoutionCh <- struct{}{} + case <-v.Ctx.Done(): + bisectedSub.Unsubscribe() + challengeCompletedSub.Unsubscribe() + return + } + } else { + select { + case ctx = <-v.challengeCh: + log.Info("Validator get challenge context, create challenge assertion") + + _, err = v.Rollup.CreateAssertion( + ctx.OurAssertion.VmHash, + ctx.OurAssertion.InboxSize, + ) + if err != nil { + log.Error("UNHANDELED: Can't create assertion for challenge, validator state corrupted", "err", err) + v.challengeCh <- ctx + continue + } + case ev := <-createdCh: + if common.Address(ev.AsserterAddr) == v.Config.StakeAddr { + if ev.VmHash == ctx.OurAssertion.VmHash { + log.Info("Assertion ID", "opponentAssertion.ID", ctx.OpponentAssertion.ID, "ev.AssertionID", ev.AssertionID) + _, err := v.Rollup.ChallengeAssertion( + [2]ethcommon.Address{ + ethcommon.Address(v.Config.SequencerAddr), + ethcommon.Address(v.Config.StakeAddr), + }, + [2]*big.Int{ + ctx.OpponentAssertion.ID, + ev.AssertionID, + }, + ) + if err != nil { + log.Error("UNHANDELED: Can't start challenge, validator state corrupted", "err", err) + createdCh <- ev + continue + } + } + } + case ev := <-challengedCh: + if ctx == nil { + continue + } + log.Info("Validator saw new challenge", "assertion id", ev.AssertionID, "expected id", ctx.OpponentAssertion.ID, "block", ev.Raw.BlockNumber) + if ev.AssertionID.Cmp(ctx.OpponentAssertion.ID) == 0 { + challenge, err := bindings.NewChallenge(ev.ChallengeAddr, v.L1) + if err != nil { + log.Error("Failed to access ongoing challenge", "address", ev.ChallengeAddr, "err", err) + challengedCh <- ev + continue + } + challengeSession = &bindings.ChallengeSession{ + Contract: challenge, + CallOpts: bind.CallOpts{Pending: true, Context: v.Ctx}, + TransactOpts: *v.TransactOpts, + } + bisectedSub, err = challenge.WatchBisected(&bind.WatchOpts{Context: v.Ctx}, bisectedCh) + if err != nil { + log.Error("Failed to watch challenge event", "err", err) + challengedCh <- ev + continue + } + challengeCompletedSub, err = challenge.WatchChallengeCompleted(&bind.WatchOpts{Context: v.Ctx}, challengeCompletedCh) + if err != nil { + log.Error("Failed to watch challenge event", "err", err) + challengedCh <- ev + continue + } + parentAssertion, err := ctx.OurAssertion.GetParentAssertion(v.AssertionMap) + if err != nil { + log.Error("Failed to watch challenge event", "err", err) + challengedCh <- ev + continue + } + log.Info("Validator start to GenerateStates", "parentAssertion.InboxSize", parentAssertion.InboxSize.Uint64(), "ctx.ourAssertion.InboxSize", ctx.OurAssertion.InboxSize.Uint64()) + states, err = proof.GenerateStates( + v.ProofBackend, + v.Ctx, + parentAssertion.InboxSize.Uint64(), + ctx.OurAssertion.InboxSize.Uint64(), + nil, + ) + log.Info("Validator generate states end...") + if err != nil { + log.Error("Failed to generate states", "err", err) + challengedCh <- ev + continue + } + log.Info("Print generated states", "states[0]", states[0].Hash().String(), "states[numSteps]", states[len(states)-1].Hash().String()) + + if restart { + curr, err := challengeSession.CurrentBisected() + if err != nil { + log.Error("Failed to get current bisected", "err", err) + challengedCh <- ev + continue + } + bisectedCh <- &bindings.ChallengeBisected{ + StartState: curr.StartState, + MidState: curr.MidState, + EndState: curr.EndState, + BlockNum: curr.BlockNum, + BlockTime: curr.BlockTime, + ChallengedSegmentStart: curr.ChallengedSegmentStart, + ChallengedSegmentLength: curr.ChallengedSegmentLength, + } + restart = false + } + + inChallenge = true + } + case <-headCh: + continue // consume channel values + case <-v.Ctx.Done(): + return + } + } + } +} + +func (v *Validator) Start() error { + genesis := v.BaseService.Start(true, true) + + v.Wg.Add(2) + go v.validationLoop(genesis.Root()) + go v.challengeLoop() + log.Info("Validator started") + return nil +} + +func (v *Validator) Stop() error { + log.Info("Validator stopped") + v.Cancel() + v.Wg.Wait() + return nil +} + +func (v *Validator) APIs() []rpc.API { + // TODO: validator APIs + return []rpc.API{} +} diff --git a/fraud-proof/rollup/types/assertion.go b/fraud-proof/rollup/types/assertion.go new file mode 100644 index 000000000..a3bef8a94 --- /dev/null +++ b/fraud-proof/rollup/types/assertion.go @@ -0,0 +1,42 @@ +package types + +import ( + "math/big" + + "github.com/mantlenetworkio/mantle/fraud-proof/bindings" + "github.com/mantlenetworkio/mantle/l2geth/common" +) + +// Assertion represents disputable assertion for L1 rollup contract +type Assertion struct { + ID *big.Int + VmHash common.Hash + InboxSize *big.Int + Parent *big.Int + Deadline *big.Int + ProposalTime *big.Int +} + +func (a *Assertion) Copy() *Assertion { + return &Assertion{ + ID: new(big.Int).Set(a.ID), + VmHash: a.VmHash, + InboxSize: new(big.Int).Set(a.InboxSize), + Deadline: new(big.Int).Set(a.Deadline), + } +} + +func (a *Assertion) GetParentAssertion(assertionMap *bindings.AssertionMapCallerSession) (*Assertion, error) { + ret, err := assertionMap.Assertions(a.Parent) + if err != nil { + return nil, err + } + return &Assertion{ + ID: a.Parent, + VmHash: ret.StateHash, + InboxSize: ret.InboxSize, + Parent: ret.Parent, + Deadline: ret.Deadline, + ProposalTime: ret.ProposalTime, + }, nil +} diff --git a/fraud-proof/rollup/types/staker.go b/fraud-proof/rollup/types/staker.go new file mode 100644 index 000000000..d7a28c73a --- /dev/null +++ b/fraud-proof/rollup/types/staker.go @@ -0,0 +1,15 @@ +package types + +import ( + "math/big" + + "github.com/ethereum/go-ethereum/common" +) + +// Staker represents fraud-proof assertion stake status +type Staker struct { + IsStaked bool + AmountStaked *big.Int + AssertionID *big.Int + CurrentChallenge common.Address +} diff --git a/fraud-proof/rollup/types/tx_batch.go b/fraud-proof/rollup/types/tx_batch.go new file mode 100644 index 000000000..d61882f83 --- /dev/null +++ b/fraud-proof/rollup/types/tx_batch.go @@ -0,0 +1,162 @@ +package types + +import ( + "bytes" + "encoding/binary" + "errors" + "math/big" + + "github.com/mantlenetworkio/mantle/l2geth/common" + "github.com/mantlenetworkio/mantle/l2geth/core/types" + "github.com/mantlenetworkio/mantle/l2geth/rlp" +) + +// TxBatch represents a transaction batch to be sequenced to L1 sequencer inbox +// It may contain multiple blocks +type TxBatch struct { + Blocks types.Blocks + Contexts []SequenceContext + Txs types.Transactions + GasUsed *big.Int +} + +// SequenceContext is the relavent context of each block sequenced to L1 sequncer inbox +type SequenceContext struct { + NumTxs uint64 + BlockNumber uint64 + Timestamp uint64 +} + +func NewTxBatch(blocks []*types.Block, maxBatchSize uint64) *TxBatch { + // TODO: handle maxBatchSize constraint + var contexts []SequenceContext + var txs []*types.Transaction + gasUsed := new(big.Int) + for _, block := range blocks { + blockTxs := block.Transactions() + ctx := SequenceContext{ + NumTxs: uint64(len(blockTxs)), + BlockNumber: block.Number().Uint64(), // TODO just use bigint + Timestamp: block.Time(), + } + contexts = append(contexts, ctx) + txs = append(txs, blockTxs...) + gasUsed.Add(gasUsed, new(big.Int).SetUint64(block.GasUsed())) + } + return &TxBatch{blocks, contexts, txs, gasUsed} +} + +func (b *TxBatch) LastBlockNumber() uint64 { + return b.Contexts[len(b.Contexts)-1].BlockNumber +} + +func (b *TxBatch) LastBlockRoot() common.Hash { + return b.Blocks[len(b.Blocks)-1].Root() +} + +func (b *TxBatch) InboxSize() *big.Int { + return new(big.Int).SetUint64(uint64(b.Txs.Len())) +} + +func (b *TxBatch) SerializeToArgs() ([]*big.Int, []*big.Int, []byte, error) { + var contexts, txLengths []*big.Int + for _, ctx := range b.Contexts { + contexts = append(contexts, big.NewInt(0).SetUint64(ctx.NumTxs)) + contexts = append(contexts, big.NewInt(0).SetUint64(ctx.BlockNumber)) + contexts = append(contexts, big.NewInt(0).SetUint64(ctx.Timestamp)) + } + + buf := new(bytes.Buffer) + for _, tx := range b.Txs { + curLen := buf.Len() + if err := writeTx(buf, tx); err != nil { + return nil, nil, nil, err + } + txLengths = append(txLengths, big.NewInt(int64(buf.Len()-curLen))) + } + return contexts, txLengths, buf.Bytes(), nil +} + +func (b *TxBatch) ToAssertion(parent *Assertion) *Assertion { + return &Assertion{ + ID: new(big.Int).Add(parent.ID, big.NewInt(1)), + VmHash: b.LastBlockRoot(), + InboxSize: big.NewInt(int64(b.LastBlockNumber())), // TODO-FIXME uint64 -> int64 -> big.Int + Parent: parent.ID, + } +} + +func writeContext(w *bytes.Buffer, ctx *SequenceContext) error { + if err := writePrimitive(w, ctx.NumTxs); err != nil { + return err + } + if err := writePrimitive(w, ctx.BlockNumber); err != nil { + return err + } + return writePrimitive(w, ctx.Timestamp) +} + +func writeTx(w *bytes.Buffer, tx *types.Transaction) error { + var txBuf bytes.Buffer + if err := tx.EncodeRLP(&txBuf); err != nil { + return err + } + txBytes := txBuf.Bytes() + _, err := w.Write(txBytes) + return err +} + +func writePrimitive(w *bytes.Buffer, data interface{}) error { + return binary.Write(w, binary.BigEndian, data) +} + +var TxBatchParseFailedError = errors.New("Failed to create TxBatch from decoded tx data") + +// TxBatchFromDecoded decodes the input of SequencerInbox#appendTxBatch call +// It will only fill Contexts and Txs fields +func TxBatchFromDecoded(decoded []interface{}) (*TxBatch, error) { + if len(decoded) != 3 { + return nil, TxBatchParseFailedError + } + contexts := decoded[0].([]*big.Int) + txLengths := decoded[1].([]*big.Int) + txBatch := decoded[2].([]byte) + blockNum := len(txLengths) + if len(contexts) != 3*blockNum { + return nil, TxBatchParseFailedError + } + var txs []*types.Transaction + var ctxs []SequenceContext + var txLen uint64 = 0 + for idx, l := range txLengths { + length := l.Uint64() + if uint64(len(txBatch)) < txLen+length { + return nil, TxBatchParseFailedError + } + ctx := SequenceContext{ + NumTxs: contexts[3*idx].Uint64(), + BlockNumber: contexts[3*idx+1].Uint64(), + Timestamp: contexts[3*idx+2].Uint64(), + } + raw := txBatch[txLen : txLen+length] + var tx types.Transaction + err := rlp.DecodeBytes(raw, &tx) + if err != nil { + return nil, err + } + ctxs = append(ctxs, ctx) + txs = append(txs, &tx) + } + batch := &TxBatch{ + Contexts: ctxs, + Txs: txs, + } + return batch, nil +} + +// SequenceBlock is a block sequenced to L1 sequencer inbox +// It is used by validators to reconstruct L2 chain from L1 activities +type SequenceBlock struct { + SequenceContext + Txs types.Transactions +} diff --git a/fraud-proof/service.go b/fraud-proof/service.go new file mode 100644 index 000000000..cab9c4e50 --- /dev/null +++ b/fraud-proof/service.go @@ -0,0 +1,58 @@ +package rollup + +import ( + "bytes" + "math/big" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + + "github.com/mantlenetworkio/mantle/fraud-proof/rollup/services" + "github.com/mantlenetworkio/mantle/fraud-proof/rollup/services/sequencer" + "github.com/mantlenetworkio/mantle/fraud-proof/rollup/services/validator" + "github.com/mantlenetworkio/mantle/l2geth/accounts" + "github.com/mantlenetworkio/mantle/l2geth/accounts/keystore" + "github.com/mantlenetworkio/mantle/l2geth/eth" + "github.com/mantlenetworkio/mantle/l2geth/log" + "github.com/mantlenetworkio/mantle/l2geth/node" +) + +// RegisterFraudProofService registers rollup service configured by ctx +// Either a sequncer service or a validator service will be registered +func RegisterFraudProofService(stack *node.Node, cfg *services.Config) { + // Unlock account for L1 transaction signer + var ks *keystore.KeyStore + if keystores := stack.AccountManager().Backends(keystore.KeyStoreType); len(keystores) > 0 { + ks = keystores[0].(*keystore.KeyStore) + } + if ks == nil { + log.Crit("Failed to register the Rollup service: keystore not found") + } + chainID := big.NewInt(int64(cfg.L1ChainID)) + json, err := ks.Export(accounts.Account{Address: cfg.StakeAddr}, cfg.Passphrase, cfg.Passphrase) + if err != nil { + log.Crit("Failed to register the Rollup service", "err", err) + } + auth, err := bind.NewTransactorWithChainID(bytes.NewReader(json), cfg.Passphrase, chainID) + if err != nil { + log.Crit("Failed to register the Rollup service", "err", err) + } + + var ethService *eth.Ethereum + if err := stack.Service(ðService); err != nil { + log.Crit("Failed to retrieve eth service backend", "err", err) + } + + // Register services + log.Info("Print log type", "cfg.Node", cfg.Node) + if cfg.Node == services.NODE_SCHEDULER { + log.Info("Start NODE_SCHEDULER...") + sequencer.RegisterService(ethService, ethService.APIBackend, cfg, auth) + log.Info("Start NODE_SCHEDULER end...") + } else if cfg.Node == services.NODE_VERIFIER { + log.Info("Start NODE_VERIFIER...") + validator.RegisterService(ethService, ethService.APIBackend, cfg, auth) + log.Info("Start NODE_VERIFIER end...") + } else { + log.Crit("Failed to register the Rollup service: Node type unkown", "type", cfg.Node) + } +} diff --git a/fraud-proof/service_test.go b/fraud-proof/service_test.go new file mode 100644 index 000000000..ab4c326c7 --- /dev/null +++ b/fraud-proof/service_test.go @@ -0,0 +1,33 @@ +package rollup + +import ( + "os" + "strconv" + "testing" + "time" +) + +func TestRuntimeEnv(t *testing.T) { + go func() { + for true { + value := os.Getenv("test") + t.Log("value is: ", value) + time.Sleep(1 * time.Second) + } + }() + + go func() { + count := 0 + ticker := time.NewTicker(2 * time.Second) + for true { + select { + case <-ticker.C: + count++ + os.Setenv("test", strconv.Itoa(count)) + } + } + }() + + errChan := make(chan struct{}) + <-errChan +} diff --git a/go.work b/go.work index 9e2402211..ccee15b71 100644 --- a/go.work +++ b/go.work @@ -9,9 +9,10 @@ use ( ./l2geth-exporter ./proxyd ./state-surgery - integration-tests/go-tests + ./integration-tests/go-tests ./tss ./mt-batcher + ./fraud-proof ./mt-challenger ) diff --git a/go.work.sum b/go.work.sum index 15336eb0f..4b28f45f4 100644 --- a/go.work.sum +++ b/go.work.sum @@ -30,6 +30,7 @@ github.com/BurntSushi/toml v1.1.0 h1:ksErzDEI1khOiGPgpwuI7x2ebx/uXQNw7xJpn9Eq1+I github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/toml v1.2.0 h1:Rt8g24XnyGTyglgET/PRUNlrUeu9F5L+7FilkXfZgs0= github.com/BurntSushi/toml v1.2.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802 h1:1BDTz0u9nC3//pOCMdNH+CiXJVYJh5UQNCOBG7jbELc= github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQcITbvhmL4+C4cKA87NW0tfm3Kl9VXRoPywFg= github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 h1:sR+/8Yb4slttB4vD+b9btVEnWgL3Q00OBTzVT8B9C0c= @@ -97,102 +98,27 @@ github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEe github.com/cenkalti/backoff/v4 v4.1.1 h1:G2HAfAmvm/GcKan2oOQpBXOd2tT2G57ZnZGWa1PxPBQ= github.com/census-instrumentation/opencensus-proto v0.3.0 h1:t/LhUZLVitR1Ow2YOnduCsavhwFUklBMoGVYUCqmCqk= github.com/checkpoint-restore/go-criu/v5 v5.0.0 h1:TW8f/UvntYoVDMN1K2HlT82qH1rb0sOjpGw3m6Ym+i4= +github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE= github.com/cheekybits/is v0.0.0-20150225183255-68e9c0620927 h1:SKI1/fuSdodxmNNyVBR8d7X/HuLnRpvvFO0AgyQk764= github.com/cheekybits/is v0.0.0-20150225183255-68e9c0620927/go.mod h1:h/aW8ynjgkuj+NQRlZcDbAbM1ORAbXjXX77sX7T289U= github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE= github.com/chzyer/logex v1.2.0/go.mod h1:9+9sk7u7pGNWYMkh0hdiL++6OeibzJccyQU4p4MedaY= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8= github.com/chzyer/readline v1.5.0/go.mod h1:x22KAscuvRqlLoK9CsoYsmxoXZMMFVyOl86cAH8qUic= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 h1:q763qf9huN11kDQavWsoZXJNW3xEE4JJyHa5Q25/sd8= github.com/chzyer/test v0.0.0-20210722231415-061457976a23/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/cilium/ebpf v0.6.2 h1:iHsfF/t4aW4heW2YKfeHrVPGdtYTL4C4KocpM8KTSnI= -github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible h1:C29Ae4G5GtYyYMm1aztcyj/J5ckgJm2zwdDajFbx1NY= -github.com/circonus-labs/circonusllhist v0.1.3 h1:TJH+oke8D16535+jHExHj4nQvzlZrj7ug5D7I/orNUA= -github.com/clbanning/mxj v1.8.4 h1:HuhwZtbyvyOw+3Z1AowPkU87JkJUSv751ELWaiTpj8I= -github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec h1:EdRZT3IeKQmfCSrgo8SZ8V3MEnskuJP0wCYNpe+aiXo= -github.com/client9/misspell v0.3.4 h1:ta993UF76GwbvJcIo3Y68y/M3WxlpEHPWIGDkJYwzJI= -github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4 h1:hzAQntlaYRkVSFEfj9OTWlVV1H155FMD8BTKktLv0QI= -github.com/cncf/xds/go v0.0.0-20211130200136-a8f946100490 h1:KwaoQzs/WeUxxJqiJsZ4euOly1Az/IgZXXSxlD/UBNk= -github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa h1:OaNxuTZr7kxeODyLWsRMC+OD03aFUH+mW6r2d+MWa5Y= -github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd h1:qMd81Ts1T2OTKmB4acZcyKaMtRnY5Y44NuXGX2GFJ1w= -github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0 h1:sDMmm+q/3+BukdIpxwO365v/Rbspp2Nt5XntgQRXq8Q= -github.com/containerd/console v1.0.2 h1:Pi6D+aZXM+oUw1czuKgH5IJ+y0jhYcwBJfx5/Ghn9dE= -github.com/containerd/continuity v0.2.1 h1:/EeEo2EtN3umhbbgCveyjifoMYg0pS+nMMEemaYw634= -github.com/coreos/bbolt v1.3.2 h1:wZwiHHUieZCquLkDL0B8UhzreNWsPHooDAG3q34zk0s= -github.com/coreos/etcd v3.3.10+incompatible h1:jFneRYjIvLMLhDLCzuTuU4rSJUjRplcJQ7pD7MnhC04= -github.com/coreos/go-etcd v2.0.0+incompatible h1:bXhRBIXoTm9BYHS3gE0TtQuyNZyeEMux2sDi4oo5YOo= -github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d h1:t5Wuyh53qYyg9eqn4BbnlIT+vmhyww0TatL+zT3uWgI= -github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e h1:Wf6HqHfScWJN9/ZjdUKyjop4mf3Qdd+1TvvltAvM3m8= -github.com/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534 h1:rtAn27wIbmOGUs7RIbVgPEjb31ehTVniDwPGXyMxm5U= -github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f h1:lBNOc5arjvs8E5mO2tbpBpLoyyu8B6e44T7hJy6potg= -github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d h1:49RLWk1j44Xu4fjHb6JFYmeUnDORVwHNkDxaQ0ctCVU= github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk= -github.com/creack/pty v1.1.9 h1:uDmaGzcdjhF4i/plgjmEsriH11Y0o7RKapEf/LDaM3w= -github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c h1:/ovYnF02fwL0kvspmy9AuyKg1JhdTRUgPw4nUxd9oZM= -github.com/cyphar/filepath-securejoin v0.2.2 h1:jCwT2GTP+PY5nBz3c/YL5PAIbusElVrPujOBSCj8xRg= -github.com/dave/jennifer v1.2.0 h1:S15ZkFMRoJ36mGAQgWL1tnr0NQJh9rZ8qatseX/VbBc= -github.com/decred/dcrd/lru v1.0.0 h1:Kbsb1SFDsIlaupWPwsPp+dkxiBY1frcS07PCPgotKz8= -github.com/dgraph-io/badger v1.6.2 h1:mNw0qs90GVgGGWylh0umH5iag1j6n/PeJtNvL6KY/x8= -github.com/dgraph-io/badger/v2 v2.2007.4 h1:TRWBQg8UrlUhaFdco01nO2uXwzKS7zd+HVdwV/GHc4o= -github.com/dgraph-io/ristretto v0.0.3-0.20200630154024-f66de99634de h1:t0UHb5vdojIDUqktM6+xJAfScFBsVpXZmqC9dsgJmeA= -github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= -github.com/dgryski/go-bitstream v0.0.0-20180413035011-3522498ce2c8 h1:akOQj8IVgoeFfBTzGOEQakCYshWD6RNo1M5pivFXt70= -github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczCTSixgIKmwPv6+wP5DGjqLYw5SUiA= -github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954 h1:RMLoZVzv4GliuWafOuPuQDKSm1SJph7uCRnnS61JAn4= -github.com/djherbis/atime v1.1.0 h1:rgwVbP/5by8BvvjBNrbh64Qz33idKT3pSnMSJsxhi0g= github.com/djherbis/atime v1.1.0/go.mod h1:28OF6Y8s3NQWwacXc5eZTsEsiMzp7LF8MbXE+XJPdBE= -github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91 h1:Izz0+t1Z5nI16/II7vuEo/nHjodOg0p7+OiDpjX5t1E= -github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI= github.com/docker/docker v1.6.2/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= -github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= -github.com/dop251/goja v0.0.0-20220405120441-9037c2b61cbf h1:Yt+4K30SdjOkRoRRm3vYNQgR+/ZIy0RmeUDZo7Y8zeQ= github.com/dop251/goja v0.0.0-20220405120441-9037c2b61cbf/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk= -github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7 h1:tYwu/z8Y0NkkzGEh3z21mSWggMg4LwLRFucLS7TjARg= -github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= -github.com/eapache/go-resiliency v1.1.0 h1:1NtRmCAqadE2FN4ZcN6g90TP3uk8cg9rn9eNK2197aU= -github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21 h1:YEetp8/yCZMuEPMUDHG0CW/brkkEp8mzqk2+ODEitlw= -github.com/eapache/queue v1.1.0 h1:YOEu7KNc61ntiQlcEeUIoDTJ2o8mQznoNvUhiigpIqc= -github.com/eclipse/paho.mqtt.golang v1.2.0 h1:1F8mhG9+aO5/xpdtFkW4SxOJB67ukuDC3t2y2qayIX0= -github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385 h1:clC1lXBpe2kTj2VHdaIu9ajZQe4kcEY9j0NsnDDBZ3o= -github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1 h1:xvqufLtNVwAhN8NMyWklVgxnWohi+wtMGQMhtxexlm0= github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= -github.com/envoyproxy/protoc-gen-validate v0.6.2 h1:JiO+kJTpmYGjEodY7O1Zk8oZcNz1+f30UtwtXoFUPzE= -github.com/etcd-io/bbolt v1.3.3 h1:gSJmxrs37LgTqR/oyJBWok6k6SvXEUerFTbltIhXkBM= -github.com/facebookgo/ensure v0.0.0-20160127193407-b4ab57deab51 h1:0JZ+dUmQeA8IIVUMzysrX4/AKuQwWhV2dYQuPZdvdSQ= -github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 h1:JWuenKqqX8nojtoVVWjGfOF9635RETekkoH6Cc9SX0A= -github.com/facebookgo/subset v0.0.0-20150612182917-8dac2c3c4870 h1:E2s37DuLxFhQDg5gKsWoLBOB0n+ZW8s599zru8FJ2/Y= -github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072 h1:DddqAaWDpywytcG8w/qoQ5sAN8X12d3Z3koB0C3Rxsc= github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= -github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= -github.com/fjl/gencodec v0.0.0-20220412091415-8bb9e558978c h1:CndMRAH4JIwxbW8KYq6Q+cGWcGHz0FjGR3QqcInWcW0= github.com/fjl/gencodec v0.0.0-20220412091415-8bb9e558978c/go.mod h1:AzA8Lj6YtixmJWL+wkKoBGsLWy9gFrAzi4g+5bCKwpY= -github.com/flosch/pongo2/v4 v4.0.2 h1:gv+5Pe3vaSVmiJvh/BZa82b7/00YUGm0PIyVVLop0Hw= github.com/flosch/pongo2/v4 v4.0.2/go.mod h1:B5ObFANs/36VwxxlgKpdchIJHMvHB562PW+BWPhwZD8= -github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjrss6TZTdY2VfCqZPbv5k3iBFa2ZQ= -github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90 h1:WXb3TSNmHp2vHoCroCIB1foO/yQ36swABL8aOVeDpgg= -github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= -github.com/franela/goblin v0.0.0-20210519012713-85d372ac71e2 h1:cZqz+yOJ/R64LcKjNQOdARott/jP7BnUQ9Ah7KaZCvw= -github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8 h1:a9ENSRDFBUPkJ5lCgVZh26+ZbGyoVJG7yb5SSzF5H54= -github.com/garslo/gogen v0.0.0-20170306192744-1d203ffc1f61 h1:IZqZOB2fydHte3kUgxrzK5E1fW7RQGeDwE8F/ZZnUYc= github.com/garslo/gogen v0.0.0-20170306192744-1d203ffc1f61/go.mod h1:Q0X6pkwTILDlzrGEckF6HKjXe48EgsY/l7K7vhY4MW8= -github.com/gavv/httpexpect v2.0.0+incompatible h1:1X9kcRshkSKEjNJJxX9Y9mQ5BRfbxU5kORdjhlA1yX8= -github.com/getkin/kin-openapi v0.61.0 h1:6awGqF5nG5zkVpMsAih1QH4VgzS8phTxECUWIFo7zko= -github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= +github.com/getsentry/sentry-go v0.15.0 h1:CP9bmA7pralrVUedYZsmIHWpq/pBtXTSew7xvVpfLaA= +github.com/getsentry/sentry-go v0.15.0/go.mod h1:RZPJKSw+adu8PBNygiri/A98FqVr2HtRckJk9XVxJ9I= github.com/gin-gonic/gin v1.8.1 h1:4+fr/el88TOO3ewCmQr8cx/CtZ/umlIRIs5M4NTNjf8= github.com/gin-gonic/gin v1.8.1/go.mod h1:ji8BvRH1azfM+SYow9zQ6SZMvR8qOMZHmsCuWR9tTTk= -github.com/gliderlabs/ssh v0.1.1 h1:j3L6gSLQalDETeEg/Jg0mGY0/y/N6zI2xX1978P0Uqw= -github.com/glycerine/go-unsnap-stream v0.0.0-20180323001048-9f0cb55181dd h1:r04MMPyLHj/QwZuMJ5+7tJcBr1AQjpiAK/rZWRrQT7o= -github.com/glycerine/goconvey v0.0.0-20190410193231-58a59202ab31 h1:gclg6gY70GLy3PbkQ1AERPfmLMMagS60DKF78eWwLn8= -github.com/go-check/check v0.0.0-20180628173108-788fd7840127 h1:0gkP6mzaMqkmpcJYCFOLkIBwI7xFExG03bbkOkCvUPI= -github.com/go-chi/chi/v5 v5.0.0 h1:DBPx88FjZJH3FsICfDAfIfnb7XxKIYVGG6lOPlhENAg= github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1 h1:QbL/5oDUmRBzO9/Z7Seo6zf912W/a6Sr4Eu0G/3Jho0= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4 h1:WtGNWLvXpe6ZudgnXrq0barxBImvnnJoMEhXAzcbM0I= -github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab h1:xveKWz2iaueeTaUgdetzel+U7exyigDYBryyVfV/rZk= -github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY= -github.com/go-openapi/swag v0.19.5 h1:lTz6Ys4CmqqCQmZPBlbQENR1/GucA2bzYTE12Pw4tFY= github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU= github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs= github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho= @@ -202,382 +128,72 @@ github.com/go-playground/validator/v10 v10.11.1 h1:prmOlTVv+YjZjmRmNSF3VmspqJIxJ github.com/go-playground/validator/v10 v10.11.1/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU= github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI= github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo= -github.com/go-sourcemap/sourcemap v2.1.3+incompatible h1:W1iEw64niKVGogNgBN3ePyLFfuisuzeidWPMPWmECqU= -github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= -github.com/go-zookeeper/zk v1.0.2 h1:4mx0EYENAdX/B/rbunjlt5+4RTA/a9SMHBRuSKdGxPM= -github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU= -github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og= -github.com/gobwas/ws v1.1.0 h1:7RFti/xnNkMJnrK7D1yQ/iCIB5OrrY/54/H930kIbHA= github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= -github.com/goccy/go-json v0.9.11 h1:/pAaQDLHEoCq/5FFmSKBswWmK6H0e8g4159Kc/X/nqk= github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= -github.com/godbus/dbus/v5 v5.0.4 h1:9349emZab16e7zQvpmsbtjc18ykshndd8y2PG3sgJbA= -github.com/gofrs/uuid v3.3.0+incompatible h1:8K4tyRfvU1CYPgJsveYFQMhpFd/wXNM7iK6rR7UHz84= -github.com/gogo/googleapis v1.1.0 h1:kFkMAZBNAn4j7K0GiZr8cRYzejq68VbheufiV3YuyFI= -github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g= -github.com/golang/geo v0.0.0-20190916061304-5b978397cfec h1:lJwO/92dFXWeXOZdoGXgptLmNLwynMSHUmU6besqtiw= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= -github.com/golang/lint v0.0.0-20180702182130-06c8688daad7 h1:2hRPrmiwPrp3fQX967rNJIhQPtiGXdlQWAxKbKw3VHA= -github.com/golangci/lint-1 v0.0.0-20181222135242-d2cdd8c08219 h1:utua3L2IbQJmauC5IXdEA547bcoU5dozgQAfc8Onsg4= -github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo= -github.com/google/flatbuffers v1.11.0 h1:O7CEyB8Cb3/DmtxODGtLHcEvpr81Jm5qLg/hsHnxA2A= -github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= -github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY= -github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= -github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa h1:Q75Upo5UN4JbPFURXZ8nLKYUvF85dyFRop/vQ0Rv+64= -github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no= -github.com/google/martian/v3 v3.2.1 h1:d8MncMlErDFTwQGBK1xhv026j9kqhvw1Qv9IbWT1VLQ= -github.com/google/orderedcode v0.0.1 h1:UzfcAexk9Vhv8+9pNOgRu41f16lHq725vPwnSeiG/Us= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec= -github.com/google/renameio v0.1.0 h1:GOZbcHa3HfsPKPlmyPyN2KEohoMXOhdMbHrvbpl2QaA= -github.com/google/subcommands v1.2.0 h1:vWQspBTo2nEqTUFita5/KeEWlUL8kQObDFbub/EN9oE= -github.com/googleapis/gax-go v2.0.0+incompatible h1:j0GKcs05QVmm7yesiZq2+9cxHkNK9YM6zKx4D2qucQU= -github.com/googleapis/gax-go/v2 v2.1.1 h1:dp3bWCh+PPO1zjRRiCSczJav13sBvG4UhNyVTa1KqdU= -github.com/googleapis/gax-go/v2 v2.2.0/go.mod h1:as02EH8zWkzwUoLbBaFeQ+arQaj/OthfcblKl4IGNaM= -github.com/googleapis/gax-go/v2 v2.3.0/go.mod h1:b8LNqSzNabLiUpXKkY7HAR5jr6bIT99EXz9pXxye9YM= -github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK9wbMD5+iXC6c= -github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8 h1:tlyzajkF3030q6M8SvmJSemC9DTHL/xaMa18b65+JM4= -github.com/gopherjs/gopherjs v1.17.2 h1:fQnZVsXk8uxXIStYb0N4bGk7jeyTalG/wsZjQ25dO0g= -github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8= -github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY= github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c= -github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ= -github.com/gotestyourself/gotestyourself v2.2.0+incompatible h1:AQwinXlbQR2HvPjQZOmDhRqsv5mZf+Jb1RnSLxcqZcI= -github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 h1:pdN6V1QBWetyv/0+wjACpqVH+eVULgEjkurDLq3goeM= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4 h1:z53tR0945TRRQO/fLEVPI6SMv7ZflF0TEaTAoU7tOzg= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= -github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= -github.com/gtank/merlin v0.1.1 h1:eQ90iG7K9pOhtereWsmyRJ6RAwcP4tHTDBHXNg+u5is= -github.com/gtank/ristretto255 v0.1.2 h1:JEqUCPA1NvLq5DwYtuzigd7ss8fwbYay9fi4/5uMzcc= -github.com/gxed/hashland/keccakpg v0.0.1 h1:wrk3uMNaMxbXiHibbPO4S0ymqJMm41WiudyFSs7UnsU= -github.com/gxed/hashland/murmur3 v0.0.1 h1:SheiaIt0sda5K+8FLz952/1iWS9zrnKsEJaOJu4ZbSc= -github.com/hashicorp/consul/api v1.12.0 h1:k3y1FYv6nuKyNTqj6w9gXOx5r5CfLj/k/euUeBXj1OY= -github.com/hashicorp/consul/sdk v0.8.0 h1:OJtKBtEjboEZvG6AOUdh4Z1Zbyu0WcxQ0qatRrZHTVU= -github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= -github.com/hashicorp/go-hclog v1.0.0 h1:bkKf0BeBXcSYa7f5Fyi9gMuQ8gNsxeiNpZjR6VxNZeo= -github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc= -github.com/hashicorp/go-msgpack v0.5.3 h1:zKjpN5BK/P5lMYrLmBHdBULWbJ0XpYR+7NGzqkZzoD4= -github.com/hashicorp/go-retryablehttp v0.5.3 h1:QlWt0KvWT0lq8MFppF9tsJGF+ynG7ztc2KIPhzRGk7s= -github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc= -github.com/hashicorp/go-sockaddr v1.0.0 h1:GeH6tui99pF4NJgfnhp+L6+FfobzVW3Ah46sLo0ICXs= -github.com/hashicorp/go-syslog v1.0.0 h1:KaodqZuhUoZereWVIYmpUgZysurB1kBLX2j0MwMrUAE= -github.com/hashicorp/go-uuid v1.0.1 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1BE= -github.com/hashicorp/go-version v1.2.0 h1:3vNe/fWF5CBgRIguda1meWhsZHy3m8gCJ5wx+dIzX/E= -github.com/hashicorp/go.net v0.0.1 h1:sNCoNyDEvN1xa+X0baata4RdcpKwcMS6DH+xwfqPgjw= -github.com/hashicorp/logutils v1.0.0 h1:dLEQVugN8vlakKOUE3ihGLTZJRB4j+M2cdTm/ORI65Y= -github.com/hashicorp/mdns v1.0.4 h1:sY0CMhFmjIPDMlTB+HfymFHCaYLhgifZ0QhjaYKD/UQ= -github.com/hashicorp/memberlist v0.3.0 h1:8+567mCcFDnS5ADl7lrpxPMWiFCElyUEeW0gtj34fMA= -github.com/hashicorp/serf v0.9.6 h1:uuEX1kLR6aoda1TBttmJQKDLZE1Ob7KN0NPdE7EtCDc= -github.com/herumi/bls-eth-go-binary v0.0.0-20210302070600-dfaa902c7773/go.mod h1:luAnRm3OsMQeokhGzpYmc0ZKwawY7o87PUEP11Z7r7U= -github.com/holiman/uint256 v1.1.1/go.mod h1:y4ga/t+u+Xwd7CpDgZESaRcWy0I7XMlTMA25ApIH5Jw= -github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= -github.com/hudl/fargo v1.4.0 h1:ZDDILMbB37UlAVLlWcJ2Iz1XuahZZTDZfdCKeclfq2s= -github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150 h1:vlNjIqmUZ9CMAWsbURYl3a6wZbw7q5RHVvlXTNS/Bs8= -github.com/iancoleman/strcase v0.2.0 h1:05I4QRnGpI0m37iZQRuskXh+w77mr6Z41lwQzuHLwW0= -github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639 h1:mV02weKRL81bEnm8A0HT1/CAelMQDBuQIfLw8n+d6xI= github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= -github.com/imkira/go-interpol v1.1.0 h1:KIiKr0VSG2CUW1hl1jpiyuzuJeKUUpC8iM1AIE7N1Vk= -github.com/influxdata/flux v0.65.1 h1:77BcVUCzvN5HMm8+j9PRBQ4iZcu98Dl4Y9rf+J5vhnc= -github.com/influxdata/influxdb1-client v0.0.0-20200827194710-b269163b24ab h1:HqW4xhhynfjrtEiiSGcQUd6vrK23iMam1FO8rI7mwig= -github.com/influxdata/influxql v1.1.1-0.20200828144457-65d3ef77d385 h1:ED4e5Cc3z5vSN2Tz2GkOHN7vs4Sxe2yds6CXvDnvZFE= -github.com/influxdata/promql/v2 v2.12.0 h1:kXn3p0D7zPw16rOtfDR+wo6aaiH8tSMfhPwONTxrlEc= -github.com/influxdata/roaring v0.4.13-0.20180809181101-fc520f41fab6 h1:UzJnB7VRL4PSkUJHwsyzseGOmrO/r4yA+AuxGJxiZmA= -github.com/influxdata/tdigest v0.0.0-20181121200506-bf2b5ad3c0a9 h1:MHTrDWmQpHq/hkq+7cw9oYAt2PqUw52TZazRA0N7PGE= -github.com/influxdata/usage-client v0.0.0-20160829180054-6d3895376368 h1:+TUUmaFa4YD1Q+7bH9o5NCHQGPMqZCYJiNW6lIIS9z4= -github.com/ipfs/go-ds-badger v0.3.0 h1:xREL3V0EH9S219kFFueOYJJTcjgNSZ2HY1iSvN7U1Ro= -github.com/ipfs/go-ds-leveldb v0.5.0 h1:s++MEBbD3ZKc9/8/njrn4flZLnCuY9I79v94gBUNumo= -github.com/ipfs/go-ipfs-delay v0.0.0-20181109222059-70721b86a9a8 h1:NAviDvJ0WXgD+yiL2Rj35AmnfgI11+pHXbdciD917U0= -github.com/iris-contrib/blackfriday v2.0.0+incompatible h1:o5sHQHHm0ToHUlAJSTjW9UWicjJSDDauOOQ2AHuIVp4= -github.com/iris-contrib/go.uuid v2.0.0+incompatible h1:XZubAYg61/JwnJNbZilGjf3b3pB80+OQg2qf6c8BfWE= -github.com/iris-contrib/httpexpect/v2 v2.3.1 h1:A69ilxKGW1jDRKK5UAhjTL4uJYh3RjD4qzt9vNZ7fpY= -github.com/iris-contrib/jade v1.1.4 h1:WoYdfyJFfZIUgqNAeOyRfTNQZOksSlZ6+FnXR3AEpX0= github.com/iris-contrib/jade v1.1.4/go.mod h1:EDqR+ur9piDl6DUgs6qRrlfzmlx/D5UybogqrXvJTBE= -github.com/iris-contrib/pongo2 v0.0.1 h1:zGP7pW51oi5eQZMIlGA3I+FHY9/HOQWDB+572yin0to= -github.com/iris-contrib/schema v0.0.6 h1:CPSBLyx2e91H2yJzPuhGuifVRnZBBJ3pCOMbOvPZaTw= github.com/iris-contrib/schema v0.0.6/go.mod h1:iYszG0IOsuIsfzjymw1kMzTL8YQcCWlm65f3wX8J5iA= -github.com/jackpal/gateway v1.0.5 h1:qzXWUJfuMdlLMtt0a3Dgt+xkWQiA5itDEITVJtuSwMc= -github.com/jbenet/go-cienv v0.1.0 h1:Vc/s0QbQtoxX8MwwSLWWh+xNNZvM3Lw7NsTcHrvvhMc= -github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e h1:UvSe12bq+Uj2hWd8aOlwPmoZ+CITRFrdit+sDGfAg8U= -github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1 h1:ujPKutqRlJtcfWk6toYVYagwra7HQHbXOaS171b4Tg8= -github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA= -github.com/jmhodges/levigo v1.0.0 h1:q5EC36kV79HWeTBWsod3mG11EgStG3qArTKcvlksN1U= -github.com/jonboulle/clockwork v0.1.0 h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0hcPo= -github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= -github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA= -github.com/jrick/logrotate v1.0.0 h1:lQ1bL/n9mBNeIXoTUoYRlK4dHuNJVofX9oWqBtPnSzI= -github.com/jstemmer/go-junit-report v0.9.1 h1:6QPYqodiu3GuPL+7mfx+NwDdp2eTkp9IfEUpgAwUN0o= -github.com/jsternberg/zap-logfmt v1.0.0 h1:0Dz2s/eturmdUS34GM82JwNEdQ9hPoJgqptcEKcbpzY= -github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5 h1:PJr+ZMXIecYc1Ey2zucXdR73SMBtgjPgwa31099IMv0= -github.com/jwilder/encoding v0.0.0-20170811194829-b4e1701a28ef h1:2jNeR4YUziVtswNP9sEFAI913cVrzH85T+8Q6LpYbT0= -github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88 h1:uC1QfSlInpQF+M0ao65imhwqKnz3Q2z/d8PWZRMQvDM= -github.com/kami-zh/go-capturer v0.0.0-20171211120116-e492ea43421d h1:cVtBfNW5XTHiKQe7jDaDBSh/EVM4XLPutLAGboIXuM0= -github.com/kataras/blocks v0.0.7 h1:cF3RDY/vxnSRezc7vLFlQFTYXG/yAr1o7WImJuZbzC4= github.com/kataras/blocks v0.0.7/go.mod h1:UJIU97CluDo0f+zEjbnbkeMRlvYORtmc1304EeyXf4I= -github.com/kataras/golog v0.1.7 h1:0TY5tHn5L5DlRIikepcaRR/6oInIr9AiWsxzt0vvlBE= github.com/kataras/golog v0.1.7/go.mod h1:jOSQ+C5fUqsNSwurB/oAHq1IFSb0KI3l6GMa7xB6dZA= -github.com/kataras/iris/v12 v12.2.0-beta5 h1:grB/oCf5baZhmYIeDMfgN3LYrtEcmK8pbxlRvEZ2pgw= github.com/kataras/iris/v12 v12.2.0-beta5/go.mod h1:q26aoWJ0Knx/00iPKg5iizDK7oQQSPjbD8np0XDh6dc= -github.com/kataras/jwt v0.1.8 h1:u71baOsYD22HWeSOg32tCHbczPjdCk7V4MMeJqTtmGk= -github.com/kataras/neffos v0.0.20 h1:swTzKZ3Mo2sIQ8ATKSKf0xDG1tuhr6w4tZmmRsvCYlg= github.com/kataras/pio v0.0.10/go.mod h1:gS3ui9xSD+lAUpbYnjOGiQyY7sUMJO+EHpiRzhtZ5no= -github.com/kataras/pio v0.0.11 h1:kqreJ5KOEXGMwHAWHDwIl+mjfNCPhAwZPa8gK7MKlyw= github.com/kataras/pio v0.0.11/go.mod h1:38hH6SWH6m4DKSYmRhlrCJ5WItwWgCVrTNU62XZyUvI= -github.com/kataras/sitemap v0.0.6 h1:w71CRMMKYMJh6LR2wTgnk5hSgjVNB9KL60n5e2KHvLY= github.com/kataras/sitemap v0.0.6/go.mod h1:dW4dOCNs896OR1HmG+dMLdT7JjDk7mYBzoIRwuj5jA4= -github.com/kataras/tunnel v0.0.4 h1:sCAqWuJV7nPzGrlb0os3j49lk2JhILT0rID38NHNLpA= github.com/kataras/tunnel v0.0.4/go.mod h1:9FkU4LaeifdMWqZu7o20ojmW4B7hdhv2CMLwfnHGpYw= -github.com/kilic/bls12-381 v0.1.1-0.20210208205449-6045b0235e36/go.mod h1:tlkavyke+Ac7h8R3gZIjI5LKBcvMlSWnXNMgT3vZXo8= -github.com/kisielk/errcheck v1.5.0 h1:e8esj/e4R+SAOwFwN+n3zr0nYeCyeweozKfO23MvHzY= -github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg= -github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23 h1:FOOIBWrEkLgmlgGfMuZT83xIwfPDxEI2OHu6xUmJMFE= github.com/klauspost/compress v1.15.0/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= -github.com/klauspost/compress v1.15.11 h1:Lcadnb3RKGin4FYM/orgq0qde+nc15E5Cbqg4B9Sx9c= github.com/klauspost/compress v1.15.11/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM= -github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5 h1:2U0HzY8BJ8hVwDKIzp7y4voR9CX/nvcfymLmg2UiOio= github.com/klauspost/cpuid v1.2.1 h1:vJi+O/nMdFt0vqm8NZBI6wzALWdA2X+egi0ogNyrC/w= -github.com/klauspost/crc32 v0.0.0-20161016154125-cb6bfca970f6 h1:KAZ1BW2TCmT6PRihDPpocIy1QTtsAsrx6TneU/4+CMg= -github.com/klauspost/pgzip v1.0.2-0.20170402124221-0bf5dcad4ada h1:3L+neHp83cTjegPdCiOxVOJtRIy7/8RldvMTsyPYH10= -github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8= -github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515 h1:T+h1c/A9Gawja4Y9mFVWj2vyii2bbUNDw3kt9VxK2EY= -github.com/kr/pty v1.1.3 h1:/Um6a/ZmD5tF7peoOJ5oN5KMQ0DrGVQSXLNwyckutPk= github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w= github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= -github.com/lib/pq v1.10.4 h1:SO9z7FRPzA03QhHKJrH5BXA6HU1rS4V2nIVrrNC1iYk= -github.com/libp2p/go-libp2p-crypto v0.1.0 h1:k9MFy+o2zGDNGsaoZl0MA3iZ75qXxr9OOoAZF+sD5OQ= -github.com/libp2p/go-libp2p-loggables v0.1.0 h1:h3w8QFfCt2UJl/0/NW4K829HX/0S4KD31PQ7m8UXXO8= -github.com/libp2p/go-libp2p-peer v0.2.0 h1:EQ8kMjaCUwt/Y5uLgjT8iY2qg0mGUT0N1zUjer50DsY= -github.com/libp2p/go-libp2p-routing-helpers v0.2.3 h1:xY61alxJ6PurSi+MXbywZpelvuU4U4p/gPTxjqCqTzY= -github.com/libp2p/go-libp2p-secio v0.2.2 h1:rLLPvShPQAcY6eNurKNZq3eZjPWfU9kXF2eI9jIYdrg= -github.com/libp2p/go-libp2p-xor v0.0.0-20210714161855-5c005aca55db h1:EDoDKW8ZAHd6SIDeo+thU51PyQppqLYkBxx0ObvFj/w= -github.com/libp2p/go-stream-muxer v0.0.1 h1:Ce6e2Pyu+b5MC1k3eeFtAax0pW4gc6MosYSLV05UeLw= -github.com/libp2p/go-yamux v1.4.1 h1:P1Fe9vF4th5JOxxgQvfbOHkrGqIZniTLf+ddhZp8YTI= -github.com/libp2p/zeroconf/v2 v2.1.1 h1:XAuSczA96MYkVwH+LqqqCUZb2yH3krobMJ1YE+0hG2s= -github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743 h1:143Bb8f8DuGWck/xpNUOckBVYfFbBTnLevfRZ1aVVqo= -github.com/lightstep/lightstep-tracer-go v0.18.1 h1:vi1F1IQ8N7hNWytK9DpJsUfQhGuNSc19z330K6vl4zk= -github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= -github.com/lunixbochs/vtclean v1.0.0 h1:xu2sLAri4lGiovBDQKxl5mrXyESr3gUr5m5SM5+LVb8= -github.com/lyft/protoc-gen-star v0.5.3 h1:zSGLzsUew8RT+ZKPHc3jnf8XLaVyHzTcAFBzHtCNR20= -github.com/lyft/protoc-gen-validate v0.0.13 h1:KNt/RhmQTOLr7Aj8PsJ7mTronaFyx80mRTT9qF261dA= -github.com/mailgun/raymond/v2 v2.0.46 h1:aOYHhvTpF5USySJ0o7cpPno/Uh2I5qg2115K25A+Ft4= github.com/mailgun/raymond/v2 v2.0.46/go.mod h1:lsgvL50kgt1ylcFJYZiULi5fjPBkkhNfj4KA0W54Z18= -github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/marten-seemann/qpack v0.2.1 h1:jvTsT/HpCn2UZJdP+UUB53FfUUgeOyG5K1ns0OJOGVs= -github.com/marten-seemann/qtls v0.10.0 h1:ECsuYUKalRL240rRD4Ri33ISb7kAQ3qGDlrrl55b2pc= -github.com/marten-seemann/qtls-go1-15 v0.1.5 h1:Ci4EIUN6Rlb+D6GmLdej/bCQ4nPYNtVXQB+xjiXE1nk= -github.com/matryer/moq v0.0.0-20190312154309-6cfb0558e1bd h1:HvFwW+cm9bCbZ/+vuGNq7CRWXql8c0y8nGeYpqmpvmk= -github.com/matryer/try v0.0.0-20161228173917-9ac251b645a2 h1:JAEbJn3j/FrhdWA9jW8B5ajsLIjeuEHLi8xE4fk997o= +github.com/mantlenetworkio/mantle/bss-core v0.0.0-20221201061228-0589a659d047/go.mod h1:NFQHTC7R0jDLH9ihMAFaDzCOW4i3PtaV3MQDRvIJFQQ= +github.com/mantlenetworkio/mantle/l2geth v0.0.0-20221201061228-0589a659d047/go.mod h1:Gb5aIh6+aStBbatHciL8aapFApOgEFaGpIGNfZukgV0= github.com/matryer/try v0.0.0-20161228173917-9ac251b645a2/go.mod h1:0KeJpeMD6o+O4hW7qJOT7vyQPKrWmj26uf5wMc/IiIs= -github.com/mattn/go-sqlite3 v1.14.9 h1:10HX2Td0ocZpYEjhilsuo6WWtUqttj2Kb0KtD86/KYA= -github.com/mattn/go-tty v0.0.0-20180907095812-13ff1204f104 h1:d8RFOZ2IiFtFWBcKEHAFYJcPTf0wY5q0exFNJZVWa1U= -github.com/mattn/goveralls v0.0.2 h1:7eJB6EqsPhRVxvwEXGnqdO2sJI0PTsrWoTMXEk9/OQc= -github.com/mediocregopher/radix/v3 v3.8.0 h1:HI8EgkaM7WzsrFpYAkOXIgUKbjNonb2Ne7K6Le61Pmg= -github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4= -github.com/microcosm-cc/bluemonday v1.0.21 h1:dNH3e4PSyE4vNX+KlRGHT5KrSvjeUkoNPwEORjffHJg= github.com/microcosm-cc/bluemonday v1.0.21/go.mod h1:ytNkv4RrDrLJ2pqlsSI46O6IVXmZOBBD4SaJyDwwTkM= -github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643 h1:hLDRPB66XQT/8+wG9WsDpiCvZf1yKO7sz7scAjSlBa0= -github.com/minio/highwayhash v1.0.2 h1:Aak5U0nElisjDCfPSG79Tgzkn2gl66NxOMspRrKnA/g= -github.com/mitchellh/cli v1.1.0 h1:tEElEatulEHDeedTxwckzyYMA5c86fbmNIUL1hBIiTg= -github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= -github.com/mitchellh/go-testing-interface v1.0.0 h1:fzU/JVNcaqHQEcVFAKeR41fkiLdIPrefOvVG1VZ96U0= -github.com/mitchellh/gox v0.4.0 h1:lfGJxY7ToLJQjHHwi0EX6uYBdK78egf954SQl13PQJc= -github.com/mitchellh/iochan v1.0.0 h1:C+X3KsSTLFVBr/tK1eYN/vs4rJcvsiLU338UhYPJWeY= -github.com/mmcloughlin/profile v0.1.1 h1:jhDmAqPyebOsVDOCICJoINoLb/AnLBaUw58nFzxWS2w= -github.com/moby/sys/mountinfo v0.4.1 h1:1O+1cHA1aujwEwwVMa2Xm2l+gIpUHyd3+D+d7LZh1kM= -github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5 h1:8Q0qkMVC/MmWkpIdlvZgcv2o2jrlF6zqVOh7W5YHdMA= -github.com/moul/http2curl v1.0.0 h1:dRMWoAtb+ePxMlLkrCbAqh4TlPHXvoGUSQ323/9Zahs= -github.com/mrunalp/fileutils v0.5.0 h1:NKzVxiH7eSk+OQ4M+ZYW1K6h27RUV3MI6NUTsHhU6Z4= -github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae h1:VeRdUYdCw49yizlSbMEn2SZ+gT+3IUKx8BqxyQdz+BY= -github.com/multiformats/go-multiaddr-net v0.2.0 h1:MSXRGN0mFymt6B1yo/6BPnIRpLPEnKgQNvVfCX5VDJk= -github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU= -github.com/nats-io/jwt v1.2.2 h1:w3GMTO969dFg+UOKTmmyuu7IGdusK+7Ytlt//OYH/uU= -github.com/nats-io/jwt/v2 v2.3.0 h1:z2mA1a7tIf5ShggOFlR1oBPgd6hGqcDYsISxZByUzdI= github.com/nats-io/jwt/v2 v2.3.0/go.mod h1:0tqz9Hlu6bCBFLWAASKhE5vUA4c24L9KPUUgvwumE/k= -github.com/nats-io/nats-server/v2 v2.5.0 h1:wsnVaaXH9VRSg+A2MVg5Q727/CqxnmPLGFQ3YZYKTQg= -github.com/nats-io/nats.go v1.16.0 h1:zvLE7fGBQYW6MWaFaRdsgm9qT39PJDQoju+DS8KsO1g= github.com/nats-io/nats.go v1.16.0/go.mod h1:BPko4oXsySz4aSWeFgOHLZs3G4Jq4ZAyE6/zMCxRT6w= -github.com/nats-io/nkeys v0.3.0 h1:cgM5tL53EvYRU+2YLXIK0G2mJtK12Ft9oeooSZMA2G8= -github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= -github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86 h1:D6paGObi5Wud7xg83MaEFyjxQB1W5bz5d0IFppr+ymk= -github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab h1:eFXv9Nu1lGbrNbj619aWwZfVF5HBrm9Plte8aNptuTI= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= -github.com/oklog/oklog v0.3.2 h1:wVfs8F+in6nTBMkA7CbRw+zZMIB7nNM825cM1wuzoTk= -github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw= -github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= -github.com/onsi/ginkgo/v2 v2.0.0 h1:CcuG/HvWNkkaqCUpJifQY8z7qEMBJya6aLPx6ftGyjQ= github.com/onsi/ginkgo/v2 v2.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= -github.com/onsi/ginkgo/v2 v2.2.0/go.mod h1:MEH45j8TBi6u9BMogfbp0stKC5cdGjumZj5Y7AG4VIk= github.com/onsi/ginkgo/v2 v2.4.0/go.mod h1:iHkDK1fKGcBoEHT5W7YBq4RFWaQulw+caOMkAt4OrFo= github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= -github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE= github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs= -github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 h1:lDH9UUVJtmYCjyT0CI4q8xvlXPxeZ0gYCVvWbmPlp88= -github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= -github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM= -github.com/opencontainers/runc v1.0.3 h1:1hbqejyQWCJBvtKAfdO0b1FmaEf2z/bxnjqbARass5k= -github.com/opencontainers/selinux v1.8.2 h1:c4ca10UMgRcvZ6h0K4HtS15UaVSBEaE+iln2LVpAuGc= -github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492 h1:lM6RxxfUMrYL/f8bWEUqdXrANWtrL7Nndbm9iFN0DlU= -github.com/opentracing/basictracer-go v1.0.0 h1:YyUAhaEfjoWXclZVJ9sGoNct7j4TVk7lZWlQw5UXuoo= -github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5 h1:ZCnq+JUrvXcDVhX/xRolRBZifmabN1HcS1wrPSvxhrU= -github.com/openzipkin/zipkin-go v0.2.5 h1:UwtQQx2pyPIgWYHRg+epgdx1/HnBQTgN3/oIYEJTQzU= -github.com/ory/dockertest v3.3.5+incompatible h1:iLLK6SQwIhcbrG783Dghaaa3WPzGc+4Emza6EbVUUGA= -github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95 h1:+OLn68pqasWca0z5ryit9KGfp3sUsW4Lqg32iRMJyzs= -github.com/pact-foundation/pact-go v1.0.4 h1:OYkFijGHoZAYbOIb1LWXrwKQbMMRUv1oQ89blD2Mh2Q= -github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= -github.com/paulbellamy/ratecounter v0.2.0 h1:2L/RhJq+HA8gBQImDXtLPrDXK5qAj6ozWVK/zFXVJGs= github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo= github.com/pelletier/go-toml/v2 v2.0.5 h1:ipoSadvV8oGUjnUbMub59IDPPwfxF694nG/jwbMiyQg= github.com/pelletier/go-toml/v2 v2.0.5/go.mod h1:OMHamSCAODeSsVrwwvcJOaoN0LIUIaFVNZzmWyNfXas= -github.com/performancecopilot/speed v3.0.0+incompatible h1:2WnRzIquHa5QxaJKShDkLM+sc0JPuwhXzK8OYOyt3Vg= -github.com/performancecopilot/speed/v4 v4.0.0 h1:VxEDCmdkfbQYDlcr/GC9YoN9PQ6p8ulk9xVsepYy9ZY= -github.com/philhofer/fwd v1.1.1 h1:GdGcTjf5RNAxwS4QLsiMzJYj5KEvPJD3Abr261yRQXQ= -github.com/pierrec/lz4 v2.0.5+incompatible h1:2xWsjqPFWcplujydGg4WmhC/6fZqK42wMM8aXeqhl0I= -github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e h1:aoZm08cpOy4WuID//EZDgcC4zIxODThtZNPirFr42+A= -github.com/pkg/profile v1.2.1 h1:F++O52m40owAmADcojzM+9gyjmMOY/T4oYJkgFDH8RE= -github.com/pkg/sftp v1.13.1 h1:I2qBYMChEhIjOgazfJmV3/mZM256btk6wkCDRmW7JYs= -github.com/pkg/term v0.0.0-20180730021639-bffc007b7fd5 h1:tFwafIEMf0B7NlcxV/zJ6leBIa81D3hgGSgsE5hCkOQ= -github.com/posener/complete v1.2.3 h1:NP0eAhjcjImqslEwo/1hq7gpajME0fTLTezBKDqfXqo= -github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= -github.com/protolambda/go-kzg v0.0.0-20220220065500-36404333406f/go.mod h1:P9wXBp1WMjLHx2C22Gg7FyqQcJktMAohrKj3tdaWIH0= -github.com/retailnext/hllpp v1.0.1-0.20180308014038-101a6d2f8b52 h1:RnWNS9Hlm8BIkjr6wx8li5abe0fr73jljLycdfemTp0= -github.com/rogpeppe/fastuuid v1.2.0 h1:Ppwyp6VYCF1nvBTXL3trRso7mXMlRrw9ooo375wvi2s= github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= -github.com/rs/xid v1.3.0 h1:6NjYksEUlhurdVehpc7S7dk6DAmcKv8V9gG0FsVN2U4= github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo= -github.com/ryanuber/columnize v2.1.0+incompatible h1:j1Wcmh8OrK4Q7GXY+V7SVSY8nUWQxHW5TkBe7YUl+2s= -github.com/sagikazarmark/crypt v0.4.0 h1:Rqcx6Sf/bWQUmmfGQhcFx3wQQEfb2UZWhAKvGRairm0= -github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da h1:p3Vo3i64TCLY7gIfzeQaUJ+kppEO5WQG3cL8iE8tGHU= -github.com/schollz/closestmatch v2.1.0+incompatible h1:Uel2GXEpJqOWBrlyI+oY9LTiyyjYS17cCYRqP13/SHk= -github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I= -github.com/seccomp/libseccomp-golang v0.9.1 h1:NJjM5DNFOs0s3kYE1WUOr6G8V97sdt46rlXTMfXGWBo= -github.com/segmentio/kafka-go v0.2.0 h1:HtCSf6B4gN/87yc5qTl7WsxPKQIIGXLPPM1bMCPOsoY= -github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= -github.com/shirou/gopsutil/v3 v3.22.8 h1:a4s3hXogo5mE2PfdfJIonDbstO/P+9JszdfhAHSzD9Y= -github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4 h1:Fth6mevc5rX7glNLpbAMJnqKlfIkcTjZCSHEeqvKbcI= -github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48 h1:vabduItPAIz9px5iryD5peyx7O3Ya8TBThapgXim98o= -github.com/shurcooL/github_flavored_markdown v0.0.0-20181002035957-2122de532470 h1:qb9IthCFBmROJ6YBS31BEMeSYjOscSiG+EO+JVNTz64= -github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e h1:MZM7FHLqUHYI0Y/mQAt3d2aYa0SiNms/hFqC9qJYolM= -github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041 h1:llrF3Fs4018ePo4+G/HV/uQUqEI1HMDjCeOf2V6puPc= -github.com/shurcooL/gofontwoff v0.0.0-20180329035133-29b52fc0a18d h1:Yoy/IzG4lULT6qZg62sVC+qyBL8DQkmD2zv6i7OImrc= -github.com/shurcooL/gopherjslib v0.0.0-20160914041154-feb6d3990c2c h1:UOk+nlt1BJtTcH15CT7iNO7YVWTfTv/DNwEAQHLIaDQ= -github.com/shurcooL/highlight_diff v0.0.0-20170515013008-09bb4053de1b h1:vYEG87HxbU6dXj5npkeulCS96Dtz5xg3jcfCgpcvbIw= -github.com/shurcooL/highlight_go v0.0.0-20181028180052-98c3abbbae20 h1:7pDq9pAMCQgRohFmd25X8hIH8VxmT3TaDm+r9LHxgBk= -github.com/shurcooL/home v0.0.0-20181020052607-80b7ffcb30f9 h1:MPblCbqA5+z6XARjScMfz1TqtJC7TuTRj0U9VqIBs6k= -github.com/shurcooL/htmlg v0.0.0-20170918183704-d01228ac9e50 h1:crYRwvwjdVh1biHzzciFHe8DrZcYrVcZFlJtykhRctg= -github.com/shurcooL/httperror v0.0.0-20170206035902-86b7830d14cc h1:eHRtZoIi6n9Wo1uR+RU44C247msLWwyA89hVKwRLkMk= -github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371 h1:SWV2fHctRpRrp49VXJ6UZja7gU9QLHwRpIPBN89SKEo= -github.com/shurcooL/httpgzip v0.0.0-20180522190206-b1c53ac65af9 h1:fxoFD0in0/CBzXoyNhMTjvBZYW6ilSnTw7N7y/8vkmM= -github.com/shurcooL/issues v0.0.0-20181008053335-6292fdc1e191 h1:T4wuULTrzCKMFlg3HmKHgXAF8oStFb/+lOIupLV2v+o= -github.com/shurcooL/issuesapp v0.0.0-20180602232740-048589ce2241 h1:Y+TeIabU8sJD10Qwd/zMty2/LEaT9GNDaA6nyZf+jgo= -github.com/shurcooL/notifications v0.0.0-20181007000457-627ab5aea122 h1:TQVQrsyNaimGwF7bIhzoVC9QkKm4KsWd8cECGzFx8gI= -github.com/shurcooL/octicon v0.0.0-20181028054416-fa4f57f9efb2 h1:bu666BQci+y4S0tVRVjsHUeRon6vUXmsGBwdowgMrg4= -github.com/shurcooL/reactions v0.0.0-20181006231557-f2e0b4ca5b82 h1:LneqU9PHDsg/AkPDU3AkqMxnMYL+imaqkpflHu73us8= -github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= -github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537 h1:YGaxtkYjb8mnTvtufv2LKLwCQu2/C7qFB7UtrOlTWOY= -github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133 h1:JtcyT0rk/9PKOdnKQzuDR+FSjh7SGtJwpgVpfZBRKlQ= -github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/smartystreets/assertions v1.13.0 h1:Dx1kYM01xsSqKPno3aqLnrwac2LetPvN23diwyr69Qs= -github.com/smola/gocompat v0.2.0 h1:6b1oIMlUXIpz//VKEDzPVBK8KG7beVwmHIUEBIs/Pns= -github.com/snikch/goodman v0.0.0-20171125024755-10e37e294daa h1:YJfZp12Z3AFhSBeXOlv4BO55RMwPn2NoQeDsrdWnBtY= -github.com/soheilhy/cmux v0.1.4 h1:0HKaf1o97UwFjHH9o5XsHUOF+tqmdA7KEzXLpiyaw0E= -github.com/sony/gobreaker v0.4.1 h1:oMnRNZXX5j85zso6xCPRNPtmAycat+WcoKbklScLDgQ= -github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d h1:yKm7XZV6j9Ev6lojP2XaIshpT4ymkqhMeSghO5Ps00E= -github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e h1:qpG93cPwA5f7s/ZPBJnGOYQNK/vKsaDaseuKT5Asee8= -github.com/spacemonkeygo/openssl v0.0.0-20181017203307-c2dcc5cca94a h1:/eS3yfGjQKG+9kayBkj0ip1BGhq6zJ3eaVksphxAaek= github.com/spf13/cobra v1.5.0 h1:X+jTBEBqF0bHN+9cSMgmfuvv2VHJ9ezmFNf9Y/XstYU= github.com/spf13/cobra v1.5.0/go.mod h1:dWXEIy2H428czQCjInthrTRUg7yKbok+2Qi/yBIJoUM= -github.com/src-d/envconfig v1.0.0 h1:/AJi6DtjFhZKNx3OB2qMsq7y4yT5//AeSZIe7rk+PX8= -github.com/streadway/amqp v1.0.0 h1:kuuDrUJFZL1QYL9hUNuCxNObNzB0bV/ZG5jV3RWAQgo= -github.com/streadway/handy v0.0.0-20200128134331-0f66f006fb2e h1:mOtuXaRAbVZsxAHVdPR3IjfmN8T1h2iczJLynhLybf8= -github.com/stretchr/objx v0.4.0 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= -github.com/supranational/blst v0.3.8-0.20220526154634-513d2456b344 h1:m+8fKfQwCAy1QjzINvKe/pYtLjo2dl59x2w9YSEJxuY= github.com/supranational/blst v0.3.8-0.20220526154634-513d2456b344/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= -github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 h1:kdXcSzyDtseVEc4yCz2qF8ZrQvIDBJLl4S1c3GCXmoI= -github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07 h1:UyzmZLoiDWMRywV4DUYb9Fbt8uiOSooupjTq10vpvnU= -github.com/tdewolff/minify/v2 v2.12.4 h1:kejsHQMM17n6/gwdw53qsi6lg0TGddZADVyQOz1KMdE= github.com/tdewolff/minify/v2 v2.12.4/go.mod h1:h+SRvSIX3kwgwTFOpSckvSxgax3uy8kZTSF1Ojrr3bk= -github.com/tdewolff/parse/v2 v2.6.4 h1:KCkDvNUMof10e3QExio9OPZJT8SbdKojLBumw8YZycQ= github.com/tdewolff/parse/v2 v2.6.4/go.mod h1:woz0cgbLwFdtbjJu8PIKxhW05KplTFQkOdX78o+Jgrs= -github.com/tdewolff/test v1.0.7 h1:8Vs0142DmPFW/bQeHRP3MV19m1gvndjUb1sn8yy74LM= github.com/tdewolff/test v1.0.7/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE= -github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c h1:g+WoO5jjkqGAzHWCjJB1zZfXPIAaDpzXIEJ0eS6B5Ok= -github.com/tendermint/tm-db v0.6.6 h1:EzhaOfR0bdKyATqcd5PNeyeq8r+V4bRPHBfyFdD9kGM= -github.com/tinylib/msgp v1.1.5 h1:2gXmtWueD2HefZHQe1QOy9HVzmFrLOVvsXwXBQ0ayy0= -github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5 h1:LnC5Kc/wtumK+WB441p7ynQJzVuNRJiqddSIE3IlSEQ= -github.com/ttacon/chalk v0.0.0-20160626202418-22c06c80ed31 h1:OXcKh35JaYsGMRzpvFkLv/MEyPuL49CThT1pZ8aSml4= -github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c h1:u6SKchux2yDvFQnDHS3lPnIRmfVJ5Sxy3ao2SIdysLQ= github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= github.com/ugorji/go v1.2.7 h1:qYhyWUUd6WbiM+C6JZAUkIJt/1WrjzNHY9+KCIjVqTo= github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M= github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0= github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY= -github.com/urfave/cli/v2 v2.10.2/go.mod h1:f8iq5LtQ/bLxafbdBSLPPNsgaW0l/2fYYEHhAyPlwvo= -github.com/urfave/negroni v1.0.0 h1:kIimOitoypq34K7TG7DUaJ9kq/N4Ofuwi1sjz0KipXc= -github.com/valyala/fasthttp v1.40.0 h1:CRq/00MfruPGFLTQKY8b+8SfdK60TxNztjRMnH0t1Yc= +github.com/urfave/cli v1.22.10/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/valyala/fasthttp v1.40.0/go.mod h1:t/G+3rLek+CyY9bnIE+YlMRddxVAAGjhxndDB4i4C0I= -github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8= github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= -github.com/viant/assertly v0.4.8 h1:5x1GzBaRteIwTr5RAGFVG14uNeRFxVNbXPWrK2qAgpc= -github.com/viant/toolbox v0.24.0 h1:6TteTDQ68CjgcCe8wH3D3ZhUQQOJXMTbj/D9rkk2a1k= -github.com/vishvananda/netlink v1.1.0 h1:1iyaYNBLmP6L0220aDnYQpo1QEV4t4hJ+xEEhhJH8j0= -github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df h1:OviZH7qLw/7ZovXvuNyL3XQl8UFofeikI1NW1Gypu7k= -github.com/vmihailenco/msgpack/v5 v5.3.5 h1:5gO0H1iULLWGhs2H5tbAHIZTV8/cYafcFOr9znI5mJU= github.com/vmihailenco/msgpack/v5 v5.3.5/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q/V5KbhBonMG9jc= -github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= -github.com/wangjia184/sortedset v0.0.0-20160527075905-f5d03557ba30 h1:kZiWylALnUy4kzoKJemjH8eqwCl3RjW1r1ITCjjW7G8= -github.com/whyrusleeping/go-logging v0.0.1 h1:fwpzlmT0kRC/Fmd0MdmGgJG/CXIZ6gFq46FQZjprUcc= -github.com/whyrusleeping/mafmt v1.2.8 h1:TCghSl5kkwEE0j+sU/gudyhVMRlpBin8fMBBHg59EbA= -github.com/whyrusleeping/mdns v0.0.0-20190826153040-b9b60ed33aa9 h1:Y1/FEOpaCpD21WxrmfeIYCFPuVPRCY2XZTWzTNHGw30= -github.com/willf/bitset v1.1.3 h1:ekJIKh6+YbUIVt9DfNbkR5d6aFcFTLDRyJNAACURBg8= -github.com/x-cray/logrus-prefixed-formatter v0.5.2 h1:00txxvfBM9muc0jiLIEAkAcIMJzfthRT6usrui8uGmg= -github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= -github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= -github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= -github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8= -github.com/xlab/treeprint v0.0.0-20180616005107-d6fb6747feb6 h1:YdYsPAZ2pC6Tow/nPZOPQ96O3hm/ToAkGsPLzedXERk= -github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77 h1:ESFSdwYZvkeru3RtdrYueztKhOBCSAAzS4Gf+k0tEow= -github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= -github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0 h1:6fRhSjgLCkTD3JnJxvaJ4Sj+TYblw757bqYgZaOq5ZY= -github.com/yosssi/ace v0.0.5 h1:tUkIP/BLdKqrlrPwcmH0shwEEhTRHoGnc1wFIWmaBUA= github.com/yosssi/ace v0.0.5/go.mod h1:ALfIzm2vT7t5ZE7uoIZqF3TQ7SAOyupFZnkrF5id+K0= -github.com/yudai/gojsondiff v1.0.0 h1:27cbfqXLVEJ1o8I6v3y9lg8Ydm53EKqHXAOMxEGlCOA= -github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3IfnEUduWvb9is428/nNb5L3U01M= -github.com/yudai/pp v2.0.1+incompatible h1:Q4//iY4pNF6yPLZIigmvcl7k/bPgrcTPIFIcmawg5bI= -github.com/yuin/goldmark v1.4.13 h1:fVcFKWvrslecOb/tg+Cc05dkeYx540o0FuFt3nUVDoE= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU= -go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738 h1:VcrIfasaLFkyjk6KNlXQSzO+B0fZcnECiDrKJsfxka0= -go.etcd.io/etcd/api/v3 v3.5.1 h1:v28cktvBq+7vGyJXF8G+rWJmj+1XUmMtqcLnH8hDocM= -go.etcd.io/etcd/client/pkg/v3 v3.5.1 h1:XIQcHCFSG53bJETYeRJtIxdLv2EWRGxcfzR8lSnTH4E= -go.etcd.io/etcd/client/v2 v2.305.1 h1:vtxYCKWA9x31w0WJj7DdqsHFNjhkigdAnziDtkZb/l4= -go.etcd.io/etcd/client/v3 v3.5.0 h1:62Eh0XOro+rDwkrypAGDfgmNh5Joq+z+W9HZdlXMzek= -go.opentelemetry.io/otel v0.20.0 h1:eaP0Fqu7SXHwvjiqDq83zImeehOHX8doTvU9AwXON8g= -go.opentelemetry.io/otel/metric v0.20.0 h1:4kzhXFP+btKm4jwxpjIqjs41A7MakRFUS86bqLHTIw8= -go.opentelemetry.io/otel/oteltest v0.20.0 h1:HiITxCawalo5vQzdHfKeZurV8x7ljcqAgiWzF6Vaeaw= -go.opentelemetry.io/otel/trace v0.20.0 h1:1DL6EXUdcg95gukhuRRvLDO/4X5THh/5dIV52lqtnbw= -go.opentelemetry.io/proto/otlp v0.7.0 h1:rwOQPCuKAKmwGKq2aVNnYIibI6wnV7EvzgfTCzcdGg8= go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= -go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4= -go4.org v0.0.0-20180809161055-417644f6feb5 h1:+hE86LblG4AyDgwMCLTE6FOlM9+qjHSYS+rKqxUVdsM= -golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d h1:E2M5QgjZ/Jg+ObCQAudsXxuTsLj7Nl5RV/lZcQZmKSo= golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220926161630-eccd6366d1be/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/exp v0.0.0-20220426173459-3bcf042a4bf5 h1:rxKZ2gOnYxjfmakvUUqh9Gyb6KXfrj7JWTxORTYqb0E= golang.org/x/exp v0.0.0-20220426173459-3bcf042a4bf5/go.mod h1:lgLbSvA5ygNOMpwM/9anMpWVlVJ7Z+cHWq/eFuinpGE= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b h1:+qEpEAPhDZ1o0x3tHzZTQDArnOixOzGD9HUJfcg0mb4= -golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug= -golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028 h1:4+4C/Iv2U4fMZBiMCc98MG1In4gJY5YRhtpDNeDeHWs= golang.org/x/mod v0.6.0-dev.0.20211013180041-c96bc1413d57/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI= @@ -585,23 +201,15 @@ golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20221002022538-bcab6841153b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= -golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= -golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 h1:RerP+noqYHUQ8CMRcPlC2nvTa4dcBIjegkuWdcUDuqg= -golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852 h1:xYq6+9AtI+xP3M4r0N1hCkHrInHDBohhquRgx9Kk6gI= golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20210305034016-7844c3c200c3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220727055044-e65921a090b8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220928140112-f11e5e49a4ec/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.3.0 h1:qoo4akIqOcDME5bhc/NgxUdovd6BSS2uMsVjB56q1xI= golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= -golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/tools v0.1.8-0.20211029000441-d6a9af8af023/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= diff --git a/l2geth/cmd/geth/config.go b/l2geth/cmd/geth/config.go index f8af13e2d..6ff3e7570 100644 --- a/l2geth/cmd/geth/config.go +++ b/l2geth/cmd/geth/config.go @@ -25,7 +25,7 @@ import ( "reflect" "unicode" - cli "gopkg.in/urfave/cli.v1" + "gopkg.in/urfave/cli.v1" "github.com/mantlenetworkio/mantle/l2geth/cmd/utils" "github.com/mantlenetworkio/mantle/l2geth/eth" @@ -153,7 +153,7 @@ func makeFullNode(ctx *cli.Context) *node.Node { if ctx.GlobalIsSet(utils.OverrideMuirGlacierFlag.Name) { cfg.Eth.OverrideMuirGlacier = new(big.Int).SetUint64(ctx.GlobalUint64(utils.OverrideMuirGlacierFlag.Name)) } - utils.RegisterEthService(stack, &cfg.Eth) + utils.RegisterEthService(stack, &cfg.Eth) // TODO-FIXME // Whisper must be explicitly enabled by specifying at least 1 whisper flag or in dev mode shhEnabled := enableWhisper(ctx) diff --git a/l2geth/cmd/geth/main.go b/l2geth/cmd/geth/main.go index 85dcac9b0..18819cbbc 100644 --- a/l2geth/cmd/geth/main.go +++ b/l2geth/cmd/geth/main.go @@ -29,6 +29,8 @@ import ( "time" "github.com/elastic/gosigar" + fp "github.com/mantlenetworkio/mantle/fraud-proof" + fpcmd "github.com/mantlenetworkio/mantle/fraud-proof/cmd" "github.com/mantlenetworkio/mantle/l2geth/accounts" "github.com/mantlenetworkio/mantle/l2geth/accounts/keystore" "github.com/mantlenetworkio/mantle/l2geth/cmd/utils" @@ -164,11 +166,21 @@ var ( utils.RollupEnforceFeesFlag, utils.RollupFeeThresholdDownFlag, utils.RollupFeeThresholdUpFlag, + utils.RollupRoleFlag, utils.RollupGenesisTimeoutSecondsFlag, utils.SequencerClientHttpFlag, utils.RollupEigenClientHttpFlag, - utils.L1MsgSenderFlag, utils.DtlEigenEnableFlag, + + // fraud proof flags + utils.FraudProofL1EndpointFlag, + utils.FraudProofL1ChainIDFlag, + utils.FraudProofL1ConfirmationsFlag, + utils.FraudProofSequencerAddrFlag, + utils.FraudProofRollupAddrFlag, + utils.FraudProofStakeAddrFlag, + utils.FraudProofStakeAmount, + utils.FraudProofChallengeVerify, } rpcFlags = []cli.Flag{ @@ -468,6 +480,13 @@ func startNode(ctx *cli.Context, stack *node.Node) { } } } + + // + if ctx.IsSet(utils.RollupRoleFlag.Name) { + cfg := fpcmd.MakeFraudProofConfig(ctx) + fp.RegisterFraudProofService(stack, cfg) + } + // } // unlockAccounts unlocks any account specifically requested. diff --git a/l2geth/cmd/utils/flags.go b/l2geth/cmd/utils/flags.go index 26c391935..918db1475 100644 --- a/l2geth/cmd/utils/flags.go +++ b/l2geth/cmd/utils/flags.go @@ -846,6 +846,11 @@ var ( Value: time.Minute * 3, EnvVar: "ROLLUP_TIMESTAMP_REFRESH", } + RollupRoleFlag = cli.StringFlag{ + Name: "rollup.role", + Usage: "Set rollup node role", + EnvVar: "ROLLUP_ROLE", + } // sequencer / verify /schedual RollupBackendFlag = cli.StringFlag{ Name: "rollup.backend", Usage: "Sync backend for verifiers (\"l1\", \"l2\" or \"da\"), defaults to l1", @@ -894,6 +899,56 @@ var ( Usage: "HTTP endpoint for the sequencer client", EnvVar: "SEQUENCER_CLIENT_HTTP", } + + // fraud proof flags + FraudProofL1EndpointFlag = &cli.StringFlag{ + Name: "fp.l1endpoint", + Usage: "The api endpoint of L1 client", + EnvVar: "L1_ENDPOINT", + Value: "", + } + FraudProofL1ChainIDFlag = &cli.Uint64Flag{ + Name: "fp.l1chainid", + Usage: "The chain ID of L1 client", + EnvVar: "L1_CHAIN_ID", + Value: 31337, + } + FraudProofL1ConfirmationsFlag = &cli.Uint64Flag{ + Name: "fp.l1confirmations", + Usage: "The confirmation block number of L1", + EnvVar: "L1_CONFIRMATIONS", + Value: 31337, + } + FraudProofSequencerAddrFlag = &cli.StringFlag{ + Name: "fp.sequencer-addr", + Usage: "The account address of sequencer", + EnvVar: "SEQUENCER_ADDR", + Value: "", + } + // FraudProofRollupAddrFlag rollup contract address + FraudProofRollupAddrFlag = &cli.StringFlag{ + Name: "fp.rollup-addr", + Usage: "The contract address of L1 rollup", + EnvVar: "ROLLUP_ADDR", + Value: "", + } + FraudProofStakeAddrFlag = &cli.StringFlag{ + Name: "fp.stake-addr", + Usage: "The sequencer/validator address to be unlocked (pass passphrash via --password)", + EnvVar: "STAKE_ADDR", + Value: "", + } + FraudProofStakeAmount = &cli.Uint64Flag{ + Name: "fp.stake-amount", + Usage: "Required staking amount", + EnvVar: "STAKE_AMOUNT", + Value: 1000000000000000000, + } + FraudProofChallengeVerify = &cli.BoolTFlag{ + Name: "fp.challenge-verify", + Usage: "Challenge verify", + EnvVar: "CHALLENGE_VERIFY", + } ) // MakeDataDir retrieves the currently requested data directory, terminating @@ -1185,6 +1240,19 @@ func setRollup(ctx *cli.Context, cfg *rollup.Config) { if ctx.GlobalIsSet(SequencerClientHttpFlag.Name) { cfg.SequencerClientHttp = ctx.GlobalString(SequencerClientHttpFlag.Name) } + if ctx.GlobalIsSet(RollupRoleFlag.Name) { + str := ctx.GlobalString(RollupRoleFlag.Name) + switch str { + case "scheduler", "SCHEDULER": + cfg.RollupRole = rollup.SCHEDULER_NODE + case "sequencer", "SEQUENCER": + cfg.RollupRole = rollup.SEQUENCER_NODE + case "replica", "REPLICA", "verifier", "VERIFIER": + cfg.RollupRole = rollup.VERIFIER_NODE + default: + log.Crit("invalid rollup role", "role", str) + } + } } // setLes configures the les server and ultra light client settings from the command line flags. diff --git a/l2geth/core/blockchain.go b/l2geth/core/blockchain.go index 37ba594c5..37c95dd05 100644 --- a/l2geth/core/blockchain.go +++ b/l2geth/core/blockchain.go @@ -1451,6 +1451,66 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types. return status, nil } +// WriteBlockAndSetHead writes the given block and all associated state to the database, +// and applies the block as the new chain head. +func (bc *BlockChain) WriteBlockAndSetHead(block *types.Block, receipts []*types.Receipt, logs []*types.Log, state *state.StateDB, emitHeadEvent bool) (status WriteStatus, err error) { + if !bc.chainmu.TryLock() { + return NonStatTy, errors.New("blockchain is stopped") + } + defer bc.chainmu.Unlock() + + return bc.writeBlockAndSetHead(block, receipts, logs, state, emitHeadEvent) +} + +// writeBlockAndSetHead is the internal implementation of WriteBlockAndSetHead. +// This function expects the chain mutex to be held. +func (bc *BlockChain) writeBlockAndSetHead(block *types.Block, receipts []*types.Receipt, logs []*types.Log, state *state.StateDB, emitHeadEvent bool) (status WriteStatus, err error) { + if _, err := bc.writeBlockWithState(block, receipts, logs, state, emitHeadEvent); err != nil { + return NonStatTy, err + } + // TODO-FIXME test this + //currentBlock := bc.CurrentBlock() + // ignore reorg logics + //reorg, err := bc.forker.ReorgNeeded(currentBlock.Header(), block.Header()) + //if err != nil { + // return NonStatTy, err + //} + //if reorg { + // // Reorganise the chain if the parent is not the head block + // if block.ParentHash() != currentBlock.Hash() { + // if err := bc.reorg(currentBlock, block); err != nil { + // return NonStatTy, err + // } + // } + // status = CanonStatTy + //} else { + status = SideStatTy + //} + // Set new head. + if status == CanonStatTy { + bc.writeHeadBlock(block) + } + bc.futureBlocks.Remove(block.Hash()) + + if status == CanonStatTy { + bc.chainFeed.Send(ChainEvent{Block: block, Hash: block.Hash(), Logs: logs}) + if len(logs) > 0 { + bc.logsFeed.Send(logs) + } + // In theory we should fire a ChainHeadEvent when we inject + // a canonical block, but sometimes we can insert a batch of + // canonical blocks. Avoid firing too many ChainHeadEvents, + // we will fire an accumulated ChainHeadEvent and disable fire + // event here. + if emitHeadEvent { + bc.chainHeadFeed.Send(ChainHeadEvent{Block: block}) + } + } else { + bc.chainSideFeed.Send(ChainSideEvent{Block: block}) + } + return status, nil +} + // addFutureBlock checks if the block is within the max allowed window to get // accepted for future processing, and returns an error if the block is too far // ahead and was not added. diff --git a/l2geth/core/evm.go b/l2geth/core/evm.go index 6002c93e8..f3e1aa2d8 100644 --- a/l2geth/core/evm.go +++ b/l2geth/core/evm.go @@ -37,6 +37,40 @@ type ChainContext interface { GetHeader(common.Hash, uint64) *types.Header } +// NewEVMBlockContext creates a new context for use in the EVM. +func NewEVMBlockContext(header *types.Header, chain ChainContext, author *common.Address) vm.BlockContext { + var ( + beneficiary common.Address + baseFee *big.Int + random *common.Hash + ) + + // If we don't have an explicit author (i.e. not mining), extract from the header + if author == nil { + beneficiary, _ = chain.Engine().Author(header) // Ignore error, we're past header validation + } else { + beneficiary = *author + } + //if header.BaseFee != nil { + // baseFee = new(big.Int).Set(header.BaseFee) + //} + if header.Difficulty.Cmp(common.Big0) == 0 { + random = &header.MixDigest + } + return vm.BlockContext{ + CanTransfer: CanTransfer, + Transfer: Transfer, + GetHash: GetHashFn(header, chain), + Coinbase: beneficiary, + BlockNumber: new(big.Int).Set(header.Number), + Time: new(big.Int).SetUint64(header.Time), + Difficulty: new(big.Int).Set(header.Difficulty), + BaseFee: baseFee, + GasLimit: header.GasLimit, + Random: random, + } +} + // NewEVMContext creates a new context for use in the EVM. func NewEVMContext(msg Message, header *types.Header, chain ChainContext, author *common.Address) vm.Context { // If we don't have an explicit author (i.e. not mining), extract from the header diff --git a/l2geth/core/rawdb/accessors_chain.go b/l2geth/core/rawdb/accessors_chain.go index ec71176b6..d5542eedc 100644 --- a/l2geth/core/rawdb/accessors_chain.go +++ b/l2geth/core/rawdb/accessors_chain.go @@ -30,6 +30,33 @@ import ( "github.com/mantlenetworkio/mantle/l2geth/rlp" ) +func ReadFPValidatorChallengeCtx(db ethdb.Reader) []byte { + exist, err := db.Has(FPValidatorChallengeCtx) + if err != nil { + log.Crit("Failed to check fp challenge ctx", "err", err) + } + if !exist { + return nil + } + data, err := db.Get(FPValidatorChallengeCtx) + if err != nil { + log.Crit("Failed to get fp challenge ctx", "err", err) + } + return data +} + +func WriteFPValidatorChallengeCtx(db ethdb.Writer, data []byte) { + if err := db.Put(FPValidatorChallengeCtx, data); err != nil { + log.Crit("Failed to store fp challenge ctx", "err", err) + } +} + +func DeleteFPValidatorChallengeCtx(db ethdb.Writer) { + if err := db.Delete(FPValidatorChallengeCtx); err != nil { + log.Crit("Failed to store fp challenge ctx", "err", err) + } +} + // ReadCanonicalHash retrieves the hash assigned to a canonical block number. func ReadCanonicalHash(db ethdb.Reader, number uint64) common.Hash { data, _ := db.Ancient(freezerHashTable, number) diff --git a/l2geth/core/rawdb/schema.go b/l2geth/core/rawdb/schema.go index 46e872e1a..42bd03512 100644 --- a/l2geth/core/rawdb/schema.go +++ b/l2geth/core/rawdb/schema.go @@ -76,6 +76,9 @@ var ( preimageCounter = metrics.NewRegisteredCounter("db/preimage/total", nil) preimageHitCounter = metrics.NewRegisteredCounter("db/preimage/hits", nil) + + FPSchedulerConfirmLoopNumberCache = []byte("FPSchedulerConfirmLoopNumberCache") + FPValidatorChallengeCtx = []byte("FPValidatorChallengeCtx") ) const ( diff --git a/l2geth/core/rawdb/table.go b/l2geth/core/rawdb/table.go index 82644bd61..88dba4159 100644 --- a/l2geth/core/rawdb/table.go +++ b/l2geth/core/rawdb/table.go @@ -166,6 +166,18 @@ func (t *table) NewBatch() ethdb.Batch { return &tableBatch{t.db.NewBatch(), t.prefix} } +// NewBatchWithSize creates a write-only database batch with pre-allocated buffer. +func (t *table) NewBatchWithSize(size int) ethdb.Batch { + return &tableBatch{t.db.NewBatchWithSize(size), t.prefix} +} + +//// NewSnapshot creates a database snapshot based on the current state. +//// The created snapshot will not be affected by all following mutations +//// happened on the database. +//func (t *table) NewSnapshot() (ethdb.Snapshot, error) { +// return t.db.NewSnapshot() +//} + // tableBatch is a wrapper around a database batch that prefixes each key access // with a pre-configured string. type tableBatch struct { diff --git a/l2geth/core/state/database.go b/l2geth/core/state/database.go index 634f784b8..559a3c64f 100644 --- a/l2geth/core/state/database.go +++ b/l2geth/core/state/database.go @@ -18,7 +18,6 @@ package state import ( "fmt" - lru "github.com/hashicorp/golang-lru" "github.com/mantlenetworkio/mantle/l2geth/common" "github.com/mantlenetworkio/mantle/l2geth/ethdb" @@ -103,6 +102,17 @@ func NewDatabase(db ethdb.Database) Database { return NewDatabaseWithCache(db, 0) } +//// NewDatabaseWithConfig creates a backing store for state. The returned database +//// is safe for concurrent use and retains a lot of collapsed RLP trie nodes in a +//// large memory cache. +//func NewDatabaseWithConfig(db ethdb.Database, config *trie.Config) Database { +// csc, _ := lru.New(codeSizeCacheSize) +// return &cachingDB{ +// db: trie.NewDatabaseWithConfig(db, config), +// codeSizeCache: csc, +// } +//} + // NewDatabaseWithCache creates a backing store for state. The returned database // is safe for concurrent use and retains a lot of collapsed RLP trie nodes in a // large memory cache. diff --git a/l2geth/core/state/statedb.go b/l2geth/core/state/statedb.go index 34f1bd9b0..370b4c3e7 100644 --- a/l2geth/core/state/statedb.go +++ b/l2geth/core/state/statedb.go @@ -580,8 +580,8 @@ func (s *StateDB) createObject(addr common.Address) (newobj, prev *stateObject) // CreateAccount is called during the EVM CREATE operation. The situation might arise that // a contract does the following: // -// 1. sends funds to sha(account ++ (nonce + 1)) -// 2. tx_create(sha(account ++ nonce)) (note that this gets the address of 1) +// 1. sends funds to sha(account ++ (nonce + 1)) +// 2. tx_create(sha(account ++ nonce)) (note that this gets the address of 1) // // Carrying over the balance ensures that Ether doesn't disappear. func (s *StateDB) CreateAccount(addr common.Address) { @@ -888,3 +888,89 @@ func (s *StateDB) AddressInAccessList(addr common.Address) bool { func (s *StateDB) SlotInAccessList(addr common.Address, slot common.Hash) (addressPresent bool, slotPresent bool) { return s.accessList.Contains(addr, slot) } + +// +func (s *StateDB) GetCurrentLogs() []*types.Log { + return s.logs[s.thash] +} + +func (s *StateDB) GetCurrentAccessListForProof() (map[common.Address]int, []map[common.Hash]struct{}) { + return s.accessList.addresses, s.accessList.slots +} + +func (s *StateDB) GetStateRootForProof(addr common.Address) common.Hash { + stateObject := s.getStateObject(addr) + if stateObject == nil { + return common.Hash{} + } + return stateObject.data.Root +} + +func (s *StateDB) GetRootForProof() common.Hash { + return s.trie.Hash() +} + +func (s *StateDB) CommitForProof() { + addressesToPrefetch := make([][]byte, 0, len(s.journal.dirties)) + for addr := range s.journal.dirties { + obj, exist := s.stateObjects[addr] + if !exist { + continue + } + if obj.empty() { // rollup-specific: we ignore suicided accounts here + obj.deleted = true + //if s.snap != nil { + // s.snapDestructs[obj.addrHash] = struct{}{} // We need to maintain account deletions explicitly (will remain set indefinitely) + // delete(s.snapAccounts, obj.addrHash) // Clear out any previously updated account data (may be recreated via a ressurrect) + // delete(s.snapStorage, obj.addrHash) // Clear out any previously updated storage data (may be recreated via a ressurrect) + //} + } else { + obj.finalise() // Prefetch slots in the background + } + s.stateObjectsPending[addr] = struct{}{} + s.stateObjectsDirty[addr] = struct{}{} + addressesToPrefetch = append(addressesToPrefetch, common.CopyBytes(addr[:])) // Copy needed for closure + } + //if s.prefetcher != nil && len(addressesToPrefetch) > 0 { + // s.prefetcher.prefetch(common.Hash{}, s.originalRoot, addressesToPrefetch) + //} + for addr := range s.stateObjectsPending { + if obj := s.stateObjects[addr]; !obj.deleted { + obj.updateRoot(s.db) + } + } + //if s.prefetcher != nil { + // if trie := s.prefetcher.trie(common.Hash{}, s.originalRoot); trie != nil { + // s.trie = trie + // } + //} + for addr := range s.stateObjectsPending { + if obj := s.stateObjects[addr]; obj.deleted { + s.deleteStateObject(obj) + } else { + s.updateStateObject(obj) + } + } + if len(s.stateObjectsPending) > 0 { + s.stateObjectsPending = make(map[common.Address]struct{}) + } +} + +func (s *StateDB) DeleteSuicidedAccountForProof(addr common.Address) { + obj, exist := s.stateObjects[addr] + if !exist { + return + } + obj.deleted = true + //if s.prefetcher != nil { + // s.prefetcher.prefetch(common.Hash{}, s.originalRoot, [][]byte{common.CopyBytes(addr[:])}) + //} + //if s.prefetcher != nil { + // if trie := s.prefetcher.trie(common.Hash{}, s.originalRoot); trie != nil { + // s.trie = trie + // } + //} + s.deleteStateObject(obj) +} + +// diff --git a/l2geth/core/vm/evm.go b/l2geth/core/vm/evm.go index 7784a91db..04c2bc535 100644 --- a/l2geth/core/vm/evm.go +++ b/l2geth/core/vm/evm.go @@ -75,6 +75,27 @@ func run(evm *EVM, contract *Contract, input []byte, readOnly bool) ([]byte, err return nil, ErrNoCompatibleInterpreter } +// BlockContext provides the EVM with auxiliary information. Once provided +// it shouldn't be modified. +type BlockContext struct { + // CanTransfer returns whether the account contains + // sufficient ether to transfer the value + CanTransfer CanTransferFunc + // Transfer transfers ether from one account to the other + Transfer TransferFunc + // GetHash returns the hash corresponding to n + GetHash GetHashFunc + + // Block information + Coinbase common.Address // Provides information for COINBASE + GasLimit uint64 // Provides information for GASLIMIT + BlockNumber *big.Int // Provides information for NUMBER + Time *big.Int // Provides information for TIME + Difficulty *big.Int // Provides information for DIFFICULTY + BaseFee *big.Int // Provides information for BASEFEE + Random *common.Hash // Provides information for RANDOM +} + // Context provides the EVM with auxiliary information. Once provided // it shouldn't be modified. type Context struct { @@ -229,7 +250,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas if precompiles[addr] == nil && evm.chainRules.IsEIP158 && value.Sign() == 0 { // Calling a non existing account, don't do anything, but ping the tracer if evm.vmConfig.Debug && evm.depth == 0 { - evm.vmConfig.Tracer.CaptureStart(caller.Address(), addr, false, input, gas, value) + evm.vmConfig.Tracer.CaptureStart(evm, caller.Address(), addr, false, input, gas, value) evm.vmConfig.Tracer.CaptureEnd(ret, 0, 0, nil) } return nil, gas, nil @@ -247,7 +268,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas // Capture the tracer start/end events in debug mode if evm.vmConfig.Debug && evm.depth == 0 { - evm.vmConfig.Tracer.CaptureStart(caller.Address(), addr, false, input, gas, value) + evm.vmConfig.Tracer.CaptureStart(evm, caller.Address(), addr, false, input, gas, value) defer func() { // Lazy evaluation of the parameters evm.vmConfig.Tracer.CaptureEnd(ret, gas-contract.Gas, time.Since(start), err) @@ -433,7 +454,7 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64, } if evm.vmConfig.Debug && evm.depth == 0 { - evm.vmConfig.Tracer.CaptureStart(caller.Address(), address, true, codeAndHash.code, gas, value) + evm.vmConfig.Tracer.CaptureStart(evm, caller.Address(), address, true, codeAndHash.code, gas, value) } start := time.Now() diff --git a/l2geth/core/vm/instructions.go b/l2geth/core/vm/instructions.go index 60c3c609f..1e68f58c0 100644 --- a/l2geth/core/vm/instructions.go +++ b/l2geth/core/vm/instructions.go @@ -31,7 +31,8 @@ import ( var ( bigZero = new(big.Int) tt255 = math.BigPow(2, 255) - errWriteProtection = errors.New("evm: write protection") + ErrWriteProtection = errors.New("evm: write protection") + ErrNonceUintOverflow = errors.New("nonce uint64 overflow") errReturnDataOutOfBounds = errors.New("evm: return data out of bounds") errExecutionReverted = errors.New("evm: execution reverted") errMaxCodeSizeExceeded = errors.New("evm: max code size exceeded") @@ -520,16 +521,21 @@ func opExtCodeCopy(pc *uint64, interpreter *EVMInterpreter, contract *Contract, // opExtCodeHash returns the code hash of a specified account. // There are several cases when the function is called, while we can relay everything // to `state.GetCodeHash` function to ensure the correctness. -// (1) Caller tries to get the code hash of a normal contract account, state +// +// (1) Caller tries to get the code hash of a normal contract account, state +// // should return the relative code hash and set it as the result. // -// (2) Caller tries to get the code hash of a non-existent account, state should +// (2) Caller tries to get the code hash of a non-existent account, state should +// // return common.Hash{} and zero will be set as the result. // -// (3) Caller tries to get the code hash for an account without contract code, +// (3) Caller tries to get the code hash for an account without contract code, +// // state should return emptyCodeHash(0xc5d246...) as the result. // -// (4) Caller tries to get the code hash of a precompiled account, the result +// (4) Caller tries to get the code hash of a precompiled account, the result +// // should be zero or emptyCodeHash. // // It is worth noting that in order to avoid unnecessary create and clean, @@ -538,10 +544,12 @@ func opExtCodeCopy(pc *uint64, interpreter *EVMInterpreter, contract *Contract, // If the precompile account is not transferred any amount on a private or // customized chain, the return value will be zero. // -// (5) Caller tries to get the code hash for an account which is marked as suicided +// (5) Caller tries to get the code hash for an account which is marked as suicided +// // in the current transaction, the code hash of this account should be returned. // -// (6) Caller tries to get the code hash for an account which is marked as deleted, +// (6) Caller tries to get the code hash for an account which is marked as deleted, +// // this account should be regarded as a non-existent account and zero should be returned. func opExtCodeHash(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { slot := stack.peek() diff --git a/l2geth/core/vm/interface.go b/l2geth/core/vm/interface.go index b3eda8946..595bf2310 100644 --- a/l2geth/core/vm/interface.go +++ b/l2geth/core/vm/interface.go @@ -17,6 +17,7 @@ package vm import ( + "github.com/mantlenetworkio/mantle/l2geth/core/state" "math/big" "github.com/mantlenetworkio/mantle/l2geth/common" @@ -74,6 +75,18 @@ type StateDB interface { AddPreimage(common.Hash, []byte) ForEachStorage(common.Address, func(common.Hash, common.Hash) bool) error + + // + Copy() *state.StateDB + GetCurrentLogs() []*types.Log + GetCurrentAccessListForProof() (map[common.Address]int, []map[common.Hash]struct{}) + GetStateRootForProof(common.Address) common.Hash + GetProof(common.Address) ([][]byte, error) + GetStorageProof(common.Address, common.Hash) ([][]byte, error) + GetRootForProof() common.Hash + CommitForProof() + DeleteSuicidedAccountForProof(addr common.Address) + // } // CallContext provides a basic interface for the EVM calling conventions. The EVM diff --git a/l2geth/core/vm/interpreter.go b/l2geth/core/vm/interpreter.go index 7b880a619..c5f913d9d 100644 --- a/l2geth/core/vm/interpreter.go +++ b/l2geth/core/vm/interpreter.go @@ -189,7 +189,7 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) ( defer func() { if err != nil { if !logged { - in.cfg.Tracer.CaptureState(in.evm, pcCopy, op, gasCopy, cost, mem, stack, contract, in.evm.depth, err) + in.cfg.Tracer.CaptureState(in.evm, pcCopy, op, gasCopy, cost, mem, stack, contract, in.returnData, in.evm.depth, err) } else { in.cfg.Tracer.CaptureFault(in.evm, pcCopy, op, gasCopy, cost, mem, stack, contract, in.evm.depth, err) } @@ -227,7 +227,7 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) ( // account to the others means the state is modified and should also // return with an error. if operation.writes || (op == CALL && stack.Back(2).Sign() != 0) { - return nil, errWriteProtection + return nil, ErrWriteProtection } } // Static portion of gas @@ -268,7 +268,7 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) ( } if in.cfg.Debug { - in.cfg.Tracer.CaptureState(in.evm, pc, op, gasCopy, cost, mem, stack, contract, in.evm.depth, err) + in.cfg.Tracer.CaptureState(in.evm, pc, op, gasCopy, cost, mem, stack, contract, in.returnData, in.evm.depth, err) logged = true } diff --git a/l2geth/core/vm/logger.go b/l2geth/core/vm/logger.go index ad6f8f60f..0b87e05a8 100644 --- a/l2geth/core/vm/logger.go +++ b/l2geth/core/vm/logger.go @@ -102,8 +102,8 @@ func (s *StructLog) ErrorString() string { // Note that reference types are actual VM data structures; make copies // if you need to retain them beyond the current call. type Tracer interface { - CaptureStart(from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) error - CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *Memory, stack *Stack, contract *Contract, depth int, err error) error + CaptureStart(env *EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) error + CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *Memory, stack *Stack, contract *Contract, rData []byte, depth int, err error) error CaptureFault(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *Memory, stack *Stack, contract *Contract, depth int, err error) error CaptureEnd(output []byte, gasUsed uint64, t time.Duration, err error) error } @@ -134,14 +134,14 @@ func NewStructLogger(cfg *LogConfig) *StructLogger { } // CaptureStart implements the Tracer interface to initialize the tracing operation. -func (l *StructLogger) CaptureStart(from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) error { +func (l *StructLogger) CaptureStart(env *EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) error { return nil } // CaptureState logs a new structured log message and pushes it out to the environment // // CaptureState also tracks SSTORE ops to track dirty values. -func (l *StructLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *Memory, stack *Stack, contract *Contract, depth int, err error) error { +func (l *StructLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *Memory, stack *Stack, contract *Contract, rData []byte, depth int, err error) error { // check if already accumulated the specified number of logs if l.cfg.Limit != 0 && l.cfg.Limit <= len(l.logs) { return ErrTraceLimitReached @@ -274,7 +274,7 @@ func NewMarkdownLogger(cfg *LogConfig, writer io.Writer) *mdLogger { return l } -func (t *mdLogger) CaptureStart(from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) error { +func (t *mdLogger) CaptureStart(env *EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) error { if !create { fmt.Fprintf(t.out, "From: `%v`\nTo: `%v`\nData: `0x%x`\nGas: `%d`\nValue `%v` wei\n", from.String(), to.String(), @@ -292,7 +292,7 @@ func (t *mdLogger) CaptureStart(from common.Address, to common.Address, create b return nil } -func (t *mdLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *Memory, stack *Stack, contract *Contract, depth int, err error) error { +func (t *mdLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *Memory, stack *Stack, contract *Contract, rData []byte, depth int, err error) error { fmt.Fprintf(t.out, "| %4d | %10v | %3d |", pc, op, cost) if !t.cfg.DisableStack { diff --git a/l2geth/core/vm/logger_json.go b/l2geth/core/vm/logger_json.go index f7bdd0443..aa3793d29 100644 --- a/l2geth/core/vm/logger_json.go +++ b/l2geth/core/vm/logger_json.go @@ -41,12 +41,12 @@ func NewJSONLogger(cfg *LogConfig, writer io.Writer) *JSONLogger { return l } -func (l *JSONLogger) CaptureStart(from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) error { +func (l *JSONLogger) CaptureStart(env *EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) error { return nil } // CaptureState outputs state information on the logger. -func (l *JSONLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *Memory, stack *Stack, contract *Contract, depth int, err error) error { +func (l *JSONLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *Memory, stack *Stack, contract *Contract, rData []byte, depth int, err error) error { log := StructLog{ Pc: pc, Op: op, diff --git a/l2geth/eth/api_backend.go b/l2geth/eth/api_backend.go index 33a1aecac..ed9598f6a 100644 --- a/l2geth/eth/api_backend.go +++ b/l2geth/eth/api_backend.go @@ -20,6 +20,7 @@ import ( "context" "errors" "fmt" + "github.com/mantlenetworkio/mantle/l2geth/consensus" "math/big" "github.com/mantlenetworkio/mantle/l2geth/accounts" @@ -410,3 +411,14 @@ func (b *EthAPIBackend) ServiceFilter(ctx context.Context, session *bloombits.Ma go session.Multiplex(bloomRetrievalBatch, bloomRetrievalWait, b.eth.bloomRequests) } } + +func (b *EthAPIBackend) Engine() consensus.Engine { + return b.eth.engine +} +func (b *EthAPIBackend) StateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base *state.StateDB, checkLive, preferDisk bool) (*state.StateDB, error) { + return b.eth.StateAtBlock(block, reexec, base, checkLive, preferDisk) +} + +func (b *EthAPIBackend) StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (core.Message, vm.Context, *state.StateDB, error) { + return b.eth.stateAtTransaction(block, txIndex, reexec) +} diff --git a/l2geth/eth/backend.go b/l2geth/eth/backend.go index 4db535407..c88bcee50 100644 --- a/l2geth/eth/backend.go +++ b/l2geth/eth/backend.go @@ -26,6 +26,7 @@ import ( "sync" "sync/atomic" + "github.com/mantlenetworkio/mantle/fraud-proof/proof" "github.com/mantlenetworkio/mantle/l2geth/accounts" "github.com/mantlenetworkio/mantle/l2geth/accounts/abi/bind" "github.com/mantlenetworkio/mantle/l2geth/common" @@ -302,6 +303,10 @@ func CreateConsensusEngine(ctx *node.ServiceContext, chainConfig *params.ChainCo func (s *Ethereum) APIs() []rpc.API { apis := ethapi.GetAPIs(s.APIBackend) + // + apis = append(apis, proof.APIs(s.APIBackend)...) + // + // Append any APIs exposed explicitly by the les server if s.lesServer != nil { apis = append(apis, s.lesServer.APIs()...) @@ -309,11 +314,6 @@ func (s *Ethereum) APIs() []rpc.API { // Append any APIs exposed explicitly by the consensus engine apis = append(apis, s.engine.APIs(s.BlockChain())...) - // Append any APIs exposed explicitly by the les server - if s.lesServer != nil { - apis = append(apis, s.lesServer.APIs()...) - } - // Append all the local APIs and return return append(apis, []rpc.API{ { diff --git a/l2geth/eth/state_accessor.go b/l2geth/eth/state_accessor.go new file mode 100644 index 000000000..84d5a19cd --- /dev/null +++ b/l2geth/eth/state_accessor.go @@ -0,0 +1,201 @@ +// Copyright 2021 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package eth + +import ( + "errors" + "fmt" + "time" + + "github.com/ethereum/go-ethereum/trie" + "github.com/mantlenetworkio/mantle/l2geth/common" + "github.com/mantlenetworkio/mantle/l2geth/core" + "github.com/mantlenetworkio/mantle/l2geth/core/state" + "github.com/mantlenetworkio/mantle/l2geth/core/types" + "github.com/mantlenetworkio/mantle/l2geth/core/vm" + "github.com/mantlenetworkio/mantle/l2geth/log" +) + +// StateAtBlock retrieves the state database associated with a certain block. +// If no state is locally available for the given block, a number of blocks +// are attempted to be reexecuted to generate the desired state. The optional +// base layer statedb can be passed then it's regarded as the statedb of the +// parent block. +// Parameters: +// - block: The block for which we want the state (== state at the stateRoot of the parent) +// - reexec: The maximum number of blocks to reprocess trying to obtain the desired state +// - base: If the caller is tracing multiple blocks, the caller can provide the parent state +// continuously from the callsite. +// - checklive: if true, then the live 'blockchain' state database is used. If the caller want to +// perform Commit or other 'save-to-disk' changes, this should be set to false to avoid +// storing trash persistently +// - preferDisk: this arg can be used by the caller to signal that even though the 'base' is provided, +// it would be preferable to start from a fresh state, if we have it on disk. +func (eth *Ethereum) StateAtBlock(block *types.Block, reexec uint64, base *state.StateDB, checkLive bool, preferDisk bool) (statedb *state.StateDB, err error) { + var ( + current *types.Block + database state.Database + report = true + origin = block.NumberU64() + ) + // Check the live database first if we have the state fully available, use that. + if checkLive { + statedb, err = eth.blockchain.StateAt(block.Root()) + if err == nil { + return statedb, nil + } + } + if base != nil { + if preferDisk { + // Create an ephemeral trie.Database for isolating the live one. Otherwise + // the internal junks created by tracing will be persisted into the disk. + database = state.NewDatabaseWithCache(eth.chainDb, 16) + if statedb, err = state.New(block.Root(), database); err == nil { + log.Info("Found disk backend for state trie", "root", block.Root(), "number", block.Number()) + return statedb, nil + } + } + // The optional base statedb is given, mark the start point as parent block + statedb, database, report = base, base.Database(), false + current = eth.blockchain.GetBlock(block.ParentHash(), block.NumberU64()-1) + } else { + // Otherwise try to reexec blocks until we find a state or reach our limit + current = block + + // Create an ephemeral trie.Database for isolating the live one. Otherwise + // the internal junks created by tracing will be persisted into the disk. + database = state.NewDatabaseWithCache(eth.chainDb, 16) + + // If we didn't check the dirty database, do check the clean one, otherwise + // we would rewind past a persisted block (specific corner case is chain + // tracing from the genesis). + if !checkLive { + statedb, err = state.New(current.Root(), database) + if err == nil { + return statedb, nil + } + } + // Database does not have the state for the given block, try to regenerate + for i := uint64(0); i < reexec; i++ { + if current.NumberU64() == 0 { + return nil, errors.New("genesis state is missing") + } + parent := eth.blockchain.GetBlock(current.ParentHash(), current.NumberU64()-1) + if parent == nil { + return nil, fmt.Errorf("missing block %v %d", current.ParentHash(), current.NumberU64()-1) + } + current = parent + + statedb, err = state.New(current.Root(), database) + if err == nil { + break + } + } + if err != nil { + switch err.(type) { + case *trie.MissingNodeError: + return nil, fmt.Errorf("required historical state unavailable (reexec=%d)", reexec) + default: + return nil, err + } + } + } + // State was available at historical point, regenerate + var ( + start = time.Now() + logged time.Time + parent common.Hash + ) + for current.NumberU64() < origin { + // Print progress logs if long enough time elapsed + if time.Since(logged) > 8*time.Second && report { + log.Info("Regenerating historical state", "block", current.NumberU64()+1, "target", origin, "remaining", origin-current.NumberU64()-1, "elapsed", time.Since(start)) + logged = time.Now() + } + // Retrieve the next block to regenerate and process it + next := current.NumberU64() + 1 + if current = eth.blockchain.GetBlockByNumber(next); current == nil { + return nil, fmt.Errorf("block #%d not found", next) + } + _, _, _, err := eth.blockchain.Processor().Process(current, statedb, vm.Config{}) + if err != nil { + return nil, fmt.Errorf("processing block %d failed: %v", current.NumberU64(), err) + } + // Finalize the state so any modifications are written to the trie + root, err := statedb.Commit(eth.blockchain.Config().IsEIP158(current.Number())) + if err != nil { + return nil, fmt.Errorf("stateAtBlock commit failed, number %d root %v: %w", + current.NumberU64(), current.Root().Hex(), err) + } + statedb, err = state.New(root, database) + if err != nil { + return nil, fmt.Errorf("state reset after block %d failed: %v", current.NumberU64(), err) + } + database.TrieDB().Reference(root, common.Hash{}) + if parent != (common.Hash{}) { + database.TrieDB().Dereference(parent) + } + parent = root + } + if report { + nodes, imgs := database.TrieDB().Size() + log.Info("Historical state regenerated", "block", current.NumberU64(), "elapsed", time.Since(start), "nodes", nodes, "preimages", imgs) + } + return statedb, nil +} + +// stateAtTransaction returns the execution environment of a certain transaction. +func (eth *Ethereum) stateAtTransaction(block *types.Block, txIndex int, reexec uint64) (core.Message, vm.Context, *state.StateDB, error) { + // Short circuit if it's genesis block. + if block.NumberU64() == 0 { + return nil, vm.Context{}, nil, errors.New("no transaction in genesis") + } + // Create the parent state database + parent := eth.blockchain.GetBlock(block.ParentHash(), block.NumberU64()-1) + if parent == nil { + return nil, vm.Context{}, nil, fmt.Errorf("parent %#x not found", block.ParentHash()) + } + // Lookup the statedb of parent block from the live database, + // otherwise regenerate it on the flight. + statedb, err := eth.StateAtBlock(parent, reexec, nil, true, false) + if err != nil { + return nil, vm.Context{}, nil, err + } + if txIndex == 0 && len(block.Transactions()) == 0 { + return nil, vm.Context{}, statedb, nil + } + // Recompute transactions up to the target index. + signer := types.MakeSigner(eth.blockchain.Config(), block.Number()) + for idx, tx := range block.Transactions() { + // Assemble the transaction call message and return if the requested offset + msg, _ := tx.AsMessage(signer) + context := core.NewEVMContext(msg, block.Header(), eth.blockchain, nil) + if idx == txIndex { + return msg, context, statedb, nil + } + // Not yet the searched for transaction, execute on top of the current state + vmenv := vm.NewEVM(context, statedb, eth.blockchain.Config(), vm.Config{}) + statedb.Prepare(tx.Hash(), block.Header().Hash(), idx) + if _, _, _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(tx.Gas())); err != nil { + return nil, vm.Context{}, nil, fmt.Errorf("transaction %#x failed: %v", tx.Hash(), err) + } + // Ensure any modifications are committed to the state + // Only delete empty objects if EIP158/161 (a.k.a Spurious Dragon) is in effect + statedb.Finalise(vmenv.ChainConfig().IsEIP158(block.Number())) + } + return nil, vm.Context{}, nil, fmt.Errorf("transaction index %d out of range for block %#x", txIndex, block.Hash()) +} diff --git a/l2geth/eth/tracers/tracer.go b/l2geth/eth/tracers/tracer.go index 14276f3ce..c6aad680e 100644 --- a/l2geth/eth/tracers/tracer.go +++ b/l2geth/eth/tracers/tracer.go @@ -517,7 +517,7 @@ func wrapError(context string, err error) error { } // CaptureStart implements the Tracer interface to initialize the tracing operation. -func (jst *Tracer) CaptureStart(from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) error { +func (jst *Tracer) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) error { jst.ctx["type"] = "CALL" if create { jst.ctx["type"] = "CREATE" @@ -532,7 +532,7 @@ func (jst *Tracer) CaptureStart(from common.Address, to common.Address, create b } // CaptureState implements the Tracer interface to trace a single step of VM execution. -func (jst *Tracer) CaptureState(env *vm.EVM, pc uint64, op vm.OpCode, gas, cost uint64, memory *vm.Memory, stack *vm.Stack, contract *vm.Contract, depth int, err error) error { +func (jst *Tracer) CaptureState(env *vm.EVM, pc uint64, op vm.OpCode, gas, cost uint64, memory *vm.Memory, stack *vm.Stack, contract *vm.Contract, rData []byte, depth int, err error) error { if jst.err == nil { // Initialize the context if it wasn't done yet if !jst.inited { diff --git a/l2geth/eth/tracers/tracer_test.go b/l2geth/eth/tracers/tracer_test.go index 3510cbd99..cd2506564 100644 --- a/l2geth/eth/tracers/tracer_test.go +++ b/l2geth/eth/tracers/tracer_test.go @@ -136,10 +136,10 @@ func TestHaltBetweenSteps(t *testing.T) { env := vm.NewEVM(vm.Context{BlockNumber: big.NewInt(1)}, &dummyStatedb{}, params.TestChainConfig, vm.Config{Debug: true, Tracer: tracer}) contract := vm.NewContract(&account{}, &account{}, big.NewInt(0), 0) - tracer.CaptureState(env, 0, 0, 0, 0, nil, nil, contract, 0, nil) + tracer.CaptureState(env, 0, 0, 0, 0, nil, nil, contract, nil, 0, nil) timeout := errors.New("stahp") tracer.Stop(timeout) - tracer.CaptureState(env, 0, 0, 0, 0, nil, nil, contract, 0, nil) + tracer.CaptureState(env, 0, 0, 0, 0, nil, nil, contract, nil, 0, nil) if _, err := tracer.GetResult(); err.Error() != timeout.Error() { t.Errorf("Expected timeout error, got %v", err) diff --git a/l2geth/ethdb/batch.go b/l2geth/ethdb/batch.go index e261415bf..c1c0c9abf 100644 --- a/l2geth/ethdb/batch.go +++ b/l2geth/ethdb/batch.go @@ -43,4 +43,7 @@ type Batcher interface { // NewBatch creates a write-only database that buffers changes to its host db // until a final write is called. NewBatch() Batch + + // NewBatchWithSize creates a write-only database batch with pre-allocated buffer. + NewBatchWithSize(size int) Batch } diff --git a/l2geth/ethdb/database.go b/l2geth/ethdb/database.go index 0dc14624b..8c498a819 100644 --- a/l2geth/ethdb/database.go +++ b/l2geth/ethdb/database.go @@ -17,7 +17,9 @@ // Package ethdb defines the interfaces for an Ethereum data store. package ethdb -import "io" +import ( + "io" +) // KeyValueReader wraps the Has and Get method of a backing data store. type KeyValueReader interface { @@ -127,5 +129,6 @@ type Database interface { Iteratee Stater Compacter + //Snapshotter io.Closer } diff --git a/l2geth/ethdb/leveldb/leveldb.go b/l2geth/ethdb/leveldb/leveldb.go index 6d11ba772..382fb13c8 100644 --- a/l2geth/ethdb/leveldb/leveldb.go +++ b/l2geth/ethdb/leveldb/leveldb.go @@ -184,6 +184,27 @@ func (db *Database) NewBatch() ethdb.Batch { } } +// NewBatchWithSize creates a write-only database batch with pre-allocated buffer. +func (db *Database) NewBatchWithSize(size int) ethdb.Batch { + return &batch{ + db: db.db, + b: leveldb.MakeBatch(size), + } +} + +// NewSnapshot creates a database snapshot based on the current state. +// The created snapshot will not be affected by all following mutations +// happened on the database. +// Note don't forget to release the snapshot once it's used up, otherwise +// the stale data will never be cleaned up by the underlying compactor. +func (db *Database) NewSnapshot() (ethdb.Snapshot, error) { + snap, err := db.db.GetSnapshot() + if err != nil { + return nil, err + } + return &snapshot{db: snap}, nil +} + // NewIterator creates a binary-alphabetical iterator over the entire keyspace // contained within the leveldb database. func (db *Database) NewIterator() ethdb.Iterator { @@ -228,13 +249,14 @@ func (db *Database) Path() string { // the metrics subsystem. // // This is how a LevelDB stats table looks like (currently): -// Compactions -// Level | Tables | Size(MB) | Time(sec) | Read(MB) | Write(MB) -// -------+------------+---------------+---------------+---------------+--------------- -// 0 | 0 | 0.00000 | 1.27969 | 0.00000 | 12.31098 -// 1 | 85 | 109.27913 | 28.09293 | 213.92493 | 214.26294 -// 2 | 523 | 1000.37159 | 7.26059 | 66.86342 | 66.77884 -// 3 | 570 | 1113.18458 | 0.00000 | 0.00000 | 0.00000 +// +// Compactions +// Level | Tables | Size(MB) | Time(sec) | Read(MB) | Write(MB) +// -------+------------+---------------+---------------+---------------+--------------- +// 0 | 0 | 0.00000 | 1.27969 | 0.00000 | 12.31098 +// 1 | 85 | 109.27913 | 28.09293 | 213.92493 | 214.26294 +// 2 | 523 | 1000.37159 | 7.26059 | 66.86342 | 66.77884 +// 3 | 570 | 1113.18458 | 0.00000 | 0.00000 | 0.00000 // // This is how the write delay look like (currently): // DelayN:5 Delay:406.604657ms Paused: false @@ -489,3 +511,26 @@ func (r *replayer) Delete(key []byte) { } r.failure = r.writer.Delete(key) } + +// snapshot wraps a leveldb snapshot for implementing the Snapshot interface. +type snapshot struct { + db *leveldb.Snapshot +} + +// Has retrieves if a key is present in the snapshot backing by a key-value +// data store. +func (snap *snapshot) Has(key []byte) (bool, error) { + return snap.db.Has(key, nil) +} + +// Get retrieves the given key if it's present in the snapshot backing by +// key-value data store. +func (snap *snapshot) Get(key []byte) ([]byte, error) { + return snap.db.Get(key, nil) +} + +// Release releases associated resources. Release should always succeed and can +// be called multiple times without causing error. +func (snap *snapshot) Release() { + snap.db.Release() +} diff --git a/l2geth/ethdb/memorydb/memorydb.go b/l2geth/ethdb/memorydb/memorydb.go index cad15846a..39acd1fd1 100644 --- a/l2geth/ethdb/memorydb/memorydb.go +++ b/l2geth/ethdb/memorydb/memorydb.go @@ -129,6 +129,20 @@ func (db *Database) NewBatch() ethdb.Batch { } } +// NewBatchWithSize creates a write-only database batch with pre-allocated buffer. +func (db *Database) NewBatchWithSize(size int) ethdb.Batch { + return &batch{ + db: db, + } +} + +// NewSnapshot creates a database snapshot based on the current state. +// The created snapshot will not be affected by all following mutations +// happened on the database. +func (db *Database) NewSnapshot() (ethdb.Snapshot, error) { + return newSnapshot(db), nil +} + // NewIterator creates a binary-alphabetical iterator over the entire keyspace // contained within the memory database. func (db *Database) NewIterator() ethdb.Iterator { @@ -342,3 +356,59 @@ func (it *iterator) Value() []byte { func (it *iterator) Release() { it.keys, it.values = nil, nil } + +// snapshot wraps a batch of key-value entries deep copied from the in-memory +// database for implementing the Snapshot interface. +type snapshot struct { + db map[string][]byte + lock sync.RWMutex +} + +// newSnapshot initializes the snapshot with the given database instance. +func newSnapshot(db *Database) *snapshot { + db.lock.RLock() + defer db.lock.RUnlock() + + copied := make(map[string][]byte) + for key, val := range db.db { + copied[key] = common.CopyBytes(val) + } + return &snapshot{db: copied} +} + +// Has retrieves if a key is present in the snapshot backing by a key-value +// data store. +func (snap *snapshot) Has(key []byte) (bool, error) { + snap.lock.RLock() + defer snap.lock.RUnlock() + + if snap.db == nil { + return false, errors.New("snapshot released") + } + _, ok := snap.db[string(key)] + return ok, nil +} + +// Get retrieves the given key if it's present in the snapshot backing by +// key-value data store. +func (snap *snapshot) Get(key []byte) ([]byte, error) { + snap.lock.RLock() + defer snap.lock.RUnlock() + + if snap.db == nil { + return nil, errors.New("snapshot released") + } + if entry, ok := snap.db[string(key)]; ok { + return common.CopyBytes(entry), nil + } + return nil, errMemorydbNotFound +} + +// Release releases associated resources. Release should always succeed and can +// be called multiple times without causing error. +func (snap *snapshot) Release() { + snap.lock.Lock() + defer snap.lock.Unlock() + + snap.db = nil +} diff --git a/l2geth/ethdb/snapshot.go b/l2geth/ethdb/snapshot.go new file mode 100644 index 000000000..03b7794a7 --- /dev/null +++ b/l2geth/ethdb/snapshot.go @@ -0,0 +1,41 @@ +// Copyright 2022 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package ethdb + +type Snapshot interface { + // Has retrieves if a key is present in the snapshot backing by a key-value + // data store. + Has(key []byte) (bool, error) + + // Get retrieves the given key if it's present in the snapshot backing by + // key-value data store. + Get(key []byte) ([]byte, error) + + // Release releases associated resources. Release should always succeed and can + // be called multiple times without causing error. + Release() +} + +// Snapshotter wraps the Snapshot method of a backing data store. +type Snapshotter interface { + // NewSnapshot creates a database snapshot based on the current state. + // The created snapshot will not be affected by all following mutations + // happened on the database. + // Note don't forget to release the snapshot once it's used up, otherwise + // the stale data will never be cleaned up by the underlying compactor. + NewSnapshot() (Snapshot, error) +} diff --git a/l2geth/params/config.go b/l2geth/params/config.go index ddf79743d..5c6688084 100644 --- a/l2geth/params/config.go +++ b/l2geth/params/config.go @@ -614,7 +614,7 @@ type Rules struct { ChainID *big.Int IsHomestead, IsEIP150, IsEIP155, IsEIP158 bool IsByzantium, IsConstantinople, IsPetersburg, IsIstanbul bool - IsBerlin bool + IsBerlin, IsLondon bool ISUpdateGaslimitBlock bool } diff --git a/l2geth/params/protocol_params.go b/l2geth/params/protocol_params.go index d1d10ff76..e5be27a99 100644 --- a/l2geth/params/protocol_params.go +++ b/l2geth/params/protocol_params.go @@ -145,6 +145,11 @@ const ( Bn256PairingBaseGasIstanbul uint64 = 45000 // Base price for an elliptic curve pairing check Bn256PairingPerPointGasByzantium uint64 = 80000 // Byzantium per-point price for an elliptic curve pairing check Bn256PairingPerPointGasIstanbul uint64 = 34000 // Per-point price for an elliptic curve pairing check + + // The Refund Quotient is the cap on how much of the used gas can be refunded. Before EIP-3529, + // up to half the consumed gas could be refunded. Redefined as 1/5th in EIP-3529 + RefundQuotient uint64 = 2 + RefundQuotientEIP3529 uint64 = 5 ) var ( diff --git a/l2geth/rollup/config.go b/l2geth/rollup/config.go index ca892c347..1b647bfc5 100644 --- a/l2geth/rollup/config.go +++ b/l2geth/rollup/config.go @@ -47,6 +47,10 @@ type Config struct { FeeThresholdUp *big.Float // HTTP endpoint of the sequencer SequencerClientHttp string + // stake amount + StakeAmount *big.Int + // node character + RollupRole Role MpcVerifier bool } diff --git a/l2geth/rollup/types.go b/l2geth/rollup/types.go index bbdfc1359..7165e7c2d 100644 --- a/l2geth/rollup/types.go +++ b/l2geth/rollup/types.go @@ -98,3 +98,11 @@ func isCtcTxEqual(a, b *types.Transaction) bool { } return true } + +type Role uint8 + +const ( + SCHEDULER_NODE Role = 0 + SEQUENCER_NODE Role = 1 + VERIFIER_NODE Role = 2 +) diff --git a/mt-batcher/go.mod b/mt-batcher/go.mod index aab773776..fa9a7a556 100644 --- a/mt-batcher/go.mod +++ b/mt-batcher/go.mod @@ -9,7 +9,7 @@ replace github.com/Layr-Labs/datalayr/lib/merkzg => ../datalayr-mantle/lib/merkz replace github.com/mantlenetworkio/mantle/l2geth v0.0.0 => ../l2geth require ( - // github.com/Layr-Labs/datalayr/common v0.0.0-00010101000000-000000000000 + github.com/Layr-Labs/datalayr/common v0.0.0-00010101000000-000000000000 github.com/ethereum/go-ethereum v1.10.26 github.com/go-resty/resty/v2 v2.7.0 github.com/mantlenetworkio/mantle/l2geth v0.0.0 @@ -27,10 +27,7 @@ require ( github.com/tyler-smith/go-bip39 v1.1.0 ) -require ( - github.com/Layr-Labs/datalayr/common v0.0.0-00010101000000-000000000000 - github.com/shurcooL/graphql v0.0.0-20220606043923-3cf50f8a0a29 -) +require github.com/shurcooL/graphql v0.0.0-20220606043923-3cf50f8a0a29 require ( github.com/Layr-Labs/datalayr/lib/merkzg v0.0.0-00010101000000-000000000000 // indirect @@ -63,6 +60,7 @@ require ( github.com/google/go-cmp v0.5.9 // indirect github.com/google/uuid v1.3.0 // indirect github.com/gorilla/websocket v1.5.0 // indirect + github.com/hashicorp/go-bexpr v0.1.11 // indirect github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d // indirect github.com/holiman/bloomfilter/v2 v2.0.3 // indirect github.com/holiman/uint256 v1.2.0 // indirect diff --git a/mt-batcher/go.sum b/mt-batcher/go.sum index 48afe5829..4ea20f2d0 100644 --- a/mt-batcher/go.sum +++ b/mt-batcher/go.sum @@ -387,8 +387,9 @@ github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFb github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/errwrap v1.0.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-bexpr v0.1.11 h1:6DqdA/KBjurGby9yTY0bmkathya0lfwF2SeuubCI7dY= +github.com/hashicorp/go-bexpr v0.1.11/go.mod h1:f03lAo0duBlDIUMGCuad8oLcgejw4m7U+N8T+6Kz1AE= github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= @@ -541,8 +542,9 @@ github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/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/pointerstructure v1.2.1 h1:ZhBBeX8tSlRpu/FFhXH4RC4OJzFlqsQhoHZAz4x7TIw= +github.com/mitchellh/pointerstructure v1.2.1/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= 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= diff --git a/mt-challenger/go.mod b/mt-challenger/go.mod index df9a21cce..9d57c3569 100644 --- a/mt-challenger/go.mod +++ b/mt-challenger/go.mod @@ -53,13 +53,13 @@ require ( github.com/golang/snappy v0.0.4 // indirect github.com/google/uuid v1.3.0 // indirect github.com/gorilla/websocket v1.5.0 // indirect - github.com/hashicorp/go-bexpr v0.1.11 // indirect github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d // indirect github.com/holiman/bloomfilter/v2 v2.0.3 // indirect github.com/holiman/uint256 v1.2.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.16 // indirect github.com/mattn/go-runewidth v0.0.13 // indirect + github.com/mitchellh/pointerstructure v1.2.1 // indirect github.com/mmcloughlin/addchain v0.4.0 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/prometheus/tsdb v0.10.0 // indirect diff --git a/mt-challenger/go.sum b/mt-challenger/go.sum index 18dd7f393..e23f262bc 100644 --- a/mt-challenger/go.sum +++ b/mt-challenger/go.sum @@ -351,7 +351,6 @@ github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyN github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= github.com/hashicorp/go-bexpr v0.1.11 h1:6DqdA/KBjurGby9yTY0bmkathya0lfwF2SeuubCI7dY= -github.com/hashicorp/go-bexpr v0.1.11/go.mod h1:f03lAo0duBlDIUMGCuad8oLcgejw4m7U+N8T+6Kz1AE= github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= diff --git a/ops/docker-compose.yml b/ops/docker-compose.yml index 81d6a6011..6c620fa77 100644 --- a/ops/docker-compose.yml +++ b/ops/docker-compose.yml @@ -86,6 +86,7 @@ services: entrypoint: sh ./geth.sh env_file: - ./envs/geth.env + - ./envs/fraud_proof.env volumes: - ./data/l2geth:/root/.ethereum/geth/ environment: @@ -105,6 +106,8 @@ services: ROLLUP_FEE_THRESHOLD_UP: 1.1 GASPRICE: 0 + + ROLLUP_ROLE: 'scheduler' ports: - ${L2GETH_HTTP_PORT:-8545}:8545 - ${L2GETH_WS_PORT:-8546}:8546 @@ -143,6 +146,7 @@ services: entrypoint: sh ./geth.sh env_file: - ./envs/geth.env + - ./envs/fraud_proof.env volumes: - ./data/verifier:/root/.ethereum/geth/ environment: @@ -154,6 +158,7 @@ services: ETH1_CTC_DEPLOYMENT_HEIGHT: 8 RETRIES: 60 ROLLUP_VERIFIER_ENABLE: 'true' + ROLLUP_ROLE: 'verifier' ports: - ${VERIFIER_HTTP_PORT:-8547}:8545 - ${VERIFIER_WS_PORT:-8548}:8546 diff --git a/ops/envs/deployer.env b/ops/envs/deployer.env index e44bde78c..b3de8833b 100644 --- a/ops/envs/deployer.env +++ b/ops/envs/deployer.env @@ -14,3 +14,4 @@ # PRIVATE_KEY IS CONTRACT DEPLOYER KEY CONTRACTS_DEPLOYER_KEY= L1_BIT_ADDRESS=0xdf3BD218A936A92be5e43592143ecc7a33cef514 +NODE_OPTIONS="--max-old-space-size=9000" diff --git a/ops/envs/fraud_proof.env b/ops/envs/fraud_proof.env new file mode 100644 index 000000000..533eb060d --- /dev/null +++ b/ops/envs/fraud_proof.env @@ -0,0 +1,7 @@ +L1_ENDPOINT=ws://127.0.0.1:9545 +L1_CHAIN_ID=31337 +L1_CONFIRMATIONS=0 +SEQUENCER_ADDR=0xd5b002298b2e81b4ced1b6c8cf1964023cdc3758 +ROLLUP_ADDR=0x4f958F2C2303BDca22b739339cD633F8543BB07D +STAKE_ADDR=0xd5b002298b2e81b4ced1b6c8cf1964023cdc3758 +STAKE_AMOUNT=100000000000000000 diff --git a/ops/scripts/batch-submitter.sh b/ops/scripts/batch-submitter.sh index 42d7788e9..ea558c25e 100755 --- a/ops/scripts/batch-submitter.sh +++ b/ops/scripts/batch-submitter.sh @@ -17,6 +17,7 @@ if [[ ! -z "$URL" ]]; then # set the env export CTC_ADDRESS=$(echo $ADDRESSES | jq -r '.CanonicalTransactionChain') export SCC_ADDRESS=$(echo $ADDRESSES | jq -r '.StateCommitmentChain') + export FP_ROLLUP_ADDRESS=$(echo $ADDRESSES | jq -r '.Proxy__Rollup') fi diff --git a/ops/scripts/deployer.sh b/ops/scripts/deployer.sh index faa03b58f..bc3b75998 100755 --- a/ops/scripts/deployer.sh +++ b/ops/scripts/deployer.sh @@ -31,9 +31,20 @@ echo "test point1" if [ $CONTRACTS_TARGET_NETWORK == "local" ] ;then DEPLOY_CMD="npx hardhat deploy --network $CONTRACTS_TARGET_NETWORK" + # todo: remove + # whiteListInit + WHITELIST_INIT="npx hardhat whiteListInit --rollup $ROLLUP_CONTRACT_ADDRESS" + # fraud proof verifier deploy + DEPLOY_VERIFIER="npx hardhat deployVerifier --verifier $VERIFIER_ENTRY_ADDRESS" + echo "Deploying contracts. Deployment command:" echo "$DEPLOY_CMD" eval "$DEPLOY_CMD" + echo "$DEPLOY_VERIFIER" + eval "$DEPLOY_VERIFIER" + echo "$WHITELIST_INIT" + eval "$WHITELIST_INIT" + elif [ $SKIP_CONTRACT_DEPLOY == "NO" ] ; then DEPLOY_CMD="npx hardhat deploy --network $CONTRACTS_TARGET_NETWORK" echo $PWD diff --git a/packages/contracts/addresses.json b/packages/contracts/addresses.json index f0d3f8cc2..73f437e76 100644 --- a/packages/contracts/addresses.json +++ b/packages/contracts/addresses.json @@ -1,13 +1,17 @@ { + "Proxy__Verifier": "0x4f958F2C2303BDca22b739339cD633F8543BB07D", "ChainStorageContainer-SCC-batches": "0x0090171f848B2aa86918E5Ef2406Ab3d424fdd83", + "Proxy__AssertionMap": "0x86E10B59cFDFeFBCf3ED5b40D018949CbFCE8B59", "StateCommitmentChain": "0x8BAccFF561FDe61D6bC8B6f299fFBa561d2189B9", "TestBitToken": "0x92aBAD50368175785e4270ca9eFd169c949C4ce1", "ChainStorageContainer-CTC-batches": "0x7A8B94a9fA2bb0581D2EEA2fEd875FCA97494612", "Proxy__BVM_L1StandardBridge": "0x52753615226F8aC8a464bfecb11Ef798CFF3793f", + "Rollup": "0x2eC3980EcddA68E073c39afD44909f8fe0fE3000", "TssStakingSlashing": "0x36fCf02Fc651c0b7ef2ECA446Dd2405364F85337", "BVM_L1CrossDomainMessenger": "0xD076364Fa5de1a4512c58b39ad63DD720B7B9E11", "Proxy__TSS_GroupManager": "0xa83239cf2b900682001f9144144B5E5e5788A631", "Lib_AddressManager": "0x19C22f181280dF6Ad1d97285cdD430173Df91C12", + "VerifierEntry": "0x9109811E8eEe02520219612bB5D47C60c382F4aa", "AddressDictator": "0xE6A251EefaEE70E8645FBAdf21E9B1246e07C374", "BVM_EigenDataLayrChain": "0xc2E4F2038D456AfEFfF2351234BCaFCB6837baC1", "CanonicalTransactionChain": "0x9faB987C9C469EB23Da31B7848B28aCf30905eA8", @@ -18,5 +22,7 @@ "Proxy__BVM_L1CrossDomainMessenger": "0xd9e2F450525079e1e29fB23Bc7Caca6F61f8fD4a", "Proxy__TSS_StakingSlashing": "0xe6cd9e7b620964bECd42c7Ad41e56724f515E284", "BondManager": "0xEd5166f12FCb48a0804B62FDccB37f59F1F1bc3B", + "AssertionMap": "0x1Edd37fc504513bAa00D782E52478d0a3f675553", + "Proxy__Rollup": "0x8013ac56e4c4A562b72a6D8B39D60cDa7aE173A9", "AddressManager": "0x19C22f181280dF6Ad1d97285cdD430173Df91C12" } diff --git a/packages/contracts/addresses.txt b/packages/contracts/addresses.txt index 02ab74e32..1db1b13b3 100644 --- a/packages/contracts/addresses.txt +++ b/packages/contracts/addresses.txt @@ -1,12 +1,16 @@ +0x4f958F2C2303BDca22b739339cD633F8543BB07D 0x0090171f848B2aa86918E5Ef2406Ab3d424fdd83 +0x86E10B59cFDFeFBCf3ED5b40D018949CbFCE8B59 0x8BAccFF561FDe61D6bC8B6f299fFBa561d2189B9 0x92aBAD50368175785e4270ca9eFd169c949C4ce1 0x7A8B94a9fA2bb0581D2EEA2fEd875FCA97494612 0x52753615226F8aC8a464bfecb11Ef798CFF3793f +0x2eC3980EcddA68E073c39afD44909f8fe0fE3000 0x36fCf02Fc651c0b7ef2ECA446Dd2405364F85337 0xD076364Fa5de1a4512c58b39ad63DD720B7B9E11 0xa83239cf2b900682001f9144144B5E5e5788A631 0x19C22f181280dF6Ad1d97285cdD430173Df91C12 +0x9109811E8eEe02520219612bB5D47C60c382F4aa 0xE6A251EefaEE70E8645FBAdf21E9B1246e07C374 0xc2E4F2038D456AfEFfF2351234BCaFCB6837baC1 0x9faB987C9C469EB23Da31B7848B28aCf30905eA8 @@ -17,3 +21,5 @@ 0xd9e2F450525079e1e29fB23Bc7Caca6F61f8fD4a 0xe6cd9e7b620964bECd42c7Ad41e56724f515E284 0xEd5166f12FCb48a0804B62FDccB37f59F1F1bc3B +0x1Edd37fc504513bAa00D782E52478d0a3f675553 +0x8013ac56e4c4A562b72a6D8B39D60cDa7aE173A9 diff --git a/packages/contracts/contracts/L1/fraud-proof/AssertionMap.sol b/packages/contracts/contracts/L1/fraud-proof/AssertionMap.sol new file mode 100644 index 000000000..d7d4f27d8 --- /dev/null +++ b/packages/contracts/contracts/L1/fraud-proof/AssertionMap.sol @@ -0,0 +1,137 @@ +// SPDX-License-Identifier: Apache-2.0 + +/* + * Modifications Copyright 2022, Specular contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; +import "./libraries/Errors.sol"; + +// Exists only to reduce size of Rollup contract (maybe revert since Rollup fits under optimized compilation). +contract AssertionMap is Initializable { + error ChildInboxSizeMismatch(); + + error SiblingStateHashExists(); + + struct Assertion { + bytes32 stateHash; // Hash of execution state associated with assertion (see `RollupLib.stateHash`) + uint256 inboxSize; // Inbox size this assertion advanced to + uint256 parent; // Parent assertion ID + uint256 deadline; // Confirmation deadline (L1 block timestamp) + uint256 proposalTime; // L1 block number at which assertion was proposed + // Staking state + uint256 numStakers; // total number of stakers that have ever staked on this assertion. increasing only. + mapping(address => bool) stakers; // all stakers that have ever staked on this assertion. + // Child state + uint256 childInboxSize; // child assertion inbox state + mapping(bytes32 => bool) childStateHashes; // child assertion vm hashes + } + + mapping(uint256 => Assertion) public assertions; + address public rollupAddress; + + modifier rollupOnly() { + if (msg.sender != rollupAddress) { + revert NotRollup(msg.sender, rollupAddress); + } + _; + } + + constructor() { + _disableInitializers(); + } + + function initialize() public initializer {} + + function setRollupAddress(address _rollupAddress) public { + require( + address(rollupAddress) == address(0), + "rollupAddress already initialized." + ); + require(_rollupAddress != address(0), "ZERO_ADDRESS"); + rollupAddress = _rollupAddress; + } + + function getStateHash(uint256 assertionID) external view returns (bytes32) { + return assertions[assertionID].stateHash; + } + + function getInboxSize(uint256 assertionID) external view returns (uint256) { + return assertions[assertionID].inboxSize; + } + + function getParentID(uint256 assertionID) external view returns (uint256) { + return assertions[assertionID].parent; + } + + function getDeadline(uint256 assertionID) external view returns (uint256) { + return assertions[assertionID].deadline; + } + + function getProposalTime(uint256 assertionID) external view returns (uint256) { + return assertions[assertionID].proposalTime; + } + + function getNumStakers(uint256 assertionID) external view returns (uint256) { + return assertions[assertionID].numStakers; + } + + function isStaker(uint256 assertionID, address stakerAddress) external view returns (bool) { + return assertions[assertionID].stakers[stakerAddress]; + } + + function createAssertion( + uint256 assertionID, + bytes32 stateHash, + uint256 inboxSize, + uint256 parentID, + uint256 deadline + ) external rollupOnly { + Assertion storage assertion = assertions[assertionID]; + Assertion storage parentAssertion = assertions[parentID]; + // Child assertions must have same inbox size + uint256 parentChildInboxSize = parentAssertion.childInboxSize; + if (parentChildInboxSize == 0) { + parentAssertion.childInboxSize = inboxSize; + } else { + if (inboxSize != parentChildInboxSize) { + revert("ChildInboxSizeMismatch"); + } + } + if (parentAssertion.childStateHashes[stateHash]) { + revert("SiblingStateHashExists"); + } + + parentAssertion.childStateHashes[stateHash] = true; + + assertion.stateHash = stateHash; + assertion.inboxSize = inboxSize; + assertion.parent = parentID; + assertion.deadline = deadline; + assertion.proposalTime = block.number; + } + + function stakeOnAssertion(uint256 assertionID, address stakerAddress) external rollupOnly { + Assertion storage assertion = assertions[assertionID]; + assertion.stakers[stakerAddress] = true; + assertion.numStakers++; + } + + function deleteAssertion(uint256 assertionID) external rollupOnly { + delete assertions[assertionID]; + } +} diff --git a/packages/contracts/contracts/L1/fraud-proof/IRollup.sol b/packages/contracts/contracts/L1/fraud-proof/IRollup.sol new file mode 100644 index 000000000..966a6ad4e --- /dev/null +++ b/packages/contracts/contracts/L1/fraud-proof/IRollup.sol @@ -0,0 +1,246 @@ +// SPDX-License-Identifier: Apache-2.0 + +/* + * Modifications Copyright 2022, Specular contributors + * + * This file was changed in accordance to Apache License, Version 2.0. + * + * Copyright 2021, Offchain Labs, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +pragma solidity ^0.8.0; + +import "./AssertionMap.sol"; + +interface IRollup { + event AssertionCreated( + uint256 assertionID, address asserterAddr, bytes32 vmHash, uint256 inboxSize + ); + + event AssertionChallenged(uint256 assertionID, address challengeAddr); + + event AssertionConfirmed(uint256 assertionID); + + event AssertionRejected(uint256 assertionID); + + event StakerStaked(address stakerAddr, uint256 assertionID); + + /// @dev Thrown when address that have not staked any token calls a only-staked function + error NotStaked(); + + /// @dev Thrown when the function is called with Insufficient Stake + error InsufficientStake(); + + /// @dev Thrown when the caller is staked on unconfirmed assertion. + error StakedOnUnconfirmedAssertion(); + + /// @dev Thrown when transfer fails + error TransferFailed(); + + /// @dev Thrown when a staker tries to advance stake to invalid assertionId. + error AssertionOutOfRange(); + + /// @dev Thrown when a staker tries to advance stake to non-child assertion + error ParentAssertionUnstaked(); + + /// @dev Thrown when a sender tries to create assertion before the minimum assertion time period + error MinimumAssertionPeriodNotPassed(); + + /// @dev Thrown when parent's statehash is not equal to the start state(or previous state)/ + error PreviousStateHash(); + + /// @dev Thrown when a sender tries to create assertion without any tx. + error EmptyAssertion(); + + /// @dev Thrown when the requested assertion read past the end of current Inbox. + error InboxReadLimitExceeded(); + + /// @dev Thrown when the challenge assertion Id is not ordered or in range. + error WrongOrder(); + + /// @dev Thrown when the challenger tries to challenge an unproposed assertion + error UnproposedAssertion(); + + /// @dev Thrown when the assertion is already resolved + error AssertionAlreadyResolved(); + + /// @dev Thrown when there is no unresolved assertion + error NoUnresolvedAssertion(); + + /// @dev Thrown when the challenge period has not passed + error ChallengePeriodPending(); + + /// @dev Thrown when the challenger and defender didn't attest to sibling assertions + error DifferentParent(); + + /// @dev Thrown when the assertion's parent is not the last confirmed assertion + error InvalidParent(); + + /// @dev Thrown when the staker is not in a challenge + error NotInChallenge(); + + /// @dev Thrown when the two stakers are in different challenge + /// @param staker1Challenge challenge address of staker 1 + /// @param staker2Challenge challenge address of staker 2 + error InDifferentChallenge(address staker1Challenge, address staker2Challenge); + + /// @dev Thrown when the staker is currently in Challenge + error ChallengedStaker(); + + /// @dev Thrown when all the stakers are not staked + error NotAllStaked(); + + /// @dev Thrown staker's assertion is descendant of firstUnresolved assertion + error StakerStakedOnTarget(); + + /// @dev Thrown when there are staker's present on the assertion + error StakersPresent(); + + /// @dev Thrown when there are zero stakers + error NoStaker(); + + /// @dev Thrown when slot is not blank in initialize step + error RedundantInitialized(); + + /// @dev Thrown when function is called with a zero address argument + error ZeroAddress(); + + function assertions() external view returns (AssertionMap); + + /** + * @param addr User address. + * @return True if address is staked, else False. + */ + function isStaked(address addr) external view returns (bool); + + /** + * @return The current required stake amount. + */ + function currentRequiredStake() external view returns (uint256); + + /** + * @return confirmedInboxSize size of inbox confirmed + */ + function confirmedInboxSize() external view returns (uint256); + + /** + * @notice Deposits stake on staker's current assertion (or the last confirmed assertion if not currently staked). + * @notice currently use Ether to stake; stakeAmount Token amount to deposit. Must be > than defined threshold if this is a new stake. + */ + // function stake(uint256 stakeAmount) external payable; + function stake() external payable; + + /** + * @notice Withdraws stakeAmount from staker's stake by if assertion it is staked on is confirmed. + * @param stakeAmount Token amount to withdraw. Must be <= sender's current stake minus the current required stake. + */ + function unstake(uint256 stakeAmount) external; + + /** + * @notice Removes stakerAddress from the set of stakers and withdraws the full stake amount to stakerAddress. + * This can be called by anyone since it is currently necessary to keep the chain progressing. + * @param stakerAddress Address of staker for which to unstake. + */ + function removeStake(address stakerAddress) external; + + /** + * @notice Advances msg.sender's existing sake to assertionID. + * @param assertionID ID of assertion to advance stake to. Currently this must be a child of the current assertion. + * TODO: generalize to arbitrary descendants. + */ + function advanceStake(uint256 assertionID) external; + + /** + * @notice Withdraws all of msg.sender's withdrawable funds. + */ + function withdraw() external; + + /** + * @notice Creates a new DA representing the rollup state after executing a block of transactions (sequenced in SequencerInbox). + * Block is represented by all transactions in range [prevInboxSize, inboxSize]. The latest staked DA of the sender + * is considered to be the predecessor. Moves sender stake onto the new DA. + * + * The new DA stores the hash of the parameters: vmHash + * + * @param vmHash New VM hash. + * @param inboxSize Size of inbox corresponding to assertion (number of transactions). + */ + function createAssertion( + bytes32 vmHash, + uint256 inboxSize + ) external; + + /** + * + * @notice create assertion with scc state batch + * + * @param vmHash New VM hash. + * @param inboxSize Size of inbox corresponding to assertion (number of transactions). + * @param _batch Batch of state roots. + * @param _shouldStartAtElement Index of the element at which this batch should start. + * @param _signature tss group signature of state batches. + */ + function createAssertionWithStateBatch( + bytes32 vmHash, + uint256 inboxSize, + bytes32[] calldata _batch, + uint256 _shouldStartAtElement, + bytes calldata _signature + ) external; + + + /** + * @notice Initiates a dispute between a defender and challenger on an unconfirmed DA. + * @param players Defender (first) and challenger (second) addresses. Must be staked on DAs on different branches. + * @param assertionIDs Assertion IDs of the players engaged in the challenge. The first ID should be the earlier-created and is the one being challenged. + * @return Newly created challenge contract address. + */ + function challengeAssertion(address[2] calldata players, uint256[2] calldata assertionIDs) + external + returns (address); + + /** + * @notice Confirms first unresolved assertion. Assertion is confirmed if and only if: + * (1) there is at least one staker, and + * (2) challenge period has passed, and + * (3) predecessor has been confirmed, and + * (4) all stakers are staked on the assertion. + */ + function confirmFirstUnresolvedAssertion() external; + + /** + * @notice Rejects first unresolved assertion. Assertion is rejected if and only if: + * (1) all of the following are true: + * (a) challenge period has passed, and + * (b) at least one staker exists, and + * (c) no staker remains staked on the assertion (all have been destroyed). + * OR + * (2) predecessor has been rejected + */ + function rejectFirstUnresolvedAssertion() external; + +//* @param stakerAddress Address of a staker staked on a different branch to the first unresolved assertion. +//* If the first unresolved assertion's parent is confirmed, this parameter is used to establish that a staker exists +//* on a different branch of the assertion chain. This parameter is ignored when the parent of the first unresolved +//* assertion is not the last confirmed assertion. +// function rejectFirstUnresolvedAssertion(address stakerAddress) external; + + /** + * @notice Completes ongoing challenge. Callback, called by a challenge contract. + * @param winner Address of winning staker. + * @param loser Address of losing staker. + */ + function completeChallenge(address winner, address loser) external; +} diff --git a/packages/contracts/contracts/L1/fraud-proof/Rollup.sol b/packages/contracts/contracts/L1/fraud-proof/Rollup.sol new file mode 100644 index 000000000..03abcf7c9 --- /dev/null +++ b/packages/contracts/contracts/L1/fraud-proof/Rollup.sol @@ -0,0 +1,549 @@ +// SPDX-License-Identifier: Apache-2.0 + +/* + * Modifications Copyright 2022, Specular contributors + * + * This file was changed in accordance to Apache License, Version 2.0. + * + * Copyright 2021, Offchain Labs, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; + +import "hardhat/console.sol"; + +import "./challenge/Challenge.sol"; +import "./challenge/ChallengeLib.sol"; +import "./AssertionMap.sol"; +import "./IRollup.sol"; +import "./RollupLib.sol"; +import "./WhiteList.sol"; +import "./verifier/IVerifier.sol"; +import {Lib_AddressResolver} from "../../libraries/resolver/Lib_AddressResolver.sol"; +import {Lib_AddressManager} from "../../libraries/resolver/Lib_AddressManager.sol"; + +abstract contract RollupBase is IRollup, Initializable { + // Config parameters + uint256 public confirmationPeriod; // number of L1 blocks + uint256 public challengePeriod; // number of L1 blocks + uint256 public minimumAssertionPeriod; // number of L1 blocks + uint256 public baseStakeAmount; // number of stake tokens + + IERC20 public stakeToken; + AssertionMap public override assertions; + IVerifierEntry public verifier; + + struct Staker { + bool isStaked; + uint256 amountStaked; + uint256 assertionID; // latest staked assertion ID + address currentChallenge; // address(0) if none + } + + struct Zombie { + address stakerAddress; + uint256 lastAssertionID; + } + + struct ChallengeCtx { + bool completed; + address challengeAddress; + address defenderAddress; + address challengerAddress; + uint256 defenderAssertionID; + uint256 challengerAssertionID; + } +} + +contract Rollup is Lib_AddressResolver, RollupBase, Whitelist { + modifier stakedOnly() { + if (!isStaked(msg.sender)) { + revert("NotStaked"); + } + _; + } + + // Assertion state + uint256 public lastResolvedAssertionID; + uint256 public lastConfirmedAssertionID; + uint256 public lastCreatedAssertionID; + + // Staking state + uint256 public numStakers; // current total number of stakers + mapping(address => Staker) public stakers; // mapping from staker addresses to corresponding stakers + mapping(address => uint256) public withdrawableFunds; // mapping from addresses to withdrawable funds (won in challenge) + Zombie[] public zombies; // stores stakers that lost a challenge + ChallengeCtx public challengeCtx; // stores challenge context + + constructor() Lib_AddressResolver(address(0)) { + _disableInitializers(); + } + + function initialize( + address _owner, + address _verifier, + address _stakeToken, + address _libAddressManager, + address _assertionMap, + uint256 _confirmationPeriod, + uint256 _challengePeriod, + uint256 _minimumAssertionPeriod, + uint256 _baseStakeAmount, + bytes32 _initialVMhash, + address[] calldata whitelists + ) public initializer { + if (_owner == address(0) || _verifier == address(0)) { + revert("ZeroAddress"); + } + owner = _owner; + stakeToken = IERC20(_stakeToken); + verifier = IVerifierEntry(_verifier); + + if (address(libAddressManager) != address(0)) { + revert("RedundantInitialized"); + } + libAddressManager = Lib_AddressManager(_libAddressManager); + + if (address(assertions) != address(0)) { + revert("RedundantInitialized"); + } + assertions = AssertionMap(_assertionMap); + + confirmationPeriod = _confirmationPeriod; + challengePeriod = _challengePeriod; // TODO: currently unused. + minimumAssertionPeriod = _minimumAssertionPeriod; + baseStakeAmount = _baseStakeAmount; + + assertions.setRollupAddress(address(this)); + lastResolvedAssertionID = 0; + lastConfirmedAssertionID = 0; + lastCreatedAssertionID = 0; + + assertions.createAssertion( + lastResolvedAssertionID, // assertionID + _initialVMhash, + 0, // inboxSize (genesis) + 0, // parentID + block.number // deadline (unchallengeable) + ); + + for (uint i = 0; i < whitelists.length; i++) { + whitelist[whitelists[i]] = true; + } + } + + /// @inheritdoc IRollup + function isStaked(address addr) public view override returns (bool) { + return stakers[addr].isStaked; + } + + /// @inheritdoc IRollup + function currentRequiredStake() public view override returns (uint256) { + return baseStakeAmount; + } + + /// @inheritdoc IRollup + function confirmedInboxSize() public view override returns (uint256) { + return assertions.getInboxSize(lastConfirmedAssertionID); + } + + /// @inheritdoc IRollup + function stake() external payable override whitelistOnly { + if (isStaked(msg.sender)) { + stakers[msg.sender].amountStaked += msg.value; + } else { + if (msg.value < baseStakeAmount) { + revert("InsufficientStake"); + } + stakers[msg.sender] = Staker(true, msg.value, 0, address(0)); + numStakers++; + stakeOnAssertion(msg.sender, lastConfirmedAssertionID); + } + } + + /// @inheritdoc IRollup + function unstake(uint256 stakeAmount) external override { + requireStaked(msg.sender); + // Require that staker is staked on a confirmed assertion. + Staker storage staker = stakers[msg.sender]; + if (staker.assertionID > lastConfirmedAssertionID) { + revert("StakedOnUnconfirmedAssertion"); + } + if (stakeAmount > staker.amountStaked - currentRequiredStake()) { + revert("InsufficientStake"); + } + staker.amountStaked -= stakeAmount; + // Note: we don't need to modify assertion state because you can only unstake from a confirmed assertion. + (bool success,) = msg.sender.call{value: stakeAmount}(""); + if (!success) revert("TransferFailed"); + } + + /// @inheritdoc IRollup + function removeStake(address stakerAddress) external override { + requireStaked(stakerAddress); + // Require that staker is staked on a confirmed assertion. + Staker storage staker = stakers[stakerAddress]; + if (staker.assertionID > lastConfirmedAssertionID) { + revert("StakedOnUnconfirmedAssertion"); + } + deleteStaker(stakerAddress); + // Note: we don't need to modify assertion state because you can only unstake from a confirmed assertion. + (bool success,) = stakerAddress.call{value: staker.amountStaked}(""); + if (!success) revert("TransferFailed"); + } + + /// @inheritdoc IRollup + function advanceStake(uint256 assertionID) external override stakedOnly { + Staker storage staker = stakers[msg.sender]; + if (assertionID <= staker.assertionID && assertionID > lastCreatedAssertionID) { + revert("AssertionOutOfRange"); + } + // TODO: allow arbitrary descendant of current staked assertionID, not just child. + if (staker.assertionID != assertions.getParentID(assertionID)) { + revert("ParentAssertionUnstaked"); + } + stakeOnAssertion(msg.sender, assertionID); + } + + /// @inheritdoc IRollup + function withdraw() external override { + uint256 withdrawableFund = withdrawableFunds[msg.sender]; + withdrawableFunds[msg.sender] = 0; + (bool success,) = msg.sender.call{value: withdrawableFund}(""); + if (!success) revert("TransferFailed"); + } + + /// @inheritdoc IRollup + function createAssertion( + bytes32 vmHash, + uint256 inboxSize + ) public override stakedOnly { + require(stakers[msg.sender].currentChallenge == address(0),"can not create assertion when staker in challenge"); + uint256 parentID = stakers[msg.sender].assertionID; + // Require that enough time has passed since the last assertion. + if (block.number - assertions.getProposalTime(parentID) < minimumAssertionPeriod) { + revert("MinimumAssertionPeriodNotPassed"); + } + // Require that the assertion at least includes one transaction + if (inboxSize <= assertions.getInboxSize(parentID)) { + revert("EmptyAssertion"); + } + + // Initialize assertion. + lastCreatedAssertionID++; + emit AssertionCreated(lastCreatedAssertionID, msg.sender, vmHash, inboxSize); + assertions.createAssertion( + lastCreatedAssertionID, vmHash, inboxSize, parentID, newAssertionDeadline() + ); + + // Update stake. + stakeOnAssertion(msg.sender, lastCreatedAssertionID); + } + + /// @inheritdoc IRollup + function createAssertionWithStateBatch( + bytes32 vmHash, + uint256 inboxSize, + bytes32[] calldata _batch, + uint256 _shouldStartAtElement, + bytes calldata _signature + ) external override stakedOnly { // todo batch submitter only + // permissions only allow rollup proposer to submit assertion, only allow RollupContract to append new batch + require(msg.sender == resolve("BVM_Rolluper"), "msg.sender is not rollup proposer, can't append batch"); + // create assertion + createAssertion(vmHash, inboxSize); + // append state batch + address scc = resolve("StateCommitmentChain"); + (bool success, ) = scc.call( + abi.encodeWithSignature("appendStateBatch(bytes32[],uint256,bytes)", _batch, _shouldStartAtElement, _signature) + ); + require(success, "scc append state batch failed, revert all"); + } + + function challengeAssertion(address[2] calldata players, uint256[2] calldata assertionIDs) + external + override + returns (address) + { + uint256 defenderAssertionID = assertionIDs[0]; + uint256 challengerAssertionID = assertionIDs[1]; + // Require IDs ordered and in-range. + if (defenderAssertionID >= challengerAssertionID) { + revert("WrongOrder"); + } + if (challengerAssertionID > lastCreatedAssertionID) { + revert("UnproposedAssertion"); + } + if (lastConfirmedAssertionID >= defenderAssertionID) { + revert("AssertionAlreadyResolved"); + } + // Require that players have attested to sibling assertions. + uint256 parentID = assertions.getParentID(defenderAssertionID); + if (parentID != assertions.getParentID(challengerAssertionID)) { + revert("DifferentParent"); + } + + // Require that neither player is currently engaged in a challenge. + address defender = players[0]; + address challenger = players[1]; + requireUnchallengedStaker(defender); + requireUnchallengedStaker(challenger); + + // TODO: Calculate upper limit for allowed node proposal time. + + // Initialize challenge. + Challenge challenge = new Challenge(); + address challengeAddr = address(challenge); + stakers[challenger].currentChallenge = challengeAddr; + stakers[defender].currentChallenge = challengeAddr; + + challengeCtx = ChallengeCtx(false,challengeAddr,defender,challenger,defenderAssertionID,challengerAssertionID); + emit AssertionChallenged(defenderAssertionID, challengeAddr); + uint256 inboxSize = assertions.getInboxSize(parentID); + bytes32 parentStateHash = assertions.getStateHash(parentID); + bytes32 defenderStateHash = assertions.getStateHash(defenderAssertionID); + challenge.initialize( + defender, + challenger, + verifier, + address(this), + inboxSize, + parentStateHash, + defenderStateHash + ); + return challengeAddr; + } + + /// @inheritdoc IRollup + function confirmFirstUnresolvedAssertion() external override { + if (lastResolvedAssertionID >= lastCreatedAssertionID) { + revert("NoUnresolvedAssertion"); + } + + // (1) there is at least one staker, and + if (numStakers <= 0) revert("NoStaker"); + + uint256 lastUnresolvedID = lastResolvedAssertionID + 1; + + // (2) challenge period has passed + if (block.timestamp < assertions.getDeadline(lastUnresolvedID)) { + revert("ChallengePeriodPending"); + } + + // (3) predecessor has been confirmed + if (assertions.getParentID(lastUnresolvedID) != lastConfirmedAssertionID) { + revert("InvalidParent"); + } + + // Remove old zombies + // removeOldZombies(); + + // (4) all stakers are staked on the block. + // if (assertions.getNumStakers(lastUnresolvedID) != numStakers) { + // revert("NotAllStaked"); + // } + + // Confirm assertion. + // assertions.deleteAssertion(lastConfirmedAssertionID); + lastResolvedAssertionID++; + lastConfirmedAssertionID = lastResolvedAssertionID; + emit AssertionConfirmed(lastResolvedAssertionID); + } + + /// @inheritdoc IRollup + function rejectFirstUnresolvedAssertion() external override { + if (lastResolvedAssertionID >= lastCreatedAssertionID) { + revert("NoUnresolvedAssertion"); + } + + uint256 firstUnresolvedAssertionID = lastResolvedAssertionID + 1; + + // First case - parent of first unresolved is last confirmed (`if` condition below). e.g. + // [1] <- [3] | valid chain ([1] is last confirmed, [3] is stakerAddress's unresolved assertion) + // ^---- [2] | invalid chain ([2] is firstUnresolved) + // Second case (trivial) - parent of first unresolved is not last confirmed. i.e.: + // parent is previous rejected, e.g. + // [1] <- [4] | valid chain ([1] is last confirmed, [4] is stakerAddress's unresolved assertion) + // [2] <- [3] | invalid chain ([3] is firstUnresolved) + // OR + // parent is previous confirmed, e.g. + // [1] <- [2] <- [4] | valid chain ([2] is last confirmed, [4] is stakerAddress's unresolved assertion) + // ^---- [3] | invalid chain ([3] is firstUnresolved) + if (assertions.getParentID(firstUnresolvedAssertionID) == lastConfirmedAssertionID) { + // 1a. challenge period has passed. + if (block.timestamp < assertions.getDeadline(firstUnresolvedAssertionID)) { + revert("ChallengePeriodPending"); + } + // 1b. at least one staker exists (on a sibling) + // - stakerAddress is indeed a staker + // requireStaked(stakerAddress); + // - staker's assertion can't be a ancestor of firstUnresolved (because staker's assertion is also unresolved) + // if (stakers[stakerAddress].assertionID < firstUnresolvedAssertionID) { + // revert("AssertionAlreadyResolved"); + // } + // - staker's assertion can't be a descendant of firstUnresolved (because staker has never staked on firstUnresolved) + // if (assertions.isStaker(firstUnresolvedAssertionID, stakerAddress)) { + // revert("StakerStakedOnTarget"); + // } + // If a staker is staked on an assertion that is neither an ancestor nor a descendant of firstUnresolved, it must be a sibling, QED + + // 1c. no staker is staked on this assertion + // removeOldZombies(); + if (assertions.getNumStakers(firstUnresolvedAssertionID) != countStakedZombies(firstUnresolvedAssertionID)) + { + revert("StakersPresent"); + } + } + + // Reject assertion. + lastResolvedAssertionID++; + emit AssertionRejected(lastResolvedAssertionID); + assertions.deleteAssertion(lastResolvedAssertionID); + } + + /// @inheritdoc IRollup + function completeChallenge(address winner, address loser) external override { + requireStaked(loser); + + address challenge = getChallenge(winner, loser); + if (msg.sender != challenge) { + revert("NotChallenge"); + } + uint256 amountWon; + uint256 loserStake = stakers[loser].amountStaked; + uint256 winnerStake = stakers[winner].amountStaked; + if (loserStake > baseStakeAmount) { + // If loser has a higher stake than the winner, refund the difference. + // Loser gets deleted anyways, so maybe unnecessary to set amountStaked. + // stakers[loser].amountStaked = winnerStake; + withdrawableFunds[loser] += (loserStake - baseStakeAmount); + amountWon = baseStakeAmount; + } else { + amountWon = loserStake; + } + // Reward the winner with half the remaining stake + stakers[winner].amountStaked += amountWon; // why +stake instead of +withdrawable? + stakers[winner].currentChallenge = address(0); + // Turning loser into zombie renders the loser's remaining stake inaccessible. + uint256 assertionID = stakers[loser].assertionID; + deleteStaker(loser); + // Track as zombie so we can account for it during assertion resolution. + zombies.push(Zombie(loser, assertionID)); + challengeCtx.completed = true; + } + + /** + * @notice Updates staker and assertion metadata. + * @param stakerAddress Address of existing staker. + * @param assertionID ID of existing assertion to stake on. + */ + function stakeOnAssertion(address stakerAddress, uint256 assertionID) private { + stakers[stakerAddress].assertionID = assertionID; + assertions.stakeOnAssertion(assertionID, stakerAddress); + emit StakerStaked(stakerAddress, assertionID); + } + + /** + * @notice Deletes the staker from global state. Does not touch assertion staker state. + * @param stakerAddress Address of the staker to delete + */ + function deleteStaker(address stakerAddress) private { + numStakers--; + delete stakers[stakerAddress]; + } + + /** + * @notice Checks to see whether the two stakers are in the same challenge + * @param staker1Address Address of the first staker + * @param staker2Address Address of the second staker + * @return Address of the challenge that the two stakers are in + */ + function getChallenge(address staker1Address, address staker2Address) private view returns (address) { + Staker storage staker1 = stakers[staker1Address]; + Staker storage staker2 = stakers[staker2Address]; + address challenge = staker1.currentChallenge; + if (challenge == address(0)) { + revert("NotInChallenge"); + } + if (challenge != staker2.currentChallenge) { + revert("InDifferentChallenge"); + } + return challenge; + } + + function newAssertionDeadline() private returns (uint256) { + // TODO: account for prev assertion, gas + // return block.number + confirmationPeriod; + address scc = resolve("StateCommitmentChain"); + (bool success, bytes memory data) = scc.call( + abi.encodeWithSignature("FRAUD_PROOF_WINDOW()") + ); + uint256 confirmationWindow = uint256(bytes32(data)); + return block.timestamp + confirmationWindow; + } + + // ***************** + // zombie processing + // ***************** + + function removeOldZombies() external stakedOnly { + delete zombies; + } + /** + * @notice Removes any zombies whose latest stake is earlier than the first unresolved assertion. + * @dev Uses pop() instead of delete to prevent gaps, although order is not preserved + */ + // function removeOldZombies() private { + // } + + /** + * @notice Counts the number of zombies staked on an assertion. + * @dev O(n), where n is # of zombies (but is expected to be small). + * This function could be uncallable if there are too many zombies. However, + * removeOldZombies() can be used to remove any zombies that exist so that this + * will then be callable. + * @param assertionID The assertion on which to count staked zombies + * @return The number of zombies staked on the assertion + */ + function countStakedZombies(uint256 assertionID) private view returns (uint256) { + uint256 numStakedZombies = 0; + for (uint256 i = 0; i < zombies.length; i++) { + if (assertions.isStaker(assertionID, zombies[i].stakerAddress)) { + numStakedZombies++; + } + } + return numStakedZombies; + } + + // ************ + // requirements + // ************ + + function requireStaked(address stakerAddress) private view { + if (!isStaked(stakerAddress)) { + revert("NotStaked"); + } + } + + function requireUnchallengedStaker(address stakerAddress) private view { + requireStaked(stakerAddress); + if (stakers[stakerAddress].currentChallenge != address(0)) { + revert("ChallengedStaker"); + } + } +} diff --git a/packages/contracts/contracts/L1/fraud-proof/RollupLib.sol b/packages/contracts/contracts/L1/fraud-proof/RollupLib.sol new file mode 100644 index 000000000..47561f3c0 --- /dev/null +++ b/packages/contracts/contracts/L1/fraud-proof/RollupLib.sol @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: Apache-2.0 + +/* + * Modifications Copyright 2022, Specular contributors + * + * This file was changed in accordance to Apache License, Version 2.0. + * + * Copyright 2021, Offchain Labs, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +pragma solidity ^0.8.0; + +import "./challenge/ChallengeLib.sol"; + +// TODO: move into ChallengeLib. +library RollupLib { + struct ExecutionState { + bytes32 vmHash; + } + + /** + * @notice Computes the hash of `execState`. + */ + function stateHash(ExecutionState memory execState) internal pure returns (bytes32) { + return keccak256(abi.encodePacked(execState.vmHash)); + } +} diff --git a/packages/contracts/contracts/L1/fraud-proof/WhiteList.sol b/packages/contracts/contracts/L1/fraud-proof/WhiteList.sol new file mode 100644 index 000000000..587901aa2 --- /dev/null +++ b/packages/contracts/contracts/L1/fraud-proof/WhiteList.sol @@ -0,0 +1,55 @@ +abstract contract Whitelist { + modifier onlyOwner() { + require(msg.sender == owner, "Ownable: caller is not the owner"); + _; + } + + modifier whitelistOnly() { + if (!whitelist[msg.sender]) { + revert("NOT_IN_WHITELIST"); + } + _; + } + + address public owner; + mapping(address => bool) public whitelist; + + event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); + + /** + * @notice Add to whitelist + */ + function addToWhitelist(address[] calldata toAddAddresses) external onlyOwner { + for (uint i = 0; i < toAddAddresses.length; i++) { + whitelist[toAddAddresses[i]] = true; + } + } + + /** + * @notice Remove from whitelist + */ + function removeFromWhitelist(address[] calldata toRemoveAddresses) external onlyOwner { + for (uint i = 0; i < toRemoveAddresses.length; i++) { + delete whitelist[toRemoveAddresses[i]]; + } + } + + /** + * @dev Transfers ownership of the contract to a new account (`newOwner`). + * Can only be called by the current owner. + */ + function transferOwnership(address newOwner) public virtual onlyOwner { + require(newOwner != address(0), "Ownable: new owner is the zero address"); + _transferOwnership(newOwner); + } + + /** + * @dev Transfers ownership of the contract to a new account (`newOwner`). + * Internal function without access restriction. + */ + function _transferOwnership(address newOwner) internal virtual { + address oldOwner = owner; + owner = newOwner; + emit OwnershipTransferred(oldOwner, newOwner); + } +} diff --git a/packages/contracts/contracts/L1/fraud-proof/challenge/Challenge.sol b/packages/contracts/contracts/L1/fraud-proof/challenge/Challenge.sol new file mode 100644 index 000000000..65f86d2ce --- /dev/null +++ b/packages/contracts/contracts/L1/fraud-proof/challenge/Challenge.sol @@ -0,0 +1,301 @@ +// SPDX-License-Identifier: Apache-2.0 + +/* + * Modifications Copyright 2022, Specular contributors + * + * This file was changed in accordance to Apache License, Version 2.0. + * + * Copyright 2021, Offchain Labs, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +pragma solidity ^0.8.0; + +import "./IChallenge.sol"; +import "./ChallengeLib.sol"; +import "../IRollup.sol"; + +contract Challenge is IChallenge { + struct BisectedStore { + bytes32 startState; + bytes32 midState; + bytes32 endState; + uint256 blockNum; + uint256 blockTime; + uint256 challengedSegmentStart; + uint256 challengedSegmentLength; + } + + enum Turn { + NoChallenge, + Challenger, + Defender + } + + // Error codes + + // Can only initialize once + string private constant CHAL_INIT_STATE = "CHAL_INIT_STATE"; + // deadline expired + string private constant BIS_DEADLINE = "BIS_DEADLINE"; + // Only original asserter can continue bisect + string private constant BIS_SENDER = "BIS_SENDER"; + // Incorrect previous state + string private constant BIS_PREV = "BIS_PREV"; + // Can't timeout before deadline + string private constant TIMEOUT_DEADLINE = "TIMEOUT_DEADLINE"; + + bytes32 private constant UNREACHABLE_ASSERTION = bytes32(uint256(0)); + + uint256 private constant MAX_BISECTION_DEGREE = 2; + + // Other contracts + address internal resultReceiver; + IVerifierEntry internal verifier; + + // Challenge state + address public defender; + address public challenger; + uint256 public lastMoveBlockTime; + uint256 public defenderTimeLeft; + uint256 public challengerTimeLeft; + + Turn public turn; + // See `ChallengeLib.computeBisectionHash` for the format of this commitment. + bytes32 public bisectionHash; + bytes32[3] public prevBisection; + + // Initial state used to initialize bisectionHash (write-once). + bytes32 private startStateHash; + bytes32 private endStateHash; + + address public winner; + + bool public rollback; + uint256 public startInboxSize; + + BisectedStore public currentBisected; + + /** + * @notice Pre-condition: `msg.sender` is correct and still has time remaining. + * Post-condition: `turn` changes and `lastMoveBlock` set to current `block.number`. + */ + modifier onlyOnTurn() { + require(msg.sender == currentResponder(), BIS_SENDER); + require(block.timestamp - lastMoveBlockTime <= currentResponderTimeLeft(), BIS_DEADLINE); + + _; + + if (turn == Turn.Challenger) { + challengerTimeLeft = challengerTimeLeft - (block.timestamp- lastMoveBlockTime); + turn = Turn.Defender; + } else if (turn == Turn.Defender) { + defenderTimeLeft = defenderTimeLeft - (block.timestamp - lastMoveBlockTime); + turn = Turn.Challenger; + } + lastMoveBlockTime = block.timestamp; + } + + /** + * @notice Ensures challenge has been initialized. + */ + modifier postInitialization() { + require(bisectionHash != 0, "NOT_INITIALIZED"); + _; + } + + modifier onlyDefender(){ + require(defender != address(0),"Defender not set"); + require(msg.sender==defender,"Caller not defender"); + _; + } + + function initialize( + address _defender, + address _challenger, + IVerifierEntry _verifier, + address _resultReceiver, + uint256 _startInboxSize, + bytes32 _startStateHash, + bytes32 _endStateHash + ) external override { + require(turn == Turn.NoChallenge, CHAL_INIT_STATE); + require(_defender != address(0) && _challenger != address(0) && _resultReceiver != address(0), "ZERO_ADDRESS"); + defender = _defender; + challenger = _challenger; + verifier = _verifier; + resultReceiver = _resultReceiver; + startStateHash = _startStateHash; + endStateHash = _endStateHash; + + turn = Turn.Defender; + lastMoveBlockTime = block.timestamp; + // TODO(ujval): initialize timeout + defenderTimeLeft = 150; + challengerTimeLeft = 150; + prevBisection[0] = _startStateHash; + prevBisection[1] = bytes32(0); + prevBisection[2] = _endStateHash; + + startInboxSize = _startInboxSize; + } + + function initializeChallengeLength(bytes32 checkStateHash, uint256 _numSteps) external override onlyOnTurn { + require(bisectionHash == 0, CHAL_INIT_STATE); + require(_numSteps > 0, "INVALID_NUM_STEPS"); + bisectionHash = ChallengeLib.computeBisectionHash(0, _numSteps); + // TODO: consider emitting a different event? + currentBisected = BisectedStore(startStateHash, checkStateHash, endStateHash, block.number, block.timestamp, 0, _numSteps); + emit Bisected(startStateHash, checkStateHash, endStateHash, block.number, block.timestamp, 0, _numSteps); + } + + function bisectExecution( + bytes32[3] calldata bisection, + uint256 challengedSegmentIndex, + uint256 challengedSegmentStart, + uint256 challengedSegmentLength, + uint256 prevChallengedSegmentStart, + uint256 prevChallengedSegmentLength + ) external override onlyOnTurn postInitialization { + // Verify provided prev bisection. + bytes32 prevHash = ChallengeLib.computeBisectionHash(prevChallengedSegmentStart, prevChallengedSegmentLength); + require(prevHash == bisectionHash, BIS_PREV); + + // Require agreed upon start state hash and disagreed upon end state hash. + if (prevBisection[1] != bytes32(0)) { + require(bisection[0] == prevBisection[0] || bisection[0] == prevBisection[1], "AMBIGUOUS_START"); + } + require(bisection[2] != prevBisection[2], "INVALID_END"); + + // Compute segment start/length. + require(challengedSegmentLength > 0, "TOO_SHORT"); + + // Compute new challenge state. + prevBisection[0] = bisection[0]; + prevBisection[1] = bisection[1]; + prevBisection[2] = bisection[2]; + bisectionHash = ChallengeLib.computeBisectionHash(challengedSegmentStart, challengedSegmentLength); + currentBisected = BisectedStore(bisection[0], bisection[1], bisection[2], block.number, block.timestamp, challengedSegmentStart, challengedSegmentLength); + emit Bisected(bisection[0], bisection[1], bisection[2], block.number, block.timestamp, challengedSegmentStart, challengedSegmentLength); + } + + function verifyOneStepProof( + VerificationContext.Context calldata ctx, + uint8 verifyType, + bytes calldata proof, + uint256 challengedStepIndex, + uint256 prevChallengedSegmentStart, + uint256 prevChallengedSegmentLength + ) external override onlyOnTurn { + // Verify provided prev bisection. + bytes32 prevHash = + ChallengeLib.computeBisectionHash(prevChallengedSegmentStart, prevChallengedSegmentLength); + require(prevHash == bisectionHash, BIS_PREV); + // require(challengedStepIndex > 0 && challengedStepIndex < prevBisection.length, "INVALID_INDEX"); + // Require that this is the last round. + require(prevChallengedSegmentLength / MAX_BISECTION_DEGREE <= 1, "BISECTION_INCOMPLETE"); + + // verify OSP + // IVerificationContext ctx = ; + + bytes32 nextStateHash = verifier.verifyOneStepProof( + ctx, + verifyType, + prevBisection[challengedStepIndex-1], + proof + ); + if (nextStateHash == prevBisection[challengedStepIndex]) { + // osp verified, current win + _currentWin(CompletionReason.OSP_VERIFIED); + } else { + _currentLose(CompletionReason.OSP_VERIFIED); + } + } + + function setRollback() public { + if (rollback) { + revert("ALREADY_SET_ROLLBACK"); + } + rollback = true; + } + + function timeout() external override { + require(block.timestamp - lastMoveBlockTime > currentResponderTimeLeft(), TIMEOUT_DEADLINE); + if (turn == Turn.Defender) { + _challengerWin(CompletionReason.TIMEOUT); + } else { + _asserterWin(CompletionReason.TIMEOUT); + } + } + + function currentResponder() public view override returns (address) { + if (turn == Turn.Defender) { + return defender; + } else if (turn == Turn.Challenger) { + return challenger; + } else { + revert("NO_TURN"); + } + } + + function currentResponderTimeLeft() public view override returns (uint256) { + if (turn == Turn.Defender) { + return defenderTimeLeft; + } else if (turn == Turn.Challenger) { + return challengerTimeLeft; + } else { + revert("NO_TURN"); + } + } + + function _currentWin(CompletionReason reason) private { + if (turn == Turn.Defender) { + _asserterWin(reason); + } else { + winner = challenger; + _challengerWin(reason); + } + } + + function _currentLose(CompletionReason reason) private { + if (turn == Turn.Defender) { + _challengerWin(reason); + } else { + _asserterWin(reason); + } + } + + function _asserterWin(CompletionReason reason) private { + winner = defender; + emit ChallengeCompleted(defender, challenger, reason); + } + + function _challengerWin(CompletionReason reason) private { + winner = challenger; + emit ChallengeCompleted(challenger, defender, reason); + } + + function completeChallenge(bool result) external onlyDefender{ + require(winner != address(0),"Do not have winner"); + + if (winner == challenger) { + if (result) { + IRollup(resultReceiver).completeChallenge(challenger, defender); + return; + } + winner = defender; + } + IRollup(resultReceiver).completeChallenge(defender, challenger); + } +} diff --git a/packages/contracts/contracts/L1/fraud-proof/challenge/ChallengeLib.sol b/packages/contracts/contracts/L1/fraud-proof/challenge/ChallengeLib.sol new file mode 100644 index 000000000..35dfdce9f --- /dev/null +++ b/packages/contracts/contracts/L1/fraud-proof/challenge/ChallengeLib.sol @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: Apache-2.0 + +/* + * Modifications Copyright 2022, Specular contributors + * + * This file was changed in accordance to Apache License, Version 2.0. + * + * Copyright 2021, Offchain Labs, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +pragma solidity ^0.8.0; + +library ChallengeLib { + /** + * @notice Computes the initial bisection hash. + * @param numSteps Number of steps from the end of `startState` to the end of `endState`. + */ + function initialBisectionHash(uint256 numSteps) + internal + pure + returns (bytes32) + { + return ChallengeLib.computeBisectionHash(0, numSteps); + } + + /** + * @notice Computes H(bisection || segmentStart || segmentLength) + * @param challengedSegmentStart The number of steps preceding `bisection[1]`, relative to the assertion being challenged. + * @param challengedSegmentLength Length of bisected segment (in steps), from the start of bisection[1] to the end of bisection[-1]. + */ + function computeBisectionHash( + uint256 challengedSegmentStart, + uint256 challengedSegmentLength + ) internal pure returns (bytes32) { + return keccak256(abi.encodePacked(challengedSegmentStart, challengedSegmentLength)); + } + + /** + * @notice Returns length of first segment in a bisection. + */ + function firstSegmentLength(uint256 length, uint256 bisectionDegree) internal pure returns (uint256) { + return length / bisectionDegree + length % bisectionDegree; + } + + /** + * @notice Returns length of a segment (after first) in a bisection. + */ + function otherSegmentLength(uint256 length, uint256 bisectionDegree) internal pure returns (uint256) { + return length / bisectionDegree; + } +} diff --git a/packages/contracts/contracts/L1/fraud-proof/challenge/IChallenge.sol b/packages/contracts/contracts/L1/fraud-proof/challenge/IChallenge.sol new file mode 100644 index 000000000..68f76b97e --- /dev/null +++ b/packages/contracts/contracts/L1/fraud-proof/challenge/IChallenge.sol @@ -0,0 +1,121 @@ +// SPDX-License-Identifier: Apache-2.0 + +/* + * Modifications Copyright 2022, Specular contributors + * + * This file was changed in accordance to Apache License, Version 2.0. + * + * Copyright 2021, Offchain Labs, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +pragma solidity ^0.8.0; + +import "../verifier/IVerifierEntry.sol"; + +/** + * @notice Protocol execution: + * `initialize` (challenger, via Rollup) -> + * `initializeChallengeLength` (defender) -> + * `bisectExecution` (challenger, defender -- alternating) -> + * `verifyOneStepProof` + */ +interface IChallenge { + enum CompletionReason { + OSP_VERIFIED, // OSP verified by winner. + TIMEOUT // Loser timed out before completing their round. + } + + event ChallengeCompleted(address winner, address loser, CompletionReason reason); + + event Bisected(bytes32 startState, bytes32 midState, bytes32 endState, uint256 blockNum, uint256 blockTime, uint256 challengedSegmentStart, uint256 challengedSegmentLength); + + /** + * @notice Initializes contract. + * @param _defender Defending party. + * @param _challenger Challenging party. Challenger starts. + * @param _verifier Address of the verifier contract. + * @param _resultReceiver Address of contract that will receive the outcome (via callback `completeChallenge`). + * @param _startStateHash Bisection root being challenged. + * @param _endStateHash Bisection root being challenged. + */ + function initialize( + address _defender, + address _challenger, + IVerifierEntry _verifier, + address _resultReceiver, + uint256 _startInboxSize, + bytes32 _startStateHash, + bytes32 _endStateHash + ) external; + + /** + * @notice Initializes the length of the challenge. Must be called by defender before bisection rounds begin. + * @param _numSteps Number of steps executed from the start of the assertion to its end. + * If this parameter is incorrect, the defender will be slashed (assuming successful execution of the protocol by the challenger). + */ + function initializeChallengeLength(bytes32 checkStateHash, uint256 _numSteps) external; + + /** + * @notice Bisects a segment. The challenged segment is defined by: {`challengedSegmentStart`, `challengedSegmentLength`, `bisection[0]`, `oldEndHash`} + * @param bisection Bisection of challenged segment. Each element is a state hash (see `ChallengeLib.stateHash`). + * The first element is the last agreed upon state hash. Must be of length MAX_BISECTION_LENGTH for all rounds except the last. + * In the last round, the bisection segments must be single steps. + * @param challengedSegmentIndex Index into `prevBisection`. Must be greater than 0 (since the first is agreed upon). + * @param challengedSegmentStart Offset of the segment challenged in the preceding round (in steps). + * @param challengedSegmentLength Length of the segment challenged in the preceding round (in steps). + * @param prevChallengedSegmentStart Offset of the segment challenged in the preceding round (in steps). + * Note: this is relative to the assertion being challenged (i.e. always between 0 and the initial `numSteps`). + * @param prevChallengedSegmentLength Length of the segment challenged in the preceding round (in steps). + */ + function bisectExecution( + bytes32[3] calldata bisection, + uint256 challengedSegmentIndex, + uint256 challengedSegmentStart, + uint256 challengedSegmentLength, + uint256 prevChallengedSegmentStart, + uint256 prevChallengedSegmentLength + ) external; + + /** + * @notice Verifies one step proof and completes challenge protocol. + * @param ctx execution context. + * @param verifyType Index into `prevBisection`. Must be greater than 0 (since the first is agreed upon). + * @param proof one step proof. + * @param prevChallengedSegmentStart Offset of the segment challenged in the preceding round (in steps). + * Note: this is relative to the assertion being challenged (i.e. always between 0 and the initial `numSteps`). + * @param prevChallengedSegmentLength Length of the segment challenged in the preceding round (in steps). + */ + function verifyOneStepProof( + VerificationContext.Context calldata ctx, + uint8 verifyType, + bytes calldata proof, + uint256 challengedStepIndex, + uint256 prevChallengedSegmentStart, + uint256 prevChallengedSegmentLength + ) external; + + function setRollback() external; + + /** + * @notice Triggers completion of challenge protocol if a responder timed out. + */ + function timeout() external; + + function currentResponder() external view returns (address); + + function currentResponderTimeLeft() external view returns (uint256); + + function completeChallenge(bool) external; +} diff --git a/packages/contracts/contracts/L1/fraud-proof/libraries/BitLen.sol b/packages/contracts/contracts/L1/fraud-proof/libraries/BitLen.sol new file mode 100644 index 000000000..7ee479fe8 --- /dev/null +++ b/packages/contracts/contracts/L1/fraud-proof/libraries/BitLen.sol @@ -0,0 +1,79 @@ +// SPDX-License-Identifier: Apache-2.0 + +/* + * Copyright 2022, Specular contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +pragma solidity ^0.8.0; + +// For EXP opcode gas calculation +// Based on go packages `math/bits` and `holiman/uint256` +// TODO: seems for EXP we only need bytelen +library BitLen { + uint64 constant UINT16_MINIMUM = 1 << 8; + uint64 constant UINT32_MINIMUM = 1 << 16; + uint64 constant UINT64_MINIMUM = 1 << 32; + uint256 constant UINT128_MINIMUM = 1 << 64; + uint256 constant UINT192_MINIMUM = 1 << 128; + uint256 constant UINT256_MINIMUM = 1 << 192; + + function len8(uint8 x) internal pure returns (uint64 n) { + if (x == 0) { + return 0; + } else if (x == 1) { + return 1; + } else if (x <= 3) { + return 2; + } else if (x <= 7) { + return 3; + } else if (x <= 15) { + return 4; + } else if (x <= 31) { + return 5; + } else if (x <= 63) { + return 6; + } else if (x <= 127) { + return 7; + } + return 8; + } + + function len64(uint64 x) internal pure returns (uint64 n) { + if (x >= UINT64_MINIMUM) { + x >>= 32; + n = 32; + } + if (x >= UINT32_MINIMUM) { + x >>= 16; + n += 16; + } + if (x >= UINT16_MINIMUM) { + x >>= 8; + n += 8; + } + return n + len8(uint8(x)); + } + + function bitLen(uint256 x) internal pure returns (uint64) { + if (x >= UINT256_MINIMUM) { + return 192 + len64(uint64(x >> 192)); + } else if (x >= UINT192_MINIMUM) { + return 128 + len64(uint64(x >> 128)); + } else if (x >= UINT128_MINIMUM) { + return 64 + len64(uint64(x >> 64)); + } + return len64(uint64(x)); + } +} diff --git a/packages/contracts/contracts/L1/fraud-proof/libraries/BytesLib.sol b/packages/contracts/contracts/L1/fraud-proof/libraries/BytesLib.sol new file mode 100644 index 000000000..823f476f6 --- /dev/null +++ b/packages/contracts/contracts/L1/fraud-proof/libraries/BytesLib.sol @@ -0,0 +1,494 @@ +// SPDX-License-Identifier: Unlicense + +/* + * @title Solidity Bytes Arrays Utils + * @author Gonçalo Sá + * @custom:attribution https://github.com/GNSPS/solidity-bytes-utils + * + * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity. + * The library lets you concatenate, slice and type cast bytes arrays both in memory and storage. + */ + +pragma solidity >=0.8.0 <0.9.0; + +library BytesLib { + function concat(bytes memory _preBytes, bytes memory _postBytes) internal pure returns (bytes memory) { + bytes memory tempBytes; + + assembly { + // Get a location of some free memory and store it in tempBytes as + // Solidity does for memory variables. + tempBytes := mload(0x40) + + // Store the length of the first bytes array at the beginning of + // the memory for tempBytes. + let length := mload(_preBytes) + mstore(tempBytes, length) + + // Maintain a memory counter for the current write location in the + // temp bytes array by adding the 32 bytes for the array length to + // the starting location. + let mc := add(tempBytes, 0x20) + // Stop copying when the memory counter reaches the length of the + // first bytes array. + let end := add(mc, length) + + for { + // Initialize a copy counter to the start of the _preBytes data, + // 32 bytes into its memory. + let cc := add(_preBytes, 0x20) + } lt(mc, end) { + // Increase both counters by 32 bytes each iteration. + mc := add(mc, 0x20) + cc := add(cc, 0x20) + } { + // Write the _preBytes data into the tempBytes memory 32 bytes + // at a time. + mstore(mc, mload(cc)) + } + + // Add the length of _postBytes to the current length of tempBytes + // and store it as the new length in the first 32 bytes of the + // tempBytes memory. + length := mload(_postBytes) + mstore(tempBytes, add(length, mload(tempBytes))) + + // Move the memory counter back from a multiple of 0x20 to the + // actual end of the _preBytes data. + mc := end + // Stop copying when the memory counter reaches the new combined + // length of the arrays. + end := add(mc, length) + + for { let cc := add(_postBytes, 0x20) } lt(mc, end) { + mc := add(mc, 0x20) + cc := add(cc, 0x20) + } { mstore(mc, mload(cc)) } + + // Update the free-memory pointer by padding our last write location + // to 32 bytes: add 31 bytes to the end of tempBytes to move to the + // next 32 byte block, then round down to the nearest multiple of + // 32. If the sum of the length of the two arrays is zero then add + // one before rounding down to leave a blank 32 bytes (the length block with 0). + mstore( + 0x40, + and( + add(add(end, iszero(add(length, mload(_preBytes)))), 31), + not(31) // Round down to the nearest 32 bytes. + ) + ) + } + + return tempBytes; + } + + function concatStorage(bytes storage _preBytes, bytes memory _postBytes) internal { + assembly { + // Read the first 32 bytes of _preBytes storage, which is the length + // of the array. (We don't need to use the offset into the slot + // because arrays use the entire slot.) + let fslot := sload(_preBytes.slot) + // Arrays of 31 bytes or less have an even value in their slot, + // while longer arrays have an odd value. The actual length is + // the slot divided by two for odd values, and the lowest order + // byte divided by two for even values. + // If the slot is even, bitwise and the slot with 255 and divide by + // two to get the length. If the slot is odd, bitwise and the slot + // with -1 and divide by two. + let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2) + let mlength := mload(_postBytes) + let newlength := add(slength, mlength) + // slength can contain both the length and contents of the array + // if length < 32 bytes so let's prepare for that + // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage + switch add(lt(slength, 32), lt(newlength, 32)) + case 2 { + // Since the new array still fits in the slot, we just need to + // update the contents of the slot. + // uint256(bytes_storage) = uint256(bytes_storage) + uint256(bytes_memory) + new_length + sstore( + _preBytes.slot, + // all the modifications to the slot are inside this + // next block + add( + // we can just add to the slot contents because the + // bytes we want to change are the LSBs + fslot, + add( + mul( + div( + // load the bytes from memory + mload(add(_postBytes, 0x20)), + // zero all bytes to the right + exp(0x100, sub(32, mlength)) + ), + // and now shift left the number of bytes to + // leave space for the length in the slot + exp(0x100, sub(32, newlength)) + ), + // increase length by the double of the memory + // bytes length + mul(mlength, 2) + ) + ) + ) + } + case 1 { + // The stored value fits in the slot, but the combined value + // will exceed it. + // get the keccak hash to get the contents of the array + mstore(0x0, _preBytes.slot) + let sc := add(keccak256(0x0, 0x20), div(slength, 32)) + + // save new length + sstore(_preBytes.slot, add(mul(newlength, 2), 1)) + + // The contents of the _postBytes array start 32 bytes into + // the structure. Our first read should obtain the `submod` + // bytes that can fit into the unused space in the last word + // of the stored array. To get this, we read 32 bytes starting + // from `submod`, so the data we read overlaps with the array + // contents by `submod` bytes. Masking the lowest-order + // `submod` bytes allows us to add that value directly to the + // stored value. + + let submod := sub(32, slength) + let mc := add(_postBytes, submod) + let end := add(_postBytes, mlength) + let mask := sub(exp(0x100, submod), 1) + + sstore( + sc, + add( + and(fslot, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00), + and(mload(mc), mask) + ) + ) + + for { + mc := add(mc, 0x20) + sc := add(sc, 1) + } lt(mc, end) { + sc := add(sc, 1) + mc := add(mc, 0x20) + } { sstore(sc, mload(mc)) } + + mask := exp(0x100, sub(mc, end)) + + sstore(sc, mul(div(mload(mc), mask), mask)) + } + default { + // get the keccak hash to get the contents of the array + mstore(0x0, _preBytes.slot) + // Start copying to the last used word of the stored array. + let sc := add(keccak256(0x0, 0x20), div(slength, 32)) + + // save new length + sstore(_preBytes.slot, add(mul(newlength, 2), 1)) + + // Copy over the first `submod` bytes of the new data as in + // case 1 above. + let slengthmod := mod(slength, 32) + let mlengthmod := mod(mlength, 32) + let submod := sub(32, slengthmod) + let mc := add(_postBytes, submod) + let end := add(_postBytes, mlength) + let mask := sub(exp(0x100, submod), 1) + + sstore(sc, add(sload(sc), and(mload(mc), mask))) + + for { + sc := add(sc, 1) + mc := add(mc, 0x20) + } lt(mc, end) { + sc := add(sc, 1) + mc := add(mc, 0x20) + } { sstore(sc, mload(mc)) } + + mask := exp(0x100, sub(mc, end)) + + sstore(sc, mul(div(mload(mc), mask), mask)) + } + } + } + + function slice(bytes memory _bytes, uint256 _start, uint256 _length) internal pure returns (bytes memory) { + require(_length + 31 >= _length, "slice_overflow"); + require(_bytes.length >= _start + _length, "slice_outOfBounds"); + + bytes memory tempBytes; + + assembly { + switch iszero(_length) + case 0 { + // Get a location of some free memory and store it in tempBytes as + // Solidity does for memory variables. + tempBytes := mload(0x40) + + // The first word of the slice result is potentially a partial + // word read from the original array. To read it, we calculate + // the length of that partial word and start copying that many + // bytes into the array. The first word we copy will start with + // data we don't care about, but the last `lengthmod` bytes will + // land at the beginning of the contents of the new array. When + // we're done copying, we overwrite the full first word with + // the actual length of the slice. + let lengthmod := and(_length, 31) + + // The multiplication in the next line is necessary + // because when slicing multiples of 32 bytes (lengthmod == 0) + // the following copy loop was copying the origin's length + // and then ending prematurely not copying everything it should. + let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod))) + let end := add(mc, _length) + + for { + // The multiplication in the next line has the same exact purpose + // as the one above. + let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start) + } lt(mc, end) { + mc := add(mc, 0x20) + cc := add(cc, 0x20) + } { mstore(mc, mload(cc)) } + + mstore(tempBytes, _length) + + //update free-memory pointer + //allocating the array padded to 32 bytes like the compiler does now + mstore(0x40, and(add(mc, 31), not(31))) + } + //if we want a zero-length slice let's just return a zero-length array + default { + tempBytes := mload(0x40) + //zero out the 32 bytes slice we are about to return + //we need to do it because Solidity does not garbage collect + mstore(tempBytes, 0) + + mstore(0x40, add(tempBytes, 0x20)) + } + } + + return tempBytes; + } + + function toBytes32Pad(bytes memory _bytes, uint256 _start) internal pure returns (bytes32) { + bytes32 result; + + assembly { + result := mload(add(add(_bytes, 0x20), _start)) + } + + if (_bytes.length < _start + 32) { + uint256 pad = 32 + _start - _bytes.length; + result = result >> pad << pad; + } + + return result; + } + + function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) { + require(_bytes.length >= _start + 20, "toAddress_outOfBounds"); + address tempAddress; + + assembly { + tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000) + } + + return tempAddress; + } + + function toUint8(bytes memory _bytes, uint256 _start) internal pure returns (uint8) { + require(_bytes.length >= _start + 1, "toUint8_outOfBounds"); + uint8 tempUint; + + assembly { + tempUint := mload(add(add(_bytes, 0x1), _start)) + } + + return tempUint; + } + + function toUint16(bytes memory _bytes, uint256 _start) internal pure returns (uint16) { + require(_bytes.length >= _start + 2, "toUint16_outOfBounds"); + uint16 tempUint; + + assembly { + tempUint := mload(add(add(_bytes, 0x2), _start)) + } + + return tempUint; + } + + function toUint32(bytes memory _bytes, uint256 _start) internal pure returns (uint32) { + require(_bytes.length >= _start + 4, "toUint32_outOfBounds"); + uint32 tempUint; + + assembly { + tempUint := mload(add(add(_bytes, 0x4), _start)) + } + + return tempUint; + } + + function toUint64(bytes memory _bytes, uint256 _start) internal pure returns (uint64) { + require(_bytes.length >= _start + 8, "toUint64_outOfBounds"); + uint64 tempUint; + + assembly { + tempUint := mload(add(add(_bytes, 0x8), _start)) + } + + return tempUint; + } + + function toUint96(bytes memory _bytes, uint256 _start) internal pure returns (uint96) { + require(_bytes.length >= _start + 12, "toUint96_outOfBounds"); + uint96 tempUint; + + assembly { + tempUint := mload(add(add(_bytes, 0xc), _start)) + } + + return tempUint; + } + + function toUint128(bytes memory _bytes, uint256 _start) internal pure returns (uint128) { + require(_bytes.length >= _start + 16, "toUint128_outOfBounds"); + uint128 tempUint; + + assembly { + tempUint := mload(add(add(_bytes, 0x10), _start)) + } + + return tempUint; + } + + function toUint256(bytes memory _bytes, uint256 _start) internal pure returns (uint256) { + require(_bytes.length >= _start + 32, "toUint256_outOfBounds"); + uint256 tempUint; + + assembly { + tempUint := mload(add(add(_bytes, 0x20), _start)) + } + + return tempUint; + } + + function toBytes32(bytes memory _bytes, uint256 _start) internal pure returns (bytes32) { + require(_bytes.length >= _start + 32, "toBytes32_outOfBounds"); + bytes32 tempBytes32; + + assembly { + tempBytes32 := mload(add(add(_bytes, 0x20), _start)) + } + + return tempBytes32; + } + + function equal(bytes memory _preBytes, bytes memory _postBytes) internal pure returns (bool) { + bool success = true; + + assembly { + let length := mload(_preBytes) + + // if lengths don't match the arrays are not equal + switch eq(length, mload(_postBytes)) + case 1 { + // cb is a circuit breaker in the for loop since there's + // no said feature for inline assembly loops + // cb = 1 - don't breaker + // cb = 0 - break + let cb := 1 + + let mc := add(_preBytes, 0x20) + let end := add(mc, length) + + for { let cc := add(_postBytes, 0x20) } + // the next line is the loop condition: + // while(uint256(mc < end) + cb == 2) + eq(add(lt(mc, end), cb), 2) { + mc := add(mc, 0x20) + cc := add(cc, 0x20) + } { + // if any of these checks fails then arrays are not equal + if iszero(eq(mload(mc), mload(cc))) { + // unsuccess: + success := 0 + cb := 0 + } + } + } + default { + // unsuccess: + success := 0 + } + } + + return success; + } + + function equalStorage(bytes storage _preBytes, bytes memory _postBytes) internal view returns (bool) { + bool success = true; + + assembly { + // we know _preBytes_offset is 0 + let fslot := sload(_preBytes.slot) + // Decode the length of the stored array like in concatStorage(). + let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2) + let mlength := mload(_postBytes) + + // if lengths don't match the arrays are not equal + switch eq(slength, mlength) + case 1 { + // slength can contain both the length and contents of the array + // if length < 32 bytes so let's prepare for that + // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage + if iszero(iszero(slength)) { + switch lt(slength, 32) + case 1 { + // blank the last byte which is the length + fslot := mul(div(fslot, 0x100), 0x100) + + if iszero(eq(fslot, mload(add(_postBytes, 0x20)))) { + // unsuccess: + success := 0 + } + } + default { + // cb is a circuit breaker in the for loop since there's + // no said feature for inline assembly loops + // cb = 1 - don't breaker + // cb = 0 - break + let cb := 1 + + // get the keccak hash to get the contents of the array + mstore(0x0, _preBytes.slot) + let sc := keccak256(0x0, 0x20) + + let mc := add(_postBytes, 0x20) + let end := add(mc, mlength) + + // the next line is the loop condition: + // while(uint256(mc < end) + cb == 2) + for {} eq(add(lt(mc, end), cb), 2) { + sc := add(sc, 1) + mc := add(mc, 0x20) + } { + if iszero(eq(sload(sc), mload(mc))) { + // unsuccess: + success := 0 + cb := 0 + } + } + } + } + } + default { + // unsuccess: + success := 0 + } + } + + return success; + } +} diff --git a/packages/contracts/contracts/L1/fraud-proof/libraries/DeserializationLib.sol b/packages/contracts/contracts/L1/fraud-proof/libraries/DeserializationLib.sol new file mode 100644 index 000000000..14c6cb1f1 --- /dev/null +++ b/packages/contracts/contracts/L1/fraud-proof/libraries/DeserializationLib.sol @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: Apache-2.0 + +/* + * Copyright 2022, Specular contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +pragma solidity ^0.8.0; + +import "./BytesLib.sol"; + +library DeserializationLib { + function deserializeAddress(bytes memory data, uint256 startOffset) internal pure returns (uint256, address) { + return (startOffset + 20, BytesLib.toAddress(data, startOffset)); + } + + function deserializeUint256(bytes memory data, uint256 startOffset) internal pure returns (uint256, uint256) { + require(data.length >= startOffset && data.length - startOffset >= 32, "too short"); + return (startOffset + 32, BytesLib.toUint256(data, startOffset)); + } + + function deserializeBytes32(bytes memory data, uint256 startOffset) internal pure returns (uint256, bytes32) { + require(data.length >= startOffset && data.length - startOffset >= 32, "too short"); + return (startOffset + 32, BytesLib.toBytes32(data, startOffset)); + } +} diff --git a/packages/contracts/contracts/L1/fraud-proof/libraries/Errors.sol b/packages/contracts/contracts/L1/fraud-proof/libraries/Errors.sol new file mode 100644 index 000000000..207133cbb --- /dev/null +++ b/packages/contracts/contracts/L1/fraud-proof/libraries/Errors.sol @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: Apache-2.0 + +/* + * Copyright 2022, Specular contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +pragma solidity ^0.8.0; + +/// @dev Thrown when unauthorized (!rollup) address calls an only-rollup function +/// @param sender Address of the caller +/// @param rollup The rollup address authorized to call this function +error NotRollup(address sender, address rollup); + +/// @dev Thrown when unauthorized (!challenge) address calls an only-challenge function +/// @param sender Address of the caller +/// @param challenge The challenge address authorized to call this function +error NotChallenge(address sender, address challenge); + +/// @dev Thrown when unauthorized (!sequencer) address calls an only-sequencer function +/// @param sender Address of the caller +/// @param sequencer The sequencer address authorized to call this function +error NotSequencer(address sender, address sequencer); + +/// @dev Thrown when function is called with a zero address argument +error ZeroAddress(); + +/// @dev Thrown when function is called with a zero address argument +error RedundantInitialized(); diff --git a/packages/contracts/contracts/L1/fraud-proof/libraries/MPT.sol b/packages/contracts/contracts/L1/fraud-proof/libraries/MPT.sol new file mode 100644 index 000000000..e05824e25 --- /dev/null +++ b/packages/contracts/contracts/L1/fraud-proof/libraries/MPT.sol @@ -0,0 +1,259 @@ +//SPDX-License-Identifier: Unlicense +pragma solidity ^0.8.0; + +import "./RLPReader.sol"; + +library MPT { + using RLPReader for RLPReader.RLPItem; + using RLPReader for bytes; + + /// @dev Validates a Merkle-Patricia-Trie proof. + /// If the proof proves the inclusion of some key-value pair in the + /// trie, the value is returned. Otherwise, i.e. if the proof proves + /// the exclusion of a key from the trie, an empty byte array is + /// returned. + /// @param rootHash is the Keccak-256 hash of the root node of the MPT. + /// @param path is the key of the node whose inclusion/exclusion we are + /// proving. + /// @param stack is the stack of MPT nodes (starting with the root) that + /// need to be traversed during verification. + /// @return value whose inclusion is proved or an empty byte array for + /// a proof of exclusion + function extractProofValue(bytes32 rootHash, bytes memory path, RLPReader.RLPItem[] memory stack) + internal + pure + returns (bytes memory value) + { + bytes memory mptKey = _decodeNibbles(path, 0); + uint256 mptKeyOffset = 0; + + bytes32 nodeHashHash; + RLPReader.RLPItem[] memory node; + + RLPReader.RLPItem memory rlpValue; + + if (stack.length == 0) { + // Root hash of empty Merkle-Patricia-Trie + require(rootHash == 0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421); + return new bytes(0); + } + + // Traverse stack of nodes starting at root. + for (uint256 i = 0; i < stack.length; i++) { + // We use the fact that an rlp encoded list consists of some + // encoding of its length plus the concatenation of its + // *rlp-encoded* items. + + // The root node is hashed with Keccak-256 ... + if (i == 0 && rootHash != stack[i].rlpBytesKeccak256()) { + revert(); + } + // ... whereas all other nodes are hashed with the MPT + // hash function. + if (i != 0 && nodeHashHash != _mptHashHash(stack[i])) { + revert(); + } + // We verified that stack[i] has the correct hash, so we + // may safely decode it. + node = stack[i].toBytes().toRlpItem().toList(); + + if (node.length == 2) { + // Extension or Leaf node + + bool isLeaf; + bytes memory nodeKey; + (isLeaf, nodeKey) = _merklePatriciaCompactDecode(node[0].toBytes()); + + uint256 prefixLength = _sharedPrefixLength(mptKeyOffset, mptKey, nodeKey); + mptKeyOffset += prefixLength; + + if (prefixLength < nodeKey.length) { + // Proof claims divergent extension or leaf. (Only + // relevant for proofs of exclusion.) + // An Extension/Leaf node is divergent iff it "skips" over + // the point at which a Branch node should have been had the + // excluded key been included in the trie. + // Example: Imagine a proof of exclusion for path [1, 4], + // where the current node is a Leaf node with + // path [1, 3, 3, 7]. For [1, 4] to be included, there + // should have been a Branch node at [1] with a child + // at 3 and a child at 4. + + // Sanity check + if (i < stack.length - 1) { + // divergent node must come last in proof + revert(); + } + + return new bytes(0); + } + + if (isLeaf) { + // Sanity check + if (i < stack.length - 1) { + // leaf node must come last in proof + revert(); + } + + if (mptKeyOffset < mptKey.length) { + return new bytes(0); + } + + rlpValue = node[1]; + return rlpValue.toBytes(); + } else { + // extension + // Sanity check + if (i == stack.length - 1) { + // shouldn't be at last level + revert(); + } + + if (!node[1].isList()) { + // rlp(child) was at least 32 bytes. node[1] contains + // Keccak256(rlp(child)). + nodeHashHash = node[1].payloadKeccak256(); + } else { + // rlp(child) was less than 32 bytes. node[1] contains + // rlp(child). + nodeHashHash = node[1].rlpBytesKeccak256(); + } + } + } else if (node.length == 17) { + // Branch node + + if (mptKeyOffset != mptKey.length) { + // we haven't consumed the entire path, so we need to look at a child + uint8 nibble = uint8(mptKey[mptKeyOffset]); + mptKeyOffset += 1; + if (nibble >= 16) { + // each element of the path has to be a nibble + revert(); + } + + if (_isEmptyBytesequence(node[nibble])) { + // Sanity + if (i != stack.length - 1) { + // leaf node should be at last level + revert(); + } + + return new bytes(0); + } else if (!node[nibble].isList()) { + nodeHashHash = node[nibble].payloadKeccak256(); + } else { + nodeHashHash = node[nibble].rlpBytesKeccak256(); + } + } else { + // we have consumed the entire mptKey, so we need to look at what's contained in this node. + + // Sanity + if (i != stack.length - 1) { + // should be at last level + revert(); + } + + return node[16].toBytes(); + } + } + } + } + + function verifyAndUpdateProofValue( + bytes32 rootHash, + bytes memory path, + bytes memory oldValue, + bytes memory newValue, + bytes memory rawProof + ) internal pure returns (bytes32 newRoot) { + return 0; + } + + /// @dev Computes the hash of the Merkle-Patricia-Trie hash of the RLP item. + /// Merkle-Patricia-Tries use a weird "hash function" that outputs + /// *variable-length* hashes: If the item is shorter than 32 bytes, + /// the MPT hash is the item. Otherwise, the MPT hash is the + /// Keccak-256 hash of the item. + /// The easiest way to compare variable-length byte sequences is + /// to compare their Keccak-256 hashes. + /// @param item The RLP item to be hashed. + /// @return Keccak-256(MPT-hash(item)) + function _mptHashHash(RLPReader.RLPItem memory item) private pure returns (bytes32) { + if (item.len < 32) { + return item.rlpBytesKeccak256(); + } else { + return keccak256(abi.encodePacked(item.rlpBytesKeccak256())); + } + } + + function _isEmptyBytesequence(RLPReader.RLPItem memory item) private pure returns (bool) { + if (item.len != 1) { + return false; + } + uint8 b; + uint256 memPtr = item.memPtr; + assembly { + b := byte(0, mload(memPtr)) + } + return b == 0x80; /* empty byte string */ + } + + function _merklePatriciaCompactDecode(bytes memory compact) + private + pure + returns (bool isLeaf, bytes memory nibbles) + { + require(compact.length > 0); + uint256 first_nibble = uint8(compact[0]) >> 4 & 0xF; + uint256 skipNibbles; + if (first_nibble == 0) { + skipNibbles = 2; + isLeaf = false; + } else if (first_nibble == 1) { + skipNibbles = 1; + isLeaf = false; + } else if (first_nibble == 2) { + skipNibbles = 2; + isLeaf = true; + } else if (first_nibble == 3) { + skipNibbles = 1; + isLeaf = true; + } else { + // Not supposed to happen! + revert(); + } + return (isLeaf, _decodeNibbles(compact, skipNibbles)); + } + + function _decodeNibbles(bytes memory compact, uint256 skipNibbles) private pure returns (bytes memory nibbles) { + require(compact.length > 0); + + uint256 length = compact.length * 2; + require(skipNibbles <= length); + length -= skipNibbles; + + nibbles = new bytes(length); + uint256 nibblesLength = 0; + + for (uint256 i = skipNibbles; i < skipNibbles + length; i += 1) { + if (i % 2 == 0) { + nibbles[nibblesLength] = bytes1((uint8(compact[i / 2]) >> 4) & 0xF); + } else { + nibbles[nibblesLength] = bytes1((uint8(compact[i / 2]) >> 0) & 0xF); + } + nibblesLength += 1; + } + + assert(nibblesLength == nibbles.length); + } + + function _sharedPrefixLength(uint256 xsOffset, bytes memory xs, bytes memory ys) private pure returns (uint256) { + uint256 i; + for (i = 0; i + xsOffset < xs.length && i < ys.length; i++) { + if (xs[i + xsOffset] != ys[i]) { + return i; + } + } + return i; + } +} diff --git a/packages/contracts/contracts/L1/fraud-proof/libraries/MerkleLib.sol b/packages/contracts/contracts/L1/fraud-proof/libraries/MerkleLib.sol new file mode 100644 index 000000000..3b84eaffe --- /dev/null +++ b/packages/contracts/contracts/L1/fraud-proof/libraries/MerkleLib.sol @@ -0,0 +1,1354 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +library MerkleLib { + // Hashes a and b in the order they are passed + function hash_node(bytes32 a, bytes32 b) internal pure returns (bytes32 hash) { + assembly { + mstore(0x00, a) + mstore(0x20, b) + hash := keccak256(0x00, 0x40) + } + } + + // Hashes a and b in order define by boolean + function hash_pair(bytes32 a, bytes32 b, bool order) internal pure returns (bytes32 hash) { + hash = order ? hash_node(a, b) : hash_node(b, a); + } + + // Counts number of set bits (1's) in 32-bit unsigned integer + function bit_count_32(uint32 n) internal pure returns (uint32) { + n = n - ((n >> 1) & 0x55555555); + n = (n & 0x33333333) + ((n >> 2) & 0x33333333); + + return (((n + (n >> 4)) & 0xF0F0F0F) * 0x1010101) >> 24; + } + + // Round 32-bit unsigned integer up to the nearest power of 2 + function round_up_to_power_of_2(uint32 n) internal pure returns (uint32) { + if (bit_count_32(n) == 1) return n; + + n |= n >> 1; + n |= n >> 2; + n |= n >> 4; + n |= n >> 8; + n |= n >> 16; + + return n + 1; + } + + // Get the Element Merkle Root for a tree with just a single bytes32 element in memory + function get_root_from_one(bytes32 element) internal pure returns (bytes32) { + return keccak256(abi.encodePacked(bytes1(0), element)); + } + + // Get nodes (parent of leafs) from bytes32 elements in memory + function get_nodes_from_elements(bytes32[] memory elements) internal pure returns (bytes32[] memory nodes) { + uint256 element_count = elements.length; + uint256 node_count = (element_count >> 1) + (element_count & 1); + nodes = new bytes32[](node_count); + uint256 write_index; + uint256 left_index; + + while (write_index < node_count) { + left_index = write_index << 1; + + if (left_index == element_count - 1) { + nodes[write_index] = keccak256(abi.encodePacked(bytes1(0), elements[left_index])); + break; + } + + nodes[write_index++] = hash_node( + keccak256(abi.encodePacked(bytes1(0), elements[left_index])), + keccak256(abi.encodePacked(bytes1(0), elements[left_index + 1])) + ); + } + } + + // Get the Element Merkle Root given nodes (parent of leafs) + function get_root_from_nodes(bytes32[] memory nodes) internal pure returns (bytes32) { + uint256 node_count = nodes.length; + uint256 write_index; + uint256 left_index; + + while (node_count > 1) { + left_index = write_index << 1; + + if (left_index == node_count - 1) { + nodes[write_index] = nodes[left_index]; + write_index = 0; + node_count = (node_count >> 1) + (node_count & 1); + continue; + } + + if (left_index >= node_count) { + write_index = 0; + node_count = (node_count >> 1) + (node_count & 1); + continue; + } + + nodes[write_index++] = hash_node(nodes[left_index], nodes[left_index + 1]); + } + + return nodes[0]; + } + + // Get the Element Merkle Root for a tree with several bytes32 elements in memory + function get_root_from_many(bytes32[] memory elements) internal pure returns (bytes32) { + return get_root_from_nodes(get_nodes_from_elements(elements)); + } + + // Get the original Element Merkle Root, given a Size Proof + function get_root_from_size_proof(uint256 element_count, bytes32[] memory proof) + internal + pure + returns (bytes32 hash) + { + uint256 proof_index = bit_count_32(uint32(element_count)) - 1; + hash = proof[proof_index]; + + while (proof_index > 0) { + hash = hash_node(proof[--proof_index], hash); + } + } + + // Get the original Element Merkle Root, given an index, a leaf, and a Single Proof + function get_root_from_leaf_and_single_proof(uint256 index, bytes32 leaf, bytes32[] memory proof) + internal + pure + returns (bytes32) + { + uint256 proof_index = proof.length - 1; + uint256 upper_bound = uint256(proof[0]) - 1; + + while (proof_index > 0) { + if (index != upper_bound || (index & 1 == 1)) { + leaf = (index & 1 == 1) ? hash_node(proof[proof_index], leaf) : hash_node(leaf, proof[proof_index]); + proof_index -= 1; + } + + index >>= 1; + upper_bound >>= 1; + } + + return leaf; + } + + // Get the original Element Merkle Root, given an index, a bytes32 element, and a Single Proof + function get_root_from_single_proof(uint256 index, bytes32 element, bytes32[] memory proof) + internal + pure + returns (bytes32 hash) + { + hash = keccak256(abi.encodePacked(bytes1(0), element)); + hash = get_root_from_leaf_and_single_proof(index, hash, proof); + } + + // Get the original and updated Element Merkle Root, given an index, a leaf, an update leaf, and a Single Proof + function get_roots_from_leaf_and_single_proof_update( + uint256 index, + bytes32 leaf, + bytes32 update_leaf, + bytes32[] memory proof + ) internal pure returns (bytes32 scratch, bytes32) { + uint256 proof_index = proof.length - 1; + uint256 upper_bound = uint256(proof[0]) - 1; + + while (proof_index > 0) { + if ((index != upper_bound) || (index & 1 == 1)) { + scratch = proof[proof_index]; + proof_index -= 1; + leaf = (index & 1 == 1) ? hash_node(scratch, leaf) : hash_node(leaf, scratch); + update_leaf = (index & 1 == 1) ? hash_node(scratch, update_leaf) : hash_node(update_leaf, scratch); + } + + index >>= 1; + upper_bound >>= 1; + } + + return (leaf, update_leaf); + } + + // Get the original and updated Element Merkle Root, given an index, a bytes32 element, a bytes32 update element, and a Single Proof + function get_roots_from_single_proof_update( + uint256 index, + bytes32 element, + bytes32 update_element, + bytes32[] memory proof + ) internal pure returns (bytes32 hash, bytes32 update_hash) { + hash = keccak256(abi.encodePacked(bytes1(0), element)); + update_hash = keccak256(abi.encodePacked(bytes1(0), update_element)); + return get_roots_from_leaf_and_single_proof_update(index, hash, update_hash, proof); + } + + // Get the indices of the elements being proven, given an Existence Multi Proof + function get_indices_from_multi_proof(uint256 element_count, bytes32 flags, bytes32 skips, bytes32 orders) + internal + pure + returns (uint256[] memory indices) + { + indices = new uint256[](element_count); + uint256[] memory bits_pushed = new uint256[](element_count); + bool[] memory grouped_with_next = new bool[](element_count); + element_count -= 1; + uint256 index = element_count; + bytes32 bit_check = 0x0000000000000000000000000000000000000000000000000000000000000001; + bytes32 flag; + bytes32 skip; + bytes32 order; + uint256 bits_to_push; + + while (true) { + flag = flags & bit_check; + skip = skips & bit_check; + order = orders & bit_check; + bits_to_push = 1 << bits_pushed[index]; + + if (skip == bit_check) { + if (flag == bit_check) return indices; + + while (true) { + bits_pushed[index]++; + + if (index == 0) { + index = element_count; + break; + } + + if (!grouped_with_next[index--]) break; + } + + bit_check <<= 1; + continue; + } + + if (flag == bit_check) { + while (true) { + if (order == bit_check) { + indices[index] |= bits_to_push; + } + + bits_pushed[index]++; + + if (index == 0) { + index = element_count; + break; + } + + if (!grouped_with_next[index]) { + grouped_with_next[index--] = true; + break; + } + + grouped_with_next[index--] = true; + } + } + + while (true) { + if (order != bit_check) { + indices[index] |= bits_to_push; + } + + bits_pushed[index]++; + + if (index == 0) { + index = element_count; + break; + } + + if (!grouped_with_next[index--]) break; + } + + bit_check <<= 1; + } + } + + // Get leafs from bytes32 elements in memory, in reverse order + function get_reversed_leafs_from_elements(bytes32[] memory elements) + internal + pure + returns (bytes32[] memory leafs) + { + uint256 element_count = elements.length; + leafs = new bytes32[](element_count); + // uint256 read_index = element_count - 1; + // uint256 write_index; + + for (uint64 i = 0; i < element_count; i++) { + leafs[i] = keccak256(abi.encodePacked(bytes1(0), elements[element_count - 1 - i])); + } + + // while (write_index < element_count) { + // leafs[write_index] = keccak256(abi.encodePacked(bytes1(0), elements[read_index])); + // write_index += 1; + // read_index -= 1; + // } + } + + // Get the original Element Merkle Root, given leafs and an Existence Multi Proof + function get_root_from_leafs_and_multi_proof(bytes32[] memory leafs, bytes32[] memory proof) + internal + pure + returns (bytes32 right) + { + uint256 leaf_count = leafs.length; + uint256 read_index; + uint256 write_index; + uint256 proof_index = 4; + bytes32 bit_check = 0x0000000000000000000000000000000000000000000000000000000000000001; + bytes32 flags = proof[1]; + bytes32 skips = proof[2]; + bytes32 orders = proof[3]; + + while (true) { + if (skips & bit_check == bit_check) { + if (flags & bit_check == bit_check) return leafs[(write_index == 0 ? leaf_count : write_index) - 1]; + + leafs[write_index] = leafs[read_index]; + + read_index = (read_index + 1) % leaf_count; + write_index = (write_index + 1) % leaf_count; + bit_check <<= 1; + continue; + } + + right = (flags & bit_check == bit_check) ? leafs[read_index++] : proof[proof_index++]; + + read_index %= leaf_count; + + leafs[write_index] = hash_pair(leafs[read_index], right, orders & bit_check == bit_check); + + read_index = (read_index + 1) % leaf_count; + write_index = (write_index + 1) % leaf_count; + bit_check <<= 1; + } + } + + // Get the original Element Merkle Root, given bytes32 memory in memory and an Existence Multi Proof + function get_root_from_multi_proof(bytes32[] memory elements, bytes32[] memory proof) + internal + pure + returns (bytes32) + { + return get_root_from_leafs_and_multi_proof(get_reversed_leafs_from_elements(elements), proof); + } + + // Get current and update leafs from current bytes32 elements in memory and update bytes32 elements in memory, in reverse order + function get_reversed_leafs_from_current_and_update_elements( + bytes32[] memory elements, + bytes32[] memory update_elements + ) internal pure returns (bytes32[] memory leafs, bytes32[] memory update_leafs) { + uint256 element_count = elements.length; + require(update_elements.length == element_count, "LENGTH_MISMATCH"); + + leafs = new bytes32[](element_count); + update_leafs = new bytes32[](element_count); + // uint256 read_index = element_count - 1; + // uint256 write_index; + + // while (write_index < element_count) { + // leafs[write_index] = keccak256(abi.encodePacked(bytes1(0), elements[read_index])); + // update_leafs[write_index] = keccak256(abi.encodePacked(bytes1(0), update_elements[read_index])); + // write_index += 1; + // read_index -= 1; + // } + + for (uint64 i = 0; i < element_count; i++) { + leafs[i] = keccak256(abi.encodePacked(bytes1(0), elements[element_count - 1 - i])); + update_leafs[i] = keccak256(abi.encodePacked(bytes1(0), update_elements[element_count - 1 - i])); + } + } + + // Get the original and updated Element Merkle Root, given leafs, update leafs, and an Existence Multi Proof + function get_roots_from_leafs_and_multi_proof_update( + bytes32[] memory leafs, + bytes32[] memory update_leafs, + bytes32[] memory proof + ) internal pure returns (bytes32 flags, bytes32 skips) { + uint256 leaf_count = update_leafs.length; + uint256 read_index; + uint256 write_index; + uint256 proof_index = 4; + bytes32 bit_check = 0x0000000000000000000000000000000000000000000000000000000000000001; + flags = proof[1]; + skips = proof[2]; + bytes32 orders = proof[3]; + bytes32 scratch; + uint256 scratch_2; + + while (true) { + if (skips & bit_check == bit_check) { + if (flags & bit_check == bit_check) { + read_index = (write_index == 0 ? leaf_count : write_index) - 1; + + return (leafs[read_index], update_leafs[read_index]); + } + + leafs[write_index] = leafs[read_index]; + update_leafs[write_index] = update_leafs[read_index]; + + read_index = (read_index + 1) % leaf_count; + write_index = (write_index + 1) % leaf_count; + bit_check <<= 1; + continue; + } + + if (flags & bit_check == bit_check) { + scratch_2 = (read_index + 1) % leaf_count; + + leafs[write_index] = hash_pair(leafs[scratch_2], leafs[read_index], orders & bit_check == bit_check); + update_leafs[write_index] = + hash_pair(update_leafs[scratch_2], update_leafs[read_index], orders & bit_check == bit_check); + + read_index += 2; + } else { + scratch = proof[proof_index++]; + + leafs[write_index] = hash_pair(leafs[read_index], scratch, orders & bit_check == bit_check); + update_leafs[write_index] = + hash_pair(update_leafs[read_index], scratch, orders & bit_check == bit_check); + + read_index += 1; + } + + read_index %= leaf_count; + write_index = (write_index + 1) % leaf_count; + bit_check <<= 1; + } + } + + // Get the original and updated Element Merkle Root, + // given bytes32 elements in memory, bytes32 update elements in memory, and an Existence Multi Proof + function get_roots_from_multi_proof_update( + bytes32[] memory elements, + bytes32[] memory update_elements, + bytes32[] memory proof + ) internal pure returns (bytes32, bytes32) { + (bytes32[] memory leafs, bytes32[] memory update_leafs) = + get_reversed_leafs_from_current_and_update_elements(elements, update_elements); + return get_roots_from_leafs_and_multi_proof_update(leafs, update_leafs, proof); + } + + // Get the original Element Merkle Root, given an Append Proof + function get_root_from_append_proof(bytes32[] memory proof) internal pure returns (bytes32 hash) { + uint256 proof_index = bit_count_32(uint32(uint256(proof[0]))); + hash = proof[proof_index]; + + while (proof_index > 1) { + proof_index -= 1; + hash = hash_node(proof[proof_index], hash); + } + } + + // Get the original and updated Element Merkle Root, given append leaf and an Append Proof + function get_roots_from_leaf_and_append_proof_single_append(bytes32 append_leaf, bytes32[] memory proof) + internal + pure + returns (bytes32 hash, bytes32 scratch) + { + uint256 proof_index = bit_count_32(uint32(uint256(proof[0]))); + hash = proof[proof_index]; + append_leaf = hash_node(hash, append_leaf); + + while (proof_index > 1) { + proof_index -= 1; + scratch = proof[proof_index]; + append_leaf = hash_node(scratch, append_leaf); + hash = hash_node(scratch, hash); + } + + return (hash, append_leaf); + } + + // Get the original and updated Element Merkle Root, given a bytes32 append element in memory and an Append Proof + function get_roots_from_append_proof_single_append(bytes32 append_element, bytes32[] memory proof) + internal + pure + returns (bytes32 append_leaf, bytes32) + { + append_leaf = keccak256(abi.encodePacked(bytes1(0), append_element)); + return get_roots_from_leaf_and_append_proof_single_append(append_leaf, proof); + } + + // Get leafs from bytes32 elements in memory + function get_leafs_from_elements(bytes32[] memory elements) internal pure returns (bytes32[] memory leafs) { + uint256 element_count = elements.length; + leafs = new bytes32[](element_count); + + while (element_count > 0) { + element_count -= 1; + leafs[element_count] = keccak256(abi.encodePacked(bytes1(0), elements[element_count])); + } + } + + // Get the original and updated Element Merkle Root, given append leafs and an Append Proof + function get_roots_from_leafs_and_append_proof_multi_append(bytes32[] memory append_leafs, bytes32[] memory proof) + internal + pure + returns (bytes32 hash, bytes32) + { + uint256 leaf_count = append_leafs.length; + uint256 write_index; + uint256 read_index; + uint256 offset = uint256(proof[0]); + uint256 index = offset; + + // reuse leaf_count variable as upper_bound, since leaf_count no longer needed + leaf_count += offset; + leaf_count -= 1; + uint256 proof_index = bit_count_32(uint32(offset)); + hash = proof[proof_index]; + + while (leaf_count > 0) { + if ((write_index == 0) && (index & 1 == 1)) { + append_leafs[0] = hash_node(proof[proof_index], append_leafs[read_index]); + proof_index -= 1; + read_index += 1; + + if (proof_index > 0) { + hash = hash_node(proof[proof_index], hash); + } + + write_index = 1; + index += 1; + } else if (index < leaf_count) { + append_leafs[write_index++] = hash_node(append_leafs[read_index++], append_leafs[read_index]); + read_index += 1; + index += 2; + } + + if (index >= leaf_count) { + if (index == leaf_count) { + append_leafs[write_index] = append_leafs[read_index]; + } + + read_index = 0; + write_index = 0; + leaf_count >>= 1; + offset >>= 1; + index = offset; + } + } + + return (hash, append_leafs[0]); + } + + // Get the original and updated Element Merkle Root, given bytes32 append elements in memory and an Append Proof + function get_roots_from_append_proof_multi_append(bytes32[] memory append_elements, bytes32[] memory proof) + internal + pure + returns (bytes32, bytes32) + { + return get_roots_from_leafs_and_append_proof_multi_append(get_leafs_from_elements(append_elements), proof); + } + + // Get the updated Element Merkle Root, given an append leaf and an Append Proof + function get_new_root_from_leafs_and_append_proof_single_append(bytes32 append_leaf, bytes32[] memory proof) + internal + pure + returns (bytes32 append_hash) + { + uint256 proof_index = bit_count_32(uint32(uint256(proof[0]))); + append_hash = hash_node(proof[proof_index], append_leaf); + + while (proof_index > 1) { + proof_index -= 1; + append_hash = hash_node(proof[proof_index], append_hash); + } + } + + // Get the updated Element Merkle Root, given a bytes32 append elements in memory and an Append Proof + function get_new_root_from_append_proof_single_append(bytes32 append_element, bytes32[] memory proof) + internal + pure + returns (bytes32 append_leaf) + { + append_leaf = keccak256(abi.encodePacked(bytes1(0), append_element)); + return get_new_root_from_leafs_and_append_proof_single_append(append_leaf, proof); + } + + // Get the updated Element Merkle Root, given append leafs and an Append Proof + function get_new_root_from_leafs_and_append_proof_multi_append( + bytes32[] memory append_leafs, + bytes32[] memory proof + ) internal pure returns (bytes32) { + uint256 leaf_count = append_leafs.length; + uint256 write_index; + uint256 read_index; + uint256 offset = uint256(proof[0]); + uint256 index = offset; + + // reuse leaf_count variable as upper_bound, since leaf_count no longer needed + leaf_count += offset; + leaf_count -= 1; + uint256 proof_index = proof.length - 1; + + while (leaf_count > 0) { + if ((write_index == 0) && (index & 1 == 1)) { + append_leafs[0] = hash_node(proof[proof_index], append_leafs[read_index]); + + read_index += 1; + proof_index -= 1; + write_index = 1; + index += 1; + } else if (index < leaf_count) { + append_leafs[write_index++] = hash_node(append_leafs[read_index++], append_leafs[read_index++]); + + index += 2; + } + + if (index >= leaf_count) { + if (index == leaf_count) { + append_leafs[write_index] = append_leafs[read_index]; + } + + read_index = 0; + write_index = 0; + leaf_count >>= 1; + offset >>= 1; + index = offset; + } + } + + return append_leafs[0]; + } + + // Get the updated Element Merkle Root, given bytes32 append elements in memory and an Append Proof + function get_new_root_from_append_proof_multi_append(bytes32[] memory append_elements, bytes32[] memory proof) + internal + pure + returns (bytes32) + { + return get_new_root_from_leafs_and_append_proof_multi_append(get_leafs_from_elements(append_elements), proof); + } + + // Get the original Element Merkle Root and derive Append Proof, given an index, an append leaf, and a Single Proof + function get_append_proof_from_leaf_and_single_proof(uint256 index, bytes32 leaf, bytes32[] memory proof) + internal + pure + returns (bytes32 append_hash, bytes32[] memory append_proof) + { + uint256 proof_index = proof.length - 1; + uint256 append_node_index = uint256(proof[0]); + uint256 upper_bound = append_node_index - 1; + uint256 append_proof_index = bit_count_32(uint32(append_node_index)) + 1; + append_proof = new bytes32[](append_proof_index); + append_proof[0] = bytes32(append_node_index); + bytes32 scratch; + + while (proof_index > 0) { + if (index != upper_bound || (index & 1 == 1)) { + scratch = proof[proof_index]; + + leaf = (index & 1 == 1) ? hash_node(scratch, leaf) : hash_node(leaf, scratch); + + if (append_node_index & 1 == 1) { + append_proof_index -= 1; + append_proof[append_proof_index] = scratch; + append_hash = hash_node(scratch, append_hash); + } + + proof_index -= 1; + } else if (append_node_index & 1 == 1) { + append_proof_index -= 1; + append_proof[append_proof_index] = leaf; + append_hash = leaf; + } + + index >>= 1; + upper_bound >>= 1; + append_node_index >>= 1; + } + + require(append_proof_index == 2 || append_hash == leaf, "INVALID_PROOF"); + + if (append_proof_index == 2) { + append_proof[1] = leaf; + } + } + + // Get the original Element Merkle Root and derive Append Proof, given an index, a bytes32 element, and a Single Proof + function get_append_proof_from_single_proof(uint256 index, bytes32 element, bytes32[] memory proof) + internal + pure + returns (bytes32 leaf, bytes32[] memory) + { + leaf = keccak256(abi.encodePacked(bytes1(0), element)); + return get_append_proof_from_leaf_and_single_proof(index, leaf, proof); + } + + // Get the original Element Merkle Root and derive Append Proof, given an index, a leaf, an update leaf, and a Single Proof + function get_append_proof_from_leaf_and_single_proof_update( + uint256 index, + bytes32 leaf, + bytes32 update_leaf, + bytes32[] memory proof + ) internal pure returns (bytes32 append_hash, bytes32[] memory append_proof) { + uint256 proof_index = proof.length - 1; + uint256 append_node_index = uint256(proof[0]); + uint256 upper_bound = append_node_index - 1; + uint256 append_proof_index = bit_count_32(uint32(append_node_index)) + 1; + append_proof = new bytes32[](append_proof_index); + append_proof[0] = bytes32(append_node_index); + bytes32 scratch; + + while (proof_index > 0) { + if (index != upper_bound || (index & 1 == 1)) { + scratch = proof[proof_index]; + + leaf = (index & 1 == 1) ? hash_node(scratch, leaf) : hash_node(leaf, scratch); + + update_leaf = (index & 1 == 1) ? hash_node(scratch, update_leaf) : hash_node(update_leaf, scratch); + + if (append_node_index & 1 == 1) { + append_proof_index -= 1; + append_proof[append_proof_index] = scratch; + append_hash = hash_node(scratch, append_hash); + } + + proof_index -= 1; + } else if (append_node_index & 1 == 1) { + append_proof_index -= 1; + append_proof[append_proof_index] = update_leaf; + append_hash = leaf; + } + + index >>= 1; + upper_bound >>= 1; + append_node_index >>= 1; + } + + require(append_proof_index == 2 || append_hash == leaf, "INVALID_PROOF"); + + if (append_proof_index == 2) { + append_proof[1] = update_leaf; + } + } + + // Get the original Element Merkle Root and derive Append Proof, + // given an index, a bytes32 element, a bytes32 update element, and a Single Proof + function get_append_proof_from_single_proof_update( + uint256 index, + bytes32 element, + bytes32 update_element, + bytes32[] memory proof + ) internal pure returns (bytes32 leaf, bytes32[] memory) { + leaf = keccak256(abi.encodePacked(bytes1(0), element)); + bytes32 update_leaf = keccak256(abi.encodePacked(bytes1(0), update_element)); + return get_append_proof_from_leaf_and_single_proof_update(index, leaf, update_leaf, proof); + } + + // Hashes leaf at read index and next index (circular) to write index + function hash_within_leafs( + bytes32[] memory leafs, + uint256 write_index, + uint256 read_index, + uint256 leaf_count, + bool order + ) internal pure { + leafs[write_index] = order + ? hash_node(leafs[(read_index + 1) % leaf_count], leafs[read_index]) + : hash_node(leafs[read_index], leafs[(read_index + 1) % leaf_count]); + } + + // Hashes value with leaf at read index to write index + function hash_with_leafs(bytes32[] memory leafs, bytes32 value, uint256 write_index, uint256 read_index, bool order) + internal + pure + { + leafs[write_index] = order ? hash_node(leafs[read_index], value) : hash_node(value, leafs[read_index]); + } + + // Get the original Element Merkle Root and derive Append Proof, given leafs and an Existence Multi Proof + function get_append_proof_from_leafs_and_multi_proof(bytes32[] memory leafs, bytes32[] memory proof) + internal + pure + returns (bytes32 append_hash, bytes32[] memory append_proof) + { + uint256 leaf_count = leafs.length; + uint256 read_index; + uint256 write_index; + uint256 proof_index = 4; + uint256 append_node_index = uint256(proof[0]); + uint256 append_proof_index = uint256(bit_count_32(uint32(append_node_index))) + 1; + append_proof = new bytes32[](append_proof_index); + append_proof[0] = bytes32(append_node_index); + bytes32 bit_check = 0x0000000000000000000000000000000000000000000000000000000000000001; + bytes32 skips = proof[2]; + uint256 read_index_of_append_node; + bool scratch; + + while (true) { + if (skips & bit_check == bit_check) { + if (proof[1] & bit_check == bit_check) { + read_index = (write_index == 0 ? leaf_count : write_index) - 1; + + // reuse bit_check as scratch variable + bit_check = leafs[read_index]; + + require(append_proof_index == 2 || append_hash == bit_check, "INVALID_PROOF"); + + if (append_proof_index == 2) { + append_proof[1] = bit_check; + } + + return (append_hash, append_proof); + } + + if (append_node_index & 1 == 1) { + append_proof_index -= 1; + append_hash = leafs[read_index]; // TODO scratch this leafs[read_index] above + append_proof[append_proof_index] = leafs[read_index]; + } + + read_index_of_append_node = write_index; + append_node_index >>= 1; + + leafs[write_index] = leafs[read_index]; + + read_index = (read_index + 1) % leaf_count; + write_index = (write_index + 1) % leaf_count; + bit_check <<= 1; + continue; + } + + scratch = proof[1] & bit_check == bit_check; + + if (read_index_of_append_node == read_index) { + if (append_node_index & 1 == 1) { + append_proof_index -= 1; + + if (scratch) { + // reuse read_index_of_append_node as temporary scratch variable + read_index_of_append_node = (read_index + 1) % leaf_count; + + append_hash = hash_node(leafs[read_index_of_append_node], append_hash); + append_proof[append_proof_index] = leafs[read_index_of_append_node]; + } else { + append_hash = hash_node(proof[proof_index], append_hash); + append_proof[append_proof_index] = proof[proof_index]; + } + } + + read_index_of_append_node = write_index; + append_node_index >>= 1; + } + + if (scratch) { + scratch = proof[3] & bit_check == bit_check; + hash_within_leafs(leafs, write_index, read_index, leaf_count, scratch); + read_index += 2; + } else { + scratch = proof[3] & bit_check == bit_check; + hash_with_leafs(leafs, proof[proof_index], write_index, read_index, scratch); + proof_index += 1; + read_index += 1; + } + + read_index %= leaf_count; + write_index = (write_index + 1) % leaf_count; + bit_check <<= 1; + } + } + + // Get the original Element Merkle Root and derive Append Proof, given bytes32 elements in memory and an Existence Multi Proof + function get_append_proof_from_multi_proof(bytes32[] memory elements, bytes32[] memory proof) + internal + pure + returns (bytes32, bytes32[] memory) + { + return get_append_proof_from_leafs_and_multi_proof(get_reversed_leafs_from_elements(elements), proof); + } + + // Get combined current and update leafs from current bytes32 elements in memory and update bytes32 elements in memory, in reverse order + function get_reversed_combined_leafs_from_current_and_update_elements( + bytes32[] memory elements, + bytes32[] memory update_elements + ) internal pure returns (bytes32[] memory combined_leafs) { + uint256 element_count = elements.length; + require(update_elements.length == element_count, "LENGTH_MISMATCH"); + + combined_leafs = new bytes32[](element_count << 1); + // uint256 read_index = element_count - 1; + // uint256 write_index; + + // while (write_index < element_count) { + // combined_leafs[write_index] = keccak256(abi.encodePacked(bytes1(0), elements[read_index])); + // combined_leafs[element_count + write_index] = + // keccak256(abi.encodePacked(bytes1(0), update_elements[read_index])); + // write_index += 1; + // read_index -= 1; + // } + + for (uint64 i = 0; i < element_count; i++) { + combined_leafs[i] = keccak256(abi.encodePacked(bytes1(0), elements[element_count - 1 - i])); + combined_leafs[element_count + i] = + keccak256(abi.encodePacked(bytes1(0), update_elements[element_count - 1 - i])); + } + } + + // Copy leaf and update leaf at read indices and to write indices + function copy_within_combined_leafs( + bytes32[] memory combined_leafs, + uint256 write_index, + uint256 read_index, + uint256 leaf_count + ) internal pure { + combined_leafs[write_index] = combined_leafs[read_index]; + combined_leafs[leaf_count + write_index] = combined_leafs[leaf_count + read_index]; + } + + // Hashes leaf and update leaf at read indices and next indices (circular) to write indices + function hash_within_combined_leafs( + bytes32[] memory combined_leafs, + uint256 write_index, + uint256 read_index, + uint256 leaf_count, + bool order + ) internal pure { + uint256 scratch = (read_index + 1) % leaf_count; + + combined_leafs[write_index] = order + ? hash_node(combined_leafs[scratch], combined_leafs[read_index]) + : hash_node(combined_leafs[read_index], combined_leafs[scratch]); + + combined_leafs[leaf_count + write_index] = order + ? hash_node(combined_leafs[leaf_count + scratch], combined_leafs[leaf_count + read_index]) + : hash_node(combined_leafs[leaf_count + read_index], combined_leafs[leaf_count + scratch]); + } + + // Hashes value with leaf and update leaf at read indices to write indices + function hash_with_combined_leafs( + bytes32[] memory combined_leafs, + bytes32 value, + uint256 write_index, + uint256 read_index, + uint256 leaf_count, + bool order + ) internal pure { + combined_leafs[write_index] = + order ? hash_node(combined_leafs[read_index], value) : hash_node(value, combined_leafs[read_index]); + + combined_leafs[leaf_count + write_index] = order + ? hash_node(combined_leafs[leaf_count + read_index], value) + : hash_node(value, combined_leafs[leaf_count + read_index]); + } + + // Get the original Element Merkle Root and derive Append Proof, given combined leafs and update leafs and an Existence Multi Proof + function get_append_proof_from_leafs_and_multi_proof_update(bytes32[] memory combined_leafs, bytes32[] memory proof) + internal + pure + returns (bytes32 append_hash, bytes32[] memory append_proof) + { + uint256 leaf_count = combined_leafs.length >> 1; + uint256 read_index; + uint256 write_index; + uint256 read_index_of_append_node; + uint256 proof_index = 4; + uint256 append_node_index = uint256(proof[0]); + uint256 append_proof_index = bit_count_32(uint32(append_node_index)) + 1; + append_proof = new bytes32[](append_proof_index); + append_proof[0] = bytes32(append_node_index); + bytes32 bit_check = 0x0000000000000000000000000000000000000000000000000000000000000001; + bool scratch; + + while (true) { + if (proof[2] & bit_check == bit_check) { + if (proof[1] & bit_check == bit_check) { + read_index = (write_index == 0 ? leaf_count : write_index) - 1; + + // reuse bit_check as scratch variable + bit_check = combined_leafs[read_index]; + + require(append_proof_index == 2 || append_hash == bit_check, "INVALID_PROOF"); + + if (append_proof_index == 2) { + append_proof[1] = combined_leafs[leaf_count + read_index]; + } + + return (bit_check, append_proof); + } + + if (append_node_index & 1 == 1) { + append_proof_index -= 1; + append_hash = combined_leafs[read_index]; + append_proof[append_proof_index] = combined_leafs[leaf_count + read_index]; + } + + read_index_of_append_node = write_index; + append_node_index >>= 1; + + copy_within_combined_leafs(combined_leafs, write_index, read_index, leaf_count); + + read_index = (read_index + 1) % leaf_count; + write_index = (write_index + 1) % leaf_count; + bit_check <<= 1; + continue; + } + + scratch = proof[1] & bit_check == bit_check; + + if (read_index_of_append_node == read_index) { + if (append_node_index & 1 == 1) { + append_proof_index -= 1; + + if (scratch) { + // use read_index_of_append_node as temporary scratch + read_index_of_append_node = (read_index + 1) % leaf_count; + + append_hash = hash_node(combined_leafs[read_index_of_append_node], append_hash); + append_proof[append_proof_index] = combined_leafs[leaf_count + read_index_of_append_node]; + } else { + append_hash = hash_node(proof[proof_index], append_hash); + append_proof[append_proof_index] = proof[proof_index]; + } + } + + read_index_of_append_node = write_index; + append_node_index >>= 1; + } + + if (scratch) { + scratch = proof[3] & bit_check == bit_check; + + hash_within_combined_leafs(combined_leafs, write_index, read_index, leaf_count, scratch); + + read_index += 2; + } else { + scratch = proof[3] & bit_check == bit_check; + + hash_with_combined_leafs( + combined_leafs, proof[proof_index], write_index, read_index, leaf_count, scratch + ); + + proof_index += 1; + read_index += 1; + } + + read_index %= leaf_count; + write_index = (write_index + 1) % leaf_count; + bit_check <<= 1; + } + } + + // Get the original Element Merkle Root and derive Append Proof, + // given bytes32 elements in memory, bytes32 update elements in memory, and an Existence Multi Proof + function get_append_proof_from_multi_proof_update( + bytes32[] memory elements, + bytes32[] memory update_elements, + bytes32[] memory proof + ) internal pure returns (bytes32, bytes32[] memory) { + return get_append_proof_from_leafs_and_multi_proof_update( + get_reversed_combined_leafs_from_current_and_update_elements(elements, update_elements), proof + ); + } + + // INTERFACE: Check if bytes32 element exists at index, given a root and a Single Proof + function element_exists(bytes32 root, uint256 index, bytes32 element, bytes32[] memory proof) + internal + pure + returns (bool) + { + return hash_node(proof[0], get_root_from_single_proof(index, element, proof)) == root; + } + + // INTERFACE: Check if bytes32 elements in memory exist, given a root and a Single Proof + function elements_exist(bytes32 root, bytes32[] memory elements, bytes32[] memory proof) + internal + pure + returns (bool) + { + return hash_node(proof[0], get_root_from_multi_proof(elements, proof)) == root; + } + + // INTERFACE: Get the indices of the bytes32 elements in memory, given an Existence Multi Proof + function get_indices(bytes32[] memory elements, bytes32[] memory proof) internal pure returns (uint256[] memory) { + return get_indices_from_multi_proof(elements.length, proof[1], proof[2], proof[3]); + } + + // INTERFACE: Check tree size, given a Size Proof + function verify_size_with_proof(bytes32 root, uint256 size, bytes32[] memory proof) internal pure returns (bool) { + if (root == bytes32(0) && size == 0) return true; + + return hash_node(bytes32(size), get_root_from_size_proof(size, proof)) == root; + } + + // INTERFACE: Check tree size, given a the Element Merkle Root + function verify_size(bytes32 root, uint256 size, bytes32 element_root) internal pure returns (bool) { + if (root == bytes32(0) && size == 0) return true; + + return hash_node(bytes32(size), element_root) == root; + } + + // INTERFACE: Try to update a bytes32 element, given a root, and index, an bytes32 element, and a Single Proof + function try_update_one( + bytes32 root, + uint256 index, + bytes32 element, + bytes32 update_element, + bytes32[] memory proof + ) internal pure returns (bytes32 new_element_root) { + bytes32 total_element_count = proof[0]; + + require(root != bytes32(0) || total_element_count == bytes32(0), "EMPTY_TREE"); + + bytes32 old_element_root; + (old_element_root, new_element_root) = get_roots_from_single_proof_update(index, element, update_element, proof); + + require(hash_node(total_element_count, old_element_root) == root, "INVALID_PROOF"); + + return hash_node(total_element_count, new_element_root); + } + + // INTERFACE: Try to update bytes32 elements in memory, given a root, bytes32 elements in memory, and an Existence Multi Proof + function try_update_many( + bytes32 root, + bytes32[] memory elements, + bytes32[] memory update_elements, + bytes32[] memory proof + ) internal pure returns (bytes32 new_element_root) { + bytes32 total_element_count = proof[0]; + + require(root != bytes32(0) || total_element_count == bytes32(0), "EMPTY_TREE"); + + bytes32 old_element_root; + (old_element_root, new_element_root) = get_roots_from_multi_proof_update(elements, update_elements, proof); + + require(hash_node(total_element_count, old_element_root) == root, "INVALID_PROOF"); + + return hash_node(total_element_count, new_element_root); + } + + // INTERFACE: Try to append a bytes32 element, given a root and an Append Proof + function try_append_one(bytes32 root, bytes32 append_element, bytes32[] memory proof) + internal + pure + returns (bytes32 new_element_root) + { + bytes32 total_element_count = proof[0]; + + require((root == bytes32(0)) == (total_element_count == bytes32(0)), "INVALID_TREE"); + + if (root == bytes32(0)) return hash_node(bytes32(uint256(1)), get_root_from_one(append_element)); + + bytes32 old_element_root; + (old_element_root, new_element_root) = get_roots_from_append_proof_single_append(append_element, proof); + + require(hash_node(total_element_count, old_element_root) == root, "INVALID_PROOF"); + + return hash_node(bytes32(uint256(total_element_count) + 1), new_element_root); + } + + // INTERFACE: Try to append bytes32 elements in memory, given a root and an Append Proof + function try_append_many(bytes32 root, bytes32[] memory append_elements, bytes32[] memory proof) + internal + pure + returns (bytes32 new_element_root) + { + bytes32 total_element_count = proof[0]; + + require((root == bytes32(0)) == (total_element_count == bytes32(0)), "INVALID_TREE"); + + if (root == bytes32(0)) { + return hash_node(bytes32(append_elements.length), get_root_from_many(append_elements)); + } + + bytes32 old_element_root; + (old_element_root, new_element_root) = get_roots_from_append_proof_multi_append(append_elements, proof); + + require(hash_node(total_element_count, old_element_root) == root, "INVALID_PROOF"); + + return hash_node(bytes32(uint256(total_element_count) + append_elements.length), new_element_root); + } + + // INTERFACE: Try to append a bytes32 element, given a root, an index, a bytes32 element, and a Single Proof + function try_append_one_using_one( + bytes32 root, + uint256 index, + bytes32 element, + bytes32 append_element, + bytes32[] memory proof + ) internal pure returns (bytes32 element_root) { + bytes32 total_element_count = proof[0]; + + require(root != bytes32(0) || total_element_count == bytes32(0), "EMPTY_TREE"); + + bytes32[] memory append_proof; + (element_root, append_proof) = get_append_proof_from_single_proof(index, element, proof); + + require(hash_node(total_element_count, element_root) == root, "INVALID_PROOF"); + + element_root = get_new_root_from_append_proof_single_append(append_element, append_proof); + + return hash_node(bytes32(uint256(total_element_count) + 1), element_root); + } + + // INTERFACE: Try to append bytes32 elements in memory, given a root, an index, a bytes32 element, and a Single Proof + function try_append_many_using_one( + bytes32 root, + uint256 index, + bytes32 element, + bytes32[] memory append_elements, + bytes32[] memory proof + ) internal pure returns (bytes32 element_root) { + bytes32 total_element_count = proof[0]; + + require(root != bytes32(0) || total_element_count == bytes32(0), "EMPTY_TREE"); + + bytes32[] memory append_proof; + (element_root, append_proof) = get_append_proof_from_single_proof(index, element, proof); + + require(hash_node(total_element_count, element_root) == root, "INVALID_PROOF"); + + element_root = get_new_root_from_append_proof_multi_append(append_elements, append_proof); + + return hash_node(bytes32(uint256(total_element_count) + append_elements.length), element_root); + } + + // INTERFACE: Try to append a bytes32 element, given a root, bytes32 elements in memory, and an Existence Multi Proof + function try_append_one_using_many( + bytes32 root, + bytes32[] memory elements, + bytes32 append_element, + bytes32[] memory proof + ) internal pure returns (bytes32 element_root) { + bytes32 total_element_count = proof[0]; + + require(root != bytes32(0) || total_element_count == bytes32(0), "EMPTY_TREE"); + + bytes32[] memory append_proof; + (element_root, append_proof) = get_append_proof_from_multi_proof(elements, proof); + + require(hash_node(total_element_count, element_root) == root, "INVALID_PROOF"); + + element_root = get_new_root_from_append_proof_single_append(append_element, append_proof); + + return hash_node(bytes32(uint256(total_element_count) + 1), element_root); + } + + // INTERFACE: Try to append bytes32 elements in memory, given a root, bytes32 elements in memory, and an Existence Multi Proof + function try_append_many_using_many( + bytes32 root, + bytes32[] memory elements, + bytes32[] memory append_elements, + bytes32[] memory proof + ) internal pure returns (bytes32 element_root) { + bytes32 total_element_count = proof[0]; + + require(root != bytes32(0) || total_element_count == bytes32(0), "EMPTY_TREE"); + + bytes32[] memory append_proof; + (element_root, append_proof) = get_append_proof_from_multi_proof(elements, proof); + + require(hash_node(total_element_count, element_root) == root, "INVALID_PROOF"); + + element_root = get_new_root_from_append_proof_multi_append(append_elements, append_proof); + + return hash_node(bytes32(uint256(total_element_count) + append_elements.length), element_root); + } + + // INTERFACE: Try to update a bytes32 element and append a bytes32 element, + // given a root, an index, a bytes32 element, and a Single Proof + function try_update_one_and_append_one( + bytes32 root, + uint256 index, + bytes32 element, + bytes32 update_element, + bytes32 append_element, + bytes32[] memory proof + ) internal pure returns (bytes32 element_root) { + bytes32 total_element_count = proof[0]; + + require(root != bytes32(0) || total_element_count == bytes32(0), "EMPTY_TREE"); + + bytes32[] memory append_proof; + (element_root, append_proof) = get_append_proof_from_single_proof_update(index, element, update_element, proof); + + require(hash_node(total_element_count, element_root) == root, "INVALID_PROOF"); + + element_root = get_new_root_from_append_proof_single_append(append_element, append_proof); + + return hash_node(bytes32(uint256(total_element_count) + 1), element_root); + } + + // INTERFACE: Try to update a bytes32 element and append bytes32 elements in memory, + // given a root, an index, a bytes32 element, and a Single Proof + function try_update_one_and_append_many( + bytes32 root, + uint256 index, + bytes32 element, + bytes32 update_element, + bytes32[] memory append_elements, + bytes32[] memory proof + ) internal pure returns (bytes32 element_root) { + bytes32 total_element_count = proof[0]; + + require(root != bytes32(0) || total_element_count == bytes32(0), "EMPTY_TREE"); + + bytes32[] memory append_proof; + (element_root, append_proof) = get_append_proof_from_single_proof_update(index, element, update_element, proof); + + require(hash_node(total_element_count, element_root) == root, "INVALID_PROOF"); + + element_root = get_new_root_from_append_proof_multi_append(append_elements, append_proof); + + return hash_node(bytes32(uint256(total_element_count) + append_elements.length), element_root); + } + + // INTERFACE: Try to update bytes32 elements in memory and append a bytes32 element, + // given a root, bytes32 elements in memory, and a Single Proof + function try_update_many_and_append_one( + bytes32 root, + bytes32[] memory elements, + bytes32[] memory update_elements, + bytes32 append_element, + bytes32[] memory proof + ) internal pure returns (bytes32 element_root) { + bytes32 total_element_count = proof[0]; + + require(root != bytes32(0) || total_element_count == bytes32(0), "EMPTY_TREE"); + + bytes32[] memory append_proof; + (element_root, append_proof) = get_append_proof_from_multi_proof_update(elements, update_elements, proof); + + require(hash_node(total_element_count, element_root) == root, "INVALID_PROOF"); + + element_root = get_new_root_from_append_proof_single_append(append_element, append_proof); + + return hash_node(bytes32(uint256(total_element_count) + 1), element_root); + } + + // INTERFACE: Try to update bytes32 elements in memory and append bytes32 elements in memory, + // given a root, bytes32 elements in memory, and an Existence Multi Proof + function try_update_many_and_append_many( + bytes32 root, + bytes32[] memory elements, + bytes32[] memory update_elements, + bytes32[] memory append_elements, + bytes32[] memory proof + ) internal pure returns (bytes32 element_root) { + bytes32 total_element_count = proof[0]; + + require(root != bytes32(0) || total_element_count == bytes32(0), "EMPTY_TREE"); + + bytes32[] memory append_proof; + (element_root, append_proof) = get_append_proof_from_multi_proof_update(elements, update_elements, proof); + + require(hash_node(total_element_count, element_root) == root, "INVALID_PROOF"); + + element_root = get_new_root_from_append_proof_multi_append(append_elements, append_proof); + + return hash_node(bytes32(uint256(total_element_count) + append_elements.length), element_root); + } + + // INTERFACE: Create a tree and return the root, given a bytes32 element + function create_from_one(bytes32 element) internal pure returns (bytes32 new_element_root) { + return hash_node(bytes32(uint256(1)), get_root_from_one(element)); + } + + // INTERFACE: Create a tree and return the root, given bytes32 elements in memory + function create_from_many(bytes32[] memory elements) internal pure returns (bytes32 new_element_root) { + return hash_node(bytes32(elements.length), get_root_from_many(elements)); + } +} diff --git a/packages/contracts/contracts/L1/fraud-proof/libraries/RLPReader.sol b/packages/contracts/contracts/L1/fraud-proof/libraries/RLPReader.sol new file mode 100644 index 000000000..0a6424c9f --- /dev/null +++ b/packages/contracts/contracts/L1/fraud-proof/libraries/RLPReader.sol @@ -0,0 +1,369 @@ +// SPDX-License-Identifier: Apache-2.0 + +/* + * @author Hamdi Allam hamdi.allam97@gmail.com + * Please reach out with any questions or concerns + */ + +pragma solidity ^0.8.0; + +library RLPReader { + uint8 constant STRING_SHORT_START = 0x80; + uint8 constant STRING_LONG_START = 0xb8; + uint8 constant LIST_SHORT_START = 0xc0; + uint8 constant LIST_LONG_START = 0xf8; + uint8 constant WORD_SIZE = 32; + + struct RLPItem { + uint256 len; + uint256 memPtr; + } + + struct Iterator { + RLPItem item; // Item that's being iterated over. + uint256 nextPtr; // Position of the next item in the list. + } + + /* + * @dev Returns the next element in the iteration. Reverts if it has not next element. + * @param self The iterator. + * @return The next element in the iteration. + */ + function next(Iterator memory self) internal pure returns (RLPItem memory) { + require(hasNext(self)); + + uint256 ptr = self.nextPtr; + uint256 itemLength = _itemLength(ptr); + self.nextPtr = ptr + itemLength; + + return RLPItem(itemLength, ptr); + } + + /* + * @dev Returns true if the iteration has more elements. + * @param self The iterator. + * @return true if the iteration has more elements. + */ + function hasNext(Iterator memory self) internal pure returns (bool) { + RLPItem memory item = self.item; + return self.nextPtr < item.memPtr + item.len; + } + + /* + * @param item RLP encoded bytes + */ + function toRlpItem(bytes memory item) internal pure returns (RLPItem memory) { + uint256 memPtr; + assembly { + memPtr := add(item, 0x20) + } + + return RLPItem(item.length, memPtr); + } + + /* + * @dev Create an iterator. Reverts if item is not a list. + * @param self The RLP item. + * @return An 'Iterator' over the item. + */ + function iterator(RLPItem memory self) internal pure returns (Iterator memory) { + require(isList(self)); + + uint256 ptr = self.memPtr + _payloadOffset(self.memPtr); + return Iterator(self, ptr); + } + + /* + * @param the RLP item. + */ + function rlpLen(RLPItem memory item) internal pure returns (uint256) { + return item.len; + } + + /* + * @param the RLP item. + * @return (memPtr, len) pair: location of the item's payload in memory. + */ + function payloadLocation(RLPItem memory item) internal pure returns (uint256, uint256) { + uint256 offset = _payloadOffset(item.memPtr); + uint256 memPtr = item.memPtr + offset; + uint256 len = item.len - offset; // data length + return (memPtr, len); + } + + /* + * @param the RLP item. + * @return RLPItem of (memPtr, len) pair: location of the item's payload in memory. + */ + function payloadToRlpItem(RLPItem memory item) internal pure returns (RLPItem memory) { + uint256 offset = _payloadOffset(item.memPtr); + uint256 memPtr = item.memPtr + offset; + uint256 len = item.len - offset; // data length + return RLPItem(memPtr, len); + } + + /* + * @param the RLP item. + */ + function payloadLen(RLPItem memory item) internal pure returns (uint256) { + (, uint256 len) = payloadLocation(item); + return len; + } + + /* + * @param the RLP item containing the encoded list. + */ + function toList(RLPItem memory item) internal pure returns (RLPItem[] memory) { + require(isList(item)); + + uint256 items = numItems(item); + RLPItem[] memory result = new RLPItem[](items); + + uint256 memPtr = item.memPtr + _payloadOffset(item.memPtr); + uint256 dataLen; + for (uint256 i = 0; i < items; i++) { + dataLen = _itemLength(memPtr); + result[i] = RLPItem(dataLen, memPtr); + memPtr = memPtr + dataLen; + } + + return result; + } + + // @return indicator whether encoded payload is a list. negate this function call for isData. + function isList(RLPItem memory item) internal pure returns (bool) { + if (item.len == 0) return false; + + uint8 byte0; + uint256 memPtr = item.memPtr; + assembly { + byte0 := byte(0, mload(memPtr)) + } + + if (byte0 < LIST_SHORT_START) { + return false; + } + return true; + } + + /* + * @dev A cheaper version of keccak256(toRlpBytes(item)) that avoids copying memory. + * @return keccak256 hash of RLP encoded bytes. + */ + function rlpBytesKeccak256(RLPItem memory item) internal pure returns (bytes32) { + uint256 ptr = item.memPtr; + uint256 len = item.len; + bytes32 result; + assembly { + result := keccak256(ptr, len) + } + return result; + } + + /* + * @dev A cheaper version of keccak256(toBytes(item)) that avoids copying memory. + * @return keccak256 hash of the item payload. + */ + function payloadKeccak256(RLPItem memory item) internal pure returns (bytes32) { + (uint256 memPtr, uint256 len) = payloadLocation(item); + bytes32 result; + assembly { + result := keccak256(memPtr, len) + } + return result; + } + + /** + * RLPItem conversions into data types * + */ + + // @returns raw rlp encoding in bytes + function toRlpBytes(RLPItem memory item) internal pure returns (bytes memory) { + bytes memory result = new bytes(item.len); + if (result.length == 0) return result; + + uint256 ptr; + assembly { + ptr := add(0x20, result) + } + + copy(item.memPtr, ptr, item.len); + return result; + } + + // any non-zero byte except "0x80" is considered true + function toBoolean(RLPItem memory item) internal pure returns (bool) { + require(item.len == 1); + uint256 result; + uint256 memPtr = item.memPtr; + assembly { + result := byte(0, mload(memPtr)) + } + + // SEE Github Issue #5. + // Summary: Most commonly used RLP libraries (i.e Geth) will encode + // "0" as "0x80" instead of as "0". We handle this edge case explicitly + // here. + if (result == 0 || result == STRING_SHORT_START) { + return false; + } else { + return true; + } + } + + function toAddress(RLPItem memory item) internal pure returns (address) { + // 1 byte for the length prefix + require(item.len == 21); + + return address(uint160(toUint(item))); + } + + function toUint(RLPItem memory item) internal pure returns (uint256) { + require(item.len > 0 && item.len <= 33); + + (uint256 memPtr, uint256 len) = payloadLocation(item); + + uint256 result; + assembly { + result := mload(memPtr) + + // shfit to the correct location if neccesary + if lt(len, 32) { result := div(result, exp(256, sub(32, len))) } + } + + return result; + } + + // enforces 32 byte length + function toUintStrict(RLPItem memory item) internal pure returns (uint256) { + // one byte prefix + require(item.len == 33); + + uint256 result; + uint256 memPtr = item.memPtr + 1; + assembly { + result := mload(memPtr) + } + + return result; + } + + function toBytes(RLPItem memory item) internal pure returns (bytes memory) { + require(item.len > 0); + + (uint256 memPtr, uint256 len) = payloadLocation(item); + bytes memory result = new bytes(len); + + uint256 destPtr; + assembly { + destPtr := add(0x20, result) + } + + copy(memPtr, destPtr, len); + return result; + } + + /* + * Private Helpers + */ + + // @return number of payload items inside an encoded list. + function numItems(RLPItem memory item) private pure returns (uint256) { + if (item.len == 0) return 0; + + uint256 count = 0; + uint256 currPtr = item.memPtr + _payloadOffset(item.memPtr); + uint256 endPtr = item.memPtr + item.len; + while (currPtr < endPtr) { + currPtr = currPtr + _itemLength(currPtr); // skip over an item + count++; + } + + return count; + } + + // @return entire rlp item byte length + function _itemLength(uint256 memPtr) private pure returns (uint256) { + uint256 itemLen; + uint256 byte0; + assembly { + byte0 := byte(0, mload(memPtr)) + } + + if (byte0 < STRING_SHORT_START) { + itemLen = 1; + } else if (byte0 < STRING_LONG_START) { + itemLen = byte0 - STRING_SHORT_START + 1; + } else if (byte0 < LIST_SHORT_START) { + assembly { + let byteLen := sub(byte0, 0xb7) // # of bytes the actual length is + memPtr := add(memPtr, 1) // skip over the first byte + + /* 32 byte word size */ + let dataLen := div(mload(memPtr), exp(256, sub(32, byteLen))) // right shifting to get the len + itemLen := add(dataLen, add(byteLen, 1)) + } + } else if (byte0 < LIST_LONG_START) { + itemLen = byte0 - LIST_SHORT_START + 1; + } else { + assembly { + let byteLen := sub(byte0, 0xf7) + memPtr := add(memPtr, 1) + + let dataLen := div(mload(memPtr), exp(256, sub(32, byteLen))) // right shifting to the correct length + itemLen := add(dataLen, add(byteLen, 1)) + } + } + + return itemLen; + } + + // @return number of bytes until the data + function _payloadOffset(uint256 memPtr) private pure returns (uint256) { + uint256 byte0; + assembly { + byte0 := byte(0, mload(memPtr)) + } + + if (byte0 < STRING_SHORT_START) { + return 0; + } else if (byte0 < STRING_LONG_START || (byte0 >= LIST_SHORT_START && byte0 < LIST_LONG_START)) { + return 1; + } else if ( + byte0 < LIST_SHORT_START // being explicit + ) { + return byte0 - (STRING_LONG_START - 1) + 1; + } else { + return byte0 - (LIST_LONG_START - 1) + 1; + } + } + + /* + * @param src Pointer to source + * @param dest Pointer to destination + * @param len Amount of memory to copy from the source + */ + function copy(uint256 src, uint256 dest, uint256 len) private pure { + if (len == 0) return; + + // copy as many word sizes as possible + for (; len >= WORD_SIZE; len -= WORD_SIZE) { + assembly { + mstore(dest, mload(src)) + } + + src += WORD_SIZE; + dest += WORD_SIZE; + } + + if (len > 0) { + // left over bytes. Mask is used to remove unwanted bytes from the word + uint256 mask = 256 ** (WORD_SIZE - len) - 1; + assembly { + let srcpart := and(mload(src), not(mask)) // zero out src + let destpart := and(mload(dest), mask) // retrieve the bytes + mstore(dest, or(destpart, srcpart)) + } + } + } +} diff --git a/packages/contracts/contracts/L1/fraud-proof/libraries/RLPWriter.sol b/packages/contracts/contracts/L1/fraud-proof/libraries/RLPWriter.sol new file mode 100644 index 000000000..5a4762963 --- /dev/null +++ b/packages/contracts/contracts/L1/fraud-proof/libraries/RLPWriter.sol @@ -0,0 +1,217 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +/** + * @custom:attribution https://github.com/bakaoh/solidity-rlp-encode + * @title RLPWriter + * @author RLPWriter is a library for encoding Solidity types to RLP bytes. Adapted from Bakaoh's + * RLPEncode library (https://github.com/bakaoh/solidity-rlp-encode) with minor + * modifications to improve legibility. + */ +library RLPWriter { + /** + * @notice RLP encodes a byte string. + * + * @param _in The byte string to encode. + * + * @return The RLP encoded string in bytes. + */ + function writeBytes(bytes memory _in) internal pure returns (bytes memory) { + bytes memory encoded; + + if (_in.length == 1 && uint8(_in[0]) < 128) { + encoded = _in; + } else { + encoded = abi.encodePacked(_writeLength(_in.length, 128), _in); + } + + return encoded; + } + + /** + * @notice RLP encodes a list of RLP encoded byte byte strings. + * + * @param _in The list of RLP encoded byte strings. + * + * @return The RLP encoded list of items in bytes. + */ + function writeList(bytes[] memory _in) internal pure returns (bytes memory) { + bytes memory list = _flatten(_in); + return abi.encodePacked(_writeLength(list.length, 192), list); + } + + /** + * @notice RLP encodes a string. + * + * @param _in The string to encode. + * + * @return The RLP encoded string in bytes. + */ + function writeString(string memory _in) internal pure returns (bytes memory) { + return writeBytes(bytes(_in)); + } + + /** + * @notice RLP encodes an address. + * + * @param _in The address to encode. + * + * @return The RLP encoded address in bytes. + */ + function writeAddress(address _in) internal pure returns (bytes memory) { + return writeBytes(abi.encodePacked(_in)); + } + + /** + * @notice RLP encodes a uint. + * + * @param _in The uint256 to encode. + * + * @return The RLP encoded uint256 in bytes. + */ + function writeUint(uint256 _in) internal pure returns (bytes memory) { + return writeBytes(_toBinary(_in)); + } + + /** + * @notice RLP encodes a bool. + * + * @param _in The bool to encode. + * + * @return The RLP encoded bool in bytes. + */ + function writeBool(bool _in) internal pure returns (bytes memory) { + bytes memory encoded = new bytes(1); + encoded[0] = (_in ? bytes1(0x01) : bytes1(0x80)); + return encoded; + } + + /** + * @notice Encode the first byte and then the `len` in binary form if `length` is more than 55. + * + * @param _len The length of the string or the payload. + * @param _offset 128 if item is string, 192 if item is list. + * + * @return RLP encoded bytes. + */ + function _writeLength(uint256 _len, uint256 _offset) private pure returns (bytes memory) { + bytes memory encoded; + + if (_len < 56) { + encoded = new bytes(1); + encoded[0] = bytes1(uint8(_len) + uint8(_offset)); + } else { + uint256 lenLen; + uint256 i = 1; + while (_len / i != 0) { + lenLen++; + i *= 256; + } + + encoded = new bytes(lenLen + 1); + encoded[0] = bytes1(uint8(lenLen) + uint8(_offset) + 55); + for (i = 1; i <= lenLen; i++) { + encoded[i] = bytes1(uint8((_len / (256 ** (lenLen - i))) % 256)); + } + } + + return encoded; + } + + /** + * @notice Encode integer in big endian binary form with no leading zeroes. + * + * @param _x The integer to encode. + * + * @return RLP encoded bytes. + */ + function _toBinary(uint256 _x) private pure returns (bytes memory) { + bytes memory b = abi.encodePacked(_x); + + uint256 i = 0; + for (; i < 32; i++) { + if (b[i] != 0) { + break; + } + } + + bytes memory res = new bytes(32 - i); + for (uint256 j = 0; j < res.length; j++) { + res[j] = b[i++]; + } + + return res; + } + + /** + * @custom:attribution https://github.com/Arachnid/solidity-stringutils + * @notice Copies a piece of memory to another location. + * + * @param _dest Destination location. + * @param _src Source location. + * @param _len Length of memory to copy. + */ + function _memcpy(uint256 _dest, uint256 _src, uint256 _len) private pure { + uint256 dest = _dest; + uint256 src = _src; + uint256 len = _len; + + for (; len >= 32; len -= 32) { + assembly { + mstore(dest, mload(src)) + } + dest += 32; + src += 32; + } + + uint256 mask; + unchecked { + mask = 256 ** (32 - len) - 1; + } + assembly { + let srcpart := and(mload(src), not(mask)) + let destpart := and(mload(dest), mask) + mstore(dest, or(destpart, srcpart)) + } + } + + /** + * @custom:attribution https://github.com/sammayo/solidity-rlp-encoder + * @notice Flattens a list of byte strings into one byte string. + * + * @param _list List of byte strings to flatten. + * + * @return The flattened byte string. + */ + function _flatten(bytes[] memory _list) private pure returns (bytes memory) { + if (_list.length == 0) { + return new bytes(0); + } + + uint256 len; + uint256 i = 0; + for (; i < _list.length; i++) { + len += _list[i].length; + } + + bytes memory flattened = new bytes(len); + uint256 flattenedPtr; + assembly { + flattenedPtr := add(flattened, 0x20) + } + + for (i = 0; i < _list.length; i++) { + bytes memory item = _list[i]; + + uint256 listPtr; + assembly { + listPtr := add(item, 0x20) + } + + _memcpy(flattenedPtr, listPtr, item.length); + flattenedPtr += _list[i].length; + } + + return flattened; + } +} diff --git a/packages/contracts/contracts/L1/fraud-proof/verifier/IVerifier.sol b/packages/contracts/contracts/L1/fraud-proof/verifier/IVerifier.sol new file mode 100644 index 000000000..f35fa3b72 --- /dev/null +++ b/packages/contracts/contracts/L1/fraud-proof/verifier/IVerifier.sol @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: Apache-2.0 + +/* + * Copyright 2022, Specular contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +pragma solidity ^0.8.0; + +import "./libraries/VerificationContext.sol"; + +interface IVerifier { + function verifyOneStepProof(VerificationContext.Context memory ctx, bytes32 currStateHash, bytes calldata encoded) + external + pure + returns (bytes32); +} diff --git a/packages/contracts/contracts/L1/fraud-proof/verifier/IVerifierEntry.sol b/packages/contracts/contracts/L1/fraud-proof/verifier/IVerifierEntry.sol new file mode 100644 index 000000000..42d8de032 --- /dev/null +++ b/packages/contracts/contracts/L1/fraud-proof/verifier/IVerifierEntry.sol @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: Apache-2.0 + +/* + * Copyright 2022, Specular contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +pragma solidity ^0.8.0; + +import "./libraries/VerificationContext.sol"; + +interface IVerifierEntry { + function verifyOneStepProof( + VerificationContext.Context memory ctx, + uint8 verifier, + bytes32 currStateHash, + bytes calldata encoded + ) external view returns (bytes32); +} diff --git a/packages/contracts/contracts/L1/fraud-proof/verifier/VerifierEntry.sol b/packages/contracts/contracts/L1/fraud-proof/verifier/VerifierEntry.sol new file mode 100644 index 000000000..2efa4a8cf --- /dev/null +++ b/packages/contracts/contracts/L1/fraud-proof/verifier/VerifierEntry.sol @@ -0,0 +1,106 @@ +// SPDX-License-Identifier: Apache-2.0 + +/* + * Copyright 2022, Specular contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; +import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; + +import "./libraries/VerificationContext.sol"; +import "./libraries/Params.sol"; +import "./IVerifier.sol"; +import "./IVerifierEntry.sol"; + +contract VerifierEntry is IVerifierEntry, Initializable, OwnableUpgradeable { + IVerifier public blockInitiationVerifier; + IVerifier public blockFinalizationVerifier; + IVerifier public interTxVerifier; + IVerifier public stackOpVerifier; + IVerifier public environmentalOpVerifier; + IVerifier public memoryOpVerifier; + IVerifier public storageOpVerifier; + IVerifier public callOpVerifier; + IVerifier public invalidOpVerifier; + + /// @custom:oz-upgrades-unsafe-allow constructor + constructor() { + _disableInitializers(); + } + + function initialize() public initializer { + __Ownable_init(); + } + + function setVerifier(uint8 verifier, IVerifier impl) + external + onlyOwner + { + if (verifier == Params.V_BLOCK_INIT) { + blockInitiationVerifier = impl; + } else if (verifier == Params.V_BLOCK_FINAL) { + blockFinalizationVerifier = impl; + } else if (verifier == Params.V_INTER_TX) { + interTxVerifier = impl; + } else if (verifier == Params.V_STACK_OP) { + stackOpVerifier = impl; + } else if (verifier == Params.V_ENVIRONMENTAL_OP) { + environmentalOpVerifier = impl; + } else if (verifier == Params.V_MEMORY_OP) { + memoryOpVerifier = impl; + } else if (verifier == Params.V_STORAGE_OP) { + storageOpVerifier = impl; + } else if (verifier == Params.V_CALL_OP) { + callOpVerifier = impl; + } else if (verifier == Params.V_INVALID_OP) { + invalidOpVerifier = impl; + } else { + revert("unreachable"); + } + } + + function verifyOneStepProof( + VerificationContext.Context memory ctx, + uint8 verifier, + bytes32 currStateHash, + bytes calldata encoded + ) external view override returns (bytes32) { + IVerifier impl; + if (verifier == Params.V_BLOCK_INIT) { + impl = blockInitiationVerifier; + } else if (verifier == Params.V_BLOCK_FINAL) { + impl = blockFinalizationVerifier; + } else if (verifier == Params.V_INTER_TX) { + impl = interTxVerifier; + } else if (verifier == Params.V_STACK_OP) { + impl = stackOpVerifier; + } else if (verifier == Params.V_ENVIRONMENTAL_OP) { + impl = environmentalOpVerifier; + } else if (verifier == Params.V_MEMORY_OP) { + impl = memoryOpVerifier; + } else if (verifier == Params.V_STORAGE_OP) { + impl = storageOpVerifier; + } else if (verifier == Params.V_CALL_OP) { + impl = callOpVerifier; + } else if (verifier == Params.V_INVALID_OP) { + impl = invalidOpVerifier; + } else { + revert("unreachable"); + } + return impl.verifyOneStepProof(ctx, currStateHash, encoded); + } +} diff --git a/packages/contracts/contracts/L1/fraud-proof/verifier/libraries/BloomLib.sol b/packages/contracts/contracts/L1/fraud-proof/verifier/libraries/BloomLib.sol new file mode 100644 index 000000000..2f879151c --- /dev/null +++ b/packages/contracts/contracts/L1/fraud-proof/verifier/libraries/BloomLib.sol @@ -0,0 +1,72 @@ +// SPDX-License-Identifier: Apache-2.0 + +/* + * Copyright 2022, Specular contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +pragma solidity ^0.8.0; + +import "../../libraries/BytesLib.sol"; + +library BloomLib { + using BytesLib for bytes; + + struct Bloom { + bytes32[8] data; + } + + function emptyBloom() internal pure returns (Bloom memory b) { + return b; + } + + function decodeBloom(bytes calldata encoded, uint64 offset) internal pure returns (Bloom memory) { + Bloom memory bloom; + for (uint256 i = 0; i < 8; i++) { + bloom.data[i] = encoded.toBytes32(offset); + offset += 32; + } + return bloom; + } + + function addHash(Bloom memory bloom, bytes32 h) internal pure { + uint16 i1 = 255 - (uint16(uint256(h) >> 240) & 0x7ff) >> 3; + uint8 v1 = uint8(1 << (uint8(h[1]) & 0x7)); + bloom.data[i1 >> 5] = bytes32(uint256(bloom.data[i1 >> 5]) | (uint256(v1) << 8 * (31 - (i1 & 0x1f)))); + uint16 i2 = 255 - (uint16(uint256(h) >> 224) & 0x7ff) >> 3; + uint8 v2 = uint8(1 << (uint8(h[3]) & 0x7)); + bloom.data[i2 >> 5] = bytes32(uint256(bloom.data[i2 >> 5]) | (uint256(v2) << 8 * (31 - (i2 & 0x1f)))); + uint16 i3 = 255 - (uint16(uint256(h) >> 208) & 0x7ff) >> 3; + uint8 v3 = uint8(1 << (uint8(h[5]) & 0x7)); + bloom.data[i3 >> 5] = bytes32(uint256(bloom.data[i3 >> 5]) | (uint256(v3) << 8 * (31 - (i3 & 0x1f)))); + } + + function add(Bloom memory bloom, bytes memory data) internal pure { + bytes32 h; + assembly { + h := keccak256(add(data, 0x20), mload(data)) + } + addHash(bloom, h); + } + + function add(Bloom memory bloom, address data) internal pure { + bytes32 h = keccak256(abi.encodePacked(data)); + addHash(bloom, h); + } + + function add(Bloom memory bloom, bytes32 data) internal pure { + bytes32 h = keccak256(abi.encodePacked(data)); + addHash(bloom, h); + } +} diff --git a/packages/contracts/contracts/L1/fraud-proof/verifier/libraries/EVMTypesLib.sol b/packages/contracts/contracts/L1/fraud-proof/verifier/libraries/EVMTypesLib.sol new file mode 100644 index 000000000..7da62ca86 --- /dev/null +++ b/packages/contracts/contracts/L1/fraud-proof/verifier/libraries/EVMTypesLib.sol @@ -0,0 +1,141 @@ +// SPDX-License-Identifier: Apache-2.0 + +/* + * Copyright 2022, Specular contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +pragma solidity ^0.8.0; + +import "../../libraries/BytesLib.sol"; +import "../../libraries/RLPReader.sol"; +import "../../libraries/RLPWriter.sol"; +import "./BloomLib.sol"; + +library EVMTypesLib { + using BytesLib for bytes; + using RLPReader for bytes; + using RLPReader for RLPReader.RLPItem; + + struct BlockHeader { + bytes32 parentHash; + bytes32 ommerHash; + address beneficiary; + bytes32 stateRoot; + bytes32 transactionRoot; + bytes32 receiptsRoot; + uint256 difficulty; + uint256 number; + uint64 gasLimit; + uint64 gasUsed; + uint64 timestamp; + BloomLib.Bloom logsBloom; + } + + function hashBlockHeader(BlockHeader memory header) internal pure returns (bytes32) { + bytes[] memory raw = new bytes[](15); + raw[0] = RLPWriter.writeBytes(abi.encodePacked(header.parentHash)); + raw[1] = RLPWriter.writeBytes(abi.encodePacked(header.ommerHash)); + raw[2] = RLPWriter.writeAddress(header.beneficiary); + raw[3] = RLPWriter.writeBytes(abi.encodePacked(header.stateRoot)); + raw[4] = RLPWriter.writeBytes(abi.encodePacked(header.transactionRoot)); + raw[5] = RLPWriter.writeBytes(abi.encodePacked(header.receiptsRoot)); + raw[6] = RLPWriter.writeBytes(abi.encodePacked(header.logsBloom.data)); + raw[7] = RLPWriter.writeUint(header.difficulty); + raw[8] = RLPWriter.writeUint(header.number); + raw[9] = RLPWriter.writeUint(uint256(header.gasLimit)); + raw[10] = RLPWriter.writeUint(uint256(header.gasUsed)); + raw[11] = RLPWriter.writeUint(uint256(header.timestamp)); + raw[12] = RLPWriter.writeBytes(""); // Extra + raw[13] = RLPWriter.writeBytes(abi.encodePacked(bytes32(0))); // MixDigest + raw[14] = RLPWriter.writeBytes(abi.encodePacked(bytes8(0))); // Nonce + return keccak256(RLPWriter.writeList(raw)); + } + + struct Transaction { + uint64 nonce; + uint256 gasPrice; + uint64 gas; + address to; + uint256 value; + bytes data; + uint256 v; + uint256 r; + uint256 s; + } + + function decodeTransaction(bytes memory data) internal pure returns (Transaction memory transaction) { + RLPReader.RLPItem[] memory decoded = data.toRlpItem().toList(); + transaction.nonce = uint64(decoded[0].toUint()); + transaction.gasPrice = decoded[1].toUint(); + transaction.gas = uint64(decoded[2].toUint()); + transaction.to = address(uint160(decoded[3].toUint())); + transaction.value = decoded[4].toUint(); + transaction.data = decoded[5].toBytes(); + transaction.v = decoded[6].toUint(); + transaction.r = decoded[7].toUint(); + transaction.s = decoded[8].toUint(); + } + + function hashTransaction(Transaction memory txn) internal pure returns (bytes32) { + bytes[] memory raw = new bytes[](9); + raw[0] = RLPWriter.writeUint(uint256(txn.nonce)); + raw[1] = RLPWriter.writeUint(txn.gasPrice); + raw[2] = RLPWriter.writeUint(uint256(txn.gas)); + raw[3] = RLPWriter.writeAddress(txn.to); + raw[4] = RLPWriter.writeUint(txn.value); + raw[5] = RLPWriter.writeBytes(txn.data); + raw[6] = RLPWriter.writeUint(txn.v); + raw[7] = RLPWriter.writeUint(txn.r); + raw[8] = RLPWriter.writeUint(txn.s); + return keccak256(RLPWriter.writeList(raw)); + } + + struct Account { + uint64 nonce; + uint256 balance; + bytes32 storageRoot; + bytes32 codeHash; + } + + function decodeAccount(RLPReader.RLPItem memory encoded) internal pure returns (Account memory proof) { + RLPReader.RLPItem[] memory items = encoded.toList(); + require(items.length == 4, "Invalid Account"); + proof.nonce = uint64(items[0].toUint()); + proof.balance = items[1].toUint(); + proof.storageRoot = bytes32(items[2].toUint()); + proof.codeHash = bytes32(items[3].toUint()); + } + + function encodeRLP(Account memory account) internal pure returns (bytes memory) { + bytes[] memory raw = new bytes[](4); + raw[0] = RLPWriter.writeUint(uint256(account.nonce)); + raw[1] = RLPWriter.writeUint(account.balance); + raw[2] = RLPWriter.writeBytes(abi.encodePacked(account.storageRoot)); + raw[3] = RLPWriter.writeBytes(abi.encodePacked(account.codeHash)); + return RLPWriter.writeList(raw); + } + + function hashLogEntry(address addr, uint256[] memory topics, bytes memory data) internal pure returns (bytes32) { + bytes[] memory topicRaw = new bytes[](topics.length); + for (uint256 i = 0; i < topics.length; i++) { + topicRaw[i] = RLPWriter.writeBytes(abi.encodePacked(bytes32(topics[i]))); + } + bytes[] memory raw = new bytes[](3); + raw[0] = RLPWriter.writeAddress(addr); + raw[1] = RLPWriter.writeBytes(RLPWriter.writeList(topicRaw)); + raw[2] = RLPWriter.writeBytes(data); + return keccak256(RLPWriter.writeList(raw)); + } +} diff --git a/packages/contracts/contracts/L1/fraud-proof/verifier/libraries/GasTable.sol b/packages/contracts/contracts/L1/fraud-proof/verifier/libraries/GasTable.sol new file mode 100644 index 000000000..c1965666c --- /dev/null +++ b/packages/contracts/contracts/L1/fraud-proof/verifier/libraries/GasTable.sol @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: Apache-2.0 + +/* + * Copyright 2022, Specular contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +pragma solidity ^0.8.0; + +import "../../libraries/BitLen.sol"; +import "./Params.sol"; + +library GasTable { + using BitLen for uint256; + + function costMemory(uint64 mwords) internal pure returns (uint64) { + return Params.G_MEMORY * mwords + mwords * mwords / 512; + } + + function gasMemory(uint64 msize, uint64 offset, uint64 length) internal pure returns (uint64) { + if (length == 0) { + return 0; + } + uint64 newMwords = (offset + length + 31) / 32; + uint64 mwords = (msize + 31) / 32; + if (newMwords <= mwords) { + return 0; + } + return costMemory(newMwords) - costMemory(mwords); + } + + function gasExp(uint256 exponent) internal pure returns (uint64) { + if (exponent == 0) { + return Params.G_EXP; + } else { + return Params.G_EXP + Params.G_EXPBYTE * ((exponent.bitLen() + 7) / 8); + } + } + + function gasKeccak(uint64 msize, uint64 offset, uint64 length) internal pure returns (uint64) { + return gasMemory(msize, offset, length) + Params.G_KECCAK + Params.G_KECCAKWORD * ((length + 31) / 32); + } + + function gasCopy(uint64 msize, uint64 offset, uint64 length) internal pure returns (uint64) { + return gasMemory(msize, offset, length) + Params.G_VERYLOW + Params.G_COPY * ((length + 31) / 32); + } + + function gasExtCopy(uint64 msize, uint64 offset, uint64 length) internal pure returns (uint64) { + return gasMemory(msize, offset, length) + Params.G_EXTCODE + Params.G_COPY * ((length + 31) / 32); + } + + function gasLog(uint64 msize, uint64 offset, uint64 length, uint64 topicNum) internal pure returns (uint64) { + return gasMemory(msize, offset, length) + Params.G_LOG + Params.G_LOGTOPIC * topicNum + + Params.G_LOGDATA * ((length + 31) / 32); + } +} diff --git a/packages/contracts/contracts/L1/fraud-proof/verifier/libraries/MemoryLib.sol b/packages/contracts/contracts/L1/fraud-proof/verifier/libraries/MemoryLib.sol new file mode 100644 index 000000000..08ac1e427 --- /dev/null +++ b/packages/contracts/contracts/L1/fraud-proof/verifier/libraries/MemoryLib.sol @@ -0,0 +1,311 @@ +// SPDX-License-Identifier: Apache-2.0 + +/* + * Copyright 2022, Specular contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +pragma solidity ^0.8.0; + +import "../../libraries/DeserializationLib.sol"; +import "../../libraries/MerkleLib.sol"; +import "../../libraries/BytesLib.sol"; +import "./OneStepProof.sol"; + +library MemoryLib { + using BytesLib for bytes; + + function calcCellNum(uint64 offset, uint64 length) internal pure returns (uint64) { + return (offset + length + 31) / 32 - offset / 32; + } + + function getMemoryRoot(bytes memory content) internal pure returns (bytes32) { + uint64 cellNum = MemoryLib.calcCellNum(0, uint64(content.length)); + bytes32[] memory elements = new bytes32[](cellNum); + for (uint256 i = 0; i < cellNum - 1; i++) { + elements[i] = content.toBytes32(i * 32); + } + elements[cellNum - 1] = content.toBytes32Pad((cellNum - 1) * 32); + return MerkleLib.create_from_many(elements); + } + + function decodeAndVerifyMemoryReadProof( + OneStepProof.StateProof memory stateProof, + bytes calldata encoded, + uint64 offset, + uint64 memoryOffset, + uint64 memoryReadLength + ) internal pure returns (uint64, bytes memory) { + if (stateProof.memSize == 0 || memoryReadLength == 0) { + return (offset, new bytes(memoryReadLength)); + } + uint64 startCell = memoryOffset / 32; + uint64 cellNum = calcCellNum(memoryOffset, memoryReadLength); + uint64 memoryCell = calcCellNum(0, stateProof.memSize); + OneStepProof.MemoryMerkleProof memory merkleProof; + { + if (memoryCell <= startCell) { + cellNum += startCell - memoryCell; + OneStepProof.MemoryAppendProof memory appendProof; + (offset, appendProof) = OneStepProof.decodeMemoryAppendProof(encoded, offset, cellNum); + (offset, merkleProof) = OneStepProof.decodeMemoryMerkleProof(encoded, offset); + stateProof.memRoot = + MerkleLib.try_append_many(stateProof.memRoot, appendProof.appendCells, merkleProof.proof); + if (memoryOffset + memoryReadLength > stateProof.memSize) { + stateProof.memSize = (memoryOffset + memoryReadLength + 31) / 32 * 32; // Expand by words + } + bytes memory readContent = new bytes(memoryReadLength); + return (offset, readContent); + } + } + { + if (memoryCell >= startCell + cellNum) { + OneStepProof.MemoryReadProof memory readProof; + (offset, readProof) = OneStepProof.decodeMemoryReadProof(encoded, offset, cellNum); + (offset, merkleProof) = OneStepProof.decodeMemoryMerkleProof(encoded, offset); + if (cellNum == 1) { + MerkleLib.element_exists(stateProof.memRoot, startCell, readProof.cells[0], merkleProof.proof); + require( + MerkleLib.element_exists(stateProof.memRoot, startCell, readProof.cells[0], merkleProof.proof), + "IMP" + ); + } else { + { + // avoid stack too deep + uint256[] memory indices = MerkleLib.get_indices(readProof.cells, merkleProof.proof); + for (uint64 i = 0; i < cellNum; i++) { + require(indices[i] == startCell + i, "IMP"); + } + } + MerkleLib.elements_exist(stateProof.memRoot, readProof.cells, merkleProof.proof); + require(MerkleLib.elements_exist(stateProof.memRoot, readProof.cells, merkleProof.proof), "IMP"); + } + bytes memory readContent = abi.encodePacked(readProof.cells).slice(memoryOffset % 32, memoryReadLength); + return (offset, readContent); + } + } + uint64 existCellNum = memoryCell - startCell; + OneStepProof.MemoryCombinedReadProof memory combinedReadProof; + (offset, combinedReadProof) = + OneStepProof.decodeMemoryCombinedReadProof(encoded, offset, existCellNum, cellNum - existCellNum); + (offset, merkleProof) = OneStepProof.decodeMemoryMerkleProof(encoded, offset); + if (existCellNum == 1) { + stateProof.memRoot = MerkleLib.try_append_many_using_one( + stateProof.memRoot, + startCell, + combinedReadProof.cells[0], + combinedReadProof.appendCells, + merkleProof.proof + ); + } else { + { + // avoid stack too deep + uint256[] memory indices = MerkleLib.get_indices(combinedReadProof.cells, merkleProof.proof); + for (uint64 i = 0; i < existCellNum; i++) { + require(indices[i] == startCell + i, "IMP"); + } + } + stateProof.memRoot = MerkleLib.try_append_many_using_many( + stateProof.memRoot, combinedReadProof.cells, combinedReadProof.appendCells, merkleProof.proof + ); + } + if (memoryOffset + memoryReadLength > stateProof.memSize) { + stateProof.memSize = (memoryOffset + memoryReadLength + 31) / 32 * 32; // Expand by words + } + bytes memory readContent = abi.encodePacked(combinedReadProof.cells, combinedReadProof.appendCells).slice( + memoryOffset % 32, memoryReadLength + ); + return (offset, readContent); + } + + function decodeAndVerifyMemoryLikeReadProofNoAppend( + bytes32 memoryLikeRoot, + uint64 memoryLikeSize, + bytes calldata encoded, + uint64 offset, + uint64 memoryLikeOffset, + uint64 memoryLikeReadLength + ) internal pure returns (uint64, bytes memory) { + if (memoryLikeSize == 0 || memoryLikeReadLength == 0) { + return (offset, new bytes(memoryLikeReadLength)); + } + uint64 startCell = memoryLikeOffset / 32; + uint64 cellNum = calcCellNum(memoryLikeOffset, memoryLikeReadLength); + uint64 memoryCell = calcCellNum(0, memoryLikeSize); + { + if (memoryCell <= startCell) { + bytes memory readContent; + readContent = new bytes(memoryLikeReadLength); + return (offset, readContent); + } + } + { + if (memoryCell >= startCell + cellNum) { + bytes memory readContent; + OneStepProof.MemoryReadProof memory readProof; + OneStepProof.MemoryMerkleProof memory merkleProof; + (offset, readProof) = OneStepProof.decodeMemoryReadProof(encoded, offset, cellNum); + (offset, merkleProof) = OneStepProof.decodeMemoryMerkleProof(encoded, offset); + if (cellNum == 1) { + MerkleLib.element_exists(memoryLikeRoot, startCell, readProof.cells[0], merkleProof.proof); + require( + MerkleLib.element_exists(memoryLikeRoot, startCell, readProof.cells[0], merkleProof.proof), + "IMP" + ); + } else { + { + uint256[] memory indices = MerkleLib.get_indices(readProof.cells, merkleProof.proof); + for (uint64 i = 0; i < cellNum; i++) { + require(indices[i] == startCell + i, "IMP2"); + } + } + MerkleLib.elements_exist(memoryLikeRoot, readProof.cells, merkleProof.proof); + require(MerkleLib.elements_exist(memoryLikeRoot, readProof.cells, merkleProof.proof), "IMP"); + } + readContent = abi.encodePacked(readProof.cells).slice(memoryLikeOffset % 32, memoryLikeReadLength); + return (offset, readContent); + } + } + uint64 existCellNum = memoryCell - startCell; + OneStepProof.MemoryReadProof memory readProof; + OneStepProof.MemoryMerkleProof memory merkleProof; + (offset, readProof) = OneStepProof.decodeMemoryReadProof(encoded, offset, existCellNum); + (offset, merkleProof) = OneStepProof.decodeMemoryMerkleProof(encoded, offset); + if (existCellNum == 1) { + MerkleLib.element_exists(memoryLikeRoot, startCell, readProof.cells[0], merkleProof.proof); + require(MerkleLib.element_exists(memoryLikeRoot, startCell, readProof.cells[0], merkleProof.proof), "IMP"); + } else { + { + uint256[] memory indices = MerkleLib.get_indices(readProof.cells, merkleProof.proof); + for (uint64 i = 0; i < cellNum; i++) { + require(indices[i] == startCell + i, "IMP"); + } + } + MerkleLib.elements_exist(memoryLikeRoot, readProof.cells, merkleProof.proof); + require(MerkleLib.elements_exist(memoryLikeRoot, readProof.cells, merkleProof.proof), "IMP"); + } + bytes memory padding = new bytes(32 * (cellNum - existCellNum)); + bytes memory readContent; + readContent = abi.encodePacked(readProof.cells, padding).slice(memoryLikeOffset % 32, memoryLikeReadLength); + return (offset, readContent); + } + + function decodeAndVerifyMemoryWriteProof( + OneStepProof.StateProof memory stateProof, + bytes calldata encoded, + uint64 offset, + uint64 memoryOffset, + uint64 memoryWriteLength + ) internal pure returns (uint64, bytes memory) { + if (memoryWriteLength == 0) { + return (offset, new bytes(0)); + } + if (stateProof.memSize == 0) { + // Don't call decodeMemoryWriteProof if memory is empty + // Instead, update memory root and size directly + revert(); + } + uint64 startCell = memoryOffset / 32; + uint64 cellNum = calcCellNum(memoryOffset, memoryWriteLength); + uint64 memoryCell = calcCellNum(0, stateProof.memSize); + OneStepProof.MemoryMerkleProof memory merkleProof; + + { + if (memoryCell <= startCell) { + cellNum += startCell - memoryCell; + OneStepProof.MemoryAppendProof memory appendProof; + (offset, appendProof) = OneStepProof.decodeMemoryAppendProof(encoded, offset, cellNum); + (offset, merkleProof) = OneStepProof.decodeMemoryMerkleProof(encoded, offset); + if (cellNum == 1) { + stateProof.memRoot = + MerkleLib.try_append_one(stateProof.memRoot, appendProof.appendCells[0], merkleProof.proof); + } else { + stateProof.memRoot = + MerkleLib.try_append_many(stateProof.memRoot, appendProof.appendCells, merkleProof.proof); + } + if (memoryOffset + memoryWriteLength > stateProof.memSize) { + stateProof.memSize = (memoryOffset + memoryWriteLength + 31) / 32 * 32; // Expand by words + } + bytes memory writeContent = + abi.encodePacked(appendProof.appendCells).slice(memoryOffset % 32, memoryWriteLength); + return (offset, writeContent); + } + } + { + if (memoryCell >= startCell + cellNum) { + OneStepProof.MemoryWriteProof memory writeProof; + (offset, writeProof) = OneStepProof.decodeMemoryWriteProof(encoded, offset, cellNum); + (offset, merkleProof) = OneStepProof.decodeMemoryMerkleProof(encoded, offset); + if (cellNum == 1) { + stateProof.memRoot = MerkleLib.try_update_one( + stateProof.memRoot, + startCell, + writeProof.cells[0], + writeProof.updatedCells[0], + merkleProof.proof + ); + } else { + { + // Avoid stack too deep + uint256[] memory indices = MerkleLib.get_indices(writeProof.cells, merkleProof.proof); + for (uint64 i = 0; i < cellNum; i++) { + require(indices[i] == startCell + i, "IMP"); + } + } + stateProof.memRoot = MerkleLib.try_update_many( + stateProof.memRoot, writeProof.cells, writeProof.updatedCells, merkleProof.proof + ); + } + bytes memory writeContent = + abi.encodePacked(writeProof.updatedCells).slice(memoryOffset % 32, memoryWriteLength); + return (offset, writeContent); + } + } + uint64 existCellNum = memoryCell - startCell; + OneStepProof.MemoryCombinedWriteProof memory combinedWriteProof; + (offset, combinedWriteProof) = + OneStepProof.decodeMemoryCombinedWriteProof(encoded, offset, existCellNum, cellNum - existCellNum); + if (cellNum == 1) { + stateProof.memRoot = MerkleLib.try_update_one_and_append_many( + stateProof.memRoot, + startCell, + combinedWriteProof.cells[0], + combinedWriteProof.updatedCells[0], + combinedWriteProof.appendCells, + merkleProof.proof + ); + } else { + { + // avoid stack too deep + uint256[] memory indices = MerkleLib.get_indices(combinedWriteProof.cells, merkleProof.proof); + for (uint64 i = 0; i < cellNum; i++) { + require(indices[i] == startCell + i, "IMP"); + } + } + stateProof.memRoot = MerkleLib.try_update_many_and_append_many( + stateProof.memRoot, + combinedWriteProof.cells, + combinedWriteProof.updatedCells, + combinedWriteProof.appendCells, + merkleProof.proof + ); + } + if (memoryOffset + memoryWriteLength > stateProof.memSize) { + stateProof.memSize = (memoryOffset + memoryWriteLength + 31) / 32 * 32; // Expand by words + } + bytes memory writeContent = abi.encodePacked(combinedWriteProof.updatedCells, combinedWriteProof.appendCells) + .slice(memoryOffset % 32, memoryWriteLength); + return (offset, writeContent); + } +} diff --git a/packages/contracts/contracts/L1/fraud-proof/verifier/libraries/OneStepProof.sol b/packages/contracts/contracts/L1/fraud-proof/verifier/libraries/OneStepProof.sol new file mode 100644 index 000000000..1cff64414 --- /dev/null +++ b/packages/contracts/contracts/L1/fraud-proof/verifier/libraries/OneStepProof.sol @@ -0,0 +1,598 @@ +// SPDX-License-Identifier: Apache-2.0 + +/* + * Copyright 2022, Specular contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +pragma solidity ^0.8.0; + +import "../../libraries/RLPReader.sol"; +import "../../libraries/BytesLib.sol"; +import "./BloomLib.sol"; +import "./VerificationContext.sol"; + +library OneStepProof { + using BytesLib for bytes; + using RLPReader for RLPReader.RLPItem; + using RLPReader for RLPReader.Iterator; + using RLPReader for bytes; + using VerificationContext for VerificationContext.Context; + + // [encode rule] + struct StateProof { + uint64 blockNumber; // Block number of current transaction [always] + uint64 transactionIdx; // Transaction index in block [always] + uint16 depth; // Current call depth [always] + uint64 gas; // Gas left in the current call [always] + uint64 refund; // Gas refund accumulated in the current transaction [always] + bytes32 lastDepthHash; // The state hash of the last depth call frame [always] + address contractAddress; // Current executing contract address [depth > 1] + address caller; // Current caller [depth > 1] + uint256 value; // Current call value [depth > 1] + uint8 callFlag; // Current call type [depth > 1] + uint64 out; // Offset of the return data of current call to be copied to the last depth call frame [depth > 1] + uint64 outSize; // Size of the return data of current call to be copied to the last depth call frame [depth > 1] + uint64 pc; // Current program counter [always] + uint8 opCode; // Current opcode to be executed [always] + bytes32 codeHash; // Current executing contract code hash [always] + uint64 stackSize; // Size of the stack [always] + bytes32 stackHash; // Commitment of the stack [always] + uint64 memSize; // Size of the memory [always] + bytes32 memRoot; // Commitment of the memory [memSize > 0] + uint64 inputDataSize; // Size of the call data [depth > 1] + bytes32 inputDataRoot; // Commitment of the return data [depth > 1 && inputDataSize > 0] + uint64 returnDataSize; // Size of the return data [always] + bytes32 returnDataRoot; // Commitment of the return data [returnDataSize > 0] + bytes32 committedGlobalStateRoot; // Commitment of the global MPT state at the start of transaction [always] + bytes32 globalStateRoot; // Commitment of the global MPT state [always] + bytes32 selfDestructAcc; // Commitment of the self destructed contracts in the current transaction [always] + bytes32 logAcc; // Commitment of the logs emitted in the current transaction [always] + bytes32 blockHashRoot; // Commitment of the 256 previous blockhash in the current block [always] + bytes32 accessListRoot; // Commitment of the access list in the current transaction [always] + } + + function decodeStateProof(VerificationContext.Context memory ctx, bytes calldata encoded, uint64 offset) + internal + pure + returns (uint64, StateProof memory proof) + { + uint64 remainLength = uint64(encoded.length) - offset; + uint64 stateProofLen = 323; + require(remainLength >= stateProofLen, "Proof Underflow (State)"); + proof.blockNumber = encoded.toUint64(offset); + proof.transactionIdx = encoded.toUint64(offset + 8); + proof.depth = encoded.toUint16(offset + 16); + proof.gas = encoded.toUint64(offset + 18); + proof.refund = encoded.toUint64(offset + 26); + proof.lastDepthHash = encoded.toBytes32(offset + 34); + offset = offset + 66; + if (proof.depth > 1) { + stateProofLen += 97; + require(remainLength >= stateProofLen, "Proof Underflow (State)"); + proof.contractAddress = encoded.toAddress(offset); + proof.caller = encoded.toAddress(offset + 20); + proof.value = encoded.toUint256(offset + 40); + proof.callFlag = encoded.toUint8(offset + 72); + proof.out = encoded.toUint64(offset + 73); + proof.outSize = encoded.toUint64(offset + 81); + offset += 89; + } else { + proof.contractAddress = ctx.getRecipient(); + proof.caller = ctx.getOrigin(); + proof.value = ctx.getValue(); + if (ctx.getRecipient() == address(0)) { + proof.callFlag = 4; + } else { + proof.callFlag = 0; + } + } + proof.pc = encoded.toUint64(offset); + proof.opCode = encoded.toUint8(offset + 8); + proof.codeHash = encoded.toBytes32(offset + 9); + proof.stackSize = encoded.toUint64(offset + 41); + offset += 49; + if (proof.stackSize != 0) { + stateProofLen += 32; + require(remainLength >= stateProofLen, "Proof Underflow (State)"); + proof.stackHash = encoded.toBytes32(offset); + offset += 32; + } + proof.memSize = encoded.toUint64(offset); + offset += 8; + if (proof.memSize != 0) { + stateProofLen += 32; + require(remainLength >= stateProofLen, "Proof Underflow (State)"); + proof.memRoot = encoded.toBytes32(offset); + offset += 32; + } + if (proof.depth > 1) { + proof.inputDataSize = encoded.toUint64(offset); + offset += 8; + if (proof.inputDataSize != 0) { + stateProofLen += 32; + require(remainLength >= stateProofLen, "Proof Underflow (State)"); + proof.inputDataRoot = encoded.toBytes32(offset); + offset += 32; + } + } else { + proof.inputDataSize = ctx.getInputSize(); + proof.inputDataRoot = ctx.getInputRoot(); + } + proof.returnDataSize = encoded.toUint64(offset); + offset += 8; + if (proof.returnDataSize != 0) { + stateProofLen += 32; + require(remainLength >= stateProofLen, "Proof Underflow (State)"); + proof.returnDataRoot = encoded.toBytes32(offset); + offset += 32; + } + proof.committedGlobalStateRoot = encoded.toBytes32(offset); + proof.globalStateRoot = encoded.toBytes32(offset + 32); + proof.selfDestructAcc = encoded.toBytes32(offset + 64); + proof.logAcc = encoded.toBytes32(offset + 96); + proof.blockHashRoot = encoded.toBytes32(offset + 128); + proof.accessListRoot = encoded.toBytes32(offset + 160); + return (offset + 192, proof); + } + + function encodeStateProof(StateProof memory proof) internal pure returns (bytes memory encoded) { + encoded = encoded.concat(abi.encodePacked(proof.blockNumber)); + encoded = encoded.concat(abi.encodePacked(proof.transactionIdx)); + encoded = encoded.concat(abi.encodePacked(proof.depth)); + encoded = encoded.concat(abi.encodePacked(proof.gas)); + encoded = encoded.concat(abi.encodePacked(proof.refund)); + encoded = encoded.concat(abi.encodePacked(proof.lastDepthHash)); + if (proof.depth > 1) { + encoded = encoded.concat(abi.encodePacked(proof.contractAddress)); + encoded = encoded.concat(abi.encodePacked(proof.caller)); + encoded = encoded.concat(abi.encodePacked(proof.value)); + encoded = encoded.concat(abi.encodePacked(proof.callFlag)); + encoded = encoded.concat(abi.encodePacked(proof.out)); + encoded = encoded.concat(abi.encodePacked(proof.outSize)); + } + encoded = encoded.concat(abi.encodePacked(proof.pc)); + encoded = encoded.concat(abi.encodePacked(proof.opCode)); + encoded = encoded.concat(abi.encodePacked(proof.codeHash)); + encoded = encoded.concat(abi.encodePacked(proof.stackSize)); + if (proof.stackSize != 0) { + encoded = encoded.concat(abi.encodePacked(proof.stackHash)); + } + encoded = encoded.concat(abi.encodePacked(proof.memSize)); + if (proof.memSize != 0) { + encoded = encoded.concat(abi.encodePacked(proof.memRoot)); + } + if (proof.depth > 1) { + encoded = encoded.concat(abi.encodePacked(proof.inputDataSize)); + if (proof.inputDataSize != 0) { + encoded = encoded.concat(abi.encodePacked(proof.inputDataRoot)); + } + } + encoded = encoded.concat(abi.encodePacked(proof.returnDataSize)); + if (proof.returnDataSize != 0) { + encoded = encoded.concat(abi.encodePacked(proof.returnDataRoot)); + } + encoded = encoded.concat(abi.encodePacked(proof.committedGlobalStateRoot)); + encoded = encoded.concat(abi.encodePacked(proof.globalStateRoot)); + encoded = encoded.concat(abi.encodePacked(proof.selfDestructAcc)); + encoded = encoded.concat(abi.encodePacked(proof.logAcc)); + encoded = encoded.concat(abi.encodePacked(proof.blockHashRoot)); + encoded = encoded.concat(abi.encodePacked(proof.accessListRoot)); + } + + function hashStateProof(StateProof memory proof) internal pure returns (bytes32) { + if (proof.depth == 0) { + // When returning/reverting from depth 1, we can't directly return an InterStateProof + // Therefore we reuse some of the fields in the IntraStateProof to store an InterStateProof + // The field mappings are as follows: + InterStateProof memory interProof; + interProof.blockNumber = proof.blockNumber; + interProof.transactionIdx = proof.transactionIdx; + interProof.globalStateRoot = proof.globalStateRoot; + interProof.cumulativeGasUsed = proof.value; + interProof.blockGasUsed = uint256(proof.lastDepthHash); + interProof.blockHashRoot = proof.blockHashRoot; + interProof.transactionTrieRoot = proof.selfDestructAcc; + interProof.receiptTrieRoot = proof.logAcc; + return hashInterStateProof(interProof); + } + return keccak256(encodeStateProof(proof)); + } + + struct InterStateProof { + uint64 blockNumber; + uint64 transactionIdx; + bytes32 globalStateRoot; + uint256 cumulativeGasUsed; + uint256 blockGasUsed; + bytes32 blockHashRoot; + bytes32 transactionTrieRoot; + bytes32 receiptTrieRoot; + BloomLib.Bloom logsBloom; + } + + function decodeInterStateProof(bytes calldata encoded, uint64 offset) + internal + pure + returns (uint64, InterStateProof memory proof) + { + require(encoded.length - offset >= 464, "Proof Underflow (Inter)"); + proof.blockNumber = encoded.toUint64(offset); + proof.transactionIdx = encoded.toUint64(offset + 8); + proof.globalStateRoot = encoded.toBytes32(offset + 16); + proof.cumulativeGasUsed = encoded.toUint64(offset + 48); + proof.blockGasUsed = encoded.toUint64(offset + 80); + proof.blockHashRoot = encoded.toBytes32(offset + 112); + proof.transactionTrieRoot = encoded.toBytes32(offset + 144); + proof.receiptTrieRoot = encoded.toBytes32(offset + 176); + proof.logsBloom = BloomLib.decodeBloom(encoded, offset + 208); + return (offset + 464, proof); + } + + function encodeInterStateProof(InterStateProof memory proof) internal pure returns (bytes memory encoded) { + encoded = encoded.concat(abi.encodePacked(proof.blockNumber)); + encoded = encoded.concat(abi.encodePacked(proof.transactionIdx)); + encoded = encoded.concat(abi.encodePacked(proof.globalStateRoot)); + encoded = encoded.concat(abi.encodePacked(proof.cumulativeGasUsed)); + encoded = encoded.concat(abi.encodePacked(proof.blockGasUsed)); + encoded = encoded.concat(abi.encodePacked(proof.blockHashRoot)); + encoded = encoded.concat(abi.encodePacked(proof.transactionTrieRoot)); + encoded = encoded.concat(abi.encodePacked(proof.receiptTrieRoot)); + encoded = encoded.concat(abi.encodePacked(proof.logsBloom.data)); + } + + function hashInterStateProof(InterStateProof memory proof) internal pure returns (bytes32) { + return keccak256(encodeInterStateProof(proof)); + } + + struct BlockStateProof { + uint64 blockNumber; + bytes32 globalStateRoot; + uint256 cumulativeGasUsed; + bytes32 blockHashRoot; + } + + function decodeBlockStateProof(bytes calldata encoded, uint64 offset) + internal + pure + returns (uint64, BlockStateProof memory proof) + { + require(encoded.length - offset >= 104, "Proof Underflow (Block)"); + proof.blockNumber = encoded.toUint64(offset); + proof.globalStateRoot = encoded.toBytes32(offset + 8); + proof.cumulativeGasUsed = encoded.toUint64(offset + 40); + proof.blockHashRoot = encoded.toBytes32(offset + 72); + return (offset + 104, proof); + } + + function encodeBlockStateProof(BlockStateProof memory proof) internal pure returns (bytes memory encoded) { + encoded = encoded.concat(abi.encodePacked(proof.blockNumber)); + encoded = encoded.concat(abi.encodePacked(proof.globalStateRoot)); + encoded = encoded.concat(abi.encodePacked(proof.cumulativeGasUsed)); + encoded = encoded.concat(abi.encodePacked(proof.blockHashRoot)); + } + + function hashBlockStateProof(BlockStateProof memory proof) internal pure returns (bytes32) { + return keccak256(encodeBlockStateProof(proof)); + } + + struct CodeProof { + uint64 ptr; + uint64 size; + } + + function decodeCodeProof(bytes calldata encoded, uint64 offset) + internal + pure + returns (uint64, CodeProof memory proof) + { + require(encoded.length - offset >= 8, "Proof Underflow (Code)"); + // Decode bytecode size in bytes + uint64 contentSize = encoded.toUint64(offset); + require(encoded.length - offset >= 8 + contentSize, "Proof Underflow (Code)"); + offset += 8; + proof.ptr = offset; + proof.size = contentSize; + return (offset + contentSize, proof); + } + + function getOpCodeAt(CodeProof memory proof, bytes calldata encoded, uint64 idx) internal pure returns (uint8) { + if (idx >= proof.size) { + return 0; + } + return uint8(encoded[proof.ptr + idx]); + } + + function getCodeSlice(CodeProof memory proof, bytes calldata encoded, uint64 offset, uint64 size) + internal + pure + returns (bytes memory) + { + if (offset + size > proof.size) { + return encoded.slice(proof.ptr + offset, size).concat(new bytes(size - (proof.size - offset))); + } + return encoded.slice(proof.ptr + offset, size); + } + + function hashCodeProof(CodeProof memory proof, bytes calldata encoded) internal pure returns (bytes32) { + return keccak256(encoded[proof.ptr:proof.ptr + proof.size]); + } + + struct StackProof { + // The elements popped in the step + uint256[] pops; + // The stack hash after popping above elements + bytes32 stackHashAfterPops; + } + + function decodeStackProof(bytes calldata encoded, uint64 offset, uint64 popNum) + internal + pure + returns (uint64, StackProof memory proof) + { + if (popNum == 0) { + // No StackProof needed for popNum == 0 + return (offset, proof); + } + require(encoded.length - offset >= 32 * (popNum + 1), "Proof Underflow (Stack)"); + proof.pops = new uint256[](popNum); + // Decode popped elements + for (uint64 i = 0; i < popNum; i++) { + proof.pops[i] = encoded.toUint256(offset); + offset += 32; + } + // Decode stackHashAfterPops + proof.stackHashAfterPops = encoded.toBytes32(offset); + offset += 32; + return (offset, proof); + } + + function encodeStackProof(StackProof memory proof) internal pure returns (bytes memory encoded) { + for (uint64 i = 0; i < proof.pops.length; i++) { + encoded = encoded.concat(abi.encodePacked(proof.pops[i])); + } + encoded = encoded.concat(abi.encodePacked(proof.stackHashAfterPops)); + } + + struct MemoryMerkleProof { + bytes32[] proof; + } + + function decodeMemoryMerkleProof(bytes calldata encoded, uint64 offset) + internal + pure + returns (uint64, MemoryMerkleProof memory proof) + { + require(encoded.length - offset >= 8, "Proof Underflow"); + uint64 len = encoded.toUint64(offset); + offset += 8; + require(encoded.length - offset >= 32 * len, "Proof Underflow"); + proof.proof = new bytes32[](len); + for (uint64 i = 0; i < len; i++) { + proof.proof[i] = encoded.toBytes32(offset); + offset += 32; + } + return (offset, proof); + } + + struct MemoryReadProof { + bytes32[] cells; + } + + function decodeMemoryReadProof(bytes calldata encoded, uint64 offset, uint64 cellNum) + internal + pure + returns (uint64, MemoryReadProof memory proof) + { + require(encoded.length - offset >= 32 * cellNum, "Proof Underflow"); + proof.cells = new bytes32[](cellNum); + for (uint64 i = 0; i < cellNum; i++) { + proof.cells[i] = encoded.toBytes32(offset); + offset += 32; + } + return (offset, proof); + } + + struct MemoryWriteProof { + bytes32[] cells; + bytes32[] updatedCells; + } + + function decodeMemoryWriteProof(bytes calldata encoded, uint64 offset, uint64 cellNum) + internal + pure + returns (uint64, MemoryWriteProof memory proof) + { + require(encoded.length - offset >= 64 * cellNum, "Proof Underflow"); + proof.cells = new bytes32[](cellNum); + for (uint64 i = 0; i < cellNum; i++) { + proof.cells[i] = encoded.toBytes32(offset); + offset += 32; + } + proof.updatedCells = new bytes32[](cellNum); + for (uint64 i = 0; i < cellNum; i++) { + proof.updatedCells[i] = encoded.toBytes32(offset); + offset += 32; + } + return (offset, proof); + } + + struct MemoryAppendProof { + bytes32[] appendCells; + } + + function decodeMemoryAppendProof(bytes calldata encoded, uint64 offset, uint64 cellNum) + internal + pure + returns (uint64, MemoryAppendProof memory proof) + { + require(encoded.length - offset >= 32 * cellNum, "Proof Underflow"); + proof.appendCells = new bytes32[](cellNum); + for (uint64 i = 0; i < cellNum; i++) { + proof.appendCells[i] = encoded.toBytes32(offset); + offset += 32; + } + return (offset, proof); + } + + struct MemoryCombinedReadProof { + bytes32[] cells; + bytes32[] appendCells; + } + + function decodeMemoryCombinedReadProof(bytes calldata encoded, uint64 offset, uint64 cellNum, uint64 appendCellNum) + internal + pure + returns (uint64, MemoryCombinedReadProof memory proof) + { + require(encoded.length - offset >= 32 * (cellNum + appendCellNum), "Proof Underflow"); + proof.cells = new bytes32[](cellNum); + for (uint64 i = 0; i < cellNum; i++) { + proof.cells[i] = encoded.toBytes32(offset); + offset += 32; + } + proof.appendCells = new bytes32[](appendCellNum); + for (uint64 i = 0; i < appendCellNum; i++) { + proof.appendCells[i] = encoded.toBytes32(offset); + offset += 32; + } + return (offset, proof); + } + + struct MemoryCombinedWriteProof { + bytes32[] cells; + bytes32[] updatedCells; + bytes32[] appendCells; + } + + function decodeMemoryCombinedWriteProof(bytes calldata encoded, uint64 offset, uint64 cellNum, uint64 appendCellNum) + internal + pure + returns (uint64, MemoryCombinedWriteProof memory proof) + { + require(encoded.length - offset >= 32 * (2 * cellNum + appendCellNum), "Proof Underflow"); + proof.cells = new bytes32[](cellNum); + for (uint64 i = 0; i < cellNum; i++) { + proof.cells[i] = encoded.toBytes32(offset); + offset += 32; + } + proof.updatedCells = new bytes32[](cellNum); + for (uint64 i = 0; i < cellNum; i++) { + proof.updatedCells[i] = encoded.toBytes32(offset); + offset += 32; + } + proof.appendCells = new bytes32[](appendCellNum); + for (uint64 i = 0; i < appendCellNum; i++) { + proof.appendCells[i] = encoded.toBytes32(offset); + offset += 32; + } + return (offset, proof); + } + + // For MPT proof, receipt proof + struct RLPProof { + RLPReader.RLPItem proof; + } + + function decodeRLPProof(bytes calldata encoded, uint64 offset) + internal + pure + returns (uint64, RLPProof memory proof) + { + require(encoded.length - offset >= 8, "Proof Underflow"); + uint64 len = encoded.toUint64(offset); + offset += 8; + require(encoded.length - offset >= len, "Proof Underflow"); + proof.proof = encoded.slice(offset, len).toRlpItem(); + return (offset + len, proof); + } + + struct BlockHashProof { + bytes32 blockHash; + } + + function decodeBlockHashProof(bytes calldata encoded, uint64 offset) + internal + pure + returns (uint64, BlockHashProof memory proof) + { + require(encoded.length - offset >= 32, "Proof Underflow"); + proof.blockHash = encoded.toBytes32(offset); + return (offset + 32, proof); + } + + struct BlockHashMerkleProof { + uint64 path; + bytes32[] proof; + } + + function decodeBlockHashMerkleProof(bytes memory encoded, uint64 offset) + internal + pure + returns (uint64, BlockHashMerkleProof memory proof) + { + require(encoded.length - offset >= 9, "Proof Underflow"); + proof.path = encoded.toUint64(offset); + uint8 len = encoded.toUint8(offset + 8); + offset += 9; + require(encoded.length - offset >= 32 * len, "Proof Underflow"); + proof.proof = new bytes32[](len); + for (uint64 i = 0; i < len; i++) { + proof.proof[i] = encoded.toBytes32(offset); + offset += 32; + } + return (offset, proof); + } + + struct LogProof { + bytes32 accumulateHash; + BloomLib.Bloom bloom; + } + + function decodeLogProof(bytes calldata encoded, uint64 offset) + internal + pure + returns (uint64, LogProof memory proof) + { + require(encoded.length - offset >= 288, "Proof Underflow"); + proof.accumulateHash = encoded.toBytes32(offset); + proof.bloom = BloomLib.decodeBloom(encoded, offset + 32); + return (offset + 288, proof); + } + + function hashLogProof(LogProof memory proof) internal pure returns (bytes32) { + return keccak256(abi.encodePacked(proof.accumulateHash, proof.bloom.data)); + } + + struct SelfDestructSetProof { + address[] contracts; + } + + function decodeSelfDestructSetProof(bytes calldata encoded, uint64 offset) + internal + pure + returns (uint64, SelfDestructSetProof memory proof) + { + require(encoded.length - offset >= 8, "Proof Underflow"); + uint64 len = encoded.toUint64(offset); + offset += 8; + require(encoded.length - offset >= 20 * len, "Proof Underflow"); + proof.contracts = new address[](len); + for (uint64 i = 0; i < len; i++) { + proof.contracts[i] = encoded.toAddress(offset); + offset += 20; + } + return (offset, proof); + } +} diff --git a/packages/contracts/contracts/L1/fraud-proof/verifier/libraries/Params.sol b/packages/contracts/contracts/L1/fraud-proof/verifier/libraries/Params.sol new file mode 100644 index 000000000..f53a3cb21 --- /dev/null +++ b/packages/contracts/contracts/L1/fraud-proof/verifier/libraries/Params.sol @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: Apache-2.0 + +/* + * Copyright 2022, Specular contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +pragma solidity ^0.8.0; + +library Params { + // Verifier + uint8 constant V_STACK_OP = 0; + uint8 constant V_ENVIRONMENTAL_OP = 1; + uint8 constant V_MEMORY_OP = 2; + uint8 constant V_STORAGE_OP = 3; + uint8 constant V_CALL_OP = 4; + uint8 constant V_INVALID_OP = 5; + uint8 constant V_INTER_TX = 6; + uint8 constant V_BLOCK_INIT = 7; + uint8 constant V_BLOCK_FINAL = 8; + + // Gas + uint64 constant G_ZERO = 0; + uint64 constant G_JUMPDEST = 1; + uint64 constant G_BASE = 2; + uint64 constant G_VERYLOW = 3; + uint64 constant G_LOW = 5; + uint64 constant G_MID = 8; + uint64 constant G_HIGH = 10; + uint64 constant G_EXTCODE = 700; + uint64 constant G_BALANCE = 700; + uint64 constant G_SLOAD = 800; + uint64 constant G_SSET = 20000; + uint64 constant G_SRESET = 5000; + uint64 constant R_SCLEAR = 15000; + uint64 constant R_SELFDESTRUCT = 24000; + uint64 constant G_SELFDESTRUCT = 5000; + uint64 constant G_CREATE = 32000; + uint64 constant G_CODEDEPOSIT = 200; + uint64 constant G_CALL = 700; + uint64 constant G_CALLVALUE = 9000; + uint64 constant G_CALLSTIPEND = 2300; + uint64 constant G_NEWACCOUNT = 25000; + uint64 constant G_EXP = 10; + uint64 constant G_EXPBYTE = 50; + uint64 constant G_MEMORY = 3; + uint64 constant G_TXCREATE = 32000; + uint64 constant G_TXDATAZERO = 4; + uint64 constant G_TXDATANONZERO = 16; + uint64 constant G_TRANSACTION = 21000; + uint64 constant G_LOG = 375; + uint64 constant G_LOGDATA = 8; + uint64 constant G_LOGTOPIC = 375; + uint64 constant G_KECCAK = 30; + uint64 constant G_KECCAKWORD = 6; + uint64 constant G_COPY = 3; + uint64 constant G_BLOCKHASH = 20; + uint64 constant G_QUADDIVISOR = 20; + + // Stack + uint64 constant STACK_LIMIT = 1024; + + bytes32 constant EMPTY_TRIE_ROOT = 0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421; + bytes32 constant EMPTY_CODE_HASH = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; + bytes32 constant EMPTY_UNCLE_HASH = 0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347; + uint64 constant RECENT_BLOCK_HASHES_LENGTH = 256; +} diff --git a/packages/contracts/contracts/L1/fraud-proof/verifier/libraries/VerificationContext.sol b/packages/contracts/contracts/L1/fraud-proof/verifier/libraries/VerificationContext.sol new file mode 100644 index 000000000..a719b8a4a --- /dev/null +++ b/packages/contracts/contracts/L1/fraud-proof/verifier/libraries/VerificationContext.sol @@ -0,0 +1,122 @@ +// SPDX-License-Identifier: Apache-2.0 + +/* + * Copyright 2022, Specular contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +pragma solidity ^0.8.0; + +import "../../libraries/DeserializationLib.sol"; +import "../../libraries/BytesLib.sol"; +import "../../libraries/MerkleLib.sol"; + +import "./MemoryLib.sol"; +import "./EVMTypesLib.sol"; + +library VerificationContext { + using BytesLib for bytes; + using EVMTypesLib for EVMTypesLib.Transaction; + + struct Context { + address coinbase; + uint256 timestamp; + uint256 number; + address origin; + EVMTypesLib.Transaction transaction; + bytes32 inputRoot; + bytes32 txHash; + } + + function newContext(bytes calldata proof) internal view returns (Context memory ctx) { +// inbox.verifyTxInclusion(proof); +// ctx.coinbase = inbox.sequencerAddress(); + ctx.coinbase = address(0); // TODO FIXME + uint256 offset = 0; + uint256 txDataLength; + (offset, ctx.origin) = DeserializationLib.deserializeAddress(proof, offset); + (offset, ctx.number) = DeserializationLib.deserializeUint256(proof, offset); + (offset, ctx.timestamp) = DeserializationLib.deserializeUint256(proof, offset); + (offset, txDataLength) = DeserializationLib.deserializeUint256(proof, offset); + bytes memory txData = bytes(proof[offset:txDataLength]); + ctx.transaction = EVMTypesLib.decodeTransaction(txData); + } + + function getCoinbase(Context memory ctx) internal pure returns (address) { + return ctx.coinbase; + } + + function getTimestamp(Context memory ctx) internal pure returns (uint256) { + return ctx.timestamp; + } + + function getBlockNumber(Context memory ctx) internal pure returns (uint256) { + return ctx.number; + } + + function getDifficulty(Context memory) internal pure returns (uint256) { + return 1; + } + + function getGasLimit(Context memory) internal pure returns (uint64) { + return 80000000; + } + + function getChainID(Context memory) internal pure returns (uint256) { + return 13527; + } + + // Transaction + function getOrigin(Context memory ctx) internal pure returns (address) { + return ctx.origin; + } + + function getRecipient(Context memory ctx) internal pure returns (address) { + return ctx.transaction.to; + } + + function getValue(Context memory ctx) internal pure returns (uint256) { + return ctx.transaction.value; + } + + function getGas(Context memory ctx) internal pure returns (uint64) { + return ctx.transaction.gas; + } + + function getGasPrice(Context memory ctx) internal pure returns (uint256) { + return ctx.transaction.gasPrice; + } + + function getInput(Context memory ctx) internal pure returns (bytes memory) { + return ctx.transaction.data; + } + + function getInputSize(Context memory ctx) internal pure returns (uint64) { + return uint64(ctx.transaction.data.length); + } + + function getInputRoot(Context memory ctx) internal pure returns (bytes32) { + if (ctx.inputRoot == 0x0) { + ctx.inputRoot = MemoryLib.getMemoryRoot(ctx.transaction.data); + } + return ctx.inputRoot; + } + + function getTxHash(Context memory ctx) internal pure returns (bytes32) { + if (ctx.txHash == 0x0) { + ctx.txHash = ctx.transaction.hashTransaction(); + } + return ctx.transaction.hashTransaction(); + } +} diff --git a/packages/contracts/contracts/L1/fraud-proof/verifier/libraries/VerifierHelper.sol b/packages/contracts/contracts/L1/fraud-proof/verifier/libraries/VerifierHelper.sol new file mode 100644 index 000000000..0ea8e6e32 --- /dev/null +++ b/packages/contracts/contracts/L1/fraud-proof/verifier/libraries/VerifierHelper.sol @@ -0,0 +1,275 @@ +// SPDX-License-Identifier: Apache-2.0 + +/* + * Copyright 2022, Specular contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +pragma solidity ^0.8.0; + +import "./OneStepProof.sol"; +import "./VerificationContext.sol"; +import "./EVMTypesLib.sol"; +import "./BloomLib.sol"; +import "./Params.sol"; + +library VerifierHelper { + using VerificationContext for VerificationContext.Context; + using BloomLib for BloomLib.Bloom; + using OneStepProof for OneStepProof.LogProof; + + function decodeAndVerifyStackProof( + OneStepProof.StateProof memory stateProof, + uint64 popNum, + uint64 offset, + bytes calldata encoded + ) internal pure returns (uint64, OneStepProof.StackProof memory stackProof) { + // Decode StackProof + (offset, stackProof) = OneStepProof.decodeStackProof(encoded, offset, popNum); + if (popNum != 0) { + // Reconstruct the stack hash before pops + bytes32 h = stackProof.stackHashAfterPops; + for (uint8 i = uint8(stackProof.pops.length); i > 0; i--) { + h = keccak256(abi.encodePacked(h, stackProof.pops[i - 1])); + } + // Ensure the stack hash reconstructed is the same as the stack hash in stateProof + require(h == stateProof.stackHash, "Bad StackProof"); + } else { + // If no pop, the stackHashAfterPops is just the current stack hash + stackProof.stackHashAfterPops = stateProof.stackHash; + } + return (offset, stackProof); + } + + function decodeAndVerifyBlockHashProof( + uint64 offset, + bytes calldata encoded, + uint64 blockNumber, + bytes32 blockHashRoot + ) internal pure returns (uint64, bytes32) { + OneStepProof.BlockHashProof memory blockHashProof; + (offset, blockHashProof) = OneStepProof.decodeBlockHashProof(encoded, offset); + OneStepProof.BlockHashMerkleProof memory blockHashMerkleProof; + (offset, blockHashMerkleProof) = OneStepProof.decodeBlockHashMerkleProof(encoded, offset); + // Verify blockhash + bytes32 h = blockHashProof.blockHash; + uint64 path = blockHashMerkleProof.path; + uint64 num = 0; + for (uint8 i = 0; i < blockHashMerkleProof.proof.length; i++) { + if (path & 0x1 == 1) { + h = keccak256(abi.encodePacked(h, blockHashMerkleProof.proof[i])); + num |= uint64(1 << i); + } else { + h = keccak256(abi.encodePacked(blockHashMerkleProof.proof[i], h)); + } + path = path >> 1; + } + require(h == blockHashRoot, "Bad BlockHashProof"); + require(num == blockNumber, "Bad BlockHashProof"); + + return (offset, blockHashProof.blockHash); + } + + function decodeAndInsertBlockHashProof( + uint64 offset, + bytes calldata encoded, + uint64 blockNumber, + bytes32 blockHashRoot, + bytes32 newBlockHash + ) internal pure returns (uint64, bytes32) { + OneStepProof.BlockHashProof memory blockHashProof; + (offset, blockHashProof) = OneStepProof.decodeBlockHashProof(encoded, offset); + OneStepProof.BlockHashMerkleProof memory blockHashMerkleProof; + (offset, blockHashMerkleProof) = OneStepProof.decodeBlockHashMerkleProof(encoded, offset); + // Verify blockhash + bytes32 h = blockHashProof.blockHash; + uint64 path = blockHashMerkleProof.path; + uint64 num = 0; + for (uint8 i = 0; i < blockHashMerkleProof.proof.length; i++) { + if (path & 0x1 == 1) { + h = keccak256(abi.encodePacked(h, blockHashMerkleProof.proof[i])); + num |= uint64(1 << i); + } else { + h = keccak256(abi.encodePacked(blockHashMerkleProof.proof[i], h)); + } + path = path >> 1; + } + require(h == blockHashRoot, "Bad BlockHashProof"); + require(num == blockNumber, "Bad BlockHashProof"); + + h = newBlockHash; + path = blockHashMerkleProof.path; + for (uint8 i = 0; i < blockHashMerkleProof.proof.length; i++) { + if (path & 0x1 == 1) { + h = keccak256(abi.encodePacked(h, blockHashMerkleProof.proof[i])); + } else { + h = keccak256(abi.encodePacked(blockHashMerkleProof.proof[i], h)); + } + path = path >> 1; + } + // h is the new root now + return (offset, h); + } + + function updateAndHashLogProof( + OneStepProof.LogProof memory logProof, + address addr, + uint256[] memory topics, + bytes memory data + ) internal pure returns (bytes32) { + bytes32 logHash = EVMTypesLib.hashLogEntry(addr, topics, data); + logProof.accumulateHash = keccak256(abi.encodePacked(logProof.accumulateHash, logHash)); + logProof.bloom.add(addr); + for (uint8 i = 0; i < topics.length; i++) { + logProof.bloom.add(bytes32(topics[i])); + } + return logProof.hashLogProof(); + } + + function verifyRevertByError(uint64 offset, OneStepProof.StateProof memory stateProof, bytes calldata encoded) + internal + pure + returns (OneStepProof.StateProof memory) + { + bytes32 lastDepthHash = stateProof.lastDepthHash; + if (stateProof.depth == 1) {} + // require(offset == encoded.length, "Proof Overflow"); + return stateProof; + } + + function verifyTransfer(bytes32 worldState, uint256 value, uint64 offset, bytes calldata encoded) + internal + pure + returns (bytes32) + {} + + function verifyTransactionInitiation( + VerificationContext.Context memory ctx, + OneStepProof.InterStateProof memory stateProof, + EVMTypesLib.Account memory senderAccountProof, + uint64 offset, + bytes calldata encoded + ) internal pure returns (bytes32) {} + + function hashBlockHeader( + VerificationContext.Context memory ctx, + bytes32 parentBlockHash, + OneStepProof.InterStateProof memory stateProof + ) internal pure returns (bytes32) { + EVMTypesLib.BlockHeader memory blockHeader; + blockHeader.parentHash = parentBlockHash; + blockHeader.ommerHash = Params.EMPTY_UNCLE_HASH; + blockHeader.beneficiary = ctx.getCoinbase(); + blockHeader.stateRoot = stateProof.globalStateRoot; + blockHeader.transactionRoot = stateProof.transactionTrieRoot; + blockHeader.receiptsRoot = stateProof.receiptTrieRoot; + blockHeader.difficulty = ctx.getDifficulty(); + blockHeader.number = stateProof.blockNumber; + blockHeader.gasLimit = ctx.getGasLimit(); + blockHeader.gasUsed = uint64(stateProof.blockGasUsed); + blockHeader.timestamp = uint64(ctx.getTimestamp()); + blockHeader.logsBloom = stateProof.logsBloom; + return EVMTypesLib.hashBlockHeader(blockHeader); + } + + function BuildCreateState( + OneStepProof.StateProof memory stateProof, + OneStepProof.StackProof memory stackProof, + EVMTypesLib.Account memory accountProof, + OneStepProof.MemoryReadProof memory memoryReadProof + ) internal pure {} + + function BuildCreate2State( + OneStepProof.StateProof memory stateProof, + OneStepProof.StackProof memory stackProof, + EVMTypesLib.Account memory accountProof, + OneStepProof.MemoryReadProof memory memoryReadProof + ) internal pure {} + + function BuildCallState( + OneStepProof.StateProof memory stateProof, + OneStepProof.StackProof memory stackProof, + EVMTypesLib.Account memory accountProof, + OneStepProof.MemoryReadProof memory memoryReadProof + ) internal pure {} + + function BuildCallCodeState( + OneStepProof.StateProof memory stateProof, + OneStepProof.StackProof memory stackProof, + EVMTypesLib.Account memory accountProof, + OneStepProof.MemoryReadProof memory memoryReadProof + ) internal pure {} + + function BuildDelegateCallState( + OneStepProof.StateProof memory stateProof, + OneStepProof.StackProof memory stackProof, + EVMTypesLib.Account memory accountProof, + OneStepProof.MemoryReadProof memory memoryReadProof + ) internal pure {} + + function BuildStaticCallState( + OneStepProof.StateProof memory stateProof, + OneStepProof.StackProof memory stackProof, + EVMTypesLib.Account memory accountProof, + OneStepProof.MemoryReadProof memory memoryReadProof + ) internal pure {} + + function BuildIntraReturnState( + VerificationContext.Context memory ctx, + OneStepProof.StateProof memory stateProof, + OneStepProof.StateProof memory lastStateProof, + OneStepProof.StackProof memory stackProof, + OneStepProof.MemoryReadProof memory memoryReadProof, + OneStepProof.MemoryWriteProof memory memoryWriteProof + ) internal pure {} + + function BuildInterReturnState( + VerificationContext.Context memory ctx, + OneStepProof.StateProof memory stateProof, + OneStepProof.InterStateProof memory lastStateProof, + OneStepProof.StackProof memory stackProof + ) internal pure {} + + function BuildIntraRevertState( + VerificationContext.Context memory ctx, + OneStepProof.StateProof memory stateProof, + OneStepProof.StateProof memory lastStateProof, + OneStepProof.StackProof memory stackProof, + OneStepProof.MemoryReadProof memory memoryReadProof, + OneStepProof.MemoryWriteProof memory memoryWriteProof + ) internal pure {} + + function BuildInterRevertState( + VerificationContext.Context memory ctx, + OneStepProof.StateProof memory stateProof, + OneStepProof.InterStateProof memory lastStateProof, + OneStepProof.StackProof memory stackProof + ) internal pure {} + + function BuildIntraSuicideState( + VerificationContext.Context memory ctx, + OneStepProof.StateProof memory stateProof, + OneStepProof.StateProof memory lastStateProof, + OneStepProof.StackProof memory stackProof, + OneStepProof.MemoryReadProof memory memoryReadProof, + OneStepProof.MemoryWriteProof memory memoryWriteProof + ) internal pure {} + + function BuildInterSuicideState( + VerificationContext.Context memory ctx, + OneStepProof.StateProof memory stateProof, + OneStepProof.InterStateProof memory lastStateProof, + OneStepProof.StackProof memory stackProof + ) internal pure {} +} diff --git a/packages/contracts/contracts/L1/fraud-proof/verifier/subverifiers/BlockFinalizationVerifier.sol b/packages/contracts/contracts/L1/fraud-proof/verifier/subverifiers/BlockFinalizationVerifier.sol new file mode 100644 index 000000000..daad406f0 --- /dev/null +++ b/packages/contracts/contracts/L1/fraud-proof/verifier/subverifiers/BlockFinalizationVerifier.sol @@ -0,0 +1,79 @@ +// SPDX-License-Identifier: Apache-2.0 + +/* + * Copyright 2022, Specular contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +pragma solidity ^0.8.0; + +import "../../libraries/BytesLib.sol"; +import "../../libraries/MPT.sol"; +import "../IVerifier.sol"; +import "../libraries/VerificationContext.sol"; +import "../libraries/OneStepProof.sol"; +import "../libraries/Params.sol"; +import "../libraries/GasTable.sol"; +import "../libraries/VerifierHelper.sol"; +import "../libraries/EVMTypesLib.sol"; +import "../libraries/BloomLib.sol"; + +contract BlockFinalizationVerifier is IVerifier { + function verifyOneStepProof(VerificationContext.Context memory ctx, bytes32 currStateHash, bytes calldata encoded) + external + pure + override + returns (bytes32) + { + return OneStepProof.hashBlockStateProof(executeOneStepProof(ctx, currStateHash, encoded)); + } + + function executeOneStepProof(VerificationContext.Context memory ctx, bytes32 currStateHash, bytes calldata encoded) + public + pure + returns (OneStepProof.BlockStateProof memory endState) + { + uint64 offset = 0; + // Decode inter-state proof + OneStepProof.InterStateProof memory stateProof; + (offset, stateProof) = OneStepProof.decodeInterStateProof(encoded, offset); + + // Calculate the state hash from the submitted proof + bytes32 stateHashFromProof; + assembly { + let ptr := mload(0x40) + calldatacopy(ptr, encoded.offset, encoded.length) + stateHashFromProof := keccak256(ptr, offset) + } + // Ensure the state proof is valid + require(stateHashFromProof == currStateHash, "Bad State Proof"); + + // Obtain the parent block hash from the block hash tree + bytes32 parentBlockHash; + (offset, parentBlockHash) = VerifierHelper.decodeAndVerifyBlockHashProof( + offset, encoded, stateProof.blockNumber - 1, stateProof.blockHashRoot + ); + // Update the current block hash to the block hash tree + bytes32 currentBlockHash = VerifierHelper.hashBlockHeader(ctx, parentBlockHash, stateProof); + + // Create the finalized block state using last inter-state proof + (offset, endState.blockHashRoot) = VerifierHelper.decodeAndInsertBlockHashProof( + offset, encoded, stateProof.blockNumber, stateProof.blockHashRoot, currentBlockHash + ); + endState.blockNumber = stateProof.blockNumber; + endState.globalStateRoot = stateProof.globalStateRoot; + endState.cumulativeGasUsed = stateProof.cumulativeGasUsed; + return endState; + } +} diff --git a/packages/contracts/contracts/L1/fraud-proof/verifier/subverifiers/BlockInitiationVerifier.sol b/packages/contracts/contracts/L1/fraud-proof/verifier/subverifiers/BlockInitiationVerifier.sol new file mode 100644 index 000000000..847cfea99 --- /dev/null +++ b/packages/contracts/contracts/L1/fraud-proof/verifier/subverifiers/BlockInitiationVerifier.sol @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: Apache-2.0 + +/* + * Copyright 2022, Specular contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +pragma solidity ^0.8.0; + +import "../../libraries/BytesLib.sol"; +import "../../libraries/MPT.sol"; +import "../IVerifier.sol"; +import "../libraries/VerificationContext.sol"; +import "../libraries/OneStepProof.sol"; +import "../libraries/Params.sol"; +import "../libraries/GasTable.sol"; +import "../libraries/VerifierHelper.sol"; +import "../libraries/EVMTypesLib.sol"; +import "../libraries/BloomLib.sol"; + +contract BlockInitiationVerifier is IVerifier { + function verifyOneStepProof(VerificationContext.Context memory, bytes32 currStateHash, bytes calldata encoded) + external + pure + override + returns (bytes32) + { + return OneStepProof.hashInterStateProof(executeOneStepProof(currStateHash, encoded)); + } + + function executeOneStepProof(bytes32 currStateHash, bytes calldata encoded) + public + pure + returns (OneStepProof.InterStateProof memory endState) + { + uint64 offset = 0; + // Decode block state proof + OneStepProof.BlockStateProof memory blockStateProof; + (offset, blockStateProof) = OneStepProof.decodeBlockStateProof(encoded, offset); + + // Calculate the state hash from the submitted proof + bytes32 stateHashFromProof; + assembly { + let ptr := mload(0x40) + calldatacopy(ptr, encoded.offset, offset) + stateHashFromProof := keccak256(ptr, offset) + } + // Ensure the block state proof is valid + require(stateHashFromProof == currStateHash, "Bad State Proof"); + + // Create the first inter-state in the block using block state proof + endState.blockNumber = blockStateProof.blockNumber + 1; + endState.transactionIdx = 0; + endState.globalStateRoot = blockStateProof.globalStateRoot; + endState.cumulativeGasUsed = blockStateProof.cumulativeGasUsed; + endState.blockHashRoot = blockStateProof.blockHashRoot; + endState.transactionTrieRoot = Params.EMPTY_TRIE_ROOT; + endState.receiptTrieRoot = Params.EMPTY_TRIE_ROOT; + endState.logsBloom = BloomLib.emptyBloom(); + return endState; + } +} diff --git a/packages/contracts/contracts/L1/fraud-proof/verifier/subverifiers/CallOpVerifier.sol b/packages/contracts/contracts/L1/fraud-proof/verifier/subverifiers/CallOpVerifier.sol new file mode 100644 index 000000000..86dff0b8f --- /dev/null +++ b/packages/contracts/contracts/L1/fraud-proof/verifier/subverifiers/CallOpVerifier.sol @@ -0,0 +1,154 @@ +// SPDX-License-Identifier: Apache-2.0 + +/* + * Copyright 2022, Specular contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +pragma solidity ^0.8.0; + +import "../../libraries/BytesLib.sol"; +import "../../libraries/MPT.sol"; +import "../IVerifier.sol"; +import "../libraries/VerificationContext.sol"; +import "../libraries/OneStepProof.sol"; +import "../libraries/Params.sol"; +import "../libraries/GasTable.sol"; +import "../libraries/VerifierHelper.sol"; +import "../libraries/EVMTypesLib.sol"; + +contract CallOpVerifier is IVerifier { + using BytesLib for bytes; + using RLPReader for bytes; + using RLPReader for RLPReader.RLPItem; + using RLPReader for RLPReader.Iterator; + using VerificationContext for VerificationContext.Context; + using OneStepProof for OneStepProof.CodeProof; + + function verifyOneStepProof(VerificationContext.Context memory ctx, bytes32 currStateHash, bytes calldata encoded) + external + pure + override + returns (bytes32) + { + return OneStepProof.hashStateProof(executeOneStepProof(ctx, currStateHash, encoded)); + } + + function executeOneStepProof(VerificationContext.Context memory ctx, bytes32 currStateHash, bytes calldata encoded) + public + pure + returns (OneStepProof.StateProof memory endState) + { + uint64 offset = 0; + // Decode state proof + OneStepProof.StateProof memory stateProof; + (offset, stateProof) = OneStepProof.decodeStateProof(ctx, encoded, offset); + // Calculate the state hash from the submitted proof + bytes32 stateHashFromProof; + assembly { + let ptr := mload(0x40) + calldatacopy(ptr, encoded.offset, offset) + stateHashFromProof := keccak256(ptr, offset) + } + // Ensure the state proof is valid + require(stateHashFromProof == currStateHash, "Bad State Proof"); + + // Simulate EVM one-step execution based on the opcode + uint8 opCode = stateProof.opCode; + if (opCode == 0xf0) { + // CREATE + verifyOpCREATE(offset, stateProof, encoded); + } else if (opCode == 0xf1) { + // CALL + verifyOpCALL(offset, stateProof, encoded); + } else if (opCode == 0xf3) { + // RETURN + verifyOpRETURN(ctx, offset, stateProof, encoded); + } else if (opCode == 0xf2) { + // CALLCODE + verifyOpCALLCODE(offset, stateProof, encoded); + } else if (opCode == 0xf4) { + // DELEGATECALL + verifyOpDELEGATECALL(offset, stateProof, encoded); + } else if (opCode == 0xf5) { + // CREATE2 + verifyOpCREATE2(offset, stateProof, encoded); + } else if (opCode == 0xfa) { + // STATICCALL + verifyOpSTATICCALL(offset, stateProof, encoded); + } else if (opCode == 0xfd) { + // REVERT + verifyOpREVERT(ctx, offset, stateProof, encoded); + } else if (opCode == 0xff) { + // SELFDESTRUCT + verifyOpSELFDESTRUCT(ctx, offset, stateProof, encoded); + } else { + revert("Unreachable"); + } + + // Return the state hash after one-step execution + return stateProof; + } + + function verifyOpCREATE(uint64 offset, OneStepProof.StateProof memory stateProof, bytes calldata encoded) + internal + pure + {} + + function verifyOpCALL(uint64 offset, OneStepProof.StateProof memory stateProof, bytes calldata encoded) + internal + pure + {} + + function verifyOpRETURN( + VerificationContext.Context memory ctx, + uint64 offset, + OneStepProof.StateProof memory stateProof, + bytes calldata encoded + ) internal pure {} + + function verifyOpCALLCODE(uint64 offset, OneStepProof.StateProof memory stateProof, bytes calldata encoded) + internal + pure + {} + + function verifyOpDELEGATECALL(uint64 offset, OneStepProof.StateProof memory stateProof, bytes calldata encoded) + internal + pure + {} + + function verifyOpCREATE2(uint64 offset, OneStepProof.StateProof memory stateProof, bytes calldata encoded) + internal + pure + {} + + function verifyOpSTATICCALL(uint64 offset, OneStepProof.StateProof memory stateProof, bytes calldata encoded) + internal + pure + {} + + function verifyOpREVERT( + VerificationContext.Context memory ctx, + uint64 offset, + OneStepProof.StateProof memory stateProof, + bytes calldata encoded + ) internal pure {} + + function verifyOpSELFDESTRUCT( + VerificationContext.Context memory ctx, + uint64 offset, + OneStepProof.StateProof memory stateProof, + bytes calldata encoded + ) internal pure {} +} diff --git a/packages/contracts/contracts/L1/fraud-proof/verifier/subverifiers/EnvironmentalOpVerifier.sol b/packages/contracts/contracts/L1/fraud-proof/verifier/subverifiers/EnvironmentalOpVerifier.sol new file mode 100644 index 000000000..98a92a51f --- /dev/null +++ b/packages/contracts/contracts/L1/fraud-proof/verifier/subverifiers/EnvironmentalOpVerifier.sol @@ -0,0 +1,303 @@ +// SPDX-License-Identifier: Apache-2.0 + +/* + * Copyright 2022, Specular contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +pragma solidity ^0.8.0; + +import "../../libraries/BytesLib.sol"; +import "../IVerifier.sol"; +import "../libraries/VerificationContext.sol"; +import "../libraries/VerifierHelper.sol"; +import "../libraries/OneStepProof.sol"; +import "../libraries/Params.sol"; +import "../libraries/GasTable.sol"; + +contract EnvironmentalOpVerifier is IVerifier { + using BytesLib for bytes; + using VerificationContext for VerificationContext.Context; + using OneStepProof for OneStepProof.CodeProof; + + function verifyOneStepProof(VerificationContext.Context memory ctx, bytes32 currStateHash, bytes calldata encoded) + external + pure + override + returns (bytes32) + { + return OneStepProof.hashStateProof(executeOneStepProof(ctx, currStateHash, encoded)); + } + + function executeOneStepProof(VerificationContext.Context memory ctx, bytes32 currStateHash, bytes calldata encoded) + public + pure + returns (OneStepProof.StateProof memory) + { + uint64 offset = 0; + // Decode state proof + OneStepProof.StateProof memory stateProof; + (offset, stateProof) = OneStepProof.decodeStateProof(ctx, encoded, offset); + // Calculate the state hash from the submitted proof + bytes32 stateHashFromProof; + assembly { + let ptr := mload(0x40) + calldatacopy(ptr, encoded.offset, offset) + stateHashFromProof := keccak256(ptr, offset) + } + // Ensure the state proof is valid + require(stateHashFromProof == currStateHash, "Bad State Proof"); + + // Decode the code proof + OneStepProof.CodeProof memory codeProof; + (offset, codeProof) = OneStepProof.decodeCodeProof(encoded, offset); + + // Simulate EVM one-step execution based on the opcode + uint8 opCode = stateProof.opCode; + if (opCode == 0x30) { + // ADDRESS + verifyOpADDRESS(offset, stateProof, encoded); + } else if (opCode == 0x32) { + // ORIGIN + verifyOpORIGIN(ctx, offset, stateProof, encoded); + } else if (opCode == 0x33) { + // CALLER + verifyOpCALLER(offset, stateProof, encoded); + } else if (opCode == 0x34) { + // CALLVALUE + verifyOpCALLVALUE(offset, stateProof, encoded); + } else if (opCode == 0x38) { + // CODESIZE + verifyOpCODESIZE(offset, stateProof, codeProof, encoded); + } else if (opCode == 0x36) { + // CALLDATASIZE + verifyOpCALLDATASIZE(offset, stateProof, encoded); + } else if (opCode == 0x3a) { + // GASPRICE + verifyOpGASPRICE(ctx, offset, stateProof, encoded); + } else if (opCode == 0x3d) { + // RETURNDATASIZE + verifyOpRETURNDATASIZE(offset, stateProof, encoded); + } else if (opCode == 0x40) { + // BLOCKHASH + verifyOpBLOCKHASH(offset, stateProof, encoded); + } else if (opCode == 0x41) { + // COINBASE + verifyOpCOINBASE(ctx, offset, stateProof, encoded); + } else if (opCode == 0x42) { + // TIMESTAMP + verifyOpTIMESTAMP(ctx, offset, stateProof, encoded); + } else if (opCode == 0x43) { + // NUMBER + verifyOpNUMBER(ctx, offset, stateProof, encoded); + } else if (opCode == 0x44) { + // DIFFICULTY + verifyOpDIFFICULTY(ctx, offset, stateProof, encoded); + } else if (opCode == 0x45) { + // GASLIMIT + verifyOpGASLIMIT(ctx, offset, stateProof, encoded); + } else if (opCode == 0x46) { + // CHAINID + verifyOpCHAINID(ctx, offset, stateProof, encoded); + } else { + revert("Unreachable"); + } + + // Obtain the opcode at new pc + if (stateProof.depth > 0) { + if (codeProof.size > uint256(stateProof.pc)) { + stateProof.opCode = codeProof.getOpCodeAt(encoded, stateProof.pc); + } else { + stateProof.opCode = 0x00; + } + } + // Return the state hash after one-step execution + return stateProof; + } + + function verifyOnePushOpcode( + uint64 offset, + OneStepProof.StateProof memory stateProof, + uint64 gas, + uint256 push, + bytes calldata encoded + ) internal pure { + if (stateProof.stackSize >= Params.STACK_LIMIT - 1) { + VerifierHelper.verifyRevertByError(offset, stateProof, encoded); + return; + } + // Consume the gas + if (stateProof.gas < gas) { + VerifierHelper.verifyRevertByError(offset, stateProof, encoded); + return; + } + stateProof.gas -= gas; + + // Simulate pushing `push` to the stack + stateProof.stackHash = keccak256(abi.encodePacked(stateProof.stackHash, push)); + stateProof.stackSize += 1; + // Increment the pc + stateProof.pc += 1; + } + + function verifyOpADDRESS(uint64 offset, OneStepProof.StateProof memory stateProof, bytes calldata encoded) + internal + pure + { + verifyOnePushOpcode(offset, stateProof, Params.G_BASE, uint256(uint160(stateProof.contractAddress)), encoded); + } + + function verifyOpORIGIN( + VerificationContext.Context memory ctx, + uint64 offset, + OneStepProof.StateProof memory stateProof, + bytes calldata encoded + ) internal pure { + verifyOnePushOpcode(offset, stateProof, Params.G_BASE, uint256(uint160(ctx.getOrigin())), encoded); + } + + function verifyOpCALLER(uint64 offset, OneStepProof.StateProof memory stateProof, bytes calldata encoded) + internal + pure + { + verifyOnePushOpcode(offset, stateProof, Params.G_BASE, uint256(uint160(stateProof.caller)), encoded); + } + + function verifyOpCALLVALUE(uint64 offset, OneStepProof.StateProof memory stateProof, bytes calldata encoded) + internal + pure + { + verifyOnePushOpcode(offset, stateProof, Params.G_BASE, uint256(uint160(stateProof.value)), encoded); + } + + function verifyOpCODESIZE( + uint64 offset, + OneStepProof.StateProof memory stateProof, + OneStepProof.CodeProof memory codeProof, + bytes calldata encoded + ) internal pure { + verifyOnePushOpcode(offset, stateProof, Params.G_BASE, uint256(codeProof.size), encoded); + } + + function verifyOpCALLDATASIZE(uint64 offset, OneStepProof.StateProof memory stateProof, bytes calldata encoded) + internal + pure + { + verifyOnePushOpcode(offset, stateProof, Params.G_BASE, uint256(stateProof.inputDataSize), encoded); + } + + function verifyOpGASPRICE( + VerificationContext.Context memory ctx, + uint64 offset, + OneStepProof.StateProof memory stateProof, + bytes calldata encoded + ) internal pure { + verifyOnePushOpcode(offset, stateProof, Params.G_BASE, ctx.getGasPrice(), encoded); + } + + function verifyOpRETURNDATASIZE(uint64 offset, OneStepProof.StateProof memory stateProof, bytes calldata encoded) + internal + pure + { + verifyOnePushOpcode(offset, stateProof, Params.G_BASE, uint256(stateProof.returnDataSize), encoded); + } + + function verifyOpBLOCKHASH(uint64 offset, OneStepProof.StateProof memory stateProof, bytes calldata encoded) + internal + pure + { + if (stateProof.stackSize < 1) { + VerifierHelper.verifyRevertByError(offset, stateProof, encoded); + return; + } + OneStepProof.StackProof memory stackProof; + (offset, stackProof) = VerifierHelper.decodeAndVerifyStackProof(stateProof, 1, offset, encoded); + + // Consume the gas + uint64 gas = Params.G_BLOCKHASH; + if (stateProof.gas < gas) { + VerifierHelper.verifyRevertByError(offset, stateProof, encoded); + return; + } + stateProof.gas -= gas; + + uint64 num = uint64(stackProof.pops[0]); + bytes32 bhash; + if (stateProof.blockNumber >= num || stateProof.blockNumber < num - Params.RECENT_BLOCK_HASHES_LENGTH) { + bhash = 0x00; + } else { + (offset, bhash) = + VerifierHelper.decodeAndVerifyBlockHashProof(offset, encoded, num, stateProof.blockHashRoot); + } + + // Simulate pushing `bhash` to the stack + stateProof.stackHash = keccak256(abi.encodePacked(stackProof.stackHashAfterPops, bhash)); + // Increment the pc + stateProof.pc += 1; + } + + function verifyOpCOINBASE( + VerificationContext.Context memory ctx, + uint64 offset, + OneStepProof.StateProof memory stateProof, + bytes calldata encoded + ) internal pure { + verifyOnePushOpcode(offset, stateProof, Params.G_BASE, uint256(uint160(ctx.getCoinbase())), encoded); + } + + function verifyOpTIMESTAMP( + VerificationContext.Context memory ctx, + uint64 offset, + OneStepProof.StateProof memory stateProof, + bytes calldata encoded + ) internal pure { + verifyOnePushOpcode(offset, stateProof, Params.G_BASE, ctx.getTimestamp(), encoded); + } + + function verifyOpNUMBER( + VerificationContext.Context memory ctx, + uint64 offset, + OneStepProof.StateProof memory stateProof, + bytes calldata encoded + ) internal pure { + verifyOnePushOpcode(offset, stateProof, Params.G_BASE, ctx.getBlockNumber(), encoded); + } + + function verifyOpDIFFICULTY( + VerificationContext.Context memory ctx, + uint64 offset, + OneStepProof.StateProof memory stateProof, + bytes calldata encoded + ) internal pure { + verifyOnePushOpcode(offset, stateProof, Params.G_BASE, ctx.getDifficulty(), encoded); + } + + function verifyOpGASLIMIT( + VerificationContext.Context memory ctx, + uint64 offset, + OneStepProof.StateProof memory stateProof, + bytes calldata encoded + ) internal pure { + verifyOnePushOpcode(offset, stateProof, Params.G_BASE, uint256(ctx.getGasLimit()), encoded); + } + + function verifyOpCHAINID( + VerificationContext.Context memory ctx, + uint64 offset, + OneStepProof.StateProof memory stateProof, + bytes calldata encoded + ) internal pure { + verifyOnePushOpcode(offset, stateProof, Params.G_BASE, uint256(ctx.getChainID()), encoded); + } +} diff --git a/packages/contracts/contracts/L1/fraud-proof/verifier/subverifiers/InterTxVerifier.sol b/packages/contracts/contracts/L1/fraud-proof/verifier/subverifiers/InterTxVerifier.sol new file mode 100644 index 000000000..cce5e6fba --- /dev/null +++ b/packages/contracts/contracts/L1/fraud-proof/verifier/subverifiers/InterTxVerifier.sol @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: Apache-2.0 + +/* + * Copyright 2022, Specular contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +pragma solidity ^0.8.0; + +import "../../libraries/BytesLib.sol"; +import "../../libraries/MPT.sol"; +import "../IVerifier.sol"; +import "../libraries/VerificationContext.sol"; +import "../libraries/OneStepProof.sol"; +import "../libraries/Params.sol"; +import "../libraries/GasTable.sol"; +import "../libraries/VerifierHelper.sol"; +import "../libraries/EVMTypesLib.sol"; + +contract InterTxVerifier is IVerifier { + using BytesLib for bytes; + using RLPReader for bytes; + using RLPReader for RLPReader.RLPItem; + using RLPReader for RLPReader.Iterator; + using VerificationContext for VerificationContext.Context; + using OneStepProof for OneStepProof.InterStateProof; + using OneStepProof for EVMTypesLib.Account; + + function verifyOneStepProof(VerificationContext.Context memory ctx, bytes32 currStateHash, bytes calldata encoded) + external + pure + override + returns (bytes32) + { + return OneStepProof.hashStateProof(executeOneStepProof(ctx, currStateHash, encoded)); + } + + function executeOneStepProof(VerificationContext.Context memory ctx, bytes32 currStateHash, bytes calldata encoded) + public + pure + returns (OneStepProof.StateProof memory) + { + uint64 offset = 0; + // Decode inter-state proof + OneStepProof.InterStateProof memory stateProof; + (offset, stateProof) = OneStepProof.decodeInterStateProof(encoded, offset); + // Calculate the state hash from the submitted proof + bytes32 stateHashFromProof; + assembly { + let ptr := mload(0x40) + calldatacopy(ptr, encoded.offset, encoded.length) + stateHashFromProof := keccak256(ptr, offset) + } + // Ensure the state proof is valid + require(stateHashFromProof == currStateHash, "Bad State Proof"); + } +} diff --git a/packages/contracts/contracts/L1/fraud-proof/verifier/subverifiers/InvalidOpVerifier.sol b/packages/contracts/contracts/L1/fraud-proof/verifier/subverifiers/InvalidOpVerifier.sol new file mode 100644 index 000000000..70259605c --- /dev/null +++ b/packages/contracts/contracts/L1/fraud-proof/verifier/subverifiers/InvalidOpVerifier.sol @@ -0,0 +1,114 @@ +// SPDX-License-Identifier: Apache-2.0 + +/* + * Copyright 2022, Specular contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +pragma solidity ^0.8.0; + +import "../../libraries/BytesLib.sol"; +import "../IVerifier.sol"; +import "../libraries/VerificationContext.sol"; +import "../libraries/OneStepProof.sol"; +import "../libraries/Params.sol"; +import "../libraries/GasTable.sol"; +import "../libraries/VerifierHelper.sol"; + +contract InvalidOpVerifier is IVerifier { + using BytesLib for bytes; + using VerificationContext for VerificationContext.Context; + using OneStepProof for OneStepProof.CodeProof; + + function verifyOneStepProof(VerificationContext.Context memory ctx, bytes32 currStateHash, bytes calldata encoded) + external + pure + override + returns (bytes32) + { + return OneStepProof.hashStateProof(executeOneStepProof(ctx, currStateHash, encoded)); + } + + function executeOneStepProof(VerificationContext.Context memory ctx, bytes32 currStateHash, bytes calldata encoded) + public + pure + returns (OneStepProof.StateProof memory endState) + { + uint64 offset = 0; + // Decode state proof + OneStepProof.StateProof memory stateProof; + (offset, stateProof) = OneStepProof.decodeStateProof(ctx, encoded, offset); + // Calculate the state hash from the submitted proof + bytes32 stateHashFromProof; + assembly { + let ptr := mload(0x40) + calldatacopy(ptr, encoded.offset, offset) + stateHashFromProof := keccak256(ptr, offset) + } + // Ensure the state proof is valid + require(stateHashFromProof == currStateHash, "Bad State Proof"); + + // Decode the code proof + OneStepProof.CodeProof memory codeProof; + (offset, codeProof) = OneStepProof.decodeCodeProof(encoded, offset); + + // Simulate EVM one-step execution based on the opcode + uint8 opCode = stateProof.opCode; + if (!isInvalidOp(opCode)) { + revert("Unreachable"); + } + + VerifierHelper.verifyRevertByError(offset, stateProof, encoded); + + // Obtain the opcode at new pc + if (stateProof.depth > 0) { + if (codeProof.size > uint256(stateProof.pc)) { + stateProof.opCode = codeProof.getOpCodeAt(encoded, stateProof.pc); + } else { + stateProof.opCode = 0x00; + } + } + // Return the state hash after one-step execution + return stateProof; + } + + function isInvalidOp(uint8 opCode) internal pure returns (bool) { + if (opCode == 0xfe) { + // INVALID + return true; + } + if (opCode >= 0x0c && opCode <= 0x0f) { + return true; + } + if (opCode >= 0x1e && opCode <= 0x1f) { + return true; + } + if (opCode >= 0x21 && opCode <= 0x2f) { + return true; + } + if (opCode >= 0x47 && opCode <= 0x4f) { + return true; // BASEFEE not supported in Istanbul protocol + } + if (opCode >= 0x5c && opCode <= 0x5f) { + return true; + } + if (opCode >= 0xa5 && opCode <= 0xef) { + return true; + } + if (opCode >= 0xf6 && opCode <= 0xf9 || opCode == 0xfb || opCode == 0xfc) { + return true; + } + return false; + } +} diff --git a/packages/contracts/contracts/L1/fraud-proof/verifier/subverifiers/MemoryOpVerifier.sol b/packages/contracts/contracts/L1/fraud-proof/verifier/subverifiers/MemoryOpVerifier.sol new file mode 100644 index 000000000..be58cbf09 --- /dev/null +++ b/packages/contracts/contracts/L1/fraud-proof/verifier/subverifiers/MemoryOpVerifier.sol @@ -0,0 +1,412 @@ +// SPDX-License-Identifier: Apache-2.0 + +/* + * Copyright 2022, Specular contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +pragma solidity ^0.8.0; + +//import "../../libraries/BytesLib.sol"; +//import "../../libraries/MerkleLib.sol"; +//import "../libraries/VerificationContext.sol"; +//import "../libraries/OneStepProof.sol"; +//import "../libraries/Params.sol"; +//import "../libraries/GasTable.sol"; +//import "../libraries/VerifierHelper.sol"; +//import "../IVerifier.sol"; + +contract MemoryOpVerifier { +//contract MemoryOpVerifier is IVerifier { +// using BytesLib for bytes; +// using VerificationContext for VerificationContext.Context; +// using OneStepProof for OneStepProof.CodeProof; +// using OneStepProof for OneStepProof.LogProof; +// +// function verifyOneStepProof(VerificationContext.Context memory ctx, bytes32 currStateHash, bytes calldata encoded) +// external +// pure +// override +// returns (bytes32) +// { +// return OneStepProof.hashStateProof(executeOneStepProof(ctx, currStateHash, encoded)); +// } +// +// function executeOneStepProof(VerificationContext.Context memory ctx, bytes32 currStateHash, bytes calldata encoded) +// public +// pure +// returns (OneStepProof.StateProof memory) +// { +// uint64 offset = 0; +// // Decode state proof +// OneStepProof.StateProof memory stateProof; +// (offset, stateProof) = OneStepProof.decodeStateProof(ctx, encoded, offset); +// // Calculate the state hash from the submitted proof +// bytes32 stateHashFromProof; +// assembly { +// let ptr := mload(0x40) +// calldatacopy(ptr, encoded.offset, encoded.length) +// stateHashFromProof := keccak256(ptr, offset) +// } +// // Ensure the state proof is valid +// require(stateHashFromProof == currStateHash, "Bad State Proof"); +// +// // Decode the code proof +// OneStepProof.CodeProof memory codeProof; +// (offset, codeProof) = OneStepProof.decodeCodeProof(encoded, offset); +// +// // Simulate EVM one-step execution based on the opcode +// uint8 opCode = stateProof.opCode; +// if (opCode == 0x20) { +// // KECCAK256 +// verifyOpKECCAK256(offset, stateProof, encoded); +// } else if (opCode == 0x35) { +// // CALLDATALOAD +// verifyOpCALLDATALOAD(offset, stateProof, encoded); +// } else if (opCode == 0x37) { +// // CALLDATACOPY +// verifyOpCALLDATACOPY(offset, stateProof, encoded); +// } else if (opCode == 0x39) { +// // CODECOPY +// verifyOpCODECOPY(offset, stateProof, codeProof, encoded); +// } else if (opCode == 0x3e) { +// // RETURNDATACOPY +// verifyOpRETURNDATACOPY(offset, stateProof, encoded); +// } else if (opCode == 0x51) { +// // MLOAD +// verifyOpMLOAD(offset, stateProof, encoded); +// } else if (opCode == 0x52) { +// // MSTORE +// verifyOpMSTORE(offset, stateProof, encoded); +// } else if (opCode == 0x53) { +// // MSTORE8 +// verifyOpMSTORE8(offset, stateProof, encoded); +// } else if (opCode >= 0xa0 && opCode <= 0xa4) { +// // LOG +// verifyLogOpCode(offset, stateProof, encoded); +// } else { +// revert("Unreachable"); +// } +// +// // Obtain the opcode at new pc +// if (stateProof.depth > 0) { +// if (codeProof.size > uint256(stateProof.pc)) { +// stateProof.opCode = codeProof.getOpCodeAt(encoded, stateProof.pc); +// } else { +// stateProof.opCode = 0x00; +// } +// } +// // Return the state hash after one-step execution +// return stateProof; +// } +// +// function verifyOpKECCAK256(uint64 offset, OneStepProof.StateProof memory stateProof, bytes calldata encoded) +// internal +// pure +// { +// if (stateProof.stackSize < 2) { +// VerifierHelper.verifyRevertByError(offset, stateProof, encoded); +// return; +// } +// OneStepProof.StackProof memory stackProof; +// (offset, stackProof) = VerifierHelper.decodeAndVerifyStackProof(stateProof, 2, offset, encoded); +// +// uint64 memOffset = uint64(stackProof.pops[0]); +// uint64 length = uint64(stackProof.pops[1]); +// uint64 cost = GasTable.gasKeccak(stateProof.memSize, memOffset, length); +// if (stateProof.gas < cost) { +// VerifierHelper.verifyRevertByError(offset, stateProof, encoded); +// return; +// } +// stateProof.gas -= cost; +// +// bytes memory readContent; +// (offset, readContent) = MemoryLib.decodeAndVerifyMemoryReadProof(stateProof, encoded, offset, memOffset, length); +// +// bytes32 result = keccak256(abi.encodePacked(readContent)); +// stateProof.stackHash = keccak256(abi.encodePacked(stackProof.stackHashAfterPops, result)); +// stateProof.pc += 1; +// } +// +// function verifyOpCALLDATALOAD(uint64 offset, OneStepProof.StateProof memory stateProof, bytes calldata encoded) +// internal +// pure +// { +// if (stateProof.stackSize < 1) { +// VerifierHelper.verifyRevertByError(offset, stateProof, encoded); +// return; +// } +// OneStepProof.StackProof memory stackProof; +// (offset, stackProof) = VerifierHelper.decodeAndVerifyStackProof(stateProof, 1, offset, encoded); +// +// uint64 cost = Params.G_VERYLOW; +// if (stateProof.gas < cost) { +// VerifierHelper.verifyRevertByError(offset, stateProof, encoded); +// return; +// } +// stateProof.gas -= cost; +// +// uint64 memOffset = uint64(stackProof.pops[0]); +// bytes memory readContent; +// (offset, readContent) = MemoryLib.decodeAndVerifyMemoryLikeReadProofNoAppend( +// stateProof.inputDataRoot, stateProof.inputDataSize, encoded, offset, memOffset, 32 +// ); +// +// bytes32 result = readContent.toBytes32(0); +// stateProof.stackHash = keccak256(abi.encodePacked(stackProof.stackHashAfterPops, result)); +// stateProof.pc += 1; +// } +// +// function verifyOpCALLDATACOPY(uint64 offset, OneStepProof.StateProof memory stateProof, bytes calldata encoded) +// internal +// pure +// { +// if (stateProof.stackSize < 3) { +// VerifierHelper.verifyRevertByError(offset, stateProof, encoded); +// return; +// } +// OneStepProof.StackProof memory stackProof; +// (offset, stackProof) = VerifierHelper.decodeAndVerifyStackProof(stateProof, 3, offset, encoded); +// uint64 memOffset = uint64(stackProof.pops[0]); +// uint64 inputOffset = uint64(stackProof.pops[1]); +// uint64 length = uint64(stackProof.pops[2]); +// +// uint64 cost = GasTable.gasCopy(stateProof.memSize, memOffset, length); +// if (stateProof.gas < cost) { +// VerifierHelper.verifyRevertByError(offset, stateProof, encoded); +// return; +// } +// stateProof.gas -= cost; +// +// { +// bytes memory readContent; +// (offset, readContent) = MemoryLib.decodeAndVerifyMemoryLikeReadProofNoAppend( +// stateProof.inputDataRoot, stateProof.inputDataSize, encoded, offset, inputOffset, length +// ); +// +// bytes memory writeContent; +// (offset, writeContent) = +// MemoryLib.decodeAndVerifyMemoryWriteProof(stateProof, encoded, offset, memOffset, length); +// +// require(readContent.equal(writeContent), "Inconsistent Copy"); +// } +// +// stateProof.pc += 1; +// stateProof.stackHash = stackProof.stackHashAfterPops; +// } +// +// function verifyOpCODECOPY( +// uint64 offset, +// OneStepProof.StateProof memory stateProof, +// OneStepProof.CodeProof memory codeProof, +// bytes calldata encoded +// ) internal pure { +// if (stateProof.stackSize < 3) { +// VerifierHelper.verifyRevertByError(offset, stateProof, encoded); +// return; +// } +// OneStepProof.StackProof memory stackProof; +// (offset, stackProof) = VerifierHelper.decodeAndVerifyStackProof(stateProof, 3, offset, encoded); +// uint64 memOffset = uint64(stackProof.pops[0]); +// uint64 codeOffset = uint64(stackProof.pops[1]); +// uint64 length = uint64(stackProof.pops[2]); +// +// uint64 cost = GasTable.gasCopy(stateProof.memSize, memOffset, length); +// if (stateProof.gas < cost) { +// VerifierHelper.verifyRevertByError(offset, stateProof, encoded); +// return; +// } +// stateProof.gas -= cost; +// +// { +// bytes memory readContent = codeProof.getCodeSlice(encoded, codeOffset, length); +// +// bytes memory writeContent; +// (offset, writeContent) = +// MemoryLib.decodeAndVerifyMemoryWriteProof(stateProof, encoded, offset, memOffset, length); +// +// require(readContent.equal(writeContent), "Inconsistent Copy"); +// } +// +// stateProof.pc += 1; +// stateProof.stackHash = stackProof.stackHashAfterPops; +// } +// +// function verifyOpRETURNDATACOPY(uint64 offset, OneStepProof.StateProof memory stateProof, bytes calldata encoded) +// internal +// pure +// { +// if (stateProof.stackSize < 3) { +// VerifierHelper.verifyRevertByError(offset, stateProof, encoded); +// return; +// } +// OneStepProof.StackProof memory stackProof; +// (offset, stackProof) = VerifierHelper.decodeAndVerifyStackProof(stateProof, 3, offset, encoded); +// uint64 memOffset = uint64(stackProof.pops[0]); +// uint64 returnOffset = uint64(stackProof.pops[1]); +// uint64 length = uint64(stackProof.pops[2]); +// +// uint64 cost = GasTable.gasCopy(stateProof.memSize, memOffset, length); +// if (stateProof.gas < cost) { +// VerifierHelper.verifyRevertByError(offset, stateProof, encoded); +// return; +// } +// stateProof.gas -= cost; +// +// { +// bytes memory readContent; +// (offset, readContent) = MemoryLib.decodeAndVerifyMemoryLikeReadProofNoAppend( +// stateProof.returnDataRoot, stateProof.returnDataSize, encoded, offset, returnOffset, length +// ); +// +// bytes memory writeContent; +// (offset, writeContent) = +// MemoryLib.decodeAndVerifyMemoryWriteProof(stateProof, encoded, offset, memOffset, length); +// +// require(readContent.equal(writeContent), "Inconsistent Copy"); +// } +// +// stateProof.pc += 1; +// stateProof.stackHash = stackProof.stackHashAfterPops; +// } +// +// function verifyOpMLOAD(uint64 offset, OneStepProof.StateProof memory stateProof, bytes calldata encoded) +// internal +// pure +// { +// if (stateProof.stackSize < 1) { +// VerifierHelper.verifyRevertByError(offset, stateProof, encoded); +// return; +// } +// OneStepProof.StackProof memory stackProof; +// (offset, stackProof) = VerifierHelper.decodeAndVerifyStackProof(stateProof, 1, offset, encoded); +// +// uint64 cost = Params.G_VERYLOW; +// if (stateProof.gas < cost) { +// VerifierHelper.verifyRevertByError(offset, stateProof, encoded); +// return; +// } +// stateProof.gas -= cost; +// +// uint64 memOffset = uint64(stackProof.pops[0]); +// bytes memory readContent; +// (offset, readContent) = MemoryLib.decodeAndVerifyMemoryReadProof(stateProof, encoded, offset, memOffset, 32); +// +// bytes32 result = readContent.toBytes32(0); +// stateProof.stackHash = keccak256(abi.encodePacked(stackProof.stackHashAfterPops, result)); +// stateProof.pc += 1; +// } +// +// function verifyOpMSTORE(uint64 offset, OneStepProof.StateProof memory stateProof, bytes calldata encoded) +// internal +// pure +// { +// if (stateProof.stackSize < 2) { +// VerifierHelper.verifyRevertByError(offset, stateProof, encoded); +// return; +// } +// OneStepProof.StackProof memory stackProof; +// (offset, stackProof) = VerifierHelper.decodeAndVerifyStackProof(stateProof, 2, offset, encoded); +// +// uint64 cost = Params.G_VERYLOW; +// if (stateProof.gas < cost) { +// VerifierHelper.verifyRevertByError(offset, stateProof, encoded); +// return; +// } +// stateProof.gas -= cost; +// +// uint64 memOffset = uint64(stackProof.pops[0]); +// bytes32 value = bytes32(stackProof.pops[1]); +// bytes memory writeContent; +// if (stateProof.memSize == 0) { +// stateProof.memSize = (memOffset + 32 + 31) / 32 * 32; +// writeContent = abi.encodePacked(new bytes(memOffset), value); +// stateProof.memRoot = MemoryLib.getMemoryRoot(writeContent); +// } else { +// (offset, writeContent) = +// MemoryLib.decodeAndVerifyMemoryWriteProof(stateProof, encoded, offset, memOffset, 32); +// require(writeContent.toBytes32(0) == value, "Bad MemoryProof"); +// } +// stateProof.stackHash = stackProof.stackHashAfterPops; +// stateProof.pc += 1; +// } +// +// function verifyOpMSTORE8(uint64 offset, OneStepProof.StateProof memory stateProof, bytes calldata encoded) +// internal +// pure +// { +// if (stateProof.stackSize < 2) { +// VerifierHelper.verifyRevertByError(offset, stateProof, encoded); +// return; +// } +// OneStepProof.StackProof memory stackProof; +// (offset, stackProof) = VerifierHelper.decodeAndVerifyStackProof(stateProof, 2, offset, encoded); +// +// uint64 cost = Params.G_VERYLOW; +// if (stateProof.gas < cost) { +// VerifierHelper.verifyRevertByError(offset, stateProof, encoded); +// return; +// } +// stateProof.gas -= cost; +// +// uint64 memOffset = uint64(stackProof.pops[0]); +// uint8 value = uint8(stackProof.pops[1]); +// bytes memory writeContent; +// if (stateProof.memSize == 0) { +// stateProof.memSize = (memOffset + 1 + 31) / 32 * 32; +// writeContent = abi.encodePacked(new bytes(memOffset), value); +// stateProof.memRoot = MemoryLib.getMemoryRoot(writeContent); +// } else { +// (offset, writeContent) = +// MemoryLib.decodeAndVerifyMemoryWriteProof(stateProof, encoded, offset, memOffset, 1); +// require(writeContent.toUint8(0) == value, "Bad MemoryProof"); +// } +// stateProof.stackHash = stackProof.stackHashAfterPops; +// stateProof.pc += 1; +// } +// +// function verifyLogOpCode(uint64 offset, OneStepProof.StateProof memory stateProof, bytes calldata encoded) +// internal +// pure +// { +// uint8 topicNum = stateProof.opCode - 0xa0; +// if (stateProof.stackSize < 2 + topicNum) { +// VerifierHelper.verifyRevertByError(offset, stateProof, encoded); +// return; +// } +// OneStepProof.StackProof memory stackProof; +// (offset, stackProof) = VerifierHelper.decodeAndVerifyStackProof(stateProof, 2 + topicNum, offset, encoded); +// +// uint64 memOffset = uint64(stackProof.pops[0]); +// uint64 length = uint64(stackProof.pops[1]); +// uint64 cost = GasTable.gasLog(stateProof.memSize, memOffset, length, topicNum); +// if (stateProof.gas < cost) { +// VerifierHelper.verifyRevertByError(offset, stateProof, encoded); +// return; +// } +// stateProof.gas -= cost; +// +// bytes memory readContent; +// (offset, readContent) = MemoryLib.decodeAndVerifyMemoryReadProof(stateProof, encoded, offset, memOffset, length); +// +// OneStepProof.LogProof memory logProof; +// (offset, logProof) = OneStepProof.decodeLogProof(encoded, offset); +// require(logProof.hashLogProof() == stateProof.logAcc, "Bad LogProof"); +// +// stateProof.logAcc = +// VerifierHelper.updateAndHashLogProof(logProof, stateProof.contractAddress, stackProof.pops, readContent); +// stateProof.pc += 1; +// stateProof.stackHash = stackProof.stackHashAfterPops; +// } +} diff --git a/packages/contracts/contracts/L1/fraud-proof/verifier/subverifiers/StackOpVerifier.sol b/packages/contracts/contracts/L1/fraud-proof/verifier/subverifiers/StackOpVerifier.sol new file mode 100644 index 000000000..1a8533ae4 --- /dev/null +++ b/packages/contracts/contracts/L1/fraud-proof/verifier/subverifiers/StackOpVerifier.sol @@ -0,0 +1,710 @@ +// SPDX-License-Identifier: Apache-2.0 + +/* + * Copyright 2022, Specular contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +pragma solidity ^0.8.0; + +import "../../libraries/BytesLib.sol"; +import "../IVerifier.sol"; +import "../libraries/VerificationContext.sol"; +import "../libraries/OneStepProof.sol"; +import "../libraries/Params.sol"; +import "../libraries/GasTable.sol"; +import "../libraries/VerifierHelper.sol"; + +contract StackOpVerifier is IVerifier { + using BytesLib for bytes; + using VerificationContext for VerificationContext.Context; + using OneStepProof for OneStepProof.CodeProof; + + function verifyOneStepProof(VerificationContext.Context memory ctx, bytes32 currStateHash, bytes calldata encoded) + external + pure + override + returns (bytes32) + { + return OneStepProof.hashStateProof(executeOneStepProof(ctx, currStateHash, encoded)); + } + + function executeOneStepProof(VerificationContext.Context memory ctx, bytes32 currStateHash, bytes calldata encoded) + public + pure + returns (OneStepProof.StateProof memory) + { + uint64 offset = 0; + // Decode state proof + OneStepProof.StateProof memory stateProof; + (offset, stateProof) = OneStepProof.decodeStateProof(ctx, encoded, offset); + // Calculate the state hash from the submitted proof + bytes32 stateHashFromProof; + assembly { + let ptr := mload(0x40) + calldatacopy(ptr, encoded.offset, offset) + stateHashFromProof := keccak256(ptr, offset) + } + // Ensure the state proof is valid + require(stateHashFromProof == currStateHash, "Bad State Proof"); + + // Decode the code proof + OneStepProof.CodeProof memory codeProof; + (offset, codeProof) = OneStepProof.decodeCodeProof(encoded, offset); + + // Simulate EVM one-step execution based on the opcode + uint8 opCode = stateProof.opCode; + if (opCode == 0x01) { + // ADD + verifyBinaryOpCode(offset, stateProof, encoded); + } else if (opCode == 0x02) { + // MUL + verifyBinaryOpCode(offset, stateProof, encoded); + } else if (opCode == 0x03) { + // SUB + verifyBinaryOpCode(offset, stateProof, encoded); + } else if (opCode == 0x04) { + // DIV + verifyBinaryOpCode(offset, stateProof, encoded); + } else if (opCode == 0x05) { + // SDIV + verifyBinaryOpCode(offset, stateProof, encoded); + } else if (opCode == 0x06) { + // MOD + verifyBinaryOpCode(offset, stateProof, encoded); + } else if (opCode == 0x07) { + // SMOD + verifyBinaryOpCode(offset, stateProof, encoded); + } else if (opCode == 0x08) { + // ADDMOD + verifyTrinaryOpCode(offset, stateProof, encoded); + } else if (opCode == 0x09) { + // MULMOD + verifyTrinaryOpCode(offset, stateProof, encoded); + } else if (opCode == 0x0a) { + // EXP + verifyBinaryOpCode(offset, stateProof, encoded); + } else if (opCode == 0x0b) { + // SIGNEXTEND + verifyBinaryOpCode(offset, stateProof, encoded); + } else if (opCode == 0x10) { + // LT + verifyBinaryOpCode(offset, stateProof, encoded); + } else if (opCode == 0x11) { + // GT + verifyBinaryOpCode(offset, stateProof, encoded); + } else if (opCode == 0x12) { + // SLT + verifyBinaryOpCode(offset, stateProof, encoded); + } else if (opCode == 0x13) { + // SGT + verifyBinaryOpCode(offset, stateProof, encoded); + } else if (opCode == 0x14) { + // EQ + verifyBinaryOpCode(offset, stateProof, encoded); + } else if (opCode == 0x15) { + // ISZERO + verifyUnaryOpCode(offset, stateProof, encoded); + } else if (opCode == 0x16) { + // AND + verifyBinaryOpCode(offset, stateProof, encoded); + } else if (opCode == 0x17) { + // OR + verifyBinaryOpCode(offset, stateProof, encoded); + } else if (opCode == 0x18) { + // XOR + verifyBinaryOpCode(offset, stateProof, encoded); + } else if (opCode == 0x19) { + // NOT + verifyUnaryOpCode(offset, stateProof, encoded); + } else if (opCode == 0x1a) { + // BYTE + verifyBinaryOpCode(offset, stateProof, encoded); + } else if (opCode == 0x1b) { + // SHL + verifyBinaryOpCode(offset, stateProof, encoded); + } else if (opCode == 0x1c) { + // SHR + verifyBinaryOpCode(offset, stateProof, encoded); + } else if (opCode == 0x1d) { + // SAR + verifyBinaryOpCode(offset, stateProof, encoded); + } else if (opCode == 0x50) { + // POP + verifyOpPOP(offset, stateProof, encoded); + } else if (opCode == 0x56) { + // JUMP + verifyOpJUMP(offset, stateProof, encoded); + } else if (opCode == 0x57) { + // JUMPI + verifyOpJUMPI(offset, stateProof, encoded); + } else if (opCode == 0x58) { + // PC + verifyOpPC(offset, stateProof, encoded); + } else if (opCode == 0x59) { + // MSIZE + verifyOpMSIZE(offset, stateProof, encoded); + } else if (opCode == 0x5a) { + // GAS + verifyOpJUMPDEST(offset, stateProof, encoded); + } else if (opCode == 0x5b) { + // JUMPDEST + verifyOpJUMPDEST(offset, stateProof, encoded); + } else if (opCode >= 0x60 && opCode <= 0x7f) { + // PUSH + verifyPushOpCode(offset, stateProof, codeProof, encoded); + } else if (opCode >= 0x80 && opCode <= 0x8f) { + // DUP + verifyDupOpCode(offset, stateProof, encoded); + } else if (opCode >= 0x90 && opCode <= 0x9f) { + // SWAP + verifySwapOpCode(offset, stateProof, encoded); + } else { + revert("Unreachable"); + } + + // Obtain the opcode at new pc + if (stateProof.depth > 0) { + if (codeProof.size > uint256(stateProof.pc)) { + stateProof.opCode = codeProof.getOpCodeAt(encoded, stateProof.pc); + } else { + stateProof.opCode = 0x00; + } + } + // Return the state hash after one-step execution + return stateProof; + } + + function verifyStackOnlyOpcode( + OneStepProof.StateProof memory stateProof, + OneStepProof.StackProof memory stackProof, + uint256 push + ) internal pure { + // Simulate pushing the `push` element to the stack + bytes32 h = keccak256(abi.encodePacked(stackProof.stackHashAfterPops, push)); + stateProof.stackHash = h; + stateProof.stackSize += 1; + // Increment pc + stateProof.pc += 1; + } + + function verifyUnaryOpCode(uint64 offset, OneStepProof.StateProof memory stateProof, bytes calldata encoded) + internal + pure + { + if (stateProof.stackSize < 1) { + VerifierHelper.verifyRevertByError(offset, stateProof, encoded); + return; + } + // Decode StackProof + OneStepProof.StackProof memory stackProof; + (offset, stackProof) = VerifierHelper.decodeAndVerifyStackProof(stateProof, 1, offset, encoded); + + uint8 opCode = stateProof.opCode; + uint64 gasCost; + // Get the operand from stackProof + uint256 a = stackProof.pops[0]; + // Simulate the opcode execution, get result and gas cost + uint256 expected; + if (opCode == 0x15) { + assembly { + expected := iszero(a) + } + gasCost = Params.G_VERYLOW; + } else if (opCode == 0x19) { + assembly { + expected := not(a) + } + gasCost = Params.G_VERYLOW; + } else { + revert("Unreachable"); + } + // Consume gas cost + if (stateProof.gas < gasCost) { + VerifierHelper.verifyRevertByError(offset, stateProof, encoded); + return; + } + stateProof.gas -= gasCost; + // Simulate stack pop + stateProof.stackSize -= 1; + // Verify the stack proof and reconstruct the state after one-step execution + verifyStackOnlyOpcode(stateProof, stackProof, expected); + } + + function verifyBinaryOpCode(uint64 offset, OneStepProof.StateProof memory stateProof, bytes calldata encoded) + internal + pure + { + if (stateProof.stackSize < 2) { + VerifierHelper.verifyRevertByError(offset, stateProof, encoded); + return; + } + // Decode StackProof + OneStepProof.StackProof memory stackProof; + (offset, stackProof) = VerifierHelper.decodeAndVerifyStackProof(stateProof, 2, offset, encoded); + + uint8 opCode = stateProof.opCode; + uint64 gasCost; + // Get operands from stackProof + uint256 a = stackProof.pops[0]; + uint256 b = stackProof.pops[1]; + // Simulate the opcode execution, get result and gas cost + uint256 expected; + if (opCode == 0x01) { + assembly { + expected := add(a, b) + } + gasCost = Params.G_VERYLOW; + } else if (opCode == 0x02) { + assembly { + expected := mul(a, b) + } + gasCost = Params.G_LOW; + } else if (opCode == 0x03) { + assembly { + expected := sub(a, b) + } + gasCost = Params.G_VERYLOW; + } else if (opCode == 0x04) { + assembly { + expected := div(a, b) + } + gasCost = Params.G_LOW; + } else if (opCode == 0x05) { + assembly { + expected := sdiv(a, b) + } + gasCost = Params.G_LOW; + } else if (opCode == 0x06) { + assembly { + expected := mod(a, b) + } + gasCost = Params.G_LOW; + } else if (opCode == 0x07) { + assembly { + expected := smod(a, b) + } + gasCost = Params.G_LOW; + } else if (opCode == 0x0a) { + assembly { + expected := exp(a, b) + } + gasCost = GasTable.gasExp(b); + } else if (opCode == 0x0b) { + assembly { + expected := signextend(a, b) + } + gasCost = Params.G_LOW; + } else if (opCode == 0x10) { + assembly { + expected := lt(a, b) + } + gasCost = Params.G_VERYLOW; + } else if (opCode == 0x11) { + assembly { + expected := gt(a, b) + } + gasCost = Params.G_VERYLOW; + } else if (opCode == 0x12) { + assembly { + expected := slt(a, b) + } + gasCost = Params.G_VERYLOW; + } else if (opCode == 0x13) { + assembly { + expected := sgt(a, b) + } + gasCost = Params.G_VERYLOW; + } else if (opCode == 0x14) { + assembly { + expected := eq(a, b) + } + gasCost = Params.G_VERYLOW; + } else if (opCode == 0x16) { + assembly { + expected := and(a, b) + } + gasCost = Params.G_VERYLOW; + } else if (opCode == 0x17) { + assembly { + expected := or(a, b) + } + gasCost = Params.G_VERYLOW; + } else if (opCode == 0x18) { + assembly { + expected := xor(a, b) + } + gasCost = Params.G_VERYLOW; + } else if (opCode == 0x1a) { + assembly { + expected := byte(a, b) + } + gasCost = Params.G_VERYLOW; + } else if (opCode == 0x1b) { + assembly { + expected := shl(a, b) + } + gasCost = Params.G_VERYLOW; + } else if (opCode == 0x1c) { + assembly { + expected := shr(a, b) + } + gasCost = Params.G_VERYLOW; + } else if (opCode == 0x1d) { + assembly { + expected := sar(a, b) + } + gasCost = Params.G_VERYLOW; + } else { + revert("Unreachable"); + } + // Consume gas cost + if (stateProof.gas < gasCost) { + VerifierHelper.verifyRevertByError(offset, stateProof, encoded); + return; + } + stateProof.gas -= gasCost; + // Simulate stack pop + stateProof.stackSize -= 2; + // Verify the stack proof and reconstruct the state after one-step execution + verifyStackOnlyOpcode(stateProof, stackProof, expected); + } + + function verifyTrinaryOpCode(uint64 offset, OneStepProof.StateProof memory stateProof, bytes calldata encoded) + internal + pure + { + if (stateProof.stackSize < 3) { + VerifierHelper.verifyRevertByError(offset, stateProof, encoded); + return; + } + // Decode StackProof + OneStepProof.StackProof memory stackProof; + (offset, stackProof) = VerifierHelper.decodeAndVerifyStackProof(stateProof, 3, offset, encoded); + + uint8 opCode = stateProof.opCode; + uint64 gasCost; + // Get operands from stackProof + uint256 a = stackProof.pops[0]; + uint256 b = stackProof.pops[1]; + uint256 c = stackProof.pops[2]; + // Simulate the opcode execution, get result and gas cost + uint256 expected; + if (opCode == 0x08) { + assembly { + expected := addmod(a, b, c) + } + gasCost = Params.G_MID; + } else if (opCode == 0x09) { + assembly { + expected := mulmod(a, b, c) + } + gasCost = Params.G_MID; + } else { + revert("Unreachable"); + } + // Consume gas cost + if (stateProof.gas < gasCost) { + VerifierHelper.verifyRevertByError(offset, stateProof, encoded); + return; + } + stateProof.gas -= gasCost; + // Simulate stack pop + stateProof.stackSize -= 3; + // Verify the stack proof and reconstruct the state after one-step execution + verifyStackOnlyOpcode(stateProof, stackProof, expected); + } + + function verifyPushOpCode( + uint64 offset, + OneStepProof.StateProof memory stateProof, + OneStepProof.CodeProof memory codeProof, + bytes calldata encoded + ) internal pure { + if (stateProof.stackSize >= Params.STACK_LIMIT - 1) { + VerifierHelper.verifyRevertByError(offset, stateProof, encoded); + return; + } + uint8 opCode = stateProof.opCode; + // Get the number of bytes to push + uint8 pushBytes = opCode - 0x5f; + + // Slice out the push bytes from the bytecode + uint256 expected = 0; + // TODO: optimize this with assembly + for (uint64 i = 1; i <= pushBytes; i++) { + expected *= 256; + uint64 pushOffset = stateProof.pc + i; + if (pushOffset + 1 <= codeProof.size) { + expected += codeProof.getOpCodeAt(encoded, pushOffset); + } + } + // Simulate pushing the content to the stack + bytes32 h = keccak256(abi.encodePacked(stateProof.stackHash, expected)); + stateProof.stackHash = h; + stateProof.stackSize += 1; + + // Consume the gas + if (stateProof.gas < Params.G_VERYLOW) { + VerifierHelper.verifyRevertByError(offset, stateProof, encoded); + return; + } + stateProof.gas -= Params.G_VERYLOW; + // Skip the opcode and content, jump to the correct pc + stateProof.pc += 1 + pushBytes; + } + + function verifyDupOpCode(uint64 offset, OneStepProof.StateProof memory stateProof, bytes calldata encoded) + internal + pure + { + uint8 opCode = stateProof.opCode; + // Get the stack duplication position + uint8 dupPos = opCode - 0x80 + 1; + if (stateProof.stackSize >= Params.STACK_LIMIT - 1) { + VerifierHelper.verifyRevertByError(offset, stateProof, encoded); + return; + } + if (stateProof.stackSize < dupPos) { + VerifierHelper.verifyRevertByError(offset, stateProof, encoded); + return; + } + + // Decode the stack proof + OneStepProof.StackProof memory stackProof; + (offset, stackProof) = VerifierHelper.decodeAndVerifyStackProof(stateProof, dupPos, offset, encoded); + + // Simulate duplicating the stack content + // pops[0] is the element to be duplicated + bytes32 h = keccak256(abi.encodePacked(stateProof.stackHash, stackProof.pops[0])); + stateProof.stackHash = h; + stateProof.stackSize += 1; + + // Consume the gas + if (stateProof.gas < Params.G_VERYLOW) { + VerifierHelper.verifyRevertByError(offset, stateProof, encoded); + return; + } + stateProof.gas -= Params.G_VERYLOW; + // Increment the pc + stateProof.pc += 1; + } + + function verifySwapOpCode(uint64 offset, OneStepProof.StateProof memory stateProof, bytes calldata encoded) + internal + pure + { + uint8 opCode = stateProof.opCode; + // Get the stack swap position + uint8 swapPos = opCode - 0x90 + 2; + if (stateProof.stackSize >= Params.STACK_LIMIT - 1) { + VerifierHelper.verifyRevertByError(offset, stateProof, encoded); + return; + } + if (stateProof.stackSize < swapPos) { + VerifierHelper.verifyRevertByError(offset, stateProof, encoded); + return; + } + + // Decode the stack proof + OneStepProof.StackProof memory stackProof; + (offset, stackProof) = VerifierHelper.decodeAndVerifyStackProof(stateProof, swapPos, offset, encoded); + + // Simulate pushing the first swapped element + bytes32 h = keccak256(abi.encodePacked(stackProof.stackHashAfterPops, stackProof.pops[swapPos - 1])); + // Simulate pushing the intermediate unchanged elements + for (uint8 i = swapPos - 1; i > 1; i--) { + h = keccak256(abi.encodePacked(h, stackProof.pops[i - 1])); + } + // Simulate pushing the last swapped element + h = keccak256(abi.encodePacked(h, stackProof.pops[0])); + stateProof.stackHash = h; + + // Consume the gas + if (stateProof.gas < Params.G_VERYLOW) { + VerifierHelper.verifyRevertByError(offset, stateProof, encoded); + return; + } + stateProof.gas -= Params.G_VERYLOW; + // Increment the pc + stateProof.pc += 1; + } + + function verifyOpPOP(uint64 offset, OneStepProof.StateProof memory stateProof, bytes calldata encoded) + internal + pure + { + if (stateProof.stackSize < 1) { + VerifierHelper.verifyRevertByError(offset, stateProof, encoded); + return; + } + + // Decode the stack proof + OneStepProof.StackProof memory stackProof; + (offset, stackProof) = VerifierHelper.decodeAndVerifyStackProof(stateProof, 1, offset, encoded); + + // `stackHashAfterPops` is the exact stack hash in the next step state + stateProof.stackHash = stackProof.stackHashAfterPops; + stateProof.stackSize -= 1; + + // Consume the gas + if (stateProof.gas < Params.G_BASE) { + VerifierHelper.verifyRevertByError(offset, stateProof, encoded); + return; + } + stateProof.gas -= Params.G_BASE; + // Increment the pc + stateProof.pc += 1; + } + + function verifyOpJUMP(uint64 offset, OneStepProof.StateProof memory stateProof, bytes calldata encoded) + internal + pure + { + if (stateProof.stackSize < 1) { + VerifierHelper.verifyRevertByError(offset, stateProof, encoded); + return; + } + // Decode the stack proof + OneStepProof.StackProof memory stackProof; + (offset, stackProof) = VerifierHelper.decodeAndVerifyStackProof(stateProof, 1, offset, encoded); + + // `stackHashAfterPops` is the exact stack hash in the next step state + stateProof.stackHash = stackProof.stackHashAfterPops; + stateProof.stackSize -= 1; + + // Consume the gas + if (stateProof.gas < Params.G_MID) { + VerifierHelper.verifyRevertByError(offset, stateProof, encoded); + return; + } + stateProof.gas -= Params.G_MID; + // Jump the pc according to the popped element from the stack + uint64 nextPc = uint64(stackProof.pops[0]); + stateProof.pc = nextPc; + } + + function verifyOpJUMPI(uint64 offset, OneStepProof.StateProof memory stateProof, bytes calldata encoded) + internal + pure + { + if (stateProof.stackSize < 2) { + VerifierHelper.verifyRevertByError(offset, stateProof, encoded); + return; + } + + // Decode the stack proof + OneStepProof.StackProof memory stackProof; + (offset, stackProof) = VerifierHelper.decodeAndVerifyStackProof(stateProof, 2, offset, encoded); + + // `stackHashAfterPops` is the exact stack hash in the next step state + stateProof.stackHash = stackProof.stackHashAfterPops; + stateProof.stackSize -= 2; + + // Calculate the correct next pc + uint64 nextPc = stateProof.pc + 1; + if (stackProof.pops[0] != 0) { + nextPc = uint64(stackProof.pops[1]); + } + + // Consume the gas + if (stateProof.gas < Params.G_HIGH) { + VerifierHelper.verifyRevertByError(offset, stateProof, encoded); + return; + } + stateProof.gas -= Params.G_HIGH; + // Jump the pc + stateProof.pc = nextPc; + } + + function verifyOpPC(uint64 offset, OneStepProof.StateProof memory stateProof, bytes calldata encoded) + internal + pure + { + if (stateProof.stackSize >= Params.STACK_LIMIT - 1) { + VerifierHelper.verifyRevertByError(offset, stateProof, encoded); + return; + } + + // Consume the gas + if (stateProof.gas < Params.G_BASE) { + VerifierHelper.verifyRevertByError(offset, stateProof, encoded); + return; + } + stateProof.gas -= Params.G_BASE; + // Simulate pushing `pc` to the stack + stateProof.stackHash = keccak256(abi.encodePacked(stateProof.stackHash, uint256(stateProof.pc))); + stateProof.stackSize += 1; + // Increment the pc + stateProof.pc += 1; + } + + function verifyOpMSIZE(uint64 offset, OneStepProof.StateProof memory stateProof, bytes calldata encoded) + internal + pure + { + if (stateProof.stackSize >= Params.STACK_LIMIT - 1) { + VerifierHelper.verifyRevertByError(offset, stateProof, encoded); + return; + } + + // Consume the gas + if (stateProof.gas < Params.G_BASE) { + VerifierHelper.verifyRevertByError(offset, stateProof, encoded); + return; + } + stateProof.gas -= Params.G_BASE; + // Simulate pushing `msize` to the stack + stateProof.stackHash = keccak256(abi.encodePacked(stateProof.stackHash, uint256(stateProof.memSize))); + stateProof.stackSize += 1; + // Increment the pc + stateProof.pc += 1; + } + + function verifyOpGAS(uint64 offset, OneStepProof.StateProof memory stateProof, bytes calldata encoded) + internal + pure + { + if (stateProof.stackSize >= Params.STACK_LIMIT - 1) { + VerifierHelper.verifyRevertByError(offset, stateProof, encoded); + return; + } + + // Consume the gas + if (stateProof.gas < Params.G_BASE) { + VerifierHelper.verifyRevertByError(offset, stateProof, encoded); + return; + } + stateProof.gas -= Params.G_BASE; + // Simulate pushing `gas` to the stack + stateProof.stackHash = keccak256(abi.encodePacked(stateProof.stackHash, uint256(stateProof.gas))); + stateProof.stackSize += 1; + // Increment the pc + stateProof.pc += 1; + } + + function verifyOpJUMPDEST(uint64 offset, OneStepProof.StateProof memory stateProof, bytes calldata encoded) + internal + pure + { + // Consume the gas + if (stateProof.gas < Params.G_JUMPDEST) { + VerifierHelper.verifyRevertByError(offset, stateProof, encoded); + return; + } + stateProof.gas -= Params.G_JUMPDEST; + // Increment the pc + stateProof.pc += 1; + } +} diff --git a/packages/contracts/contracts/L1/fraud-proof/verifier/subverifiers/StorageOpVerifier.sol b/packages/contracts/contracts/L1/fraud-proof/verifier/subverifiers/StorageOpVerifier.sol new file mode 100644 index 000000000..b90872db9 --- /dev/null +++ b/packages/contracts/contracts/L1/fraud-proof/verifier/subverifiers/StorageOpVerifier.sol @@ -0,0 +1,322 @@ +// SPDX-License-Identifier: Apache-2.0 + +/* + * Copyright 2022, Specular contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +pragma solidity ^0.8.0; + +//import "../../libraries/BytesLib.sol"; +//import "../../libraries/MPT.sol"; +//import "../IVerifier.sol"; +//import "../libraries/VerificationContext.sol"; +//import "../libraries/OneStepProof.sol"; +//import "../libraries/Params.sol"; +//import "../libraries/GasTable.sol"; +//import "../libraries/VerifierHelper.sol"; +//import "../libraries/EVMTypesLib.sol"; + +contract StorageOpVerifier { +//contract StorageOpVerifier is IVerifier { +// using BytesLib for bytes; +// using RLPReader for bytes; +// using RLPReader for RLPReader.RLPItem; +// using RLPReader for RLPReader.Iterator; +// using VerificationContext for VerificationContext.Context; +// using OneStepProof for OneStepProof.CodeProof; +// using OneStepProof for EVMTypesLib.Account; +// +// function verifyOneStepProof(VerificationContext.Context memory ctx, bytes32 currStateHash, bytes calldata encoded) +// external +// pure +// override +// returns (bytes32) +// { +// return OneStepProof.hashStateProof(executeOneStepProof(ctx, currStateHash, encoded)); +// } +// +// function executeOneStepProof(VerificationContext.Context memory ctx, bytes32 currStateHash, bytes calldata encoded) +// public +// pure +// returns (OneStepProof.StateProof memory) +// { +// uint64 offset = 0; +// // Decode state proof +// OneStepProof.StateProof memory stateProof; +// (offset, stateProof) = OneStepProof.decodeStateProof(ctx, encoded, offset); +// // Calculate the state hash from the submitted proof +// bytes32 stateHashFromProof; +// assembly { +// let ptr := mload(0x40) +// calldatacopy(ptr, encoded.offset, offset) +// stateHashFromProof := keccak256(ptr, offset) +// } +// // Ensure the state proof is valid +// require(stateHashFromProof == currStateHash, "Bad State Proof"); +// +// // Decode the code proof +// OneStepProof.CodeProof memory codeProof; +// (offset, codeProof) = OneStepProof.decodeCodeProof(encoded, offset); +// +// // Simulate EVM one-step execution based on the opcode +// uint8 opCode = stateProof.opCode; +// if (opCode == 0x31) { +// // BALANCE +// verifyOpBALANCE(offset, stateProof, encoded); +// } else if (opCode == 0x3b) { +// // EXTCODESIZE +// verifyOpEXTCODESIZE(offset, stateProof, encoded); +// } else if (opCode == 0x3c) { +// // EXTCODECOPY +// verifyOpEXTCODECOPY(offset, stateProof, encoded); +// } else if (opCode == 0x3f) { +// // EXTCODEHASH +// verifyOpEXTCODEHASH(offset, stateProof, encoded); +// } else if (opCode == 0x47) { +// // SELFBALANCE +// verifyOpSELFBALANCE(offset, stateProof, encoded); +// } else if (opCode == 0x54) { +// // SLOAD +// verifyOpSLOAD(offset, stateProof, encoded); +// } else if (opCode == 0x55) { +// // SSTORE +// verifyOpSSTORE(offset, stateProof, encoded); +// } else { +// revert("Unreachable"); +// } +// +// // Obtain the opcode at new pc +// if (stateProof.depth > 0) { +// if (codeProof.size > uint256(stateProof.pc)) { +// stateProof.opCode = codeProof.getOpCodeAt(encoded, stateProof.pc); +// } else { +// stateProof.opCode = 0x00; +// } +// } +// // Return the state hash after one-step execution +// return stateProof; +// } +// +// function verifyOpBALANCE(uint64 offset, OneStepProof.StateProof memory stateProof, bytes calldata encoded) +// internal +// pure +// { +// if (stateProof.stackSize < 1) { +// VerifierHelper.verifyRevertByError(offset, stateProof, encoded); +// return; +// } +// OneStepProof.StackProof memory stackProof; +// (offset, stackProof) = VerifierHelper.decodeAndVerifyStackProof(stateProof, 1, offset, encoded); +// +// uint64 cost = Params.G_BALANCE; +// if (stateProof.gas < cost) { +// VerifierHelper.verifyRevertByError(offset, stateProof, encoded); +// } +// stateProof.gas -= cost; +// +// OneStepProof.RLPProof memory accountProof; +// (offset, accountProof) = OneStepProof.decodeRLPProof(encoded, offset); +// bytes32 addressHash = keccak256(abi.encodePacked(address(uint160(stackProof.pops[0])))); +// bytes memory encodedAccount = MPT.extractProofValue( +// stateProof.globalStateRoot, abi.encodePacked(addressHash), accountProof.proof.toList() +// ); +// EVMTypesLib.Account memory account = EVMTypesLib.decodeAccount(encodedAccount.toRlpItem()); +// +// stateProof.pc += 1; +// stateProof.stackHash = keccak256(abi.encodePacked(stackProof.stackHashAfterPops, account.balance)); +// } +// +// function verifyOpEXTCODESIZE(uint64 offset, OneStepProof.StateProof memory stateProof, bytes calldata encoded) +// internal +// pure +// { +// if (stateProof.stackSize < 1) { +// VerifierHelper.verifyRevertByError(offset, stateProof, encoded); +// return; +// } +// OneStepProof.StackProof memory stackProof; +// (offset, stackProof) = VerifierHelper.decodeAndVerifyStackProof(stateProof, 1, offset, encoded); +// +// uint64 cost = Params.G_EXTCODE; +// if (stateProof.gas < cost) { +// VerifierHelper.verifyRevertByError(offset, stateProof, encoded); +// } +// stateProof.gas -= cost; +// +// OneStepProof.RLPProof memory accountProof; +// (offset, accountProof) = OneStepProof.decodeRLPProof(encoded, offset); +// bytes32 addressHash = keccak256(abi.encodePacked(address(uint160(stackProof.pops[0])))); +// bytes memory encodedAccount = MPT.extractProofValue( +// stateProof.globalStateRoot, abi.encodePacked(addressHash), accountProof.proof.toList() +// ); +// EVMTypesLib.Account memory account = EVMTypesLib.decodeAccount(encodedAccount.toRlpItem()); +// +// OneStepProof.CodeProof memory codeProof; +// (offset, codeProof) = OneStepProof.decodeCodeProof(encoded, offset); +// +// require(codeProof.hashCodeProof(encoded) == account.codeHash, "Bad Code Proof"); +// +// stateProof.pc += 1; +// stateProof.stackHash = keccak256(abi.encodePacked(stackProof.stackHashAfterPops, codeProof.size)); +// } +// +// function verifyOpEXTCODECOPY(uint64 offset, OneStepProof.StateProof memory stateProof, bytes calldata encoded) +// internal +// pure +// { +// if (stateProof.stackSize < 4) { +// VerifierHelper.verifyRevertByError(offset, stateProof, encoded); +// return; +// } +// OneStepProof.StackProof memory stackProof; +// (offset, stackProof) = VerifierHelper.decodeAndVerifyStackProof(stateProof, 4, offset, encoded); +// +// { +// uint64 cost = +// GasTable.gasExtCopy(stateProof.memSize, uint64(stackProof.pops[1]), uint64(stackProof.pops[3])); +// if (stateProof.gas < cost) { +// VerifierHelper.verifyRevertByError(offset, stateProof, encoded); +// } +// stateProof.gas -= cost; +// } +// +// EVMTypesLib.Account memory account; +// { +// OneStepProof.RLPProof memory accountProof; +// (offset, accountProof) = OneStepProof.decodeRLPProof(encoded, offset); +// bytes32 addressHash = keccak256(abi.encodePacked(address(uint160(stackProof.pops[0])))); +// bytes memory encodedAccount = MPT.extractProofValue( +// stateProof.globalStateRoot, abi.encodePacked(addressHash), accountProof.proof.toList() +// ); +// account = EVMTypesLib.decodeAccount(encodedAccount.toRlpItem()); +// } +// +// OneStepProof.CodeProof memory codeProof; +// (offset, codeProof) = OneStepProof.decodeCodeProof(encoded, offset); +// +// require(codeProof.hashCodeProof(encoded) == account.codeHash, "Bad Code Proof"); +// { +// bytes memory readContent = +// codeProof.getCodeSlice(encoded, uint64(stackProof.pops[2]), uint64(stackProof.pops[3])); +// bytes memory writeContent; +// (offset, writeContent) = MemoryLib.decodeAndVerifyMemoryWriteProof( +// stateProof, encoded, offset, uint64(stackProof.pops[1]), uint64(stackProof.pops[3]) +// ); +// +// require(readContent.equal(writeContent), "Inconsistent Copy"); +// } +// +// stateProof.pc += 1; +// stateProof.stackSize -= 4; +// stateProof.stackHash = stackProof.stackHashAfterPops; +// } +// +// function verifyOpEXTCODEHASH(uint64 offset, OneStepProof.StateProof memory stateProof, bytes calldata encoded) +// internal +// pure +// { +// if (stateProof.stackSize < 1) { +// VerifierHelper.verifyRevertByError(offset, stateProof, encoded); +// return; +// } +// OneStepProof.StackProof memory stackProof; +// (offset, stackProof) = VerifierHelper.decodeAndVerifyStackProof(stateProof, 1, offset, encoded); +// +// uint64 cost = Params.G_EXTCODE; +// if (stateProof.gas < cost) { +// VerifierHelper.verifyRevertByError(offset, stateProof, encoded); +// } +// stateProof.gas -= cost; +// +// OneStepProof.RLPProof memory accountProof; +// (offset, accountProof) = OneStepProof.decodeRLPProof(encoded, offset); +// bytes32 addressHash = keccak256(abi.encodePacked(address(uint160(stackProof.pops[0])))); +// bytes memory encodedAccount = MPT.extractProofValue( +// stateProof.globalStateRoot, abi.encodePacked(addressHash), accountProof.proof.toList() +// ); +// EVMTypesLib.Account memory account = EVMTypesLib.decodeAccount(encodedAccount.toRlpItem()); +// +// stateProof.pc += 1; +// stateProof.stackHash = keccak256(abi.encodePacked(stackProof.stackHashAfterPops, account.codeHash)); +// } +// +// function verifyOpSELFBALANCE(uint64 offset, OneStepProof.StateProof memory stateProof, bytes calldata encoded) +// internal +// pure +// { +// if (stateProof.stackSize >= Params.STACK_LIMIT - 1) { +// VerifierHelper.verifyRevertByError(offset, stateProof, encoded); +// return; +// } +// +// uint64 cost = Params.G_LOW; +// if (stateProof.gas < cost) { +// VerifierHelper.verifyRevertByError(offset, stateProof, encoded); +// } +// stateProof.gas -= cost; +// +// OneStepProof.RLPProof memory accountProof; +// (offset, accountProof) = OneStepProof.decodeRLPProof(encoded, offset); +// bytes32 addressHash = keccak256(abi.encodePacked(stateProof.contractAddress)); +// bytes memory encodedAccount = MPT.extractProofValue( +// stateProof.globalStateRoot, abi.encodePacked(addressHash), accountProof.proof.toList() +// ); +// EVMTypesLib.Account memory account = EVMTypesLib.decodeAccount(encodedAccount.toRlpItem()); +// +// stateProof.pc += 1; +// stateProof.stackSize += 1; +// stateProof.stackHash = keccak256(abi.encodePacked(stateProof.stackHash, account.codeHash)); +// } +// +// function verifyOpSLOAD(uint64 offset, OneStepProof.StateProof memory stateProof, bytes calldata encoded) +// internal +// pure +// { +// if (stateProof.stackSize < 1) { +// VerifierHelper.verifyRevertByError(offset, stateProof, encoded); +// return; +// } +// OneStepProof.StackProof memory stackProof; +// (offset, stackProof) = VerifierHelper.decodeAndVerifyStackProof(stateProof, 1, offset, encoded); +// +// uint64 cost = Params.G_LOW; +// if (stateProof.gas < cost) { +// VerifierHelper.verifyRevertByError(offset, stateProof, encoded); +// } +// stateProof.gas -= cost; +// +// OneStepProof.RLPProof memory accountProof; +// (offset, accountProof) = OneStepProof.decodeRLPProof(encoded, offset); +// bytes32 addressHash = keccak256(abi.encodePacked(stateProof.contractAddress)); +// bytes memory encodedAccount = MPT.extractProofValue( +// stateProof.globalStateRoot, abi.encodePacked(addressHash), accountProof.proof.toList() +// ); +// EVMTypesLib.Account memory account = EVMTypesLib.decodeAccount(encodedAccount.toRlpItem()); +// +// OneStepProof.RLPProof memory storageProof; +// (offset, storageProof) = OneStepProof.decodeRLPProof(encoded, offset); +// bytes memory value = MPT.extractProofValue( +// account.storageRoot, abi.encodePacked(bytes32(stackProof.pops[0])), storageProof.proof.toList() +// ); +// +// stateProof.pc += 1; +// stateProof.stackHash = keccak256(abi.encodePacked(stateProof.stackHash, value.toBytes32Pad(0))); +// } +// +// function verifyOpSSTORE(uint64 offset, OneStepProof.StateProof memory stateProof, bytes calldata encoded) +// internal +// pure +// {} +} diff --git a/packages/contracts/contracts/L1/fraud-proof/verifier/test-driver/VerifierTestDriver.sol b/packages/contracts/contracts/L1/fraud-proof/verifier/test-driver/VerifierTestDriver.sol new file mode 100644 index 000000000..e00687aa4 --- /dev/null +++ b/packages/contracts/contracts/L1/fraud-proof/verifier/test-driver/VerifierTestDriver.sol @@ -0,0 +1,99 @@ +// SPDX-License-Identifier: Apache-2.0 + +/* + * Copyright 2022, Specular contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +pragma solidity ^0.8.0; + +import "../IVerifier.sol"; +import "../libraries/Params.sol"; +import "../libraries/EVMTypesLib.sol"; +import "../libraries/VerificationContext.sol"; + +contract VerifierTestDriver { + IVerifier blockInitiationVerifier; + IVerifier blockFinalizationVerifier; + IVerifier interTxVerifier; + IVerifier stackOpVerifier; + IVerifier environmentalOpVerifier; + IVerifier memoryOpVerifier; + IVerifier storageOpVerifier; + IVerifier callOpVerifier; + IVerifier invalidOpVerifier; + + constructor( + address _blockInitiationVerifier, + address _blockFinalizationVerifier, + address _interTxVerifier, + address _stackOpVerifier, + address _environmentalOpVerifier, + address _memoryOpVerifier, + address _storageOpVerifier, + address _callOpVerifier, + address _invalidOpVerifier + ) { + blockInitiationVerifier = IVerifier(_blockInitiationVerifier); + blockFinalizationVerifier = IVerifier(_blockFinalizationVerifier); + interTxVerifier = IVerifier(_interTxVerifier); + stackOpVerifier = IVerifier(_stackOpVerifier); + environmentalOpVerifier = IVerifier(_environmentalOpVerifier); + memoryOpVerifier = IVerifier(_memoryOpVerifier); + storageOpVerifier = IVerifier(_storageOpVerifier); + callOpVerifier = IVerifier(_callOpVerifier); + invalidOpVerifier = IVerifier(_invalidOpVerifier); + } + + function getVerifier(uint8 verifier) private view returns (IVerifier) { + if (verifier == Params.V_BLOCK_INIT) { + return blockInitiationVerifier; + } else if (verifier == Params.V_BLOCK_FINAL) { + return blockFinalizationVerifier; + } else if (verifier == Params.V_INTER_TX) { + return interTxVerifier; + } else if (verifier == Params.V_STACK_OP) { + return stackOpVerifier; + } else if (verifier == Params.V_ENVIRONMENTAL_OP) { + return environmentalOpVerifier; + } else if (verifier == Params.V_MEMORY_OP) { + return memoryOpVerifier; + } else if (verifier == Params.V_STORAGE_OP) { + return storageOpVerifier; + } else if (verifier == Params.V_CALL_OP) { + return callOpVerifier; + } else if (verifier == Params.V_INVALID_OP) { + return invalidOpVerifier; + } else { + revert("unreachable"); + } + } + + function verifyProof( + address sequencerAddress, + uint256 timestamp, + uint256 number, + address origin, + bytes32 txHash, + EVMTypesLib.Transaction memory transaction, + uint8 verifier, + bytes32 currStateHash, + bytes calldata proof + ) external view returns (bytes32) { + VerificationContext.Context memory ctx = + VerificationContext.Context(sequencerAddress, timestamp, number, origin, transaction, bytes32(0), txHash); + bytes32 res = getVerifier(verifier).verifyOneStepProof(ctx, currStateHash, proof); + return res; + } +} diff --git a/packages/contracts/contracts/L1/local/bit.abi b/packages/contracts/contracts/L1/local/bit.abi new file mode 100644 index 000000000..2ac13d6c9 --- /dev/null +++ b/packages/contracts/contracts/L1/local/bit.abi @@ -0,0 +1,2 @@ +[{"inputs":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"}] + diff --git a/packages/contracts/contracts/L1/local/bit.bin b/packages/contracts/contracts/L1/local/bit.bin new file mode 100644 index 000000000..59a1075b4 --- /dev/null +++ b/packages/contracts/contracts/L1/local/bit.bin @@ -0,0 +1,2 @@ +60806040523480156200001157600080fd5b506040516200197038038062001970833981810160405281019062000037919062000204565b818181600390816200004a9190620004d4565b5080600490816200005c9190620004d4565b5050505050620005bb565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b620000d08262000085565b810181811067ffffffffffffffff82111715620000f257620000f162000096565b5b80604052505050565b60006200010762000067565b9050620001158282620000c5565b919050565b600067ffffffffffffffff82111562000138576200013762000096565b5b620001438262000085565b9050602081019050919050565b60005b838110156200017057808201518184015260208101905062000153565b8381111562000180576000848401525b50505050565b60006200019d62000197846200011a565b620000fb565b905082815260208101848484011115620001bc57620001bb62000080565b5b620001c984828562000150565b509392505050565b600082601f830112620001e957620001e86200007b565b5b8151620001fb84826020860162000186565b91505092915050565b600080604083850312156200021e576200021d62000071565b5b600083015167ffffffffffffffff8111156200023f576200023e62000076565b5b6200024d85828601620001d1565b925050602083015167ffffffffffffffff81111562000271576200027062000076565b5b6200027f85828601620001d1565b9150509250929050565b600081519050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680620002dc57607f821691505b602082108103620002f257620002f162000294565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b6000600883026200035c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff826200031d565b6200036886836200031d565b95508019841693508086168417925050509392505050565b6000819050919050565b6000819050919050565b6000620003b5620003af620003a98462000380565b6200038a565b62000380565b9050919050565b6000819050919050565b620003d18362000394565b620003e9620003e082620003bc565b8484546200032a565b825550505050565b600090565b62000400620003f1565b6200040d818484620003c6565b505050565b5b81811015620004355762000429600082620003f6565b60018101905062000413565b5050565b601f82111562000484576200044e81620002f8565b62000459846200030d565b8101602085101562000469578190505b6200048162000478856200030d565b83018262000412565b50505b505050565b600082821c905092915050565b6000620004a96000198460080262000489565b1980831691505092915050565b6000620004c4838362000496565b9150826002028217905092915050565b620004df8262000289565b67ffffffffffffffff811115620004fb57620004fa62000096565b5b620005078254620002c3565b6200051482828562000439565b600060209050601f8311600181146200054c576000841562000537578287015190505b620005438582620004b6565b865550620005b3565b601f1984166200055c86620002f8565b60005b8281101562000586578489015182556001820191506020850194506020810190506200055f565b86831015620005a65784890151620005a2601f89168262000496565b8355505b6001600288020188555050505b505050505050565b6113a580620005cb6000396000f3fe608060405234801561001057600080fd5b50600436106100a95760003560e01c80633950935111610071578063395093511461016857806370a082311461019857806395d89b41146101c8578063a457c2d7146101e6578063a9059cbb14610216578063dd62ed3e14610246576100a9565b806306fdde03146100ae578063095ea7b3146100cc57806318160ddd146100fc57806323b872dd1461011a578063313ce5671461014a575b600080fd5b6100b6610276565b6040516100c39190610c3a565b60405180910390f35b6100e660048036038101906100e19190610cf5565b610308565b6040516100f39190610d50565b60405180910390f35b610104610326565b6040516101119190610d7a565b60405180910390f35b610134600480360381019061012f9190610d95565b610330565b6040516101419190610d50565b60405180910390f35b610152610428565b60405161015f9190610e04565b60405180910390f35b610182600480360381019061017d9190610cf5565b610431565b60405161018f9190610d50565b60405180910390f35b6101b260048036038101906101ad9190610e1f565b6104dd565b6040516101bf9190610d7a565b60405180910390f35b6101d0610525565b6040516101dd9190610c3a565b60405180910390f35b61020060048036038101906101fb9190610cf5565b6105b7565b60405161020d9190610d50565b60405180910390f35b610230600480360381019061022b9190610cf5565b6106a2565b60405161023d9190610d50565b60405180910390f35b610260600480360381019061025b9190610e4c565b6106c0565b60405161026d9190610d7a565b60405180910390f35b60606003805461028590610ebb565b80601f01602080910402602001604051908101604052809291908181526020018280546102b190610ebb565b80156102fe5780601f106102d3576101008083540402835291602001916102fe565b820191906000526020600020905b8154815290600101906020018083116102e157829003601f168201915b5050505050905090565b600061031c610315610747565b848461074f565b6001905092915050565b6000600254905090565b600061033d848484610918565b6000600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000610388610747565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905082811015610408576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103ff90610f5e565b60405180910390fd5b61041c85610414610747565b85840361074f565b60019150509392505050565b60006012905090565b60006104d361043e610747565b84846001600061044c610747565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546104ce9190610fad565b61074f565b6001905092915050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b60606004805461053490610ebb565b80601f016020809104026020016040519081016040528092919081815260200182805461056090610ebb565b80156105ad5780601f10610582576101008083540402835291602001916105ad565b820191906000526020600020905b81548152906001019060200180831161059057829003601f168201915b5050505050905090565b600080600160006105c6610747565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905082811015610683576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161067a90611075565b60405180910390fd5b61069761068e610747565b8585840361074f565b600191505092915050565b60006106b66106af610747565b8484610918565b6001905092915050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036107be576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107b590611107565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361082d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161082490611199565b60405180910390fd5b80600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9258360405161090b9190610d7a565b60405180910390a3505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610987576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161097e9061122b565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036109f6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109ed906112bd565b60405180910390fd5b610a01838383610b97565b60008060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905081811015610a87576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a7e9061134f565b60405180910390fd5b8181036000808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254610b1a9190610fad565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610b7e9190610d7a565b60405180910390a3610b91848484610b9c565b50505050565b505050565b505050565b600081519050919050565b600082825260208201905092915050565b60005b83811015610bdb578082015181840152602081019050610bc0565b83811115610bea576000848401525b50505050565b6000601f19601f8301169050919050565b6000610c0c82610ba1565b610c168185610bac565b9350610c26818560208601610bbd565b610c2f81610bf0565b840191505092915050565b60006020820190508181036000830152610c548184610c01565b905092915050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610c8c82610c61565b9050919050565b610c9c81610c81565b8114610ca757600080fd5b50565b600081359050610cb981610c93565b92915050565b6000819050919050565b610cd281610cbf565b8114610cdd57600080fd5b50565b600081359050610cef81610cc9565b92915050565b60008060408385031215610d0c57610d0b610c5c565b5b6000610d1a85828601610caa565b9250506020610d2b85828601610ce0565b9150509250929050565b60008115159050919050565b610d4a81610d35565b82525050565b6000602082019050610d656000830184610d41565b92915050565b610d7481610cbf565b82525050565b6000602082019050610d8f6000830184610d6b565b92915050565b600080600060608486031215610dae57610dad610c5c565b5b6000610dbc86828701610caa565b9350506020610dcd86828701610caa565b9250506040610dde86828701610ce0565b9150509250925092565b600060ff82169050919050565b610dfe81610de8565b82525050565b6000602082019050610e196000830184610df5565b92915050565b600060208284031215610e3557610e34610c5c565b5b6000610e4384828501610caa565b91505092915050565b60008060408385031215610e6357610e62610c5c565b5b6000610e7185828601610caa565b9250506020610e8285828601610caa565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680610ed357607f821691505b602082108103610ee657610ee5610e8c565b5b50919050565b7f45524332303a207472616e7366657220616d6f756e742065786365656473206160008201527f6c6c6f77616e6365000000000000000000000000000000000000000000000000602082015250565b6000610f48602883610bac565b9150610f5382610eec565b604082019050919050565b60006020820190508181036000830152610f7781610f3b565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000610fb882610cbf565b9150610fc383610cbf565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115610ff857610ff7610f7e565b5b828201905092915050565b7f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760008201527f207a65726f000000000000000000000000000000000000000000000000000000602082015250565b600061105f602583610bac565b915061106a82611003565b604082019050919050565b6000602082019050818103600083015261108e81611052565b9050919050565b7f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460008201527f7265737300000000000000000000000000000000000000000000000000000000602082015250565b60006110f1602483610bac565b91506110fc82611095565b604082019050919050565b60006020820190508181036000830152611120816110e4565b9050919050565b7f45524332303a20617070726f766520746f20746865207a65726f20616464726560008201527f7373000000000000000000000000000000000000000000000000000000000000602082015250565b6000611183602283610bac565b915061118e82611127565b604082019050919050565b600060208201905081810360008301526111b281611176565b9050919050565b7f45524332303a207472616e736665722066726f6d20746865207a65726f20616460008201527f6472657373000000000000000000000000000000000000000000000000000000602082015250565b6000611215602583610bac565b9150611220826111b9565b604082019050919050565b6000602082019050818103600083015261124481611208565b9050919050565b7f45524332303a207472616e7366657220746f20746865207a65726f206164647260008201527f6573730000000000000000000000000000000000000000000000000000000000602082015250565b60006112a7602383610bac565b91506112b28261124b565b604082019050919050565b600060208201905081810360008301526112d68161129a565b9050919050565b7f45524332303a207472616e7366657220616d6f756e742065786365656473206260008201527f616c616e63650000000000000000000000000000000000000000000000000000602082015250565b6000611339602683610bac565b9150611344826112dd565b604082019050919050565b600060208201905081810360008301526113688161132c565b905091905056fea2646970667358221220a7f1816bf36cae41287ac7433f2d7cf5e290831e4bc48eba850c8c044b8c036b64736f6c634300080f0033 + diff --git a/packages/contracts/contracts/L1/rollup/IStateCommitmentChain.sol b/packages/contracts/contracts/L1/rollup/IStateCommitmentChain.sol index c1c6e9b14..eb51b40f6 100644 --- a/packages/contracts/contracts/L1/rollup/IStateCommitmentChain.sol +++ b/packages/contracts/contracts/L1/rollup/IStateCommitmentChain.sol @@ -58,6 +58,7 @@ interface IStateCommitmentChain { * Appends a batch of state roots to the chain. * @param _batch Batch of state roots. * @param _shouldStartAtElement Index of the element at which this batch should start. + * @param _signature tss group signature of state batches. */ function appendStateBatch(bytes32[] calldata _batch, uint256 _shouldStartAtElement, bytes memory _signature) external; diff --git a/packages/contracts/contracts/L1/rollup/StateCommitmentChain.sol b/packages/contracts/contracts/L1/rollup/StateCommitmentChain.sol index ea4649da4..42be91690 100644 --- a/packages/contracts/contracts/L1/rollup/StateCommitmentChain.sol +++ b/packages/contracts/contracts/L1/rollup/StateCommitmentChain.sol @@ -303,17 +303,16 @@ contract StateCommitmentChain is IStateCommitmentChain, Lib_AddressResolver, Cro "Cannot publish state roots within the sequencer publication window." ); } - // For efficiency reasons getMerkleRoot modifies the `_batch` argument in place // while calculating the root hash therefore any arguments passed to it must not // be used again afterwards Lib_BVMCodec.ChainBatchHeader memory batchHeader = Lib_BVMCodec.ChainBatchHeader({ - batchIndex : getTotalBatches(), - batchRoot : Lib_MerkleTree.getMerkleRoot(_batch), - batchSize : _batch.length, - prevTotalElements : totalElements, - signature : _signature, - extraData : _extraData + batchIndex : getTotalBatches(), + batchRoot : Lib_MerkleTree.getMerkleRoot(_batch), + batchSize : _batch.length, + prevTotalElements : totalElements, + signature : _signature, + extraData : _extraData }); emit StateBatchAppended( diff --git a/packages/contracts/contracts/test-helpers/MockStateCommitmentChain.sol b/packages/contracts/contracts/test-helpers/MockStateCommitmentChain.sol new file mode 100644 index 000000000..4472a0d6d --- /dev/null +++ b/packages/contracts/contracts/test-helpers/MockStateCommitmentChain.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.9; + +contract MockStateCommitmentChain { + function appendStateBatch(bytes32[] memory _batch, uint256 _shouldStartAtElement, bytes memory _signature) public { + return; + } + + function FRAUD_PROOF_WINDOW() external returns(uint256){ + return 0; + } +} diff --git a/packages/contracts/deploy-config/goerli-qa.ts b/packages/contracts/deploy-config/goerli-qa.ts index 8acaefe77..fdb941cd3 100644 --- a/packages/contracts/deploy-config/goerli-qa.ts +++ b/packages/contracts/deploy-config/goerli-qa.ts @@ -13,6 +13,7 @@ const config = { l2SubmittedBlockNumber: 1, bvmSequencerAddress: process.env.BVM_SEQUENCER_ADDRESS || '0x2B1D033ddCc36cd6f4DE10A9a9C2Bc329a443bEB', bvmProposerAddress: process.env.BVM_PROPOSER_ADDRESS || '0x4e1614113AF6a1a41cA85d1a5Fe41De105BD65fA', + bvmRolluperAddress: process.env.BVM_ROLLUPER_ADDRESS || '0x4e1614113AF6a1a41cA85d1a5Fe41De105BD65fA', //default bvmBlockSignerAddress bvmBlockSignerAddress: process.env.BVM_BLOCK_SIGNER_ADDRESS || '0x00000398232E2064F896018496b4b44b3D62751F', bvmFeeWalletAddress: process.env.BVM_FEE_WALLET_ADDRESS || '0xeEbceB07eA7D2339895Dd492B3B5960641302830', diff --git a/packages/contracts/deploy-config/goerli-testnet.ts b/packages/contracts/deploy-config/goerli-testnet.ts index 0d0e8af1d..bb4b8dcee 100644 --- a/packages/contracts/deploy-config/goerli-testnet.ts +++ b/packages/contracts/deploy-config/goerli-testnet.ts @@ -13,6 +13,7 @@ const config = { l2SubmittedBlockNumber: 1, bvmSequencerAddress: process.env.BVM_SEQUENCER_ADDRESS || '0xc4AaE221f1C62E8CBC657Af5b051eA573914cFc7', bvmProposerAddress: process.env.BVM_PROPOSER_ADDRESS || '0x3079Be9D8622173f02618bA2B793F00795D4f320', + bvmRolluperAddress: process.env.BVM_ROLLUPER_ADDRESS || '0x3079Be9D8622173f02618bA2B793F00795D4f320', //default bvmBlockSignerAddress bvmBlockSignerAddress: process.env.BVM_BLOCK_SIGNER_ADDRESS || '0xa9eC80835800a59Fd022f53e3E75AA4552F22ccB', bvmFeeWalletAddress: process.env.BVM_FEE_WALLET_ADDRESS || '0x018E08C754018fe54D1CE86b27120052bFe07273', diff --git a/packages/contracts/deploy-config/hardhat.ts b/packages/contracts/deploy-config/hardhat.ts index 106aaef95..21a2b8ed3 100644 --- a/packages/contracts/deploy-config/hardhat.ts +++ b/packages/contracts/deploy-config/hardhat.ts @@ -11,6 +11,7 @@ const config = { l2SubmittedBlockNumber: 1, bvmSequencerAddress: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8', bvmProposerAddress: '0x3c44cdddb6a900fa2b585dd299e03d12fa4293bc', + bvmRolluperAddress: '0x3c44cdddb6a900fa2b585dd299e03d12fa4293bc', bvmBlockSignerAddress: '0x00000398232E2064F896018496b4b44b3D62751F', bvmFeeWalletAddress: '0x391716d440c151c42cdf1c95c1d83a5427bca52c', bvmAddressManagerOwner: '0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266', diff --git a/packages/contracts/deploy-config/local.ts b/packages/contracts/deploy-config/local.ts index 616464f35..dcd30f0d0 100644 --- a/packages/contracts/deploy-config/local.ts +++ b/packages/contracts/deploy-config/local.ts @@ -5,13 +5,14 @@ const config = { updateGaslimitBlock: 10, ctcL2GasDiscountDivisor: 32, ctcEnqueueGasCost: 60_000, - sccFaultProofWindowSeconds: 0, + sccFaultProofWindowSeconds: 60, sccSequencerPublishWindowSeconds: 12592000, blockStaleMeasure: 100, daFraudProofPeriod: 120, l2SubmittedBlockNumber: 1, bvmSequencerAddress: process.env.BVM_SEQUENCER_ADDRESS || '0x70997970c51812dc3a010c7d01b50e0d17dc79c8', - bvmProposerAddress: process.env.BVM_PROPOSER_ADDRESS || '0x3c44cdddb6a900fa2b585dd299e03d12fa4293bc', + bvmProposerAddress: process.env.BVM_PROPOSER_ADDRESS || '0x4f958F2C2303BDca22b739339cD633F8543BB07D', + bvmRolluperAddress: process.env.BVM_ROLLUPER_ADDRESS || '0x3c44cdddb6a900fa2b585dd299e03d12fa4293bc', bvmBlockSignerAddress: process.env.BVM_BLOCK_SIGNER_ADDRESS || '0x00000398232E2064F896018496b4b44b3D62751F', bvmFeeWalletAddress: process.env.BVM_FEE_WALLET_ADDRESS || '0xeEbceB07eA7D2339895Dd492B3B5960641302830', bvmAddressManagerOwner: process.env.BVM_ADDRESS_MANAGER_OWNER || '0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266', diff --git a/packages/contracts/deploy/011-AddressDictator.deploy.ts b/packages/contracts/deploy/011-AddressDictator.deploy.ts index c212244ed..eb17ce5c5 100644 --- a/packages/contracts/deploy/011-AddressDictator.deploy.ts +++ b/packages/contracts/deploy/011-AddressDictator.deploy.ts @@ -50,6 +50,12 @@ const deployFn: DeployFunction = async (hre) => { name: names.managed.accounts.BVM_Proposer, address: hre.deployConfig.bvmProposerAddress, }, + // BVM_Rolluper is the address allowed to submit state roots & assertion (transaction results) to the + // Rollup. + { + name: names.managed.accounts.BVM_Rolluper, + address: hre.deployConfig.bvmRolluperAddress, + }, // L1_BIT_ADDRESS indicate l1 bit token erc20 contract address { name: names.managed.configs.L1_BIT_ADDRESS, diff --git a/packages/contracts/deploy/019-BVM_FraudProof.deploy.ts b/packages/contracts/deploy/019-BVM_FraudProof.deploy.ts new file mode 100644 index 000000000..f20a61b88 --- /dev/null +++ b/packages/contracts/deploy/019-BVM_FraudProof.deploy.ts @@ -0,0 +1,237 @@ +/* Imports: External */ +import { DeployFunction } from 'hardhat-deploy/dist/types' + +// @ts-ignore +import { names } from '../src/address-names' +import { + deployAndVerifyAndThen, + getContractFromArtifact, +} from '../src/deploy-utils' +import {awaitCondition, hexStringEquals} from "@mantleio/core-utils"; +import {deploy} from "../test/helpers"; + +// eslint-disable-next-line @typescript-eslint/no-var-requires +const { ethers, upgrades } = require("hardhat"); + +const deployFn: DeployFunction = async (hre) => { + // @ts-ignore + const { deployer } = await hre.getNamedAccounts() + + const Lib_AddressManager = await getContractFromArtifact( + hre, + names.unmanaged.Lib_AddressManager + ) + // @ts-ignore + const owner = hre.deployConfig.bvmAddressManagerOwner + // @ts-ignore + const l1BitAddress = hre.deployConfig.l1BitAddress + + // deploy assertionMap impl + await deployAndVerifyAndThen({ + hre, + name: names.managed.fraud_proof.AssertionMap, + contract: 'AssertionMap', + args: [], + }) + const Impl__AssertionMap = await getContractFromArtifact( + hre, + names.managed.fraud_proof.AssertionMap, + { + iface: 'AssertionMap', + signerOrProvider: deployer, + } + ) + console.log('AssertionMap Implementation Address', Impl__AssertionMap.address) + console.log('deploy fraud proof assertionMap success') + + // deploy verifier impl + await deployAndVerifyAndThen({ + hre, + name: names.managed.fraud_proof.VerifierEntry, + contract: 'VerifierEntry', + args: [], + }) + const Impl__VerifierEntry = await getContractFromArtifact( + hre, + names.managed.fraud_proof.VerifierEntry, + { + iface: 'VerifierEntry', + signerOrProvider: deployer, + } + ) + console.log('Verifier Implementation Address', Impl__VerifierEntry.address) + console.log('deploy fraud proof verifier success') + + // deploy rollup impl + await deployAndVerifyAndThen({ + hre, + name: names.managed.fraud_proof.Rollup, + contract: 'Rollup', + args: [], + }) + const Impl__Rollup = await getContractFromArtifact( + hre, + names.managed.fraud_proof.Rollup, + { + iface: 'Rollup', + signerOrProvider: deployer, + } + ) + console.log('Rollup Implementation Address', Impl__Rollup.address) + console.log('deploy fraud proof assertion rollup success') + + // deploy assertionMap proxy + let callData = Impl__AssertionMap.interface.encodeFunctionData('initialize', []) + await deployAndVerifyAndThen({ + hre, + name: names.managed.fraud_proof.Proxy__AssertionMap, + contract: 'TransparentUpgradeableProxy', + iface: 'AssertionMap', + args: [Impl__AssertionMap.address, owner, callData], + }) + console.log('deploy fraud proof assertionMap proxy success') + const Proxy__AssertionMap = await getContractFromArtifact( + hre, + names.managed.fraud_proof.Proxy__AssertionMap, + { + iface: 'AssertionMap', + signerOrProvider: deployer, + } + ) + console.log('Proxy__AssertionMap Address', Proxy__AssertionMap.address) + console.log('deploy fraud proof Proxy__AssertionMap success') + + callData = Impl__VerifierEntry.interface.encodeFunctionData('initialize', []) + await deployAndVerifyAndThen({ + hre, + name: names.managed.fraud_proof.Proxy__Verifier, + contract: 'TransparentUpgradeableProxy', + iface: 'VerifierEntry', + args: [Impl__VerifierEntry.address, owner, callData], + }) + + const Proxy__VerifierEntry = await getContractFromArtifact( + hre, + names.managed.fraud_proof.Proxy__Verifier, + { + iface: 'VerifierEntry', + signerOrProvider: deployer, + } + ) + console.log('deploy fraud proof verifier proxy success') + + // deploy rollup proxy + const rollupArgs = [ + deployer, // address _owner + Proxy__VerifierEntry.address, // address _verifier, + l1BitAddress, // address _stakeToken, + Lib_AddressManager.address, // address _libAddressManager, + Proxy__AssertionMap.address, // address _assertionMap, + 5, // uint256 _confirmationPeriod, + 0, // uint256 _challengePeriod, + 0, // uint256 _minimumAssertionPeriod, + // 1000000000000, // uint256 _maxGasPerAssertion, + 0, // uint256 _baseStakeAmount + '0x89e2ce7fd44675606b4ced40dd2ccc67f7ae2851dd1b86409bdaeac791a60d3e', // bytes32 _initialVMhash //TODO-FIXME + [ + '0xd5b002298b2e81b4ced1b6c8cf1964023cdc3758', + '0xd55fe10a1acb32b6183bdfbeb42e9961c3cb8792', + '0xd55fe2797c18d721ee197d09fa0dda584f92b5af', + ], + ] + callData = Impl__Rollup.interface.encodeFunctionData('initialize', rollupArgs) + await deployAndVerifyAndThen({ + hre, + name: names.managed.fraud_proof.Proxy__Rollup, + contract: 'TransparentUpgradeableProxy', + iface: 'Rollup', + args: [Impl__Rollup.address, owner, callData], + postDeployAction: async (contract) => { + // Theoretically it's not necessary to initialize this contract since it sits behind + // a proxy. However, it's best practice to initialize it anyway just in case there's + // some unknown security hole. It also prevents another user from appearing like an + // official address because it managed to call the initialization function. + // console.log(`Initializing fraud-proof Rollup (implementation)...`) + // await contract.initialize(...rollupArgs) + + console.log(`Checking that contract was correctly initialized...`) + await awaitCondition( + async () => { + return hexStringEquals( + await contract.libAddressManager(), + Lib_AddressManager.address + ) + }, + 5000, + 100 + ) + console.log('>>>> assertions ',await contract.assertions()) + await awaitCondition( + async () => { + return hexStringEquals( + await contract.assertions(), + Proxy__AssertionMap.address + ) + }, + 5000, + 100 + ) + console.log('>>>> owner ',await contract.owner()) + await awaitCondition( + async () => { + return hexStringEquals( + await contract.owner(), + deployer + ) + }, + 5000, + 100 + ) + // console.log('>>>> whitelists', contract.whitelist()) + // await awaitCondition( + // async () => { + // return hexStringEquals( + // await contract.whitelist().length, + // "3" + // ) + // }, + // 5000, + // 100 + // ) + }, + }) + console.log('deploy fraud proof rollup proxy success') + const Proxy__Rollup = await getContractFromArtifact( + hre, + names.managed.fraud_proof.Proxy__Rollup, + { + iface: 'Rollup', + signerOrProvider: deployer, + } + ) + console.log('Proxy__Rollup Address', Proxy__Rollup.address) + console.log('deploy fraud proof Proxy__Rollup success') + // @ts-ignore + // await awaitCondition( + // async () => { + // // @ts-ignore + // // eslint-disable-next-line @typescript-eslint/no-shadow + // const wl1 = Rollup.whitelist('0xd5b002298b2e81b4ced1b6c8cf1964023cdc3758') + // // @ts-ignore + // // eslint-disable-next-line @typescript-eslint/no-shadow + // const wl2 = Rollup.whitelist('0xd55fe10a1acb32b6183bdfbeb42e9961c3cb8792') + // // @ts-ignore + // // eslint-disable-next-line @typescript-eslint/no-shadow + // const wl3 = Rollup.whitelist('0xd55fe2797c18d721ee197d09fa0dda584f92b5af') + // return wl1 === true && wl2 === true && wl3 === true + // }, + // 5000, + // 100 + // ) + // console.log('>>>> staker all whitelisted !!!!') +} + +// This is kept during an upgrade. So no upgrade tag. +deployFn.tags = ['FraudProof', 'upgrade'] + +export default deployFn diff --git a/packages/contracts/filenames.txt b/packages/contracts/filenames.txt index 427dfe85a..f2e629a9d 100644 --- a/packages/contracts/filenames.txt +++ b/packages/contracts/filenames.txt @@ -1,12 +1,16 @@ +Proxy__Verifier ChainStorageContainer-SCC-batches +Proxy__AssertionMap StateCommitmentChain TestBitToken ChainStorageContainer-CTC-batches Proxy__BVM_L1StandardBridge +Rollup TssStakingSlashing BVM_L1CrossDomainMessenger Proxy__TSS_GroupManager Lib_AddressManager +VerifierEntry AddressDictator BVM_EigenDataLayrChain CanonicalTransactionChain @@ -17,3 +21,5 @@ Proxy__BVM_EigenDataLayrChain Proxy__BVM_L1CrossDomainMessenger Proxy__TSS_StakingSlashing BondManager +AssertionMap +Proxy__Rollup diff --git a/packages/contracts/genesis/addresses.json b/packages/contracts/genesis/addresses.json index f0d3f8cc2..73f437e76 100644 --- a/packages/contracts/genesis/addresses.json +++ b/packages/contracts/genesis/addresses.json @@ -1,13 +1,17 @@ { + "Proxy__Verifier": "0x4f958F2C2303BDca22b739339cD633F8543BB07D", "ChainStorageContainer-SCC-batches": "0x0090171f848B2aa86918E5Ef2406Ab3d424fdd83", + "Proxy__AssertionMap": "0x86E10B59cFDFeFBCf3ED5b40D018949CbFCE8B59", "StateCommitmentChain": "0x8BAccFF561FDe61D6bC8B6f299fFBa561d2189B9", "TestBitToken": "0x92aBAD50368175785e4270ca9eFd169c949C4ce1", "ChainStorageContainer-CTC-batches": "0x7A8B94a9fA2bb0581D2EEA2fEd875FCA97494612", "Proxy__BVM_L1StandardBridge": "0x52753615226F8aC8a464bfecb11Ef798CFF3793f", + "Rollup": "0x2eC3980EcddA68E073c39afD44909f8fe0fE3000", "TssStakingSlashing": "0x36fCf02Fc651c0b7ef2ECA446Dd2405364F85337", "BVM_L1CrossDomainMessenger": "0xD076364Fa5de1a4512c58b39ad63DD720B7B9E11", "Proxy__TSS_GroupManager": "0xa83239cf2b900682001f9144144B5E5e5788A631", "Lib_AddressManager": "0x19C22f181280dF6Ad1d97285cdD430173Df91C12", + "VerifierEntry": "0x9109811E8eEe02520219612bB5D47C60c382F4aa", "AddressDictator": "0xE6A251EefaEE70E8645FBAdf21E9B1246e07C374", "BVM_EigenDataLayrChain": "0xc2E4F2038D456AfEFfF2351234BCaFCB6837baC1", "CanonicalTransactionChain": "0x9faB987C9C469EB23Da31B7848B28aCf30905eA8", @@ -18,5 +22,7 @@ "Proxy__BVM_L1CrossDomainMessenger": "0xd9e2F450525079e1e29fB23Bc7Caca6F61f8fD4a", "Proxy__TSS_StakingSlashing": "0xe6cd9e7b620964bECd42c7Ad41e56724f515E284", "BondManager": "0xEd5166f12FCb48a0804B62FDccB37f59F1F1bc3B", + "AssertionMap": "0x1Edd37fc504513bAa00D782E52478d0a3f675553", + "Proxy__Rollup": "0x8013ac56e4c4A562b72a6D8B39D60cDa7aE173A9", "AddressManager": "0x19C22f181280dF6Ad1d97285cdD430173Df91C12" } diff --git a/packages/contracts/genesis/local.json b/packages/contracts/genesis/local.json index b111c9107..693a3bb54 100644 --- a/packages/contracts/genesis/local.json +++ b/packages/contracts/genesis/local.json @@ -1,9 +1,5 @@ { -<<<<<<< HEAD - "commit": "c61a1efdc8517d02ad7a7d5ac64b4eb39a4e4e61", -======= - "commit": "7accccb28a63b7701eaa79033c1aeb914b3395b3", ->>>>>>> feature/ctc-rollup-switch-to-eigenlayer + "commit": "00ab47dba2b1e757c243a8b586aed40888e0b28d", "config": { "chainId": 17, "homesteadBlock": 0, @@ -29,14 +25,14 @@ "0x4200000000000000000000000000000000000000": { "balance": "00", "storage": {}, - "code": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c806382e3702d1461003b578063cafa81dc14610072575b600080fd5b61005e610049366004610112565b60006020819052908152604090205460ff1681565b604051901515815260200160405180910390f35b61008561008036600461015a565b610087565b005b6001600080833360405160200161009f929190610229565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815291815281516020928301208352908201929092520160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001691151591909117905550565b60006020828403121561012457600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006020828403121561016c57600080fd5b813567ffffffffffffffff8082111561018457600080fd5b818401915084601f83011261019857600080fd5b8135818111156101aa576101aa61012b565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156101f0576101f061012b565b8160405282815287602084870101111561020957600080fd5b826020860160208301376000928101602001929092525095945050505050565b6000835160005b8181101561024a5760208187018101518583015201610230565b81811115610259576000828501525b5060609390931b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016919092019081526014019291505056fea26469706673582212207bc608c152ff3d42d0bc53a0492fc811e6bc685922f023653d6affe9df75f55764736f6c63430008090033" + "code": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c806382e3702d1461003b578063cafa81dc14610072575b600080fd5b61005e6100493660046100d6565b60006020819052908152604090205460ff1681565b604051901515815260200160405180910390f35b610085610080366004610105565b610087565b005b6001600080833360405160200161009f9291906101b6565b60408051808303601f19018152918152815160209283012083529082019290925201600020805460ff191691151591909117905550565b6000602082840312156100e857600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b60006020828403121561011757600080fd5b813567ffffffffffffffff8082111561012f57600080fd5b818401915084601f83011261014357600080fd5b813581811115610155576101556100ef565b604051601f8201601f19908116603f0116810190838211818310171561017d5761017d6100ef565b8160405282815287602084870101111561019657600080fd5b826020860160208301376000928101602001929092525095945050505050565b6000835160005b818110156101d757602081870181015185830152016101bd565b818111156101e6576000828501525b5060609390931b6bffffffffffffffffffffffff1916919092019081526014019291505056fea2646970667358221220a5c338b6c39fb5f5d42de33bacb945608db4a507585b3f40c0324e4402967d6c64736f6c63430008090033" }, "0x4200000000000000000000000000000000000002": { "balance": "00", "storage": { "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000000" }, - "code": "0x608060405234801561001057600080fd5b50600436106100725760003560e01c80639b19251a116100505780639b19251a146100e9578063b1540a011461011c578063bdc7b54f1461012f57600080fd5b806308fd63221461007757806313af40351461008c5780638da5cb5b1461009f575b600080fd5b61008a610085366004610614565b610137565b005b61008a61009a366004610650565b610271565b6000546100bf9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b61010c6100f7366004610650565b60016020526000908152604090205460ff1681565b60405190151581526020016100e0565b61010c61012a366004610650565b61047c565b61008a6104cd565b60005473ffffffffffffffffffffffffffffffffffffffff1633146101e3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f46756e6374696f6e2063616e206f6e6c792062652063616c6c6564206279207460448201527f6865206f776e6572206f66207468697320636f6e74726163742e00000000000060648201526084015b60405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff821660008181526001602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00168515159081179091558251938452908301527f8daaf060c3306c38e068a75c054bf96ecd85a3db1252712c4d93632744c42e0d910160405180910390a15050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610318576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f46756e6374696f6e2063616e206f6e6c792062652063616c6c6564206279207460448201527f6865206f776e6572206f66207468697320636f6e74726163742e00000000000060648201526084016101da565b73ffffffffffffffffffffffffffffffffffffffff81166103e1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605160248201527f42564d5f4465706c6f79657257686974656c6973743a2063616e206f6e6c792060448201527f62652064697361626c65642076696120656e61626c654172626974726172794360648201527f6f6e74726163744465706c6f796d656e74000000000000000000000000000000608482015260a4016101da565b6000546040805173ffffffffffffffffffffffffffffffffffffffff928316815291831660208301527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c910160405180910390a1600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6000805473ffffffffffffffffffffffffffffffffffffffff1615806104c7575073ffffffffffffffffffffffffffffffffffffffff821660009081526001602052604090205460ff165b92915050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610574576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f46756e6374696f6e2063616e206f6e6c792062652063616c6c6564206279207460448201527f6865206f776e6572206f66207468697320636f6e74726163742e00000000000060648201526084016101da565b60005460405173ffffffffffffffffffffffffffffffffffffffff90911681527fc0e106cf568e50698fdbde1eff56f5a5c966cc7958e37e276918e9e4ccdf8cd49060200160405180910390a1600080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055565b803573ffffffffffffffffffffffffffffffffffffffff8116811461060f57600080fd5b919050565b6000806040838503121561062757600080fd5b610630836105eb565b91506020830135801515811461064557600080fd5b809150509250929050565b60006020828403121561066257600080fd5b61066b826105eb565b939250505056fea2646970667358221220df27bdf86bfaa0da7e2c1622f676e71f90f0b0fe09846498fe6f2e58ca9e544464736f6c63430008090033" + "code": "0x608060405234801561001057600080fd5b50600436106100625760003560e01c806308fd63221461006757806313af40351461007c5780638da5cb5b1461008f5780639b19251a146100bf578063b1540a01146100f2578063bdc7b54f14610105575b600080fd5b61007a61007536600461039b565b61010d565b005b61007a61008a3660046103d7565b6101a3565b6000546100a2906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b6100e26100cd3660046103d7565b60016020526000908152604090205460ff1681565b60405190151581526020016100b6565b6100e26101003660046103d7565b6102cc565b61007a610303565b6000546001600160a01b031633146101405760405162461bcd60e51b8152600401610137906103f9565b60405180910390fd5b6001600160a01b038216600081815260016020908152604091829020805460ff19168515159081179091558251938452908301527f8daaf060c3306c38e068a75c054bf96ecd85a3db1252712c4d93632744c42e0d910160405180910390a15050565b6000546001600160a01b031633146101cd5760405162461bcd60e51b8152600401610137906103f9565b6001600160a01b0381166102635760405162461bcd60e51b815260206004820152605160248201527f42564d5f4465706c6f79657257686974656c6973743a2063616e206f6e6c792060448201527f62652064697361626c65642076696120656e61626c65417262697472617279436064820152701bdb9d1c9858dd11195c1b1bde5b595b9d607a1b608482015260a401610137565b600054604080516001600160a01b03928316815291831660208301527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c910160405180910390a1600080546001600160a01b0319166001600160a01b0392909216919091179055565b600080546001600160a01b031615806102fd57506001600160a01b03821660009081526001602052604090205460ff165b92915050565b6000546001600160a01b0316331461032d5760405162461bcd60e51b8152600401610137906103f9565b6000546040516001600160a01b0390911681527fc0e106cf568e50698fdbde1eff56f5a5c966cc7958e37e276918e9e4ccdf8cd49060200160405180910390a1600080546001600160a01b0319169055565b80356001600160a01b038116811461039657600080fd5b919050565b600080604083850312156103ae57600080fd5b6103b78361037f565b9150602083013580151581146103cc57600080fd5b809150509250929050565b6000602082840312156103e957600080fd5b6103f28261037f565b9392505050565b6020808252603a908201527f46756e6374696f6e2063616e206f6e6c792062652063616c6c6564206279207460408201527f6865206f776e6572206f66207468697320636f6e74726163742e00000000000060608201526080019056fea264697066735822122014c54fb7ee74ea774867baf99a626bf5080d91aef21986eb9bbc65ca16a20bfd64736f6c63430008090033" }, "0x4200000000000000000000000000000000000007": { "balance": "00", @@ -45,7 +41,7 @@ "0x0000000000000000000000000000000000000000000000000000000000000005": "0x000000000000000000000000d9e2f450525079e1e29fb23bc7caca6f61f8fd4a", "0x0000000000000000000000000000000000000000000000000000000000000003": "0x00000000000000000000000000000000000000000000000000000000000186a0" }, - "code": "0x608060405234801561001057600080fd5b50600436106100885760003560e01c8063a71198691161005b578063a71198691461012a578063b1b1b2091461014a578063cbd4ece91461016d578063ecc704281461018057600080fd5b806321d800ec1461008d5780633dbb202b146100c55780636e296e45146100da57806382e3702d14610107575b600080fd5b6100b061009b366004610826565b60006020819052908152604090205460ff1681565b60405190151581526020015b60405180910390f35b6100d86100d3366004610942565b610197565b005b6100e26102e2565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100bc565b6100b0610115366004610826565b60026020526000908152604090205460ff1681565b6005546100e29073ffffffffffffffffffffffffffffffffffffffff1681565b6100b0610158366004610826565b60016020526000908152604090205460ff1681565b6100d861017b3660046109ad565b61038b565b61018960035481565b6040519081526020016100bc565b60006101a784338560035461078d565b80516020808301919091206000908152600290915260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055517fcafa81dc0000000000000000000000000000000000000000000000000000000081529091507342000000000000000000000000000000000000009063cafa81dc9061023c908490600401610a89565b600060405180830381600087803b15801561025657600080fd5b505af115801561026a573d6000803e3d6000fd5b505050508373ffffffffffffffffffffffffffffffffffffffff167fcb0f7ffd78f9aee47a248fae8db181db6eee833039123e026dcbff529522e52a3385600354866040516102bc9493929190610aa3565b60405180910390a26001600360008282546102d79190610aef565b909155505050505050565b60045460009073ffffffffffffffffffffffffffffffffffffffff1661dead141561036e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f78446f6d61696e4d65737361676553656e646572206973206e6f74207365740060448201526064015b60405180910390fd5b5060045473ffffffffffffffffffffffffffffffffffffffff1690565b60055473ffffffffffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffeeeeffffffffffffffffffffffffffffffffeeef330173ffffffffffffffffffffffffffffffffffffffff161461046a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f50726f7669646564206d65737361676520636f756c64206e6f7420626520766560448201527f7269666965642e000000000000000000000000000000000000000000000000006064820152608401610365565b60006104788585858561078d565b8051602080830191909120600081815260019092526040909120549192509060ff1615610527576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f50726f7669646564206d6573736167652068617320616c72656164792062656560448201527f6e2072656365697665642e0000000000000000000000000000000000000000006064820152608401610365565b73ffffffffffffffffffffffffffffffffffffffff8616734200000000000000000000000000000000000000141561059957600090815260016020819052604090912080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016909117905550610787565b600480547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff878116919091179091556040516000918816906105f2908790610b2e565b6000604051808303816000865af19150503d806000811461062f576040519150601f19603f3d011682016040523d82523d6000602084013e610634565b606091505b5050600480547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead1790559050801515600114156106d557600082815260016020819052604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169092179091555183917f4641df4a962071e12719d8c8c8e5ac7fc4d97b927346a3d7a335b1f7517e133c91a2610701565b60405182907f99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f90600090a25b600083334360405160200161071893929190610b4a565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181528151602092830120600090815291829052902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055505050505b50505050565b6060848484846040516024016107a69493929190610b9c565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fcbd4ece9000000000000000000000000000000000000000000000000000000001790529050949350505050565b60006020828403121561083857600080fd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461086357600080fd5b919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126108a857600080fd5b813567ffffffffffffffff808211156108c3576108c3610868565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561090957610909610868565b8160405283815286602085880101111561092257600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060006060848603121561095757600080fd5b6109608461083f565b9250602084013567ffffffffffffffff81111561097c57600080fd5b61098886828701610897565b925050604084013563ffffffff811681146109a257600080fd5b809150509250925092565b600080600080608085870312156109c357600080fd5b6109cc8561083f565b93506109da6020860161083f565b9250604085013567ffffffffffffffff8111156109f657600080fd5b610a0287828801610897565b949793965093946060013593505050565b60005b83811015610a2e578181015183820152602001610a16565b838111156107875750506000910152565b60008151808452610a57816020860160208601610a13565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000610a9c6020830184610a3f565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff85168152608060208201526000610ad26080830186610a3f565b905083604083015263ffffffff8316606083015295945050505050565b60008219821115610b29577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b500190565b60008251610b40818460208701610a13565b9190910192915050565b60008451610b5c818460208901610a13565b60609490941b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001691909301908152601481019190915260340192915050565b600073ffffffffffffffffffffffffffffffffffffffff808716835280861660208401525060806040830152610bd56080830185610a3f565b90508260608301529594505050505056fea264697066735822122060db5939914765b6ad042b95a40568e91920bfb1eadc40c6a64ec7445e27814a64736f6c63430008090033" + "code": "0x608060405234801561001057600080fd5b50600436106100885760003560e01c8063a71198691161005b578063a71198691461011d578063b1b1b20914610130578063cbd4ece914610153578063ecc704281461016657600080fd5b806321d800ec1461008d5780633dbb202b146100c55780636e296e45146100da57806382e3702d146100fa575b600080fd5b6100b061009b3660046105e5565b60006020819052908152604090205460ff1681565b60405190151581526020015b60405180910390f35b6100d86100d33660046106bd565b61017d565b005b6100e2610274565b6040516001600160a01b0390911681526020016100bc565b6100b06101083660046105e5565b60026020526000908152604090205460ff1681565b6005546100e2906001600160a01b031681565b6100b061013e3660046105e5565b60016020526000908152604090205460ff1681565b6100d8610161366004610728565b6102e9565b61016f60035481565b6040519081526020016100bc565b600061018d843385600354610598565b805160208083019190912060009081526002909152604090819020805460ff19166001179055516332bea07760e21b8152909150602160991b9063cafa81dc906101db9084906004016107e6565b600060405180830381600087803b1580156101f557600080fd5b505af1158015610209573d6000803e3d6000fd5b50505050836001600160a01b03167fcb0f7ffd78f9aee47a248fae8db181db6eee833039123e026dcbff529522e52a33856003548660405161024e9493929190610800565b60405180910390a26001600360008282546102699190610841565b909155505050505050565b6004546000906001600160a01b031661dead14156102d95760405162461bcd60e51b815260206004820152601f60248201527f78446f6d61696e4d65737361676553656e646572206973206e6f74207365740060448201526064015b60405180910390fd5b506004546001600160a01b031690565b6005546001600160a01b03167311110000000000000000000000000000000011101933016001600160a01b0316146103735760405162461bcd60e51b815260206004820152602760248201527f50726f7669646564206d65737361676520636f756c64206e6f742062652076656044820152663934b334b2b21760c91b60648201526084016102d0565b600061038185858585610598565b8051602080830191909120600081815260019092526040909120549192509060ff16156104045760405162461bcd60e51b815260206004820152602b60248201527f50726f7669646564206d6573736167652068617320616c72656164792062656560448201526a37103932b1b2b4bb32b21760a91b60648201526084016102d0565b6001600160a01b038616602160991b141561043b576000908152600160208190526040909120805460ff1916909117905550610592565b600480546001600160a01b0319166001600160a01b038781169190911790915560405160009188169061046f908790610867565b6000604051808303816000865af19150503d80600081146104ac576040519150601f19603f3d011682016040523d82523d6000602084013e6104b1565b606091505b5050600480546001600160a01b03191661dead17905590508015156001141561051c576000828152600160208190526040808320805460ff19169092179091555183917f4641df4a962071e12719d8c8c8e5ac7fc4d97b927346a3d7a335b1f7517e133c91a2610548565b60405182907f99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f90600090a25b600083334360405160200161055f93929190610883565b60408051601f1981840301815291815281516020928301206000908152918290529020805460ff19166001179055505050505b50505050565b6060848484846040516024016105b194939291906108c2565b60408051601f198184030181529190526020810180516001600160e01b031663cbd4ece960e01b1790529050949350505050565b6000602082840312156105f757600080fd5b5035919050565b80356001600160a01b038116811461061557600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600082601f83011261064157600080fd5b813567ffffffffffffffff8082111561065c5761065c61061a565b604051601f8301601f19908116603f011681019082821181831017156106845761068461061a565b8160405283815286602085880101111561069d57600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806000606084860312156106d257600080fd5b6106db846105fe565b9250602084013567ffffffffffffffff8111156106f757600080fd5b61070386828701610630565b925050604084013563ffffffff8116811461071d57600080fd5b809150509250925092565b6000806000806080858703121561073e57600080fd5b610747856105fe565b9350610755602086016105fe565b9250604085013567ffffffffffffffff81111561077157600080fd5b61077d87828801610630565b949793965093946060013593505050565b60005b838110156107a9578181015183820152602001610791565b838111156105925750506000910152565b600081518084526107d281602086016020860161078e565b601f01601f19169290920160200192915050565b6020815260006107f960208301846107ba565b9392505050565b6001600160a01b0385168152608060208201819052600090610824908301866107ba565b905083604083015263ffffffff8316606083015295945050505050565b6000821982111561086257634e487b7160e01b600052601160045260246000fd5b500190565b6000825161087981846020870161078e565b9190910192915050565b6000845161089581846020890161078e565b60609490941b6bffffffffffffffffffffffff191691909301908152601481019190915260340192915050565b6001600160a01b038581168252841660208201526080604082018190526000906108ee908301856107ba565b90508260608301529594505050505056fea264697066735822122032e1fac7ab206e7b44fe0e8299766d125b190c2e7849c927b4ebaa4d69f4fd5464736f6c63430008090033" }, "0x420000000000000000000000000000000000000F": { "balance": "00", @@ -60,7 +56,7 @@ "0x0000000000000000000000000000000000000000000000000000000000000007": "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000008": "0x0000000000000000000000008baccff561fde61d6bc8b6f299ffba561d2189b9" }, - "code": "0x608060405234801561001057600080fd5b506004361061016c5760003560e01c80638da5cb5b116100cd578063ea01cd3611610081578063f45e65d811610066578063f45e65d8146102c4578063fc55b138146102cd578063fe173b97146102e057600080fd5b8063ea01cd3614610291578063f2fde38b146102b157600080fd5b8063bf1fe420116100b2578063bf1fe42014610258578063c76478321461026b578063de26c4a11461027e57600080fd5b80638da5cb5b14610206578063bede39b51461024557600080fd5b8063519b4bd311610124578063704655971161010957806370465597146101d8578063715018a6146101eb5780638c8885c8146101f357600080fd5b8063519b4bd3146101c657806355161913146101cf57600080fd5b8063313ce56711610155578063313ce567146101955780633577afc51461019e57806349948e0e146101b357600080fd5b80630c18c162146101715780630d1e43a01461018d575b600080fd5b61017a60035481565b6040519081526020015b60405180910390f35b60065461017a565b61017a60055481565b6101b16101ac366004610ad9565b6102e9565b005b61017a6101c1366004610b21565b610391565b61017a60025481565b61017a60075481565b6101b16101e6366004610ad9565b6103ed565b6101b1610489565b6101b1610201366004610ad9565b6104fc565b60005473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610184565b6101b1610253366004610ad9565b610598565b6101b1610266366004610ad9565b610634565b6101b1610279366004610ad9565b6106d0565b61017a61028c366004610b21565b6107ce565b6008546102209073ffffffffffffffffffffffffffffffffffffffff1681565b6101b16102bf366004610bf0565b610872565b61017a60045481565b6101b16102db366004610ad9565b61096e565b61017a60015481565b60005473ffffffffffffffffffffffffffffffffffffffff1633146103555760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064015b60405180910390fd5b60038190556040518181527f32740b35c0ea213650f60d44366b4fb211c9033b50714e4a1d34e65d5beb9bb4906020015b60405180910390a150565b60008061039d836107ce565b90506000600254826103af9190610c5c565b90506000600554600a6103c29190610dbb565b90506000600454836103d49190610c5c565b905060006103e28383610dc7565b979650505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146104545760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161034c565b60048190556040518181527f3336cd9708eaf2769a0f0dc0679f30e80f15dcd88d1921b5a16858e8b85c591a90602001610386565b60005473ffffffffffffffffffffffffffffffffffffffff1633146104f05760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161034c565b6104fa6000610a64565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633146105635760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161034c565b60058190556040518181527fd68112a8707e326d08be3656b528c1bcc5bbbfc47f4177e2179b14d8640838c190602001610386565b60005473ffffffffffffffffffffffffffffffffffffffff1633146105ff5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161034c565b60028190556040518181527f351fb23757bb5ea0546c85b7996ddd7155f96b939ebaa5ff7bc49c75f27f2c4490602001610386565b60005473ffffffffffffffffffffffffffffffffffffffff16331461069b5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161034c565b60018190556040518181527ffcdccc6074c6c42e4bd578aa9870c697dc976a270968452d2b8c8dc369fae39690602001610386565b60005473ffffffffffffffffffffffffffffffffffffffff1633146107375760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161034c565b808015806107455750806001145b6107915760405162461bcd60e51b815260206004820152601c60248201527f696e76616c69642076616c75652c6d7573742062652030206f72203100000000604482015260640161034c565b60068290556040518281527fd1eaae13a99b475ddca546a1b4a45052c66c14049997f44a1731a8e7167981a7906020015b60405180910390a15050565b600080805b835181101561084b578381815181106107ee576107ee610e02565b01602001517fff000000000000000000000000000000000000000000000000000000000000001661082b57610824600483610e31565b9150610839565b610836601083610e31565b91505b8061084381610e49565b9150506107d3565b5060006003548261085c9190610e31565b905061086a81610440610e31565b949350505050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146108d95760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161034c565b73ffffffffffffffffffffffffffffffffffffffff81166109625760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161034c565b61096b81610a64565b50565b60005473ffffffffffffffffffffffffffffffffffffffff1633146109d55760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161034c565b808015806109e35750806001145b610a2f5760405162461bcd60e51b815260206004820152601c60248201527f696e76616c69642076616c75652c6d7573742062652030206f72203100000000604482015260640161034c565b60078290556040518281527f49244d4195584d0644398167ca8caa7b98ee36b674e4b4d2a2640749b27eafb7906020016107c2565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600060208284031215610aeb57600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600060208284031215610b3357600080fd5b813567ffffffffffffffff80821115610b4b57600080fd5b818401915084601f830112610b5f57600080fd5b813581811115610b7157610b71610af2565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715610bb757610bb7610af2565b81604052828152876020848701011115610bd057600080fd5b826020860160208301376000928101602001929092525095945050505050565b600060208284031215610c0257600080fd5b813573ffffffffffffffffffffffffffffffffffffffff81168114610c2657600080fd5b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615610c9457610c94610c2d565b500290565b600181815b80851115610cf257817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115610cd857610cd8610c2d565b80851615610ce557918102915b93841c9390800290610c9e565b509250929050565b600082610d0957506001610db5565b81610d1657506000610db5565b8160018114610d2c5760028114610d3657610d52565b6001915050610db5565b60ff841115610d4757610d47610c2d565b50506001821b610db5565b5060208310610133831016604e8410600b8410161715610d75575081810a610db5565b610d7f8383610c99565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115610db157610db1610c2d565b0290505b92915050565b6000610c268383610cfa565b600082610dfd577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008219821115610e4457610e44610c2d565b500190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415610e7b57610e7b610c2d565b506001019056fea26469706673582212207da82d9f1ffefb5ad9863297e3bb633970d9ab86e98a6bf78a4411e4ca1e9e2864736f6c63430008090033" + "code": "0x608060405234801561001057600080fd5b506004361061012c5760003560e01c80638da5cb5b116100ad578063ea01cd3611610071578063ea01cd3614610237578063f2fde38b1461024a578063f45e65d81461025d578063fc55b13814610266578063fe173b971461027957600080fd5b80638da5cb5b146101c6578063bede39b5146101eb578063bf1fe420146101fe578063c764783214610211578063de26c4a11461022457600080fd5b8063519b4bd3116100f4578063519b4bd314610186578063551619131461018f5780637046559714610198578063715018a6146101ab5780638c8885c8146101b357600080fd5b80630c18c162146101315780630d1e43a01461014d578063313ce567146101555780633577afc51461015e57806349948e0e14610173575b600080fd5b61013a60035481565b6040519081526020015b60405180910390f35b60065461013a565b61013a60055481565b61017161016c3660046107f0565b610282565b005b61013a61018136600461081f565b6102f1565b61013a60025481565b61013a60075481565b6101716101a63660046107f0565b61034d565b6101716103ac565b6101716101c13660046107f0565b6103e2565b6000546001600160a01b03165b6040516001600160a01b039091168152602001610144565b6101716101f93660046107f0565b610441565b61017161020c3660046107f0565b6104a0565b61017161021f3660046107f0565b6104ff565b61013a61023236600461081f565b6105c0565b6008546101d3906001600160a01b031681565b6101716102583660046108d0565b61064c565b61013a60045481565b6101716102743660046107f0565b6106e7565b61013a60015481565b6000546001600160a01b031633146102b55760405162461bcd60e51b81526004016102ac90610900565b60405180910390fd5b60038190556040518181527f32740b35c0ea213650f60d44366b4fb211c9033b50714e4a1d34e65d5beb9bb4906020015b60405180910390a150565b6000806102fd836105c0565b905060006002548261030f919061094b565b90506000600554600a6103229190610a50565b9050600060045483610334919061094b565b905060006103428383610a5c565b979650505050505050565b6000546001600160a01b031633146103775760405162461bcd60e51b81526004016102ac90610900565b60048190556040518181527f3336cd9708eaf2769a0f0dc0679f30e80f15dcd88d1921b5a16858e8b85c591a906020016102e6565b6000546001600160a01b031633146103d65760405162461bcd60e51b81526004016102ac90610900565b6103e060006107a0565b565b6000546001600160a01b0316331461040c5760405162461bcd60e51b81526004016102ac90610900565b60058190556040518181527fd68112a8707e326d08be3656b528c1bcc5bbbfc47f4177e2179b14d8640838c1906020016102e6565b6000546001600160a01b0316331461046b5760405162461bcd60e51b81526004016102ac90610900565b60028190556040518181527f351fb23757bb5ea0546c85b7996ddd7155f96b939ebaa5ff7bc49c75f27f2c44906020016102e6565b6000546001600160a01b031633146104ca5760405162461bcd60e51b81526004016102ac90610900565b60018190556040518181527ffcdccc6074c6c42e4bd578aa9870c697dc976a270968452d2b8c8dc369fae396906020016102e6565b6000546001600160a01b031633146105295760405162461bcd60e51b81526004016102ac90610900565b808015806105375750806001145b6105835760405162461bcd60e51b815260206004820152601c60248201527f696e76616c69642076616c75652c6d7573742062652030206f7220310000000060448201526064016102ac565b60068290556040518281527fd1eaae13a99b475ddca546a1b4a45052c66c14049997f44a1731a8e7167981a7906020015b60405180910390a15050565b600080805b8351811015610625578381815181106105e0576105e0610a7e565b01602001516001600160f81b031916610605576105fe600483610a94565b9150610613565b610610601083610a94565b91505b8061061d81610aac565b9150506105c5565b506000600354826106369190610a94565b905061064481610440610a94565b949350505050565b6000546001600160a01b031633146106765760405162461bcd60e51b81526004016102ac90610900565b6001600160a01b0381166106db5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016102ac565b6106e4816107a0565b50565b6000546001600160a01b031633146107115760405162461bcd60e51b81526004016102ac90610900565b8080158061071f5750806001145b61076b5760405162461bcd60e51b815260206004820152601c60248201527f696e76616c69642076616c75652c6d7573742062652030206f7220310000000060448201526064016102ac565b60078290556040518281527f49244d4195584d0644398167ca8caa7b98ee36b674e4b4d2a2640749b27eafb7906020016105b4565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60006020828403121561080257600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b60006020828403121561083157600080fd5b813567ffffffffffffffff8082111561084957600080fd5b818401915084601f83011261085d57600080fd5b81358181111561086f5761086f610809565b604051601f8201601f19908116603f0116810190838211818310171561089757610897610809565b816040528281528760208487010111156108b057600080fd5b826020860160208301376000928101602001929092525095945050505050565b6000602082840312156108e257600080fd5b81356001600160a01b03811681146108f957600080fd5b9392505050565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b634e487b7160e01b600052601160045260246000fd5b600081600019048311821515161561096557610965610935565b500290565b600181815b808511156109a557816000190482111561098b5761098b610935565b8085161561099857918102915b93841c939080029061096f565b509250929050565b6000826109bc57506001610a4a565b816109c957506000610a4a565b81600181146109df57600281146109e957610a05565b6001915050610a4a565b60ff8411156109fa576109fa610935565b50506001821b610a4a565b5060208310610133831016604e8410600b8410161715610a28575081810a610a4a565b610a32838361096a565b8060001904821115610a4657610a46610935565b0290505b92915050565b60006108f983836109ad565b600082610a7957634e487b7160e01b600052601260045260246000fd5b500490565b634e487b7160e01b600052603260045260246000fd5b60008219821115610aa757610aa7610935565b500190565b6000600019821415610ac057610ac0610935565b506001019056fea264697066735822122043d302590ccee26da66f62b9035147e6f028d5a093582f0dd3d61948a781608564736f6c63430008090033" }, "0x4200000000000000000000000000000000000010": { "balance": "00", @@ -68,7 +64,7 @@ "0x0000000000000000000000000000000000000000000000000000000000000001": "0x00000000000000000000000052753615226f8ac8a464bfecb11ef798cff3793f", "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000004200000000000000000000000000000000000007" }, - "code": "0x608060405234801561001057600080fd5b50600436106100675760003560e01c80633cb747bf116100505780633cb747bf146100ca578063662a633a146100ea578063a3a79548146100fd57600080fd5b806332b7006d1461006c57806336c717c114610081575b600080fd5b61007f61007a366004610d7c565b610110565b005b6001546100a19073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b6000546100a19073ffffffffffffffffffffffffffffffffffffffff1681565b61007f6100f8366004610ded565b610126565b61007f61010b366004610e85565b6106c1565b61011f853333878787876106d8565b5050505050565b60015473ffffffffffffffffffffffffffffffffffffffff1661015e60005473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461021d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f42564d5f58434841494e3a206d657373656e67657220636f6e7472616374207560448201527f6e61757468656e7469636174656400000000000000000000000000000000000060648201526084015b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1661025360005473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff16636e296e456040518163ffffffff1660e01b815260040160206040518083038186803b15801561029857600080fd5b505afa1580156102ac573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102d09190610f08565b73ffffffffffffffffffffffffffffffffffffffff1614610373576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f42564d5f58434841494e3a2077726f6e672073656e646572206f662063726f7360448201527f732d646f6d61696e206d657373616765000000000000000000000000000000006064820152608401610214565b61039d877f1d1d8b6300000000000000000000000000000000000000000000000000000000610a9f565b801561045357508673ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156103ec57600080fd5b505af1158015610400573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104249190610f08565b73ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff16145b15610567576040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8681166004830152602482018690528816906340c10f1990604401600060405180830381600087803b1580156104c857600080fd5b505af11580156104dc573d6000803e3d6000fd5b505050508573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff167fb0444523268717a02698be47d0803aa7468c00acbed2f8bd93a0459cde61dd898888888860405161055a9493929190610f75565b60405180910390a46106b7565b600063a9f9e67560e01b8989888a89898960405160240161058e9796959493929190610fab565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526001549091506106339073ffffffffffffffffffffffffffffffffffffffff16600083610ac4565b8673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff167f7ea89a4591614515571c2b51f5ea06494056f261c10ab1ed8c03c7590d87bce0898989896040516106ad9493929190610f75565b60405180910390a4505b5050505050505050565b6106d0863387878787876106d8565b505050505050565b6040517f9dc29fac0000000000000000000000000000000000000000000000000000000081523360048201526024810185905273ffffffffffffffffffffffffffffffffffffffff881690639dc29fac90604401600060405180830381600087803b15801561074657600080fd5b505af115801561075a573d6000803e3d6000fd5b5050505060008773ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156107a857600080fd5b505af11580156107bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107e09190610f08565b9050606073ffffffffffffffffffffffffffffffffffffffff891673deaddeaddeaddeaddeaddeaddeaddeaddead111114156108d5576040517f1532ec340000000000000000000000000000000000000000000000000000000090610851908a908a908a9089908990602401611008565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091529050610a01565b73ffffffffffffffffffffffffffffffffffffffff891673deaddeaddeaddeaddeaddeaddeaddeaddead00001415610942576040517f839f0ec60000000000000000000000000000000000000000000000000000000090610851908a908a908a9089908990602401611008565b6040517fa9f9e67500000000000000000000000000000000000000000000000000000000906109819084908c908c908c908c908b908b90602401610fab565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915290505b600154610a259073ffffffffffffffffffffffffffffffffffffffff168683610ac4565b3373ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f73d170910aba9e6d50b102db522b1dbcd796216f5128b445aa2135272886497e8a8a89896040516106ad9493929190610f75565b6000610aaa83610b55565b8015610abb5750610abb8383610bb9565b90505b92915050565b6000546040517f3dbb202b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911690633dbb202b90610b1e90869085908790600401611083565b600060405180830381600087803b158015610b3857600080fd5b505af1158015610b4c573d6000803e3d6000fd5b50505050505050565b6000610b81827f01ffc9a700000000000000000000000000000000000000000000000000000000610bb9565b8015610abe5750610bb2827fffffffff00000000000000000000000000000000000000000000000000000000610bb9565b1592915050565b604080517fffffffff00000000000000000000000000000000000000000000000000000000831660248083019190915282518083039091018152604490910182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a7000000000000000000000000000000000000000000000000000000001790529051600091908290819073ffffffffffffffffffffffffffffffffffffffff87169061753090610c739086906110ff565b6000604051808303818686fa925050503d8060008114610caf576040519150601f19603f3d011682016040523d82523d6000602084013e610cb4565b606091505b5091509150602081511015610ccf5760009350505050610abe565b818015610ceb575080806020019051810190610ceb919061111b565b9695505050505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610d1757600080fd5b50565b803563ffffffff81168114610d2e57600080fd5b919050565b60008083601f840112610d4557600080fd5b50813567ffffffffffffffff811115610d5d57600080fd5b602083019150836020828501011115610d7557600080fd5b9250929050565b600080600080600060808688031215610d9457600080fd5b8535610d9f81610cf5565b945060208601359350610db460408701610d1a565b9250606086013567ffffffffffffffff811115610dd057600080fd5b610ddc88828901610d33565b969995985093965092949392505050565b600080600080600080600060c0888a031215610e0857600080fd5b8735610e1381610cf5565b96506020880135610e2381610cf5565b95506040880135610e3381610cf5565b94506060880135610e4381610cf5565b93506080880135925060a088013567ffffffffffffffff811115610e6657600080fd5b610e728a828b01610d33565b989b979a50959850939692959293505050565b60008060008060008060a08789031215610e9e57600080fd5b8635610ea981610cf5565b95506020870135610eb981610cf5565b945060408701359350610ece60608801610d1a565b9250608087013567ffffffffffffffff811115610eea57600080fd5b610ef689828a01610d33565b979a9699509497509295939492505050565b600060208284031215610f1a57600080fd5b8151610f2581610cf5565b9392505050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b73ffffffffffffffffffffffffffffffffffffffff85168152836020820152606060408201526000610ceb606083018486610f2c565b600073ffffffffffffffffffffffffffffffffffffffff808a1683528089166020840152808816604084015280871660608401525084608083015260c060a0830152610ffb60c083018486610f2c565b9998505050505050505050565b600073ffffffffffffffffffffffffffffffffffffffff808816835280871660208401525084604083015260806060830152611048608083018486610f2c565b979650505050505050565b60005b8381101561106e578181015183820152602001611056565b8381111561107d576000848401525b50505050565b73ffffffffffffffffffffffffffffffffffffffff8416815260606020820152600083518060608401526110be816080850160208801611053565b63ffffffff93909316604083015250601f919091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160160800192915050565b60008251611111818460208701611053565b9190910192915050565b60006020828403121561112d57600080fd5b81518015158114610f2557600080fdfea2646970667358221220c3a18d6cb25a717fc2811d2494b09dcae28c97abb0e1e8f4d4292e1aa816717564736f6c63430008090033" + "code": "0x608060405234801561001057600080fd5b50600436106100575760003560e01c806332b7006d1461005c57806336c717c1146100715780633cb747bf146100a0578063662a633a146100b3578063a3a79548146100c6575b600080fd5b61006f61006a366004610968565b6100d9565b005b600154610084906001600160a01b031681565b6040516001600160a01b03909116815260200160405180910390f35b600054610084906001600160a01b031681565b61006f6100c13660046109d9565b6100ef565b61006f6100d4366004610a71565b6104c6565b6100e8853333878787876104dd565b5050505050565b6001546001600160a01b031661010d6000546001600160a01b031690565b6001600160a01b0316336001600160a01b0316146101895760405162461bcd60e51b815260206004820152602e60248201527f42564d5f58434841494e3a206d657373656e67657220636f6e7472616374207560448201526d1b985d5d1a195b9d1a58d85d195960921b60648201526084015b60405180910390fd5b806001600160a01b03166101a56000546001600160a01b031690565b6001600160a01b0316636e296e456040518163ffffffff1660e01b815260040160206040518083038186803b1580156101dd57600080fd5b505afa1580156101f1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102159190610af4565b6001600160a01b0316146102845760405162461bcd60e51b815260206004820152603060248201527f42564d5f58434841494e3a2077726f6e672073656e646572206f662063726f7360448201526f732d646f6d61696e206d65737361676560801b6064820152608401610180565b61029587631d1d8b6360e01b610742565b80156103245750866001600160a01b031663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156102d757600080fd5b505af11580156102eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061030f9190610af4565b6001600160a01b0316886001600160a01b0316145b156103eb576040516340c10f1960e01b81526001600160a01b038681166004830152602482018690528816906340c10f1990604401600060405180830381600087803b15801561037357600080fd5b505af1158015610387573d6000803e3d6000fd5b50505050856001600160a01b0316876001600160a01b0316896001600160a01b03167fb0444523268717a02698be47d0803aa7468c00acbed2f8bd93a0459cde61dd89888888886040516103de9493929190610b41565b60405180910390a46104bc565b600063a9f9e67560e01b8989888a8989896040516024016104129796959493929190610b69565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915260015490915061045f906001600160a01b0316600083610767565b866001600160a01b0316886001600160a01b03168a6001600160a01b03167f7ea89a4591614515571c2b51f5ea06494056f261c10ab1ed8c03c7590d87bce0898989896040516104b29493929190610b41565b60405180910390a4505b5050505050505050565b6104d5863387878787876104dd565b505050505050565b604051632770a7eb60e21b8152336004820152602481018590526001600160a01b03881690639dc29fac90604401600060405180830381600087803b15801561052557600080fd5b505af1158015610539573d6000803e3d6000fd5b505050506000876001600160a01b031663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561057a57600080fd5b505af115801561058e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105b29190610af4565b905060606001600160a01b03891673deaddeaddeaddeaddeaddeaddeaddeaddead111114156106365760405163054cbb0d60e21b906105fd908a908a908a9089908990602401610bba565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915290506106d8565b6001600160a01b03891673deaddeaddeaddeaddeaddeaddeaddeaddead0000141561067d576040516341cf876360e11b906105fd908a908a908a9089908990602401610bba565b60405163a9f9e67560e01b906106a39084908c908c908c908c908b908b90602401610b69565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915290505b6001546106ef906001600160a01b03168683610767565b336001600160a01b0316896001600160a01b0316836001600160a01b03167f73d170910aba9e6d50b102db522b1dbcd796216f5128b445aa2135272886497e8a8a89896040516104b29493929190610b41565b600061074d836107d2565b801561075e575061075e8383610805565b90505b92915050565b600054604051633dbb202b60e01b81526001600160a01b0390911690633dbb202b9061079b90869085908790600401610c29565b600060405180830381600087803b1580156107b557600080fd5b505af11580156107c9573d6000803e3d6000fd5b50505050505050565b60006107e5826301ffc9a760e01b610805565b801561076157506107fe826001600160e01b0319610805565b1592915050565b604080516001600160e01b0319831660248083019190915282518083039091018152604490910182526020810180516001600160e01b03166301ffc9a760e01b179052905160009190829081906001600160a01b038716906175309061086c908690610c79565b6000604051808303818686fa925050503d80600081146108a8576040519150601f19603f3d011682016040523d82523d6000602084013e6108ad565b606091505b50915091506020815110156108c85760009350505050610761565b8180156108e45750808060200190518101906108e49190610c95565b9695505050505050565b6001600160a01b038116811461090357600080fd5b50565b803563ffffffff8116811461091a57600080fd5b919050565b60008083601f84011261093157600080fd5b50813567ffffffffffffffff81111561094957600080fd5b60208301915083602082850101111561096157600080fd5b9250929050565b60008060008060006080868803121561098057600080fd5b853561098b816108ee565b9450602086013593506109a060408701610906565b9250606086013567ffffffffffffffff8111156109bc57600080fd5b6109c88882890161091f565b969995985093965092949392505050565b600080600080600080600060c0888a0312156109f457600080fd5b87356109ff816108ee565b96506020880135610a0f816108ee565b95506040880135610a1f816108ee565b94506060880135610a2f816108ee565b93506080880135925060a088013567ffffffffffffffff811115610a5257600080fd5b610a5e8a828b0161091f565b989b979a50959850939692959293505050565b60008060008060008060a08789031215610a8a57600080fd5b8635610a95816108ee565b95506020870135610aa5816108ee565b945060408701359350610aba60608801610906565b9250608087013567ffffffffffffffff811115610ad657600080fd5b610ae289828a0161091f565b979a9699509497509295939492505050565b600060208284031215610b0657600080fd5b8151610b11816108ee565b9392505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60018060a01b03851681528360208201526060604082015260006108e4606083018486610b18565b6001600160a01b03888116825287811660208301528681166040830152851660608201526080810184905260c060a08201819052600090610bad9083018486610b18565b9998505050505050505050565b6001600160a01b0386811682528516602082015260408101849052608060608201819052600090610bee9083018486610b18565b979650505050505050565b60005b83811015610c14578181015183820152602001610bfc565b83811115610c23576000848401525b50505050565b60018060a01b03841681526060602082015260008351806060840152610c56816080850160208801610bf9565b63ffffffff93909316604083015250601f91909101601f19160160800192915050565b60008251610c8b818460208701610bf9565b9190910192915050565b600060208284031215610ca757600080fd5b81518015158114610b1157600080fdfea2646970667358221220fe7ba0193a50834483182d324f34ea84cfeec79c5d6d70c7c1671af2e2c9801f64736f6c63430008090033" }, "0x4200000000000000000000000000000000000011": { "balance": "00", @@ -79,12 +75,12 @@ "0x0000000000000000000000000000000000000000000000000000000000000003": "0x000000000000000000000000000000000000000000000000000000000000dead", "0x0000000000000000000000000000000000000000000000000000000000000004": "0x000000000000000000000000000000000000000000000000000000000000000f" }, - "code": "0x6080604052600436106100cb5760003560e01c806385b5b14d11610074578063bfb084621161004e578063bfb084621461022d578063d4ff92181461024d578063f2fde38b1461027a57600080fd5b806385b5b14d146101c25780638da5cb5b146101e2578063a996d6ce1461020d57600080fd5b80635558979e116100a55780635558979e14610172578063715018a6146101975780638312f149146101ac57600080fd5b8063110b7eb0146100d757806327810b6e1461012e5780633ccfd60b1461015b57600080fd5b366100d257005b600080fd5b3480156100e357600080fd5b506002546101049073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b34801561013a57600080fd5b506003546101049073ffffffffffffffffffffffffffffffffffffffff1681565b34801561016757600080fd5b5061017061029a565b005b34801561017e57600080fd5b5061018962030d4081565b604051908152602001610125565b3480156101a357600080fd5b50610170610507565b3480156101b857600080fd5b5061018960045481565b3480156101ce57600080fd5b506101706101dd36600461094f565b610594565b3480156101ee57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff16610104565b34801561021957600080fd5b50610170610228366004610968565b61061a565b34801561023957600080fd5b50610170610248366004610968565b6106e2565b34801561025957600080fd5b506001546101049073ffffffffffffffffffffffffffffffffffffffff1681565b34801561028657600080fd5b50610170610295366004610968565b6107aa565b600154600254604080517f0d1e43a0000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff9384169390921691630d1e43a091600480820192602092909190829003018186803b15801561030c57600080fd5b505afa158015610320573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061034491906109a5565b6001141561038d575060035460045473ffffffffffffffffffffffffffffffffffffffff9091169061037e90670de0b6b3a76400006109be565b4710156103885750565b61045c565b6004546103a290670de0b6b3a76400006109be565b47101561045c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605760248201527f42564d5f53657175656e6365724665655661756c743a2077697468647261776160448201527f6c20616d6f756e74206d7573742062652067726561746572207468616e206d6960648201527f6e696d756d207769746864726177616c20616d6f756e74000000000000000000608482015260a4015b60405180910390fd5b60408051602081018252600080825291517fa3a795480000000000000000000000000000000000000000000000000000000081527342000000000000000000000000000000000000109263a3a79548926104d29273deaddeaddeaddeaddeaddeaddeaddeaddead00009287924792600401610a22565b600060405180830381600087803b1580156104ec57600080fd5b505af1158015610500573d6000803e3d6000fd5b5050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610588576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610453565b61059260006108da565b565b60005473ffffffffffffffffffffffffffffffffffffffff163314610615576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610453565b600455565b60005473ffffffffffffffffffffffffffffffffffffffff16331461069b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610453565b600380547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60005473ffffffffffffffffffffffffffffffffffffffff163314610763576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610453565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60005473ffffffffffffffffffffffffffffffffffffffff16331461082b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610453565b73ffffffffffffffffffffffffffffffffffffffff81166108ce576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610453565b6108d7816108da565b50565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60006020828403121561096157600080fd5b5035919050565b60006020828403121561097a57600080fd5b813573ffffffffffffffffffffffffffffffffffffffff8116811461099e57600080fd5b9392505050565b6000602082840312156109b757600080fd5b5051919050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615610a1d577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b500290565b600073ffffffffffffffffffffffffffffffffffffffff808816835260208188168185015286604085015263ffffffff8616606085015260a06080850152845191508160a085015260005b82811015610a895785810182015185820160c001528101610a6d565b82811115610a9b57600060c084870101525b5050601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160c001969550505050505056fea2646970667358221220b2183fcbf33cd5cb8663019340024e5a70875041f8799aeca9ffc8e7f6db0aa164736f6c63430008090033" + "code": "0x6080604052600436106100ab5760003560e01c806385b5b14d1161006457806385b5b14d1461017b5780638da5cb5b1461019b578063a996d6ce146101b9578063bfb08462146101d9578063d4ff9218146101f9578063f2fde38b1461021957600080fd5b8063110b7eb0146100b757806327810b6e146100f45780633ccfd60b146101145780635558979e1461012b578063715018a6146101505780638312f1491461016557600080fd5b366100b257005b600080fd5b3480156100c357600080fd5b506002546100d7906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561010057600080fd5b506003546100d7906001600160a01b031681565b34801561012057600080fd5b50610129610239565b005b34801561013757600080fd5b5061014262030d4081565b6040519081526020016100eb565b34801561015c57600080fd5b50610129610432565b34801561017157600080fd5b5061014260045481565b34801561018757600080fd5b5061012961019636600461061a565b610468565b3480156101a757600080fd5b506000546001600160a01b03166100d7565b3480156101c557600080fd5b506101296101d4366004610633565b610497565b3480156101e557600080fd5b506101296101f4366004610633565b6104e3565b34801561020557600080fd5b506001546100d7906001600160a01b031681565b34801561022557600080fd5b50610129610234366004610633565b61052f565b600154600254604080516268f21d60e51b815290516001600160a01b039384169390921691630d1e43a091600480820192602092909190829003018186803b15801561028457600080fd5b505afa158015610298573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102bc9190610663565b600114156102f857506003546004546001600160a01b03909116906102e990670de0b6b3a764000061067c565b4710156102f35750565b6103ad565b60045461030d90670de0b6b3a764000061067c565b4710156103ad5760405162461bcd60e51b815260206004820152605760248201527f42564d5f53657175656e6365724665655661756c743a2077697468647261776160448201527f6c20616d6f756e74206d7573742062652067726561746572207468616e206d6960648201527f6e696d756d207769746864726177616c20616d6f756e74000000000000000000608482015260a4015b60405180910390fd5b6040805160208101825260008082529151631474f2a960e31b81526010602160991b019263a3a79548926103fd9273deaddeaddeaddeaddeaddeaddeaddeaddead000092879247926004016106a9565b600060405180830381600087803b15801561041757600080fd5b505af115801561042b573d6000803e3d6000fd5b5050505050565b6000546001600160a01b0316331461045c5760405162461bcd60e51b81526004016103a49061072e565b61046660006105ca565b565b6000546001600160a01b031633146104925760405162461bcd60e51b81526004016103a49061072e565b600455565b6000546001600160a01b031633146104c15760405162461bcd60e51b81526004016103a49061072e565b600380546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b0316331461050d5760405162461bcd60e51b81526004016103a49061072e565b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b031633146105595760405162461bcd60e51b81526004016103a49061072e565b6001600160a01b0381166105be5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016103a4565b6105c7816105ca565b50565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60006020828403121561062c57600080fd5b5035919050565b60006020828403121561064557600080fd5b81356001600160a01b038116811461065c57600080fd5b9392505050565b60006020828403121561067557600080fd5b5051919050565b60008160001904831182151516156106a457634e487b7160e01b600052601160045260246000fd5b500290565b600060018060a01b03808816835260208188168185015286604085015263ffffffff8616606085015260a06080850152845191508160a085015260005b828110156107025785810182015185820160c0015281016106e6565b8281111561071457600060c084870101525b5050601f01601f19169190910160c0019695505050505050565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260408201526060019056fea26469706673582212202a2581884faf9f26be8cf5e371d77eb3190d6611f60d05e5bfed3176d8790f6b64736f6c63430008090033" }, "0x4200000000000000000000000000000000000012": { "balance": "00", "storage": {}, - "code": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c80630769a96914610030575b600080fd5b61004361003e36600461025c565b610045565b005b73ffffffffffffffffffffffffffffffffffffffff84166100c6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4d7573742070726f76696465204c3120746f6b656e2061646472657373000000604482015260640160405180910390fd5b6000734200000000000000000000000000000000000010858585856040516100ed90610175565b6100fb95949392919061036f565b604051809103906000f080158015610117573d6000803e3d6000fd5b5060405160ff8416815290915073ffffffffffffffffffffffffffffffffffffffff80831691908716907f41e27481c6f764357db26ae29b68b9f3aafc40b87444459cbf50d338c75317329060200160405180910390a35050505050565b61146d806103d183390190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126101c257600080fd5b813567ffffffffffffffff808211156101dd576101dd610182565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561022357610223610182565b8160405283815286602085880101111561023c57600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806000806080858703121561027257600080fd5b843573ffffffffffffffffffffffffffffffffffffffff8116811461029657600080fd5b9350602085013567ffffffffffffffff808211156102b357600080fd5b6102bf888389016101b1565b945060408701359150808211156102d557600080fd5b506102e2878288016101b1565b925050606085013560ff811681146102f957600080fd5b939692955090935050565b6000815180845260005b8181101561032a5760208185018101518683018201520161030e565b8181111561033c576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b600073ffffffffffffffffffffffffffffffffffffffff808816835280871660208401525060a060408301526103a860a0830186610304565b82810360608401526103ba8186610304565b91505060ff83166080830152969550505050505056fe60806040523480156200001157600080fd5b506040516200146d3803806200146d833981016040819052620000349162000247565b8251839083906200004d906003906020850190620000b7565b50805162000063906004906020840190620000b7565b5050600580546001600160a01b039687166001600160a01b0319909116179055506006805460ff909216600160a01b026001600160a81b031990921695909416949094179390931790915550620003309050565b828054620000c590620002f3565b90600052602060002090601f016020900481019282620000e9576000855562000134565b82601f106200010457805160ff191683800117855562000134565b8280016001018555821562000134579182015b828111156200013457825182559160200191906001019062000117565b506200014292915062000146565b5090565b5b8082111562000142576000815560010162000147565b80516001600160a01b03811681146200017557600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620001a257600080fd5b81516001600160401b0380821115620001bf57620001bf6200017a565b604051601f8301601f19908116603f01168101908282118183101715620001ea57620001ea6200017a565b816040528381526020925086838588010111156200020757600080fd5b600091505b838210156200022b57858201830151818301840152908201906200020c565b838211156200023d5760008385830101525b9695505050505050565b600080600080600060a086880312156200026057600080fd5b6200026b866200015d565b94506200027b602087016200015d565b60408701519094506001600160401b03808211156200029957600080fd5b620002a789838a0162000190565b94506060880151915080821115620002be57600080fd5b50620002cd8882890162000190565b925050608086015160ff81168114620002e557600080fd5b809150509295509295909350565b600181811c908216806200030857607f821691505b602082108114156200032a57634e487b7160e01b600052602260045260246000fd5b50919050565b61112d80620003406000396000f3fe608060405234801561001057600080fd5b506004361061011b5760003560e01c806370a08231116100b2578063a457c2d711610081578063ae1f6aaf11610066578063ae1f6aaf1461028a578063c01e1bd6146102cf578063dd62ed3e146102ef57600080fd5b8063a457c2d714610264578063a9059cbb1461027757600080fd5b806370a08231146101ee57806376809ce31461022457806395d89b41146102495780639dc29fac1461025157600080fd5b806323b872dd116100ee57806323b872dd14610182578063313ce5671461019557806339509351146101c657806340c10f19146101d957600080fd5b806301ffc9a71461012057806306fdde0314610148578063095ea7b31461015d57806318160ddd14610170575b600080fd5b61013361012e366004610eac565b610335565b60405190151581526020015b60405180910390f35b6101506103f5565b60405161013f9190610ef5565b61013361016b366004610f91565b610487565b6002545b60405190815260200161013f565b610133610190366004610fbb565b61049d565b60065474010000000000000000000000000000000000000000900460ff165b60405160ff909116815260200161013f565b6101336101d4366004610f91565b61056e565b6101ec6101e7366004610f91565b6105b7565b005b6101746101fc366004610ff7565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6006546101b49074010000000000000000000000000000000000000000900460ff1681565b61015061067c565b6101ec61025f366004610f91565b61068b565b610133610272366004610f91565b610744565b610133610285366004610f91565b610802565b6006546102aa9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161013f565b6005546102aa9073ffffffffffffffffffffffffffffffffffffffff1681565b6101746102fd366004611012565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b60007f01ffc9a7a5cef8baa21ed3c5c0d7e23accb804b619e9333b597f47a0d84076e27f1d1d8b63000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000084167f01ffc9a70000000000000000000000000000000000000000000000000000000014806103ed57507fffffffff00000000000000000000000000000000000000000000000000000000848116908216145b949350505050565b60606003805461040490611045565b80601f016020809104026020016040519081016040528092919081815260200182805461043090611045565b801561047d5780601f106104525761010080835404028352916020019161047d565b820191906000526020600020905b81548152906001019060200180831161046057829003601f168201915b5050505050905090565b600061049433848461080f565b50600192915050565b60006104aa84848461098f565b73ffffffffffffffffffffffffffffffffffffffff84166000908152600160209081526040808320338452909152902054828110156105565760405162461bcd60e51b815260206004820152602860248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206160448201527f6c6c6f77616e636500000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b610563853385840361080f565b506001949350505050565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490916104949185906105b29086906110c8565b61080f565b60065473ffffffffffffffffffffffffffffffffffffffff16331461061e5760405162461bcd60e51b815260206004820181905260248201527f4f6e6c79204c32204272696467652063616e206d696e7420616e64206275726e604482015260640161054d565b6106288282610bf5565b8173ffffffffffffffffffffffffffffffffffffffff167f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d41213968858260405161067091815260200190565b60405180910390a25050565b60606004805461040490611045565b60065473ffffffffffffffffffffffffffffffffffffffff1633146106f25760405162461bcd60e51b815260206004820181905260248201527f4f6e6c79204c32204272696467652063616e206d696e7420616e64206275726e604482015260640161054d565b6106fc8282610cfb565b8173ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca58260405161067091815260200190565b33600090815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff86168452909152812054828110156107eb5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f000000000000000000000000000000000000000000000000000000606482015260840161054d565b6107f8338585840361080f565b5060019392505050565b600061049433848461098f565b73ffffffffffffffffffffffffffffffffffffffff83166108975760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f7265737300000000000000000000000000000000000000000000000000000000606482015260840161054d565b73ffffffffffffffffffffffffffffffffffffffff82166109205760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f7373000000000000000000000000000000000000000000000000000000000000606482015260840161054d565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8316610a185760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f6472657373000000000000000000000000000000000000000000000000000000606482015260840161054d565b73ffffffffffffffffffffffffffffffffffffffff8216610aa15760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f6573730000000000000000000000000000000000000000000000000000000000606482015260840161054d565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610b3d5760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e63650000000000000000000000000000000000000000000000000000606482015260840161054d565b73ffffffffffffffffffffffffffffffffffffffff808516600090815260208190526040808220858503905591851681529081208054849290610b819084906110c8565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610be791815260200190565b60405180910390a350505050565b73ffffffffffffffffffffffffffffffffffffffff8216610c585760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015260640161054d565b8060026000828254610c6a91906110c8565b909155505073ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604081208054839290610ca49084906110c8565b909155505060405181815273ffffffffffffffffffffffffffffffffffffffff8316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b73ffffffffffffffffffffffffffffffffffffffff8216610d845760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f7300000000000000000000000000000000000000000000000000000000000000606482015260840161054d565b73ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604090205481811015610e205760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f6365000000000000000000000000000000000000000000000000000000000000606482015260840161054d565b73ffffffffffffffffffffffffffffffffffffffff83166000908152602081905260408120838303905560028054849290610e5c9084906110e0565b909155505060405182815260009073ffffffffffffffffffffffffffffffffffffffff8516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001610982565b600060208284031215610ebe57600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610eee57600080fd5b9392505050565b600060208083528351808285015260005b81811015610f2257858101830151858201604001528201610f06565b81811115610f34576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610f8c57600080fd5b919050565b60008060408385031215610fa457600080fd5b610fad83610f68565b946020939093013593505050565b600080600060608486031215610fd057600080fd5b610fd984610f68565b9250610fe760208501610f68565b9150604084013590509250925092565b60006020828403121561100957600080fd5b610eee82610f68565b6000806040838503121561102557600080fd5b61102e83610f68565b915061103c60208401610f68565b90509250929050565b600181811c9082168061105957607f821691505b60208210811415611093577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156110db576110db611099565b500190565b6000828210156110f2576110f2611099565b50039056fea2646970667358221220ab7ddcc069894ab0c9603724acfbe497a2711b0082f18ecb2e7e55d7bdd7907864736f6c63430008090033a2646970667358221220a8284f3e8a840cded5a59b6bef46ebaa83af9494841c13131c3e2d32c9b5710064736f6c63430008090033" + "code": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c80630769a96914610030575b600080fd5b61004361003e3660046101e4565b610045565b005b6001600160a01b03841661009f5760405162461bcd60e51b815260206004820152601d60248201527f4d7573742070726f76696465204c3120746f6b656e2061646472657373000000604482015260640160405180910390fd5b60006010602160991b01858585856040516100b990610134565b6100c79594939291906102cc565b604051809103906000f0801580156100e3573d6000803e3d6000fd5b5060405160ff841681529091506001600160a01b0380831691908716907f41e27481c6f764357db26ae29b68b9f3aafc40b87444459cbf50d338c75317329060200160405180910390a35050505050565b6111178061032183390190565b634e487b7160e01b600052604160045260246000fd5b600082601f83011261016857600080fd5b813567ffffffffffffffff8082111561018357610183610141565b604051601f8301601f19908116603f011681019082821181831017156101ab576101ab610141565b816040528381528660208588010111156101c457600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080600080608085870312156101fa57600080fd5b84356001600160a01b038116811461021157600080fd5b9350602085013567ffffffffffffffff8082111561022e57600080fd5b61023a88838901610157565b9450604087013591508082111561025057600080fd5b5061025d87828801610157565b925050606085013560ff8116811461027457600080fd5b939692955090935050565b6000815180845260005b818110156102a557602081850181015186830182015201610289565b818111156102b7576000602083870101525b50601f01601f19169290920160200192915050565b6001600160a01b0386811682528516602082015260a0604082018190526000906102f89083018661027f565b828103606084015261030a818661027f565b91505060ff83166080830152969550505050505056fe60806040523480156200001157600080fd5b506040516200111738038062001117833981016040819052620000349162000247565b8251839083906200004d906003906020850190620000b7565b50805162000063906004906020840190620000b7565b5050600580546001600160a01b039687166001600160a01b0319909116179055506006805460ff909216600160a01b026001600160a81b031990921695909416949094179390931790915550620003309050565b828054620000c590620002f3565b90600052602060002090601f016020900481019282620000e9576000855562000134565b82601f106200010457805160ff191683800117855562000134565b8280016001018555821562000134579182015b828111156200013457825182559160200191906001019062000117565b506200014292915062000146565b5090565b5b8082111562000142576000815560010162000147565b80516001600160a01b03811681146200017557600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620001a257600080fd5b81516001600160401b0380821115620001bf57620001bf6200017a565b604051601f8301601f19908116603f01168101908282118183101715620001ea57620001ea6200017a565b816040528381526020925086838588010111156200020757600080fd5b600091505b838210156200022b57858201830151818301840152908201906200020c565b838211156200023d5760008385830101525b9695505050505050565b600080600080600060a086880312156200026057600080fd5b6200026b866200015d565b94506200027b602087016200015d565b60408701519094506001600160401b03808211156200029957600080fd5b620002a789838a0162000190565b94506060880151915080821115620002be57600080fd5b50620002cd8882890162000190565b925050608086015160ff81168114620002e557600080fd5b809150509295509295909350565b600181811c908216806200030857607f821691505b602082108114156200032a57634e487b7160e01b600052602260045260246000fd5b50919050565b610dd780620003406000396000f3fe608060405234801561001057600080fd5b506004361061010b5760003560e01c806370a08231116100a2578063a457c2d711610071578063a457c2d714610225578063a9059cbb14610238578063ae1f6aaf1461024b578063c01e1bd614610276578063dd62ed3e1461028957600080fd5b806370a08231146101cd57806376809ce3146101f657806395d89b411461020a5780639dc29fac1461021257600080fd5b806323b872dd116100de57806323b872dd14610172578063313ce5671461018557806339509351146101a557806340c10f19146101b857600080fd5b806301ffc9a71461011057806306fdde0314610138578063095ea7b31461014d57806318160ddd14610160575b600080fd5b61012361011e366004610bcb565b6102c2565b60405190151581526020015b60405180910390f35b610140610320565b60405161012f9190610bfc565b61012361015b366004610c6d565b6103b2565b6002545b60405190815260200161012f565b610123610180366004610c97565b6103c8565b600654600160a01b900460ff165b60405160ff909116815260200161012f565b6101236101b3366004610c6d565b610477565b6101cb6101c6366004610c6d565b6104b3565b005b6101646101db366004610cd3565b6001600160a01b031660009081526020819052604090205490565b60065461019390600160a01b900460ff1681565b61014061055e565b6101cb610220366004610c6d565b61056d565b610123610233366004610c6d565b61060c565b610123610246366004610c6d565b6106a5565b60065461025e906001600160a01b031681565b6040516001600160a01b03909116815260200161012f565b60055461025e906001600160a01b031681565b610164610297366004610cee565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b60007f01ffc9a7a5cef8baa21ed3c5c0d7e23accb804b619e9333b597f47a0d84076e2631d1d8b6360e01b6001600160e01b031984166301ffc9a760e01b148061031857506001600160e01b0319848116908216145b949350505050565b60606003805461032f90610d21565b80601f016020809104026020016040519081016040528092919081815260200182805461035b90610d21565b80156103a85780601f1061037d576101008083540402835291602001916103a8565b820191906000526020600020905b81548152906001019060200180831161038b57829003601f168201915b5050505050905090565b60006103bf3384846106b2565b50600192915050565b60006103d58484846107d7565b6001600160a01b03841660009081526001602090815260408083203384529091529020548281101561045f5760405162461bcd60e51b815260206004820152602860248201527f45524332303a207472616e7366657220616d6f756e74206578636565647320616044820152676c6c6f77616e636560c01b60648201526084015b60405180910390fd5b61046c85338584036106b2565b506001949350505050565b3360008181526001602090815260408083206001600160a01b038716845290915281205490916103bf9185906104ae908690610d72565b6106b2565b6006546001600160a01b0316331461050d5760405162461bcd60e51b815260206004820181905260248201527f4f6e6c79204c32204272696467652063616e206d696e7420616e64206275726e6044820152606401610456565b61051782826109a6565b816001600160a01b03167f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d41213968858260405161055291815260200190565b60405180910390a25050565b60606004805461032f90610d21565b6006546001600160a01b031633146105c75760405162461bcd60e51b815260206004820181905260248201527f4f6e6c79204c32204272696467652063616e206d696e7420616e64206275726e6044820152606401610456565b6105d18282610a85565b816001600160a01b03167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca58260405161055291815260200190565b3360009081526001602090815260408083206001600160a01b03861684529091528120548281101561068e5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152608401610456565b61069b33858584036106b2565b5060019392505050565b60006103bf3384846107d7565b6001600160a01b0383166107145760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610456565b6001600160a01b0382166107755760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610456565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b6001600160a01b03831661083b5760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610456565b6001600160a01b03821661089d5760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610456565b6001600160a01b038316600090815260208190526040902054818110156109155760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610456565b6001600160a01b0380851660009081526020819052604080822085850390559185168152908120805484929061094c908490610d72565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161099891815260200190565b60405180910390a350505050565b6001600160a01b0382166109fc5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610456565b8060026000828254610a0e9190610d72565b90915550506001600160a01b03821660009081526020819052604081208054839290610a3b908490610d72565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b6001600160a01b038216610ae55760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608401610456565b6001600160a01b03821660009081526020819052604090205481811015610b595760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b6064820152608401610456565b6001600160a01b0383166000908152602081905260408120838303905560028054849290610b88908490610d8a565b90915550506040518281526000906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020016107ca565b600060208284031215610bdd57600080fd5b81356001600160e01b031981168114610bf557600080fd5b9392505050565b600060208083528351808285015260005b81811015610c2957858101830151858201604001528201610c0d565b81811115610c3b576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b0381168114610c6857600080fd5b919050565b60008060408385031215610c8057600080fd5b610c8983610c51565b946020939093013593505050565b600080600060608486031215610cac57600080fd5b610cb584610c51565b9250610cc360208501610c51565b9150604084013590509250925092565b600060208284031215610ce557600080fd5b610bf582610c51565b60008060408385031215610d0157600080fd5b610d0a83610c51565b9150610d1860208401610c51565b90509250929050565b600181811c90821680610d3557607f821691505b60208210811415610d5657634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b60008219821115610d8557610d85610d5c565b500190565b600082821015610d9c57610d9c610d5c565b50039056fea2646970667358221220ed1c890f63fc0e27aceeab528a2838fcf26ba283b930f3ff95172ea75710515064736f6c63430008090033a2646970667358221220e63bdaf15255b8d173004360440570b26855dd560516e2f4be90363f6fc1701a64736f6c63430008090033" }, "0x4200000000000000000000000000000000000013": { "balance": "00", @@ -99,7 +95,7 @@ "0x0000000000000000000000000000000000000000000000000000000000000004": "0x4249540000000000000000000000000000000000000000000000000000000006", "0x0000000000000000000000000000000000000000000000000000000000000006": "0x0000000000000000000000124200000000000000000000000000000000000010" }, - "code": "0x608060405234801561001057600080fd5b506004361061011b5760003560e01c806370a08231116100b2578063a457c2d711610081578063ae1f6aaf11610066578063ae1f6aaf1461028a578063c01e1bd6146102cf578063dd62ed3e146102ef57600080fd5b8063a457c2d714610264578063a9059cbb1461027757600080fd5b806370a08231146101ee57806376809ce31461022457806395d89b41146102495780639dc29fac1461025157600080fd5b806323b872dd116100ee57806323b872dd14610182578063313ce5671461019557806339509351146101c657806340c10f19146101d957600080fd5b806301ffc9a71461012057806306fdde0314610148578063095ea7b31461015d57806318160ddd14610170575b600080fd5b61013361012e366004610ccf565b610335565b60405190151581526020015b60405180910390f35b6101506103f5565b60405161013f9190610d18565b61013361016b366004610db4565b610487565b6002545b60405190815260200161013f565b610133610190366004610dde565b61053d565b60065474010000000000000000000000000000000000000000900460ff165b60405160ff909116815260200161013f565b6101336101d4366004610db4565b6105ee565b6101ec6101e7366004610db4565b61069f565b005b6101746101fc366004610e1a565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6006546101b49074010000000000000000000000000000000000000000900460ff1681565b61015061077e565b6101ec61025f366004610db4565b61078d565b610133610272366004610db4565b610860565b610133610285366004610db4565b610911565b6006546102aa9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161013f565b6005546102aa9073ffffffffffffffffffffffffffffffffffffffff1681565b6101746102fd366004610e35565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b60007f01ffc9a7a5cef8baa21ed3c5c0d7e23accb804b619e9333b597f47a0d84076e27f1d1d8b63000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000084167f01ffc9a70000000000000000000000000000000000000000000000000000000014806103ed57507fffffffff00000000000000000000000000000000000000000000000000000000848116908216145b949350505050565b60606003805461040490610e68565b80601f016020809104026020016040519081016040528092919081815260200182805461043090610e68565b801561047d5780601f106104525761010080835404028352916020019161047d565b820191906000526020600020905b81548152906001019060200180831161046057829003601f168201915b5050505050905090565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604260248201527f42564d5f4249543a20617070726f76652069732064697361626c65642070656e60448201527f64696e67206675727468657220636f6d6d756e6974792064697363757373696f60648201527f6e2e000000000000000000000000000000000000000000000000000000000000608482015260009060a4015b60405180910390fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604760248201527f42564d5f4249543a207472616e7366657246726f6d2069732064697361626c6560448201527f642070656e64696e67206675727468657220636f6d6d756e697479206469736360648201527f757373696f6e2e00000000000000000000000000000000000000000000000000608482015260009060a401610534565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604c60248201527f42564d5f4249543a20696e637265617365416c6c6f77616e636520697320646960448201527f7361626c65642070656e64696e67206675727468657220636f6d6d756e69747960648201527f2064697363757373696f6e2e0000000000000000000000000000000000000000608482015260009060a401610534565b60065473ffffffffffffffffffffffffffffffffffffffff163314610720576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f6e6c79204c32204272696467652063616e206d696e7420616e64206275726e6044820152606401610534565b61072a82826109c2565b8173ffffffffffffffffffffffffffffffffffffffff167f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d41213968858260405161077291815260200190565b60405180910390a25050565b60606004805461040490610e68565b60065473ffffffffffffffffffffffffffffffffffffffff16331461080e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f6e6c79204c32204272696467652063616e206d696e7420616e64206275726e6044820152606401610534565b6108188282610ae2565b8173ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca58260405161077291815260200190565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604c60248201527f42564d5f4249543a206465637265617365416c6c6f77616e636520697320646960448201527f7361626c65642070656e64696e67206675727468657220636f6d6d756e69747960648201527f2064697363757373696f6e2e0000000000000000000000000000000000000000608482015260009060a401610534565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f42564d5f4249543a207472616e736665722069732064697361626c656420706560448201527f6e64696e67206675727468657220636f6d6d756e69747920646973637573736960648201527f6f6e2e0000000000000000000000000000000000000000000000000000000000608482015260009060a401610534565b73ffffffffffffffffffffffffffffffffffffffff8216610a3f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610534565b8060026000828254610a519190610eeb565b909155505073ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604081208054839290610a8b908490610eeb565b909155505060405181815273ffffffffffffffffffffffffffffffffffffffff8316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b73ffffffffffffffffffffffffffffffffffffffff8216610b85576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f73000000000000000000000000000000000000000000000000000000000000006064820152608401610534565b73ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604090205481811015610c3b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f63650000000000000000000000000000000000000000000000000000000000006064820152608401610534565b73ffffffffffffffffffffffffffffffffffffffff83166000908152602081905260408120838303905560028054849290610c77908490610f03565b909155505060405182815260009073ffffffffffffffffffffffffffffffffffffffff8516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a3505050565b600060208284031215610ce157600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610d1157600080fd5b9392505050565b600060208083528351808285015260005b81811015610d4557858101830151858201604001528201610d29565b81811115610d57576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610daf57600080fd5b919050565b60008060408385031215610dc757600080fd5b610dd083610d8b565b946020939093013593505050565b600080600060608486031215610df357600080fd5b610dfc84610d8b565b9250610e0a60208501610d8b565b9150604084013590509250925092565b600060208284031215610e2c57600080fd5b610d1182610d8b565b60008060408385031215610e4857600080fd5b610e5183610d8b565b9150610e5f60208401610d8b565b90509250929050565b600181811c90821680610e7c57607f821691505b60208210811415610eb6577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008219821115610efe57610efe610ebc565b500190565b600082821015610f1557610f15610ebc565b50039056fea264697066735822122050aa0c31bc8b8b99d2aae33c49266a48e1ba9a4df3c34e5b7224c213c6e3194064736f6c63430008090033" + "code": "0x608060405234801561001057600080fd5b506004361061010b5760003560e01c806370a08231116100a2578063a457c2d711610071578063a457c2d714610225578063a9059cbb14610238578063ae1f6aaf1461024b578063c01e1bd614610276578063dd62ed3e1461028957600080fd5b806370a08231146101cd57806376809ce3146101f657806395d89b411461020a5780639dc29fac1461021257600080fd5b806323b872dd116100de57806323b872dd14610172578063313ce5671461018557806339509351146101a557806340c10f19146101b857600080fd5b806301ffc9a71461011057806306fdde0314610138578063095ea7b31461014d57806318160ddd14610160575b600080fd5b61012361011e3660046109c3565b6102c2565b60405190151581526020015b60405180910390f35b610140610320565b60405161012f91906109f4565b61012361015b366004610a65565b6103b2565b6002545b60405190815260200161012f565b610123610180366004610a8f565b610433565b600654600160a01b900460ff165b60405160ff909116815260200161012f565b6101236101b3366004610a65565b6104b4565b6101cb6101c6366004610a65565b61053a565b005b6101646101db366004610acb565b6001600160a01b031660009081526020819052604090205490565b60065461019390600160a01b900460ff1681565b6101406105e5565b6101cb610220366004610a65565b6105f4565b610123610233366004610a65565b610693565b610123610246366004610a65565b610719565b60065461025e906001600160a01b031681565b6040516001600160a01b03909116815260200161012f565b60055461025e906001600160a01b031681565b610164610297366004610ae6565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b60007f01ffc9a7a5cef8baa21ed3c5c0d7e23accb804b619e9333b597f47a0d84076e2631d1d8b6360e01b6001600160e01b031984166301ffc9a760e01b148061031857506001600160e01b0319848116908216145b949350505050565b60606003805461032f90610b19565b80601f016020809104026020016040519081016040528092919081815260200182805461035b90610b19565b80156103a85780601f1061037d576101008083540402835291602001916103a8565b820191906000526020600020905b81548152906001019060200180831161038b57829003601f168201915b5050505050905090565b60405162461bcd60e51b815260206004820152604260248201527f42564d5f4249543a20617070726f76652069732064697361626c65642070656e60448201527f64696e67206675727468657220636f6d6d756e6974792064697363757373696f606482015261371760f11b608482015260009060a4015b60405180910390fd5b60405162461bcd60e51b815260206004820152604760248201527f42564d5f4249543a207472616e7366657246726f6d2069732064697361626c6560448201527f642070656e64696e67206675727468657220636f6d6d756e69747920646973636064820152663ab9b9b4b7b71760c91b608482015260009060a40161042a565b60405162461bcd60e51b815260206004820152604c60248201527f42564d5f4249543a20696e637265617365416c6c6f77616e636520697320646960448201527f7361626c65642070656e64696e67206675727468657220636f6d6d756e69747960648201526b103234b9b1bab9b9b4b7b71760a11b608482015260009060a40161042a565b6006546001600160a01b031633146105945760405162461bcd60e51b815260206004820181905260248201527f4f6e6c79204c32204272696467652063616e206d696e7420616e64206275726e604482015260640161042a565b61059e8282610796565b816001600160a01b03167f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d4121396885826040516105d991815260200190565b60405180910390a25050565b60606004805461032f90610b19565b6006546001600160a01b0316331461064e5760405162461bcd60e51b815260206004820181905260248201527f4f6e6c79204c32204272696467652063616e206d696e7420616e64206275726e604482015260640161042a565b6106588282610875565b816001600160a01b03167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5826040516105d991815260200190565b60405162461bcd60e51b815260206004820152604c60248201527f42564d5f4249543a206465637265617365416c6c6f77616e636520697320646960448201527f7361626c65642070656e64696e67206675727468657220636f6d6d756e69747960648201526b103234b9b1bab9b9b4b7b71760a11b608482015260009060a40161042a565b60405162461bcd60e51b815260206004820152604360248201527f42564d5f4249543a207472616e736665722069732064697361626c656420706560448201527f6e64696e67206675727468657220636f6d6d756e69747920646973637573736960648201526237b71760e91b608482015260009060a40161042a565b6001600160a01b0382166107ec5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015260640161042a565b80600260008282546107fe9190610b6a565b90915550506001600160a01b0382166000908152602081905260408120805483929061082b908490610b6a565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b6001600160a01b0382166108d55760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b606482015260840161042a565b6001600160a01b038216600090815260208190526040902054818110156109495760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b606482015260840161042a565b6001600160a01b0383166000908152602081905260408120838303905560028054849290610978908490610b82565b90915550506040518281526000906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a3505050565b6000602082840312156109d557600080fd5b81356001600160e01b0319811681146109ed57600080fd5b9392505050565b600060208083528351808285015260005b81811015610a2157858101830151858201604001528201610a05565b81811115610a33576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b0381168114610a6057600080fd5b919050565b60008060408385031215610a7857600080fd5b610a8183610a49565b946020939093013593505050565b600080600060608486031215610aa457600080fd5b610aad84610a49565b9250610abb60208501610a49565b9150604084013590509250925092565b600060208284031215610add57600080fd5b6109ed82610a49565b60008060408385031215610af957600080fd5b610b0283610a49565b9150610b1060208401610a49565b90509250929050565b600181811c90821680610b2d57607f821691505b60208210811415610b4e57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b60008219821115610b7d57610b7d610b54565b500190565b600082821015610b9457610b94610b54565b50039056fea26469706673582212201959bd6e2d63380ecfd7deaa6b17ccc19c819a81ee3b91e93fcac6625d99493e64736f6c63430008090033" }, "0xdEAddEaDdeadDEadDEADDEAddEADDEAddead1111": { "balance": "00", @@ -109,7 +105,7 @@ "0x0000000000000000000000000000000000000000000000000000000000000004": "0x5745544800000000000000000000000000000000000000000000000000000008", "0x0000000000000000000000000000000000000000000000000000000000000006": "0x0000000000000000000000124200000000000000000000000000000000000010" }, - "code": "0x608060405234801561001057600080fd5b506004361061011b5760003560e01c806370a08231116100b2578063a457c2d711610081578063ae1f6aaf11610066578063ae1f6aaf1461028a578063c01e1bd6146102cf578063dd62ed3e146102ef57600080fd5b8063a457c2d714610264578063a9059cbb1461027757600080fd5b806370a08231146101ee57806376809ce31461022457806395d89b41146102495780639dc29fac1461025157600080fd5b806323b872dd116100ee57806323b872dd14610182578063313ce5671461019557806339509351146101c657806340c10f19146101d957600080fd5b806301ffc9a71461012057806306fdde0314610148578063095ea7b31461015d57806318160ddd14610170575b600080fd5b61013361012e366004610eac565b610335565b60405190151581526020015b60405180910390f35b6101506103f5565b60405161013f9190610ef5565b61013361016b366004610f91565b610487565b6002545b60405190815260200161013f565b610133610190366004610fbb565b61049d565b60065474010000000000000000000000000000000000000000900460ff165b60405160ff909116815260200161013f565b6101336101d4366004610f91565b61056e565b6101ec6101e7366004610f91565b6105b7565b005b6101746101fc366004610ff7565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6006546101b49074010000000000000000000000000000000000000000900460ff1681565b61015061067c565b6101ec61025f366004610f91565b61068b565b610133610272366004610f91565b610744565b610133610285366004610f91565b610802565b6006546102aa9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161013f565b6005546102aa9073ffffffffffffffffffffffffffffffffffffffff1681565b6101746102fd366004611012565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b60007f01ffc9a7a5cef8baa21ed3c5c0d7e23accb804b619e9333b597f47a0d84076e27f1d1d8b63000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000084167f01ffc9a70000000000000000000000000000000000000000000000000000000014806103ed57507fffffffff00000000000000000000000000000000000000000000000000000000848116908216145b949350505050565b60606003805461040490611045565b80601f016020809104026020016040519081016040528092919081815260200182805461043090611045565b801561047d5780601f106104525761010080835404028352916020019161047d565b820191906000526020600020905b81548152906001019060200180831161046057829003601f168201915b5050505050905090565b600061049433848461080f565b50600192915050565b60006104aa84848461098f565b73ffffffffffffffffffffffffffffffffffffffff84166000908152600160209081526040808320338452909152902054828110156105565760405162461bcd60e51b815260206004820152602860248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206160448201527f6c6c6f77616e636500000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b610563853385840361080f565b506001949350505050565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490916104949185906105b29086906110c8565b61080f565b60065473ffffffffffffffffffffffffffffffffffffffff16331461061e5760405162461bcd60e51b815260206004820181905260248201527f4f6e6c79204c32204272696467652063616e206d696e7420616e64206275726e604482015260640161054d565b6106288282610bf5565b8173ffffffffffffffffffffffffffffffffffffffff167f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d41213968858260405161067091815260200190565b60405180910390a25050565b60606004805461040490611045565b60065473ffffffffffffffffffffffffffffffffffffffff1633146106f25760405162461bcd60e51b815260206004820181905260248201527f4f6e6c79204c32204272696467652063616e206d696e7420616e64206275726e604482015260640161054d565b6106fc8282610cfb565b8173ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca58260405161067091815260200190565b33600090815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff86168452909152812054828110156107eb5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f000000000000000000000000000000000000000000000000000000606482015260840161054d565b6107f8338585840361080f565b5060019392505050565b600061049433848461098f565b73ffffffffffffffffffffffffffffffffffffffff83166108975760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f7265737300000000000000000000000000000000000000000000000000000000606482015260840161054d565b73ffffffffffffffffffffffffffffffffffffffff82166109205760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f7373000000000000000000000000000000000000000000000000000000000000606482015260840161054d565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8316610a185760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f6472657373000000000000000000000000000000000000000000000000000000606482015260840161054d565b73ffffffffffffffffffffffffffffffffffffffff8216610aa15760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f6573730000000000000000000000000000000000000000000000000000000000606482015260840161054d565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610b3d5760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e63650000000000000000000000000000000000000000000000000000606482015260840161054d565b73ffffffffffffffffffffffffffffffffffffffff808516600090815260208190526040808220858503905591851681529081208054849290610b819084906110c8565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610be791815260200190565b60405180910390a350505050565b73ffffffffffffffffffffffffffffffffffffffff8216610c585760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015260640161054d565b8060026000828254610c6a91906110c8565b909155505073ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604081208054839290610ca49084906110c8565b909155505060405181815273ffffffffffffffffffffffffffffffffffffffff8316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b73ffffffffffffffffffffffffffffffffffffffff8216610d845760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f7300000000000000000000000000000000000000000000000000000000000000606482015260840161054d565b73ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604090205481811015610e205760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f6365000000000000000000000000000000000000000000000000000000000000606482015260840161054d565b73ffffffffffffffffffffffffffffffffffffffff83166000908152602081905260408120838303905560028054849290610e5c9084906110e0565b909155505060405182815260009073ffffffffffffffffffffffffffffffffffffffff8516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001610982565b600060208284031215610ebe57600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610eee57600080fd5b9392505050565b600060208083528351808285015260005b81811015610f2257858101830151858201604001528201610f06565b81811115610f34576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610f8c57600080fd5b919050565b60008060408385031215610fa457600080fd5b610fad83610f68565b946020939093013593505050565b600080600060608486031215610fd057600080fd5b610fd984610f68565b9250610fe760208501610f68565b9150604084013590509250925092565b60006020828403121561100957600080fd5b610eee82610f68565b6000806040838503121561102557600080fd5b61102e83610f68565b915061103c60208401610f68565b90509250929050565b600181811c9082168061105957607f821691505b60208210811415611093577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156110db576110db611099565b500190565b6000828210156110f2576110f2611099565b50039056fea264697066735822122067ad8264b2307edf22081cc5f4616ebe296b49743b70a63a727a79897bad3ecb64736f6c63430008090033" + "code": "0x608060405234801561001057600080fd5b506004361061010b5760003560e01c806370a08231116100a2578063a457c2d711610071578063a457c2d714610225578063a9059cbb14610238578063ae1f6aaf1461024b578063c01e1bd614610276578063dd62ed3e1461028957600080fd5b806370a08231146101cd57806376809ce3146101f657806395d89b411461020a5780639dc29fac1461021257600080fd5b806323b872dd116100de57806323b872dd14610172578063313ce5671461018557806339509351146101a557806340c10f19146101b857600080fd5b806301ffc9a71461011057806306fdde0314610138578063095ea7b31461014d57806318160ddd14610160575b600080fd5b61012361011e366004610bcb565b6102c2565b60405190151581526020015b60405180910390f35b610140610320565b60405161012f9190610bfc565b61012361015b366004610c6d565b6103b2565b6002545b60405190815260200161012f565b610123610180366004610c97565b6103c8565b600654600160a01b900460ff165b60405160ff909116815260200161012f565b6101236101b3366004610c6d565b610477565b6101cb6101c6366004610c6d565b6104b3565b005b6101646101db366004610cd3565b6001600160a01b031660009081526020819052604090205490565b60065461019390600160a01b900460ff1681565b61014061055e565b6101cb610220366004610c6d565b61056d565b610123610233366004610c6d565b61060c565b610123610246366004610c6d565b6106a5565b60065461025e906001600160a01b031681565b6040516001600160a01b03909116815260200161012f565b60055461025e906001600160a01b031681565b610164610297366004610cee565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b60007f01ffc9a7a5cef8baa21ed3c5c0d7e23accb804b619e9333b597f47a0d84076e2631d1d8b6360e01b6001600160e01b031984166301ffc9a760e01b148061031857506001600160e01b0319848116908216145b949350505050565b60606003805461032f90610d21565b80601f016020809104026020016040519081016040528092919081815260200182805461035b90610d21565b80156103a85780601f1061037d576101008083540402835291602001916103a8565b820191906000526020600020905b81548152906001019060200180831161038b57829003601f168201915b5050505050905090565b60006103bf3384846106b2565b50600192915050565b60006103d58484846107d7565b6001600160a01b03841660009081526001602090815260408083203384529091529020548281101561045f5760405162461bcd60e51b815260206004820152602860248201527f45524332303a207472616e7366657220616d6f756e74206578636565647320616044820152676c6c6f77616e636560c01b60648201526084015b60405180910390fd5b61046c85338584036106b2565b506001949350505050565b3360008181526001602090815260408083206001600160a01b038716845290915281205490916103bf9185906104ae908690610d72565b6106b2565b6006546001600160a01b0316331461050d5760405162461bcd60e51b815260206004820181905260248201527f4f6e6c79204c32204272696467652063616e206d696e7420616e64206275726e6044820152606401610456565b61051782826109a6565b816001600160a01b03167f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d41213968858260405161055291815260200190565b60405180910390a25050565b60606004805461032f90610d21565b6006546001600160a01b031633146105c75760405162461bcd60e51b815260206004820181905260248201527f4f6e6c79204c32204272696467652063616e206d696e7420616e64206275726e6044820152606401610456565b6105d18282610a85565b816001600160a01b03167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca58260405161055291815260200190565b3360009081526001602090815260408083206001600160a01b03861684529091528120548281101561068e5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152608401610456565b61069b33858584036106b2565b5060019392505050565b60006103bf3384846107d7565b6001600160a01b0383166107145760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610456565b6001600160a01b0382166107755760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610456565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b6001600160a01b03831661083b5760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610456565b6001600160a01b03821661089d5760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610456565b6001600160a01b038316600090815260208190526040902054818110156109155760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610456565b6001600160a01b0380851660009081526020819052604080822085850390559185168152908120805484929061094c908490610d72565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161099891815260200190565b60405180910390a350505050565b6001600160a01b0382166109fc5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610456565b8060026000828254610a0e9190610d72565b90915550506001600160a01b03821660009081526020819052604081208054839290610a3b908490610d72565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b6001600160a01b038216610ae55760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608401610456565b6001600160a01b03821660009081526020819052604090205481811015610b595760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b6064820152608401610456565b6001600160a01b0383166000908152602081905260408120838303905560028054849290610b88908490610d8a565b90915550506040518281526000906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020016107ca565b600060208284031215610bdd57600080fd5b81356001600160e01b031981168114610bf557600080fd5b9392505050565b600060208083528351808285015260005b81811015610c2957858101830151858201604001528201610c0d565b81811115610c3b576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b0381168114610c6857600080fd5b919050565b60008060408385031215610c8057600080fd5b610c8983610c51565b946020939093013593505050565b600080600060608486031215610cac57600080fd5b610cb584610c51565b9250610cc360208501610c51565b9150604084013590509250925092565b600060208284031215610ce557600080fd5b610bf582610c51565b60008060408385031215610d0157600080fd5b610d0a83610c51565b9150610d1860208401610c51565b90509250929050565b600181811c90821680610d3557607f821691505b60208210811415610d5657634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b60008219821115610d8557610d85610d5c565b500190565b600082821015610d9c57610d9c610d5c565b50039056fea2646970667358221220f789dc8b2639a060e5131ee99aa91f5abc88a63a15720481d58aa30fea1b1da064736f6c63430008090033" }, "0x4200000000000000000000000000000000000006": { "balance": "00", @@ -118,7 +114,7 @@ "0x0000000000000000000000000000000000000000000000000000000000000001": "0x5745544800000000000000000000000000000000000000000000000000000008", "0x0000000000000000000000000000000000000000000000000000000000000002": "0x0000000000000000000000000000000000000000000000000000000000000012" }, - "code": "0x6080604052600436106100bc5760003560e01c8063313ce56711610074578063a9059cbb1161004e578063a9059cbb146102cb578063d0e30db0146100bc578063dd62ed3e14610311576100bc565b8063313ce5671461024b57806370a082311461027657806395d89b41146102b6576100bc565b806318160ddd116100a557806318160ddd146101aa57806323b872dd146101d15780632e1a7d4d14610221576100bc565b806306fdde03146100c6578063095ea7b314610150575b6100c4610359565b005b3480156100d257600080fd5b506100db6103a8565b6040805160208082528351818301528351919283929083019185019080838360005b838110156101155781810151838201526020016100fd565b50505050905090810190601f1680156101425780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561015c57600080fd5b506101966004803603604081101561017357600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135610454565b604080519115158252519081900360200190f35b3480156101b657600080fd5b506101bf6104c7565b60408051918252519081900360200190f35b3480156101dd57600080fd5b50610196600480360360608110156101f457600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135811691602081013590911690604001356104cb565b34801561022d57600080fd5b506100c46004803603602081101561024457600080fd5b503561066b565b34801561025757600080fd5b50610260610700565b6040805160ff9092168252519081900360200190f35b34801561028257600080fd5b506101bf6004803603602081101561029957600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610709565b3480156102c257600080fd5b506100db61071b565b3480156102d757600080fd5b50610196600480360360408110156102ee57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135610793565b34801561031d57600080fd5b506101bf6004803603604081101561033457600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160200135166107a7565b33600081815260036020908152604091829020805434908101909155825190815291517fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9281900390910190a2565b6000805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f8101849004840282018401909252818152929183018282801561044c5780601f106104215761010080835404028352916020019161044c565b820191906000526020600020905b81548152906001019060200180831161042f57829003601f168201915b505050505081565b33600081815260046020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716808552908352818420869055815186815291519394909390927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925928290030190a350600192915050565b4790565b73ffffffffffffffffffffffffffffffffffffffff83166000908152600360205260408120548211156104fd57600080fd5b73ffffffffffffffffffffffffffffffffffffffff84163314801590610573575073ffffffffffffffffffffffffffffffffffffffff841660009081526004602090815260408083203384529091529020547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff14155b156105ed5773ffffffffffffffffffffffffffffffffffffffff841660009081526004602090815260408083203384529091529020548211156105b557600080fd5b73ffffffffffffffffffffffffffffffffffffffff841660009081526004602090815260408083203384529091529020805483900390555b73ffffffffffffffffffffffffffffffffffffffff808516600081815260036020908152604080832080548890039055938716808352918490208054870190558351868152935191937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929081900390910190a35060019392505050565b3360009081526003602052604090205481111561068757600080fd5b33600081815260036020526040808220805485900390555183156108fc0291849190818181858888f193505050501580156106c6573d6000803e3d6000fd5b5060408051828152905133917f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65919081900360200190a250565b60025460ff1681565b60036020526000908152604090205481565b60018054604080516020600284861615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f8101849004840282018401909252818152929183018282801561044c5780601f106104215761010080835404028352916020019161044c565b60006107a03384846104cb565b9392505050565b60046020908152600092835260408084209091529082529020548156fea265627a7a7231582091c18790e0cca5011d2518024840ee00fecc67e11f56fd746f2cf84d5b583e0064736f6c63430005110032" + "code": "0x60806040526004361061009c5760003560e01c8063313ce56711610064578063313ce5671461021157806370a082311461023c57806395d89b411461026f578063a9059cbb14610284578063d0e30db01461009c578063dd62ed3e146102bd5761009c565b806306fdde03146100a6578063095ea7b31461013057806318160ddd1461017d57806323b872dd146101a45780632e1a7d4d146101e7575b6100a46102f8565b005b3480156100b257600080fd5b506100bb610347565b6040805160208082528351818301528351919283929083019185019080838360005b838110156100f55781810151838201526020016100dd565b50505050905090810190601f1680156101225780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561013c57600080fd5b506101696004803603604081101561015357600080fd5b506001600160a01b0381351690602001356103d5565b604080519115158252519081900360200190f35b34801561018957600080fd5b5061019261043b565b60408051918252519081900360200190f35b3480156101b057600080fd5b50610169600480360360608110156101c757600080fd5b506001600160a01b0381358116916020810135909116906040013561043f565b3480156101f357600080fd5b506100a46004803603602081101561020a57600080fd5b5035610573565b34801561021d57600080fd5b50610226610608565b6040805160ff9092168252519081900360200190f35b34801561024857600080fd5b506101926004803603602081101561025f57600080fd5b50356001600160a01b0316610611565b34801561027b57600080fd5b506100bb610623565b34801561029057600080fd5b50610169600480360360408110156102a757600080fd5b506001600160a01b03813516906020013561067d565b3480156102c957600080fd5b50610192600480360360408110156102e057600080fd5b506001600160a01b0381358116916020013516610691565b33600081815260036020908152604091829020805434908101909155825190815291517fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9281900390910190a2565b6000805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156103cd5780601f106103a2576101008083540402835291602001916103cd565b820191906000526020600020905b8154815290600101906020018083116103b057829003601f168201915b505050505081565b3360008181526004602090815260408083206001600160a01b038716808552908352818420869055815186815291519394909390927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925928290030190a350600192915050565b4790565b6001600160a01b03831660009081526003602052604081205482111561046457600080fd5b6001600160a01b03841633148015906104a257506001600160a01b038416600090815260046020908152604080832033845290915290205460001914155b15610502576001600160a01b03841660009081526004602090815260408083203384529091529020548211156104d757600080fd5b6001600160a01b03841660009081526004602090815260408083203384529091529020805483900390555b6001600160a01b03808516600081815260036020908152604080832080548890039055938716808352918490208054870190558351868152935191937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929081900390910190a35060019392505050565b3360009081526003602052604090205481111561058f57600080fd5b33600081815260036020526040808220805485900390555183156108fc0291849190818181858888f193505050501580156105ce573d6000803e3d6000fd5b5060408051828152905133917f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65919081900360200190a250565b60025460ff1681565b60036020526000908152604090205481565b60018054604080516020600284861615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156103cd5780601f106103a2576101008083540402835291602001916103cd565b600061068a33848461043f565b9392505050565b60046020908152600092835260408084209091529082529020548156fea265627a7a723158203a20a42ecfa42be2e74e4ae807d829fdcf12083ea8a3f6392d9de06662bdc10964736f6c63430005110032" }, "0x4200000000000000000000000000000000000020": { "balance": "00", @@ -130,7 +126,7 @@ "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000004200000000000000000000000000000000000007", "0x000000000000000000000000000000000000000000000000000000000000000a": "0x0000000000000000000000008baccff561fde61d6bc8b6f299ffba561d2189b9" }, - "code": "0x6080604052600436106101635760003560e01c80633cb747bf116100c0578063d8111a5711610074578063ea01cd3611610059578063ea01cd36146103b9578063f2fde38b146103e6578063fad9aba31461040657600080fd5b8063d8111a571461038d578063e5efd585146103a357600080fd5b8063715018a6116100a5578063715018a6146103385780638da5cb5b1461034d578063cfb550f11461037857600080fd5b80633cb747bf146102f65780633ccfd60b1461032357600080fd5b806319d509a11161011757806327c8f835116100fc57806327c8f835146102945780632c79db11146102c15780633b52c31e146102d657600080fd5b806319d509a1146102685780631a39d8ef1461027e57600080fd5b806310a7fd7b1161014857806310a7fd7b146101c6578063110b7eb01461020157806315c6f1661461025357600080fd5b80630b50cd3e1461016f5780630fae75d9146101a457600080fd5b3661016a57005b600080fd5b34801561017b57600080fd5b5061018f61018a3660046111bc565b61041c565b60405190151581526020015b60405180910390f35b3480156101b057600080fd5b506101c46101bf3660046111de565b6105b0565b005b3480156101d257600080fd5b506101f36101e1366004611280565b60026020526000908152604090205481565b60405190815260200161019b565b34801561020d57600080fd5b5060035461022e9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161019b565b34801561025f57600080fd5b506101f3610a63565b34801561027457600080fd5b506101f360065481565b34801561028a57600080fd5b506101f360075481565b3480156102a057600080fd5b5060045461022e9073ffffffffffffffffffffffffffffffffffffffff1681565b3480156102cd57600080fd5b506101f3610a8e565b3480156102e257600080fd5b506101c46102f1366004611280565b610b0d565b34801561030257600080fd5b5060015461022e9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561032f57600080fd5b506101c4610b79565b34801561034457600080fd5b506101c4610cae565b34801561035957600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff1661022e565b34801561038457600080fd5b506101c4610d1f565b34801561039957600080fd5b506101f360095481565b3480156103af57600080fd5b506101f360085481565b3480156103c557600080fd5b50600a5461022e9073ffffffffffffffffffffffffffffffffffffffff1681565b3480156103f257600080fd5b506101c46104013660046112bb565b610e68565b34801561041257600080fd5b506101f360055481565b60045460009073ffffffffffffffffffffffffffffffffffffffff1633146104b15760405162461bcd60e51b815260206004820152602760248201527f747373207265776172642063616c6c206d65737361676520756e61757468656e60448201527f746963617465640000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6007544710156105295760405162461bcd60e51b815260206004820152603160248201527f62616c616e6365207265636f726420616e6420636f6e74726163742062616c6160448201527f6e636520617265206e6f7420657175616c00000000000000000000000000000060648201526084016104a8565b600654610537906001611307565b83146105855760405162461bcd60e51b815260206004820152601760248201527f626c6f636b2069642075706461746520696c6c6567616c00000000000000000060448201526064016104a8565b60068390556007546105979083610f61565b6007555060009182526002602052604090912055600190565b600a5473ffffffffffffffffffffffffffffffffffffffff166105e860015473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146106885760405162461bcd60e51b815260206004820152602e60248201527f42564d5f58434841494e3a206d657373656e67657220636f6e7472616374207560448201527f6e61757468656e7469636174656400000000000000000000000000000000000060648201526084016104a8565b8073ffffffffffffffffffffffffffffffffffffffff166106be60015473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff16636e296e456040518163ffffffff1660e01b815260040160206040518083038186803b15801561070357600080fd5b505afa158015610717573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061073b919061131f565b73ffffffffffffffffffffffffffffffffffffffff16146107c45760405162461bcd60e51b815260206004820152603060248201527f42564d5f58434841494e3a2077726f6e672073656e646572206f662063726f7360448201527f732d646f6d61696e206d6573736167650000000000000000000000000000000060648201526084016104a8565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16630d1e43a06040518163ffffffff1660e01b815260040160206040518083038186803b15801561082c57600080fd5b505afa158015610840573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610864919061133c565b60011461087c5761087786868585610f74565b610a5b565b600080600060085460001415610899575050506008849055610a5b565b60085487116109105760405162461bcd60e51b815260206004820152603260248201527f61726773205f626174636854696d65206d757374206774686572207468616e2060448201527f6c617374206c617374426174636854696d65000000000000000000000000000060648201526084016104a8565b60055461091b610a63565b600854610928908a611355565b610932919061136c565b61093c9190611307565b6000600555915061094d828661112f565b925060005b858110156109ea57600087878381811061096e5761096e6113a9565b905060200201602081019061098391906112bb565b905061098f8386610f61565b60405190935073ffffffffffffffffffffffffffffffffffffffff82169086156108fc029087906000818181858888f193505050501580156109d5573d6000803e3d6000fd5b505080806109e2906113d8565b915050610952565b5060006109f7838361113b565b90508015610a1057600554610a0c9082610f61565b6005555b7ff533ef50019763ee9d95ad46e28350b533c11edd472ae7be93e8fae83c1b6d9960085489868a8a604051610a49959493929190611467565b60405180910390a15050506008859055505b505050505050565b6000610a896301e13380600954670de0b6b3a7640000610a83919061136c565b9061112f565b905090565b6000600754471015610b085760405162461bcd60e51b815260206004820152603160248201527f62616c616e6365207265636f726420616e6420636f6e74726163742062616c6160448201527f6e636520617265206e6f7420657175616c00000000000000000000000000000060648201526084016104a8565b504790565b60005473ffffffffffffffffffffffffffffffffffffffff163314610b745760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016104a8565b600955565b60005473ffffffffffffffffffffffffffffffffffffffff163314610be05760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016104a8565b600754471015610c585760405162461bcd60e51b815260206004820152603160248201527f62616c616e6365207265636f726420616e6420636f6e74726163742062616c6160448201527f6e636520617265206e6f7420657175616c00000000000000000000000000000060648201526084016104a8565b60006007554715610cac576000805460405173ffffffffffffffffffffffffffffffffffffffff909116914780156108fc02929091818181858888f19350505050158015610caa573d6000803e3d6000fd5b505b565b60005473ffffffffffffffffffffffffffffffffffffffff163314610d155760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016104a8565b610cac6000611147565b60005473ffffffffffffffffffffffffffffffffffffffff163314610d865760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016104a8565b600754471015610dfe5760405162461bcd60e51b815260206004820152603160248201527f62616c616e6365207265636f726420616e6420636f6e74726163742062616c6160448201527f6e636520617265206e6f7420657175616c00000000000000000000000000000060648201526084016104a8565b600554600754610e0e908261113b565b60075560006005558015610caa576000805460055460405173ffffffffffffffffffffffffffffffffffffffff9092169281156108fc029290818181858888f19350505050158015610e64573d6000803e3d6000fd5b5050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610ecf5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016104a8565b73ffffffffffffffffffffffffffffffffffffffff8116610f585760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016104a8565b610caa81611147565b6000610f6d8284611307565b9392505050565b6000806000805b8663ffffffff16811015610fed57610fb860026000610f9a848c611307565b81526020019081526020016000205484610f6190919063ffffffff16565b925060026000610fc8838b611307565b8152602001908152602001600020600090558080610fe5906113d8565b915050610f7b565b5081156110e7576005546110019083611307565b60006005559150611012828561112f565b925060005b848110156110bf576000868683818110611033576110336113a9565b905060200201602081019061104891906112bb565b90506110548386610f61565b600754909350611064908661113b565b60075560405173ffffffffffffffffffffffffffffffffffffffff82169086156108fc029087906000818181858888f193505050501580156110aa573d6000803e3d6000fd5b505080806110b7906113d8565b915050611017565b5060006110cc838361113b565b905080156110e5576005546110e19082610f61565b6005555b505b7f2dae6f3d42a2c50d6baa3ea3f2423a9e1ff0ba26875f8ba6ba25c40df98009fe878785888860405161111e959493929190611498565b60405180910390a150505050505050565b6000610f6d82846114c4565b6000610f6d8284611355565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600080604083850312156111cf57600080fd5b50508035926020909101359150565b6000806000806000608086880312156111f657600080fd5b85359450602086013563ffffffff8116811461121157600080fd5b935060408601359250606086013567ffffffffffffffff8082111561123557600080fd5b818801915088601f83011261124957600080fd5b81358181111561125857600080fd5b8960208260051b850101111561126d57600080fd5b9699959850939650602001949392505050565b60006020828403121561129257600080fd5b5035919050565b73ffffffffffffffffffffffffffffffffffffffff81168114610caa57600080fd5b6000602082840312156112cd57600080fd5b8135610f6d81611299565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561131a5761131a6112d8565b500190565b60006020828403121561133157600080fd5b8151610f6d81611299565b60006020828403121561134e57600080fd5b5051919050565b600082821015611367576113676112d8565b500390565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156113a4576113a46112d8565b500290565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561140a5761140a6112d8565b5060010190565b8183526000602080850194508260005b8581101561145c57813561143481611299565b73ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101611421565b509495945050505050565b85815284602082015283604082015260806060820152600061148d608083018486611411565b979650505050505050565b85815263ffffffff8516602082015283604082015260806060820152600061148d608083018486611411565b6000826114fa577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b50049056fea2646970667358221220966ea09f223dafcdbfd297d1a3f61aa7ad3d4c160e609139751d66b36b653a0864736f6c63430008090033" + "code": "0x6080604052600436106101235760003560e01c80633cb747bf116100a0578063d8111a5711610064578063d8111a571461030c578063e5efd58514610322578063ea01cd3614610338578063f2fde38b14610358578063fad9aba31461037857600080fd5b80633cb747bf1461028f5780633ccfd60b146102af578063715018a6146102c45780638da5cb5b146102d9578063cfb550f1146102f757600080fd5b806319d509a1116100e757806319d509a11461020e5780631a39d8ef1461022457806327c8f8351461023a5780632c79db111461025a5780633b52c31e1461026f57600080fd5b80630b50cd3e1461012f5780630fae75d91461016457806310a7fd7b14610186578063110b7eb0146101c157806315c6f166146101f957600080fd5b3661012a57005b600080fd5b34801561013b57600080fd5b5061014f61014a366004610d5c565b61038e565b60405190151581526020015b60405180910390f35b34801561017057600080fd5b5061018461017f366004610d7e565b6104a9565b005b34801561019257600080fd5b506101b36101a1366004610e20565b60026020526000908152604090205481565b60405190815260200161015b565b3480156101cd57600080fd5b506003546101e1906001600160a01b031681565b6040516001600160a01b03909116815260200161015b565b34801561020557600080fd5b506101b36108a6565b34801561021a57600080fd5b506101b360065481565b34801561023057600080fd5b506101b360075481565b34801561024657600080fd5b506004546101e1906001600160a01b031681565b34801561026657600080fd5b506101b36108d1565b34801561027b57600080fd5b5061018461028a366004610e20565b6108fa565b34801561029b57600080fd5b506001546101e1906001600160a01b031681565b3480156102bb57600080fd5b50610184610929565b3480156102d057600080fd5b506101846109be565b3480156102e557600080fd5b506000546001600160a01b03166101e1565b34801561030357600080fd5b506101846109f2565b34801561031857600080fd5b506101b360095481565b34801561032e57600080fd5b506101b360085481565b34801561034457600080fd5b50600a546101e1906001600160a01b031681565b34801561036457600080fd5b50610184610373366004610e4e565b610a9b565b34801561038457600080fd5b506101b360055481565b6004546000906001600160a01b031633146104005760405162461bcd60e51b815260206004820152602760248201527f747373207265776172642063616c6c206d65737361676520756e61757468656e6044820152661d1a58d85d195960ca1b60648201526084015b60405180910390fd5b6007544710156104225760405162461bcd60e51b81526004016103f790610e6b565b600654610430906001610ed2565b831461047e5760405162461bcd60e51b815260206004820152601760248201527f626c6f636b2069642075706461746520696c6c6567616c00000000000000000060448201526064016103f7565b60068390556007546104909083610b33565b6007555060009182526002602052604090912055600190565b600a546001600160a01b03166104c76001546001600160a01b031690565b6001600160a01b0316336001600160a01b03161461053e5760405162461bcd60e51b815260206004820152602e60248201527f42564d5f58434841494e3a206d657373656e67657220636f6e7472616374207560448201526d1b985d5d1a195b9d1a58d85d195960921b60648201526084016103f7565b806001600160a01b031661055a6001546001600160a01b031690565b6001600160a01b0316636e296e456040518163ffffffff1660e01b815260040160206040518083038186803b15801561059257600080fd5b505afa1580156105a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ca9190610eea565b6001600160a01b0316146106395760405162461bcd60e51b815260206004820152603060248201527f42564d5f58434841494e3a2077726f6e672073656e646572206f662063726f7360448201526f732d646f6d61696e206d65737361676560801b60648201526084016103f7565b600360009054906101000a90046001600160a01b03166001600160a01b0316630d1e43a06040518163ffffffff1660e01b815260040160206040518083038186803b15801561068757600080fd5b505afa15801561069b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106bf9190610f07565b6001146106d7576106d286868585610b46565b61089e565b6000806000600854600014156106f457505050600884905561089e565b60085487116107605760405162461bcd60e51b815260206004820152603260248201527f61726773205f626174636854696d65206d757374206774686572207468616e206044820152716c617374206c617374426174636854696d6560701b60648201526084016103f7565b60055461076b6108a6565b600854610778908a610f20565b6107829190610f37565b61078c9190610ed2565b6000600555915061079d8286610cf4565b925060005b8581101561082d5760008787838181106107be576107be610f56565b90506020020160208101906107d39190610e4e565b90506107df8386610b33565b6040519093506001600160a01b0382169086156108fc029087906000818181858888f19350505050158015610818573d6000803e3d6000fd5b5050808061082590610f6c565b9150506107a2565b50600061083a8383610d00565b905080156108535760055461084f9082610b33565b6005555b7ff533ef50019763ee9d95ad46e28350b533c11edd472ae7be93e8fae83c1b6d9960085489868a8a60405161088c959493929190610fd0565b60405180910390a15050506008859055505b505050505050565b60006108cc6301e13380600954670de0b6b3a76400006108c69190610f37565b90610cf4565b905090565b60006007544710156108f55760405162461bcd60e51b81526004016103f790610e6b565b504790565b6000546001600160a01b031633146109245760405162461bcd60e51b81526004016103f790611001565b600955565b6000546001600160a01b031633146109535760405162461bcd60e51b81526004016103f790611001565b6007544710156109755760405162461bcd60e51b81526004016103f790610e6b565b600060075547156109bc57600080546040516001600160a01b03909116914780156108fc02929091818181858888f193505050501580156109ba573d6000803e3d6000fd5b505b565b6000546001600160a01b031633146109e85760405162461bcd60e51b81526004016103f790611001565b6109bc6000610d0c565b6000546001600160a01b03163314610a1c5760405162461bcd60e51b81526004016103f790611001565b600754471015610a3e5760405162461bcd60e51b81526004016103f790610e6b565b600554600754610a4e9082610d00565b600755600060055580156109ba57600080546005546040516001600160a01b039092169281156108fc029290818181858888f19350505050158015610a97573d6000803e3d6000fd5b5050565b6000546001600160a01b03163314610ac55760405162461bcd60e51b81526004016103f790611001565b6001600160a01b038116610b2a5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016103f7565b6109ba81610d0c565b6000610b3f8284610ed2565b9392505050565b6000806000805b8663ffffffff16811015610bbf57610b8a60026000610b6c848c610ed2565b81526020019081526020016000205484610b3390919063ffffffff16565b925060026000610b9a838b610ed2565b8152602001908152602001600020600090558080610bb790610f6c565b915050610b4d565b508115610cac57600554610bd39083610ed2565b60006005559150610be48285610cf4565b925060005b84811015610c84576000868683818110610c0557610c05610f56565b9050602002016020810190610c1a9190610e4e565b9050610c268386610b33565b600754909350610c369086610d00565b6007556040516001600160a01b0382169086156108fc029087906000818181858888f19350505050158015610c6f573d6000803e3d6000fd5b50508080610c7c90610f6c565b915050610be9565b506000610c918383610d00565b90508015610caa57600554610ca69082610b33565b6005555b505b7f2dae6f3d42a2c50d6baa3ea3f2423a9e1ff0ba26875f8ba6ba25c40df98009fe8787858888604051610ce3959493929190611036565b60405180910390a150505050505050565b6000610b3f8284611062565b6000610b3f8284610f20565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60008060408385031215610d6f57600080fd5b50508035926020909101359150565b600080600080600060808688031215610d9657600080fd5b85359450602086013563ffffffff81168114610db157600080fd5b935060408601359250606086013567ffffffffffffffff80821115610dd557600080fd5b818801915088601f830112610de957600080fd5b813581811115610df857600080fd5b8960208260051b8501011115610e0d57600080fd5b9699959850939650602001949392505050565b600060208284031215610e3257600080fd5b5035919050565b6001600160a01b03811681146109ba57600080fd5b600060208284031215610e6057600080fd5b8135610b3f81610e39565b60208082526031908201527f62616c616e6365207265636f726420616e6420636f6e74726163742062616c616040820152701b98d948185c99481b9bdd08195c5d585b607a1b606082015260800190565b634e487b7160e01b600052601160045260246000fd5b60008219821115610ee557610ee5610ebc565b500190565b600060208284031215610efc57600080fd5b8151610b3f81610e39565b600060208284031215610f1957600080fd5b5051919050565b600082821015610f3257610f32610ebc565b500390565b6000816000190483118215151615610f5157610f51610ebc565b500290565b634e487b7160e01b600052603260045260246000fd5b6000600019821415610f8057610f80610ebc565b5060010190565b8183526000602080850194508260005b85811015610fc5578135610faa81610e39565b6001600160a01b031687529582019590820190600101610f97565b509495945050505050565b858152846020820152836040820152608060608201526000610ff6608083018486610f87565b979650505050505050565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b85815263ffffffff85166020820152836040820152608060608201526000610ff6608083018486610f87565b60008261107f57634e487b7160e01b600052601260045260246000fd5b50049056fea2646970667358221220796ffabdfbad4bc4abcc71948bad22b7a53f5250cc041d698f8f6ba035dd424f64736f6c63430008090033" } } } \ No newline at end of file diff --git a/packages/contracts/genesis/state-dump.latest.json b/packages/contracts/genesis/state-dump.latest.json index 9840d777d..ff704a7b0 100644 --- a/packages/contracts/genesis/state-dump.latest.json +++ b/packages/contracts/genesis/state-dump.latest.json @@ -1,9 +1,5 @@ { -<<<<<<< HEAD - "commit": "a9b2338993a860ff562434451b0f3f496502503f", -======= - "commit": "7accccb28a63b7701eaa79033c1aeb914b3395b3", ->>>>>>> feature/ctc-rollup-switch-to-eigenlayer + "commit": "00ab47dba2b1e757c243a8b586aed40888e0b28d", "config": { "chainId": 17, "homesteadBlock": 0, @@ -29,14 +25,14 @@ "0x4200000000000000000000000000000000000000": { "balance": "00", "storage": {}, - "code": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c806382e3702d1461003b578063cafa81dc14610072575b600080fd5b61005e610049366004610112565b60006020819052908152604090205460ff1681565b604051901515815260200160405180910390f35b61008561008036600461015a565b610087565b005b6001600080833360405160200161009f929190610229565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815291815281516020928301208352908201929092520160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001691151591909117905550565b60006020828403121561012457600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006020828403121561016c57600080fd5b813567ffffffffffffffff8082111561018457600080fd5b818401915084601f83011261019857600080fd5b8135818111156101aa576101aa61012b565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156101f0576101f061012b565b8160405282815287602084870101111561020957600080fd5b826020860160208301376000928101602001929092525095945050505050565b6000835160005b8181101561024a5760208187018101518583015201610230565b81811115610259576000828501525b5060609390931b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016919092019081526014019291505056fea26469706673582212207bc608c152ff3d42d0bc53a0492fc811e6bc685922f023653d6affe9df75f55764736f6c63430008090033" + "code": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c806382e3702d1461003b578063cafa81dc14610072575b600080fd5b61005e6100493660046100d6565b60006020819052908152604090205460ff1681565b604051901515815260200160405180910390f35b610085610080366004610105565b610087565b005b6001600080833360405160200161009f9291906101b6565b60408051808303601f19018152918152815160209283012083529082019290925201600020805460ff191691151591909117905550565b6000602082840312156100e857600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b60006020828403121561011757600080fd5b813567ffffffffffffffff8082111561012f57600080fd5b818401915084601f83011261014357600080fd5b813581811115610155576101556100ef565b604051601f8201601f19908116603f0116810190838211818310171561017d5761017d6100ef565b8160405282815287602084870101111561019657600080fd5b826020860160208301376000928101602001929092525095945050505050565b6000835160005b818110156101d757602081870181015185830152016101bd565b818111156101e6576000828501525b5060609390931b6bffffffffffffffffffffffff1916919092019081526014019291505056fea2646970667358221220a5c338b6c39fb5f5d42de33bacb945608db4a507585b3f40c0324e4402967d6c64736f6c63430008090033" }, "0x4200000000000000000000000000000000000002": { "balance": "00", "storage": { "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000000" }, - "code": "0x608060405234801561001057600080fd5b50600436106100725760003560e01c80639b19251a116100505780639b19251a146100e9578063b1540a011461011c578063bdc7b54f1461012f57600080fd5b806308fd63221461007757806313af40351461008c5780638da5cb5b1461009f575b600080fd5b61008a610085366004610614565b610137565b005b61008a61009a366004610650565b610271565b6000546100bf9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b61010c6100f7366004610650565b60016020526000908152604090205460ff1681565b60405190151581526020016100e0565b61010c61012a366004610650565b61047c565b61008a6104cd565b60005473ffffffffffffffffffffffffffffffffffffffff1633146101e3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f46756e6374696f6e2063616e206f6e6c792062652063616c6c6564206279207460448201527f6865206f776e6572206f66207468697320636f6e74726163742e00000000000060648201526084015b60405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff821660008181526001602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00168515159081179091558251938452908301527f8daaf060c3306c38e068a75c054bf96ecd85a3db1252712c4d93632744c42e0d910160405180910390a15050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610318576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f46756e6374696f6e2063616e206f6e6c792062652063616c6c6564206279207460448201527f6865206f776e6572206f66207468697320636f6e74726163742e00000000000060648201526084016101da565b73ffffffffffffffffffffffffffffffffffffffff81166103e1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605160248201527f42564d5f4465706c6f79657257686974656c6973743a2063616e206f6e6c792060448201527f62652064697361626c65642076696120656e61626c654172626974726172794360648201527f6f6e74726163744465706c6f796d656e74000000000000000000000000000000608482015260a4016101da565b6000546040805173ffffffffffffffffffffffffffffffffffffffff928316815291831660208301527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c910160405180910390a1600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6000805473ffffffffffffffffffffffffffffffffffffffff1615806104c7575073ffffffffffffffffffffffffffffffffffffffff821660009081526001602052604090205460ff165b92915050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610574576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f46756e6374696f6e2063616e206f6e6c792062652063616c6c6564206279207460448201527f6865206f776e6572206f66207468697320636f6e74726163742e00000000000060648201526084016101da565b60005460405173ffffffffffffffffffffffffffffffffffffffff90911681527fc0e106cf568e50698fdbde1eff56f5a5c966cc7958e37e276918e9e4ccdf8cd49060200160405180910390a1600080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055565b803573ffffffffffffffffffffffffffffffffffffffff8116811461060f57600080fd5b919050565b6000806040838503121561062757600080fd5b610630836105eb565b91506020830135801515811461064557600080fd5b809150509250929050565b60006020828403121561066257600080fd5b61066b826105eb565b939250505056fea2646970667358221220df27bdf86bfaa0da7e2c1622f676e71f90f0b0fe09846498fe6f2e58ca9e544464736f6c63430008090033" + "code": "0x608060405234801561001057600080fd5b50600436106100625760003560e01c806308fd63221461006757806313af40351461007c5780638da5cb5b1461008f5780639b19251a146100bf578063b1540a01146100f2578063bdc7b54f14610105575b600080fd5b61007a61007536600461039b565b61010d565b005b61007a61008a3660046103d7565b6101a3565b6000546100a2906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b6100e26100cd3660046103d7565b60016020526000908152604090205460ff1681565b60405190151581526020016100b6565b6100e26101003660046103d7565b6102cc565b61007a610303565b6000546001600160a01b031633146101405760405162461bcd60e51b8152600401610137906103f9565b60405180910390fd5b6001600160a01b038216600081815260016020908152604091829020805460ff19168515159081179091558251938452908301527f8daaf060c3306c38e068a75c054bf96ecd85a3db1252712c4d93632744c42e0d910160405180910390a15050565b6000546001600160a01b031633146101cd5760405162461bcd60e51b8152600401610137906103f9565b6001600160a01b0381166102635760405162461bcd60e51b815260206004820152605160248201527f42564d5f4465706c6f79657257686974656c6973743a2063616e206f6e6c792060448201527f62652064697361626c65642076696120656e61626c65417262697472617279436064820152701bdb9d1c9858dd11195c1b1bde5b595b9d607a1b608482015260a401610137565b600054604080516001600160a01b03928316815291831660208301527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c910160405180910390a1600080546001600160a01b0319166001600160a01b0392909216919091179055565b600080546001600160a01b031615806102fd57506001600160a01b03821660009081526001602052604090205460ff165b92915050565b6000546001600160a01b0316331461032d5760405162461bcd60e51b8152600401610137906103f9565b6000546040516001600160a01b0390911681527fc0e106cf568e50698fdbde1eff56f5a5c966cc7958e37e276918e9e4ccdf8cd49060200160405180910390a1600080546001600160a01b0319169055565b80356001600160a01b038116811461039657600080fd5b919050565b600080604083850312156103ae57600080fd5b6103b78361037f565b9150602083013580151581146103cc57600080fd5b809150509250929050565b6000602082840312156103e957600080fd5b6103f28261037f565b9392505050565b6020808252603a908201527f46756e6374696f6e2063616e206f6e6c792062652063616c6c6564206279207460408201527f6865206f776e6572206f66207468697320636f6e74726163742e00000000000060608201526080019056fea264697066735822122014c54fb7ee74ea774867baf99a626bf5080d91aef21986eb9bbc65ca16a20bfd64736f6c63430008090033" }, "0x4200000000000000000000000000000000000007": { "balance": "00", @@ -45,7 +41,7 @@ "0x0000000000000000000000000000000000000000000000000000000000000005": "0x000000000000000000000000d9e2f450525079e1e29fb23bc7caca6f61f8fd4a", "0x0000000000000000000000000000000000000000000000000000000000000003": "0x00000000000000000000000000000000000000000000000000000000000186a0" }, - "code": "0x608060405234801561001057600080fd5b50600436106100885760003560e01c8063a71198691161005b578063a71198691461012a578063b1b1b2091461014a578063cbd4ece91461016d578063ecc704281461018057600080fd5b806321d800ec1461008d5780633dbb202b146100c55780636e296e45146100da57806382e3702d14610107575b600080fd5b6100b061009b366004610826565b60006020819052908152604090205460ff1681565b60405190151581526020015b60405180910390f35b6100d86100d3366004610942565b610197565b005b6100e26102e2565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100bc565b6100b0610115366004610826565b60026020526000908152604090205460ff1681565b6005546100e29073ffffffffffffffffffffffffffffffffffffffff1681565b6100b0610158366004610826565b60016020526000908152604090205460ff1681565b6100d861017b3660046109ad565b61038b565b61018960035481565b6040519081526020016100bc565b60006101a784338560035461078d565b80516020808301919091206000908152600290915260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055517fcafa81dc0000000000000000000000000000000000000000000000000000000081529091507342000000000000000000000000000000000000009063cafa81dc9061023c908490600401610a89565b600060405180830381600087803b15801561025657600080fd5b505af115801561026a573d6000803e3d6000fd5b505050508373ffffffffffffffffffffffffffffffffffffffff167fcb0f7ffd78f9aee47a248fae8db181db6eee833039123e026dcbff529522e52a3385600354866040516102bc9493929190610aa3565b60405180910390a26001600360008282546102d79190610aef565b909155505050505050565b60045460009073ffffffffffffffffffffffffffffffffffffffff1661dead141561036e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f78446f6d61696e4d65737361676553656e646572206973206e6f74207365740060448201526064015b60405180910390fd5b5060045473ffffffffffffffffffffffffffffffffffffffff1690565b60055473ffffffffffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffeeeeffffffffffffffffffffffffffffffffeeef330173ffffffffffffffffffffffffffffffffffffffff161461046a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f50726f7669646564206d65737361676520636f756c64206e6f7420626520766560448201527f7269666965642e000000000000000000000000000000000000000000000000006064820152608401610365565b60006104788585858561078d565b8051602080830191909120600081815260019092526040909120549192509060ff1615610527576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f50726f7669646564206d6573736167652068617320616c72656164792062656560448201527f6e2072656365697665642e0000000000000000000000000000000000000000006064820152608401610365565b73ffffffffffffffffffffffffffffffffffffffff8616734200000000000000000000000000000000000000141561059957600090815260016020819052604090912080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016909117905550610787565b600480547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff878116919091179091556040516000918816906105f2908790610b2e565b6000604051808303816000865af19150503d806000811461062f576040519150601f19603f3d011682016040523d82523d6000602084013e610634565b606091505b5050600480547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead1790559050801515600114156106d557600082815260016020819052604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169092179091555183917f4641df4a962071e12719d8c8c8e5ac7fc4d97b927346a3d7a335b1f7517e133c91a2610701565b60405182907f99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f90600090a25b600083334360405160200161071893929190610b4a565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181528151602092830120600090815291829052902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055505050505b50505050565b6060848484846040516024016107a69493929190610b9c565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fcbd4ece9000000000000000000000000000000000000000000000000000000001790529050949350505050565b60006020828403121561083857600080fd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461086357600080fd5b919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126108a857600080fd5b813567ffffffffffffffff808211156108c3576108c3610868565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561090957610909610868565b8160405283815286602085880101111561092257600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060006060848603121561095757600080fd5b6109608461083f565b9250602084013567ffffffffffffffff81111561097c57600080fd5b61098886828701610897565b925050604084013563ffffffff811681146109a257600080fd5b809150509250925092565b600080600080608085870312156109c357600080fd5b6109cc8561083f565b93506109da6020860161083f565b9250604085013567ffffffffffffffff8111156109f657600080fd5b610a0287828801610897565b949793965093946060013593505050565b60005b83811015610a2e578181015183820152602001610a16565b838111156107875750506000910152565b60008151808452610a57816020860160208601610a13565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000610a9c6020830184610a3f565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff85168152608060208201526000610ad26080830186610a3f565b905083604083015263ffffffff8316606083015295945050505050565b60008219821115610b29577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b500190565b60008251610b40818460208701610a13565b9190910192915050565b60008451610b5c818460208901610a13565b60609490941b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001691909301908152601481019190915260340192915050565b600073ffffffffffffffffffffffffffffffffffffffff808716835280861660208401525060806040830152610bd56080830185610a3f565b90508260608301529594505050505056fea264697066735822122060db5939914765b6ad042b95a40568e91920bfb1eadc40c6a64ec7445e27814a64736f6c63430008090033" + "code": "0x608060405234801561001057600080fd5b50600436106100885760003560e01c8063a71198691161005b578063a71198691461011d578063b1b1b20914610130578063cbd4ece914610153578063ecc704281461016657600080fd5b806321d800ec1461008d5780633dbb202b146100c55780636e296e45146100da57806382e3702d146100fa575b600080fd5b6100b061009b3660046105e5565b60006020819052908152604090205460ff1681565b60405190151581526020015b60405180910390f35b6100d86100d33660046106bd565b61017d565b005b6100e2610274565b6040516001600160a01b0390911681526020016100bc565b6100b06101083660046105e5565b60026020526000908152604090205460ff1681565b6005546100e2906001600160a01b031681565b6100b061013e3660046105e5565b60016020526000908152604090205460ff1681565b6100d8610161366004610728565b6102e9565b61016f60035481565b6040519081526020016100bc565b600061018d843385600354610598565b805160208083019190912060009081526002909152604090819020805460ff19166001179055516332bea07760e21b8152909150602160991b9063cafa81dc906101db9084906004016107e6565b600060405180830381600087803b1580156101f557600080fd5b505af1158015610209573d6000803e3d6000fd5b50505050836001600160a01b03167fcb0f7ffd78f9aee47a248fae8db181db6eee833039123e026dcbff529522e52a33856003548660405161024e9493929190610800565b60405180910390a26001600360008282546102699190610841565b909155505050505050565b6004546000906001600160a01b031661dead14156102d95760405162461bcd60e51b815260206004820152601f60248201527f78446f6d61696e4d65737361676553656e646572206973206e6f74207365740060448201526064015b60405180910390fd5b506004546001600160a01b031690565b6005546001600160a01b03167311110000000000000000000000000000000011101933016001600160a01b0316146103735760405162461bcd60e51b815260206004820152602760248201527f50726f7669646564206d65737361676520636f756c64206e6f742062652076656044820152663934b334b2b21760c91b60648201526084016102d0565b600061038185858585610598565b8051602080830191909120600081815260019092526040909120549192509060ff16156104045760405162461bcd60e51b815260206004820152602b60248201527f50726f7669646564206d6573736167652068617320616c72656164792062656560448201526a37103932b1b2b4bb32b21760a91b60648201526084016102d0565b6001600160a01b038616602160991b141561043b576000908152600160208190526040909120805460ff1916909117905550610592565b600480546001600160a01b0319166001600160a01b038781169190911790915560405160009188169061046f908790610867565b6000604051808303816000865af19150503d80600081146104ac576040519150601f19603f3d011682016040523d82523d6000602084013e6104b1565b606091505b5050600480546001600160a01b03191661dead17905590508015156001141561051c576000828152600160208190526040808320805460ff19169092179091555183917f4641df4a962071e12719d8c8c8e5ac7fc4d97b927346a3d7a335b1f7517e133c91a2610548565b60405182907f99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f90600090a25b600083334360405160200161055f93929190610883565b60408051601f1981840301815291815281516020928301206000908152918290529020805460ff19166001179055505050505b50505050565b6060848484846040516024016105b194939291906108c2565b60408051601f198184030181529190526020810180516001600160e01b031663cbd4ece960e01b1790529050949350505050565b6000602082840312156105f757600080fd5b5035919050565b80356001600160a01b038116811461061557600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600082601f83011261064157600080fd5b813567ffffffffffffffff8082111561065c5761065c61061a565b604051601f8301601f19908116603f011681019082821181831017156106845761068461061a565b8160405283815286602085880101111561069d57600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806000606084860312156106d257600080fd5b6106db846105fe565b9250602084013567ffffffffffffffff8111156106f757600080fd5b61070386828701610630565b925050604084013563ffffffff8116811461071d57600080fd5b809150509250925092565b6000806000806080858703121561073e57600080fd5b610747856105fe565b9350610755602086016105fe565b9250604085013567ffffffffffffffff81111561077157600080fd5b61077d87828801610630565b949793965093946060013593505050565b60005b838110156107a9578181015183820152602001610791565b838111156105925750506000910152565b600081518084526107d281602086016020860161078e565b601f01601f19169290920160200192915050565b6020815260006107f960208301846107ba565b9392505050565b6001600160a01b0385168152608060208201819052600090610824908301866107ba565b905083604083015263ffffffff8316606083015295945050505050565b6000821982111561086257634e487b7160e01b600052601160045260246000fd5b500190565b6000825161087981846020870161078e565b9190910192915050565b6000845161089581846020890161078e565b60609490941b6bffffffffffffffffffffffff191691909301908152601481019190915260340192915050565b6001600160a01b038581168252841660208201526080604082018190526000906108ee908301856107ba565b90508260608301529594505050505056fea264697066735822122032e1fac7ab206e7b44fe0e8299766d125b190c2e7849c927b4ebaa4d69f4fd5464736f6c63430008090033" }, "0x420000000000000000000000000000000000000F": { "balance": "00", @@ -60,7 +56,7 @@ "0x0000000000000000000000000000000000000000000000000000000000000007": "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000008": "0x0000000000000000000000008baccff561fde61d6bc8b6f299ffba561d2189b9" }, - "code": "0x608060405234801561001057600080fd5b506004361061016c5760003560e01c80638da5cb5b116100cd578063ea01cd3611610081578063f45e65d811610066578063f45e65d8146102c4578063fc55b138146102cd578063fe173b97146102e057600080fd5b8063ea01cd3614610291578063f2fde38b146102b157600080fd5b8063bf1fe420116100b2578063bf1fe42014610258578063c76478321461026b578063de26c4a11461027e57600080fd5b80638da5cb5b14610206578063bede39b51461024557600080fd5b8063519b4bd311610124578063704655971161010957806370465597146101d8578063715018a6146101eb5780638c8885c8146101f357600080fd5b8063519b4bd3146101c657806355161913146101cf57600080fd5b8063313ce56711610155578063313ce567146101955780633577afc51461019e57806349948e0e146101b357600080fd5b80630c18c162146101715780630d1e43a01461018d575b600080fd5b61017a60035481565b6040519081526020015b60405180910390f35b60065461017a565b61017a60055481565b6101b16101ac366004610ad9565b6102e9565b005b61017a6101c1366004610b21565b610391565b61017a60025481565b61017a60075481565b6101b16101e6366004610ad9565b6103ed565b6101b1610489565b6101b1610201366004610ad9565b6104fc565b60005473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610184565b6101b1610253366004610ad9565b610598565b6101b1610266366004610ad9565b610634565b6101b1610279366004610ad9565b6106d0565b61017a61028c366004610b21565b6107ce565b6008546102209073ffffffffffffffffffffffffffffffffffffffff1681565b6101b16102bf366004610bf0565b610872565b61017a60045481565b6101b16102db366004610ad9565b61096e565b61017a60015481565b60005473ffffffffffffffffffffffffffffffffffffffff1633146103555760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064015b60405180910390fd5b60038190556040518181527f32740b35c0ea213650f60d44366b4fb211c9033b50714e4a1d34e65d5beb9bb4906020015b60405180910390a150565b60008061039d836107ce565b90506000600254826103af9190610c5c565b90506000600554600a6103c29190610dbb565b90506000600454836103d49190610c5c565b905060006103e28383610dc7565b979650505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146104545760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161034c565b60048190556040518181527f3336cd9708eaf2769a0f0dc0679f30e80f15dcd88d1921b5a16858e8b85c591a90602001610386565b60005473ffffffffffffffffffffffffffffffffffffffff1633146104f05760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161034c565b6104fa6000610a64565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633146105635760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161034c565b60058190556040518181527fd68112a8707e326d08be3656b528c1bcc5bbbfc47f4177e2179b14d8640838c190602001610386565b60005473ffffffffffffffffffffffffffffffffffffffff1633146105ff5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161034c565b60028190556040518181527f351fb23757bb5ea0546c85b7996ddd7155f96b939ebaa5ff7bc49c75f27f2c4490602001610386565b60005473ffffffffffffffffffffffffffffffffffffffff16331461069b5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161034c565b60018190556040518181527ffcdccc6074c6c42e4bd578aa9870c697dc976a270968452d2b8c8dc369fae39690602001610386565b60005473ffffffffffffffffffffffffffffffffffffffff1633146107375760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161034c565b808015806107455750806001145b6107915760405162461bcd60e51b815260206004820152601c60248201527f696e76616c69642076616c75652c6d7573742062652030206f72203100000000604482015260640161034c565b60068290556040518281527fd1eaae13a99b475ddca546a1b4a45052c66c14049997f44a1731a8e7167981a7906020015b60405180910390a15050565b600080805b835181101561084b578381815181106107ee576107ee610e02565b01602001517fff000000000000000000000000000000000000000000000000000000000000001661082b57610824600483610e31565b9150610839565b610836601083610e31565b91505b8061084381610e49565b9150506107d3565b5060006003548261085c9190610e31565b905061086a81610440610e31565b949350505050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146108d95760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161034c565b73ffffffffffffffffffffffffffffffffffffffff81166109625760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161034c565b61096b81610a64565b50565b60005473ffffffffffffffffffffffffffffffffffffffff1633146109d55760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161034c565b808015806109e35750806001145b610a2f5760405162461bcd60e51b815260206004820152601c60248201527f696e76616c69642076616c75652c6d7573742062652030206f72203100000000604482015260640161034c565b60078290556040518281527f49244d4195584d0644398167ca8caa7b98ee36b674e4b4d2a2640749b27eafb7906020016107c2565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600060208284031215610aeb57600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600060208284031215610b3357600080fd5b813567ffffffffffffffff80821115610b4b57600080fd5b818401915084601f830112610b5f57600080fd5b813581811115610b7157610b71610af2565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715610bb757610bb7610af2565b81604052828152876020848701011115610bd057600080fd5b826020860160208301376000928101602001929092525095945050505050565b600060208284031215610c0257600080fd5b813573ffffffffffffffffffffffffffffffffffffffff81168114610c2657600080fd5b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615610c9457610c94610c2d565b500290565b600181815b80851115610cf257817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115610cd857610cd8610c2d565b80851615610ce557918102915b93841c9390800290610c9e565b509250929050565b600082610d0957506001610db5565b81610d1657506000610db5565b8160018114610d2c5760028114610d3657610d52565b6001915050610db5565b60ff841115610d4757610d47610c2d565b50506001821b610db5565b5060208310610133831016604e8410600b8410161715610d75575081810a610db5565b610d7f8383610c99565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115610db157610db1610c2d565b0290505b92915050565b6000610c268383610cfa565b600082610dfd577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008219821115610e4457610e44610c2d565b500190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415610e7b57610e7b610c2d565b506001019056fea26469706673582212207da82d9f1ffefb5ad9863297e3bb633970d9ab86e98a6bf78a4411e4ca1e9e2864736f6c63430008090033" + "code": "0x608060405234801561001057600080fd5b506004361061012c5760003560e01c80638da5cb5b116100ad578063ea01cd3611610071578063ea01cd3614610237578063f2fde38b1461024a578063f45e65d81461025d578063fc55b13814610266578063fe173b971461027957600080fd5b80638da5cb5b146101c6578063bede39b5146101eb578063bf1fe420146101fe578063c764783214610211578063de26c4a11461022457600080fd5b8063519b4bd3116100f4578063519b4bd314610186578063551619131461018f5780637046559714610198578063715018a6146101ab5780638c8885c8146101b357600080fd5b80630c18c162146101315780630d1e43a01461014d578063313ce567146101555780633577afc51461015e57806349948e0e14610173575b600080fd5b61013a60035481565b6040519081526020015b60405180910390f35b60065461013a565b61013a60055481565b61017161016c3660046107f0565b610282565b005b61013a61018136600461081f565b6102f1565b61013a60025481565b61013a60075481565b6101716101a63660046107f0565b61034d565b6101716103ac565b6101716101c13660046107f0565b6103e2565b6000546001600160a01b03165b6040516001600160a01b039091168152602001610144565b6101716101f93660046107f0565b610441565b61017161020c3660046107f0565b6104a0565b61017161021f3660046107f0565b6104ff565b61013a61023236600461081f565b6105c0565b6008546101d3906001600160a01b031681565b6101716102583660046108d0565b61064c565b61013a60045481565b6101716102743660046107f0565b6106e7565b61013a60015481565b6000546001600160a01b031633146102b55760405162461bcd60e51b81526004016102ac90610900565b60405180910390fd5b60038190556040518181527f32740b35c0ea213650f60d44366b4fb211c9033b50714e4a1d34e65d5beb9bb4906020015b60405180910390a150565b6000806102fd836105c0565b905060006002548261030f919061094b565b90506000600554600a6103229190610a50565b9050600060045483610334919061094b565b905060006103428383610a5c565b979650505050505050565b6000546001600160a01b031633146103775760405162461bcd60e51b81526004016102ac90610900565b60048190556040518181527f3336cd9708eaf2769a0f0dc0679f30e80f15dcd88d1921b5a16858e8b85c591a906020016102e6565b6000546001600160a01b031633146103d65760405162461bcd60e51b81526004016102ac90610900565b6103e060006107a0565b565b6000546001600160a01b0316331461040c5760405162461bcd60e51b81526004016102ac90610900565b60058190556040518181527fd68112a8707e326d08be3656b528c1bcc5bbbfc47f4177e2179b14d8640838c1906020016102e6565b6000546001600160a01b0316331461046b5760405162461bcd60e51b81526004016102ac90610900565b60028190556040518181527f351fb23757bb5ea0546c85b7996ddd7155f96b939ebaa5ff7bc49c75f27f2c44906020016102e6565b6000546001600160a01b031633146104ca5760405162461bcd60e51b81526004016102ac90610900565b60018190556040518181527ffcdccc6074c6c42e4bd578aa9870c697dc976a270968452d2b8c8dc369fae396906020016102e6565b6000546001600160a01b031633146105295760405162461bcd60e51b81526004016102ac90610900565b808015806105375750806001145b6105835760405162461bcd60e51b815260206004820152601c60248201527f696e76616c69642076616c75652c6d7573742062652030206f7220310000000060448201526064016102ac565b60068290556040518281527fd1eaae13a99b475ddca546a1b4a45052c66c14049997f44a1731a8e7167981a7906020015b60405180910390a15050565b600080805b8351811015610625578381815181106105e0576105e0610a7e565b01602001516001600160f81b031916610605576105fe600483610a94565b9150610613565b610610601083610a94565b91505b8061061d81610aac565b9150506105c5565b506000600354826106369190610a94565b905061064481610440610a94565b949350505050565b6000546001600160a01b031633146106765760405162461bcd60e51b81526004016102ac90610900565b6001600160a01b0381166106db5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016102ac565b6106e4816107a0565b50565b6000546001600160a01b031633146107115760405162461bcd60e51b81526004016102ac90610900565b8080158061071f5750806001145b61076b5760405162461bcd60e51b815260206004820152601c60248201527f696e76616c69642076616c75652c6d7573742062652030206f7220310000000060448201526064016102ac565b60078290556040518281527f49244d4195584d0644398167ca8caa7b98ee36b674e4b4d2a2640749b27eafb7906020016105b4565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60006020828403121561080257600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b60006020828403121561083157600080fd5b813567ffffffffffffffff8082111561084957600080fd5b818401915084601f83011261085d57600080fd5b81358181111561086f5761086f610809565b604051601f8201601f19908116603f0116810190838211818310171561089757610897610809565b816040528281528760208487010111156108b057600080fd5b826020860160208301376000928101602001929092525095945050505050565b6000602082840312156108e257600080fd5b81356001600160a01b03811681146108f957600080fd5b9392505050565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b634e487b7160e01b600052601160045260246000fd5b600081600019048311821515161561096557610965610935565b500290565b600181815b808511156109a557816000190482111561098b5761098b610935565b8085161561099857918102915b93841c939080029061096f565b509250929050565b6000826109bc57506001610a4a565b816109c957506000610a4a565b81600181146109df57600281146109e957610a05565b6001915050610a4a565b60ff8411156109fa576109fa610935565b50506001821b610a4a565b5060208310610133831016604e8410600b8410161715610a28575081810a610a4a565b610a32838361096a565b8060001904821115610a4657610a46610935565b0290505b92915050565b60006108f983836109ad565b600082610a7957634e487b7160e01b600052601260045260246000fd5b500490565b634e487b7160e01b600052603260045260246000fd5b60008219821115610aa757610aa7610935565b500190565b6000600019821415610ac057610ac0610935565b506001019056fea264697066735822122043d302590ccee26da66f62b9035147e6f028d5a093582f0dd3d61948a781608564736f6c63430008090033" }, "0x4200000000000000000000000000000000000010": { "balance": "00", @@ -68,7 +64,7 @@ "0x0000000000000000000000000000000000000000000000000000000000000001": "0x00000000000000000000000052753615226f8ac8a464bfecb11ef798cff3793f", "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000004200000000000000000000000000000000000007" }, - "code": "0x608060405234801561001057600080fd5b50600436106100675760003560e01c80633cb747bf116100505780633cb747bf146100ca578063662a633a146100ea578063a3a79548146100fd57600080fd5b806332b7006d1461006c57806336c717c114610081575b600080fd5b61007f61007a366004610d7c565b610110565b005b6001546100a19073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b6000546100a19073ffffffffffffffffffffffffffffffffffffffff1681565b61007f6100f8366004610ded565b610126565b61007f61010b366004610e85565b6106c1565b61011f853333878787876106d8565b5050505050565b60015473ffffffffffffffffffffffffffffffffffffffff1661015e60005473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461021d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f42564d5f58434841494e3a206d657373656e67657220636f6e7472616374207560448201527f6e61757468656e7469636174656400000000000000000000000000000000000060648201526084015b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1661025360005473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff16636e296e456040518163ffffffff1660e01b815260040160206040518083038186803b15801561029857600080fd5b505afa1580156102ac573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102d09190610f08565b73ffffffffffffffffffffffffffffffffffffffff1614610373576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f42564d5f58434841494e3a2077726f6e672073656e646572206f662063726f7360448201527f732d646f6d61696e206d657373616765000000000000000000000000000000006064820152608401610214565b61039d877f1d1d8b6300000000000000000000000000000000000000000000000000000000610a9f565b801561045357508673ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156103ec57600080fd5b505af1158015610400573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104249190610f08565b73ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff16145b15610567576040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8681166004830152602482018690528816906340c10f1990604401600060405180830381600087803b1580156104c857600080fd5b505af11580156104dc573d6000803e3d6000fd5b505050508573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff167fb0444523268717a02698be47d0803aa7468c00acbed2f8bd93a0459cde61dd898888888860405161055a9493929190610f75565b60405180910390a46106b7565b600063a9f9e67560e01b8989888a89898960405160240161058e9796959493929190610fab565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526001549091506106339073ffffffffffffffffffffffffffffffffffffffff16600083610ac4565b8673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff167f7ea89a4591614515571c2b51f5ea06494056f261c10ab1ed8c03c7590d87bce0898989896040516106ad9493929190610f75565b60405180910390a4505b5050505050505050565b6106d0863387878787876106d8565b505050505050565b6040517f9dc29fac0000000000000000000000000000000000000000000000000000000081523360048201526024810185905273ffffffffffffffffffffffffffffffffffffffff881690639dc29fac90604401600060405180830381600087803b15801561074657600080fd5b505af115801561075a573d6000803e3d6000fd5b5050505060008773ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156107a857600080fd5b505af11580156107bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107e09190610f08565b9050606073ffffffffffffffffffffffffffffffffffffffff891673deaddeaddeaddeaddeaddeaddeaddeaddead111114156108d5576040517f1532ec340000000000000000000000000000000000000000000000000000000090610851908a908a908a9089908990602401611008565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091529050610a01565b73ffffffffffffffffffffffffffffffffffffffff891673deaddeaddeaddeaddeaddeaddeaddeaddead00001415610942576040517f839f0ec60000000000000000000000000000000000000000000000000000000090610851908a908a908a9089908990602401611008565b6040517fa9f9e67500000000000000000000000000000000000000000000000000000000906109819084908c908c908c908c908b908b90602401610fab565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915290505b600154610a259073ffffffffffffffffffffffffffffffffffffffff168683610ac4565b3373ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f73d170910aba9e6d50b102db522b1dbcd796216f5128b445aa2135272886497e8a8a89896040516106ad9493929190610f75565b6000610aaa83610b55565b8015610abb5750610abb8383610bb9565b90505b92915050565b6000546040517f3dbb202b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911690633dbb202b90610b1e90869085908790600401611083565b600060405180830381600087803b158015610b3857600080fd5b505af1158015610b4c573d6000803e3d6000fd5b50505050505050565b6000610b81827f01ffc9a700000000000000000000000000000000000000000000000000000000610bb9565b8015610abe5750610bb2827fffffffff00000000000000000000000000000000000000000000000000000000610bb9565b1592915050565b604080517fffffffff00000000000000000000000000000000000000000000000000000000831660248083019190915282518083039091018152604490910182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a7000000000000000000000000000000000000000000000000000000001790529051600091908290819073ffffffffffffffffffffffffffffffffffffffff87169061753090610c739086906110ff565b6000604051808303818686fa925050503d8060008114610caf576040519150601f19603f3d011682016040523d82523d6000602084013e610cb4565b606091505b5091509150602081511015610ccf5760009350505050610abe565b818015610ceb575080806020019051810190610ceb919061111b565b9695505050505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610d1757600080fd5b50565b803563ffffffff81168114610d2e57600080fd5b919050565b60008083601f840112610d4557600080fd5b50813567ffffffffffffffff811115610d5d57600080fd5b602083019150836020828501011115610d7557600080fd5b9250929050565b600080600080600060808688031215610d9457600080fd5b8535610d9f81610cf5565b945060208601359350610db460408701610d1a565b9250606086013567ffffffffffffffff811115610dd057600080fd5b610ddc88828901610d33565b969995985093965092949392505050565b600080600080600080600060c0888a031215610e0857600080fd5b8735610e1381610cf5565b96506020880135610e2381610cf5565b95506040880135610e3381610cf5565b94506060880135610e4381610cf5565b93506080880135925060a088013567ffffffffffffffff811115610e6657600080fd5b610e728a828b01610d33565b989b979a50959850939692959293505050565b60008060008060008060a08789031215610e9e57600080fd5b8635610ea981610cf5565b95506020870135610eb981610cf5565b945060408701359350610ece60608801610d1a565b9250608087013567ffffffffffffffff811115610eea57600080fd5b610ef689828a01610d33565b979a9699509497509295939492505050565b600060208284031215610f1a57600080fd5b8151610f2581610cf5565b9392505050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b73ffffffffffffffffffffffffffffffffffffffff85168152836020820152606060408201526000610ceb606083018486610f2c565b600073ffffffffffffffffffffffffffffffffffffffff808a1683528089166020840152808816604084015280871660608401525084608083015260c060a0830152610ffb60c083018486610f2c565b9998505050505050505050565b600073ffffffffffffffffffffffffffffffffffffffff808816835280871660208401525084604083015260806060830152611048608083018486610f2c565b979650505050505050565b60005b8381101561106e578181015183820152602001611056565b8381111561107d576000848401525b50505050565b73ffffffffffffffffffffffffffffffffffffffff8416815260606020820152600083518060608401526110be816080850160208801611053565b63ffffffff93909316604083015250601f919091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160160800192915050565b60008251611111818460208701611053565b9190910192915050565b60006020828403121561112d57600080fd5b81518015158114610f2557600080fdfea2646970667358221220c3a18d6cb25a717fc2811d2494b09dcae28c97abb0e1e8f4d4292e1aa816717564736f6c63430008090033" + "code": "0x608060405234801561001057600080fd5b50600436106100575760003560e01c806332b7006d1461005c57806336c717c1146100715780633cb747bf146100a0578063662a633a146100b3578063a3a79548146100c6575b600080fd5b61006f61006a366004610968565b6100d9565b005b600154610084906001600160a01b031681565b6040516001600160a01b03909116815260200160405180910390f35b600054610084906001600160a01b031681565b61006f6100c13660046109d9565b6100ef565b61006f6100d4366004610a71565b6104c6565b6100e8853333878787876104dd565b5050505050565b6001546001600160a01b031661010d6000546001600160a01b031690565b6001600160a01b0316336001600160a01b0316146101895760405162461bcd60e51b815260206004820152602e60248201527f42564d5f58434841494e3a206d657373656e67657220636f6e7472616374207560448201526d1b985d5d1a195b9d1a58d85d195960921b60648201526084015b60405180910390fd5b806001600160a01b03166101a56000546001600160a01b031690565b6001600160a01b0316636e296e456040518163ffffffff1660e01b815260040160206040518083038186803b1580156101dd57600080fd5b505afa1580156101f1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102159190610af4565b6001600160a01b0316146102845760405162461bcd60e51b815260206004820152603060248201527f42564d5f58434841494e3a2077726f6e672073656e646572206f662063726f7360448201526f732d646f6d61696e206d65737361676560801b6064820152608401610180565b61029587631d1d8b6360e01b610742565b80156103245750866001600160a01b031663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156102d757600080fd5b505af11580156102eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061030f9190610af4565b6001600160a01b0316886001600160a01b0316145b156103eb576040516340c10f1960e01b81526001600160a01b038681166004830152602482018690528816906340c10f1990604401600060405180830381600087803b15801561037357600080fd5b505af1158015610387573d6000803e3d6000fd5b50505050856001600160a01b0316876001600160a01b0316896001600160a01b03167fb0444523268717a02698be47d0803aa7468c00acbed2f8bd93a0459cde61dd89888888886040516103de9493929190610b41565b60405180910390a46104bc565b600063a9f9e67560e01b8989888a8989896040516024016104129796959493929190610b69565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915260015490915061045f906001600160a01b0316600083610767565b866001600160a01b0316886001600160a01b03168a6001600160a01b03167f7ea89a4591614515571c2b51f5ea06494056f261c10ab1ed8c03c7590d87bce0898989896040516104b29493929190610b41565b60405180910390a4505b5050505050505050565b6104d5863387878787876104dd565b505050505050565b604051632770a7eb60e21b8152336004820152602481018590526001600160a01b03881690639dc29fac90604401600060405180830381600087803b15801561052557600080fd5b505af1158015610539573d6000803e3d6000fd5b505050506000876001600160a01b031663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561057a57600080fd5b505af115801561058e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105b29190610af4565b905060606001600160a01b03891673deaddeaddeaddeaddeaddeaddeaddeaddead111114156106365760405163054cbb0d60e21b906105fd908a908a908a9089908990602401610bba565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915290506106d8565b6001600160a01b03891673deaddeaddeaddeaddeaddeaddeaddeaddead0000141561067d576040516341cf876360e11b906105fd908a908a908a9089908990602401610bba565b60405163a9f9e67560e01b906106a39084908c908c908c908c908b908b90602401610b69565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915290505b6001546106ef906001600160a01b03168683610767565b336001600160a01b0316896001600160a01b0316836001600160a01b03167f73d170910aba9e6d50b102db522b1dbcd796216f5128b445aa2135272886497e8a8a89896040516104b29493929190610b41565b600061074d836107d2565b801561075e575061075e8383610805565b90505b92915050565b600054604051633dbb202b60e01b81526001600160a01b0390911690633dbb202b9061079b90869085908790600401610c29565b600060405180830381600087803b1580156107b557600080fd5b505af11580156107c9573d6000803e3d6000fd5b50505050505050565b60006107e5826301ffc9a760e01b610805565b801561076157506107fe826001600160e01b0319610805565b1592915050565b604080516001600160e01b0319831660248083019190915282518083039091018152604490910182526020810180516001600160e01b03166301ffc9a760e01b179052905160009190829081906001600160a01b038716906175309061086c908690610c79565b6000604051808303818686fa925050503d80600081146108a8576040519150601f19603f3d011682016040523d82523d6000602084013e6108ad565b606091505b50915091506020815110156108c85760009350505050610761565b8180156108e45750808060200190518101906108e49190610c95565b9695505050505050565b6001600160a01b038116811461090357600080fd5b50565b803563ffffffff8116811461091a57600080fd5b919050565b60008083601f84011261093157600080fd5b50813567ffffffffffffffff81111561094957600080fd5b60208301915083602082850101111561096157600080fd5b9250929050565b60008060008060006080868803121561098057600080fd5b853561098b816108ee565b9450602086013593506109a060408701610906565b9250606086013567ffffffffffffffff8111156109bc57600080fd5b6109c88882890161091f565b969995985093965092949392505050565b600080600080600080600060c0888a0312156109f457600080fd5b87356109ff816108ee565b96506020880135610a0f816108ee565b95506040880135610a1f816108ee565b94506060880135610a2f816108ee565b93506080880135925060a088013567ffffffffffffffff811115610a5257600080fd5b610a5e8a828b0161091f565b989b979a50959850939692959293505050565b60008060008060008060a08789031215610a8a57600080fd5b8635610a95816108ee565b95506020870135610aa5816108ee565b945060408701359350610aba60608801610906565b9250608087013567ffffffffffffffff811115610ad657600080fd5b610ae289828a0161091f565b979a9699509497509295939492505050565b600060208284031215610b0657600080fd5b8151610b11816108ee565b9392505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60018060a01b03851681528360208201526060604082015260006108e4606083018486610b18565b6001600160a01b03888116825287811660208301528681166040830152851660608201526080810184905260c060a08201819052600090610bad9083018486610b18565b9998505050505050505050565b6001600160a01b0386811682528516602082015260408101849052608060608201819052600090610bee9083018486610b18565b979650505050505050565b60005b83811015610c14578181015183820152602001610bfc565b83811115610c23576000848401525b50505050565b60018060a01b03841681526060602082015260008351806060840152610c56816080850160208801610bf9565b63ffffffff93909316604083015250601f91909101601f19160160800192915050565b60008251610c8b818460208701610bf9565b9190910192915050565b600060208284031215610ca757600080fd5b81518015158114610b1157600080fdfea2646970667358221220fe7ba0193a50834483182d324f34ea84cfeec79c5d6d70c7c1671af2e2c9801f64736f6c63430008090033" }, "0x4200000000000000000000000000000000000011": { "balance": "00", @@ -79,12 +75,12 @@ "0x0000000000000000000000000000000000000000000000000000000000000003": "0x000000000000000000000000000000000000000000000000000000000000dead", "0x0000000000000000000000000000000000000000000000000000000000000004": "0x000000000000000000000000000000000000000000000000000000000000000f" }, - "code": "0x6080604052600436106100cb5760003560e01c806385b5b14d11610074578063bfb084621161004e578063bfb084621461022d578063d4ff92181461024d578063f2fde38b1461027a57600080fd5b806385b5b14d146101c25780638da5cb5b146101e2578063a996d6ce1461020d57600080fd5b80635558979e116100a55780635558979e14610172578063715018a6146101975780638312f149146101ac57600080fd5b8063110b7eb0146100d757806327810b6e1461012e5780633ccfd60b1461015b57600080fd5b366100d257005b600080fd5b3480156100e357600080fd5b506002546101049073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b34801561013a57600080fd5b506003546101049073ffffffffffffffffffffffffffffffffffffffff1681565b34801561016757600080fd5b5061017061029a565b005b34801561017e57600080fd5b5061018962030d4081565b604051908152602001610125565b3480156101a357600080fd5b50610170610507565b3480156101b857600080fd5b5061018960045481565b3480156101ce57600080fd5b506101706101dd36600461094f565b610594565b3480156101ee57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff16610104565b34801561021957600080fd5b50610170610228366004610968565b61061a565b34801561023957600080fd5b50610170610248366004610968565b6106e2565b34801561025957600080fd5b506001546101049073ffffffffffffffffffffffffffffffffffffffff1681565b34801561028657600080fd5b50610170610295366004610968565b6107aa565b600154600254604080517f0d1e43a0000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff9384169390921691630d1e43a091600480820192602092909190829003018186803b15801561030c57600080fd5b505afa158015610320573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061034491906109a5565b6001141561038d575060035460045473ffffffffffffffffffffffffffffffffffffffff9091169061037e90670de0b6b3a76400006109be565b4710156103885750565b61045c565b6004546103a290670de0b6b3a76400006109be565b47101561045c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605760248201527f42564d5f53657175656e6365724665655661756c743a2077697468647261776160448201527f6c20616d6f756e74206d7573742062652067726561746572207468616e206d6960648201527f6e696d756d207769746864726177616c20616d6f756e74000000000000000000608482015260a4015b60405180910390fd5b60408051602081018252600080825291517fa3a795480000000000000000000000000000000000000000000000000000000081527342000000000000000000000000000000000000109263a3a79548926104d29273deaddeaddeaddeaddeaddeaddeaddeaddead00009287924792600401610a22565b600060405180830381600087803b1580156104ec57600080fd5b505af1158015610500573d6000803e3d6000fd5b5050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610588576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610453565b61059260006108da565b565b60005473ffffffffffffffffffffffffffffffffffffffff163314610615576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610453565b600455565b60005473ffffffffffffffffffffffffffffffffffffffff16331461069b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610453565b600380547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60005473ffffffffffffffffffffffffffffffffffffffff163314610763576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610453565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60005473ffffffffffffffffffffffffffffffffffffffff16331461082b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610453565b73ffffffffffffffffffffffffffffffffffffffff81166108ce576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610453565b6108d7816108da565b50565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60006020828403121561096157600080fd5b5035919050565b60006020828403121561097a57600080fd5b813573ffffffffffffffffffffffffffffffffffffffff8116811461099e57600080fd5b9392505050565b6000602082840312156109b757600080fd5b5051919050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615610a1d577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b500290565b600073ffffffffffffffffffffffffffffffffffffffff808816835260208188168185015286604085015263ffffffff8616606085015260a06080850152845191508160a085015260005b82811015610a895785810182015185820160c001528101610a6d565b82811115610a9b57600060c084870101525b5050601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160c001969550505050505056fea2646970667358221220b2183fcbf33cd5cb8663019340024e5a70875041f8799aeca9ffc8e7f6db0aa164736f6c63430008090033" + "code": "0x6080604052600436106100ab5760003560e01c806385b5b14d1161006457806385b5b14d1461017b5780638da5cb5b1461019b578063a996d6ce146101b9578063bfb08462146101d9578063d4ff9218146101f9578063f2fde38b1461021957600080fd5b8063110b7eb0146100b757806327810b6e146100f45780633ccfd60b146101145780635558979e1461012b578063715018a6146101505780638312f1491461016557600080fd5b366100b257005b600080fd5b3480156100c357600080fd5b506002546100d7906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561010057600080fd5b506003546100d7906001600160a01b031681565b34801561012057600080fd5b50610129610239565b005b34801561013757600080fd5b5061014262030d4081565b6040519081526020016100eb565b34801561015c57600080fd5b50610129610432565b34801561017157600080fd5b5061014260045481565b34801561018757600080fd5b5061012961019636600461061a565b610468565b3480156101a757600080fd5b506000546001600160a01b03166100d7565b3480156101c557600080fd5b506101296101d4366004610633565b610497565b3480156101e557600080fd5b506101296101f4366004610633565b6104e3565b34801561020557600080fd5b506001546100d7906001600160a01b031681565b34801561022557600080fd5b50610129610234366004610633565b61052f565b600154600254604080516268f21d60e51b815290516001600160a01b039384169390921691630d1e43a091600480820192602092909190829003018186803b15801561028457600080fd5b505afa158015610298573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102bc9190610663565b600114156102f857506003546004546001600160a01b03909116906102e990670de0b6b3a764000061067c565b4710156102f35750565b6103ad565b60045461030d90670de0b6b3a764000061067c565b4710156103ad5760405162461bcd60e51b815260206004820152605760248201527f42564d5f53657175656e6365724665655661756c743a2077697468647261776160448201527f6c20616d6f756e74206d7573742062652067726561746572207468616e206d6960648201527f6e696d756d207769746864726177616c20616d6f756e74000000000000000000608482015260a4015b60405180910390fd5b6040805160208101825260008082529151631474f2a960e31b81526010602160991b019263a3a79548926103fd9273deaddeaddeaddeaddeaddeaddeaddeaddead000092879247926004016106a9565b600060405180830381600087803b15801561041757600080fd5b505af115801561042b573d6000803e3d6000fd5b5050505050565b6000546001600160a01b0316331461045c5760405162461bcd60e51b81526004016103a49061072e565b61046660006105ca565b565b6000546001600160a01b031633146104925760405162461bcd60e51b81526004016103a49061072e565b600455565b6000546001600160a01b031633146104c15760405162461bcd60e51b81526004016103a49061072e565b600380546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b0316331461050d5760405162461bcd60e51b81526004016103a49061072e565b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b031633146105595760405162461bcd60e51b81526004016103a49061072e565b6001600160a01b0381166105be5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016103a4565b6105c7816105ca565b50565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60006020828403121561062c57600080fd5b5035919050565b60006020828403121561064557600080fd5b81356001600160a01b038116811461065c57600080fd5b9392505050565b60006020828403121561067557600080fd5b5051919050565b60008160001904831182151516156106a457634e487b7160e01b600052601160045260246000fd5b500290565b600060018060a01b03808816835260208188168185015286604085015263ffffffff8616606085015260a06080850152845191508160a085015260005b828110156107025785810182015185820160c0015281016106e6565b8281111561071457600060c084870101525b5050601f01601f19169190910160c0019695505050505050565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260408201526060019056fea26469706673582212202a2581884faf9f26be8cf5e371d77eb3190d6611f60d05e5bfed3176d8790f6b64736f6c63430008090033" }, "0x4200000000000000000000000000000000000012": { "balance": "00", "storage": {}, - "code": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c80630769a96914610030575b600080fd5b61004361003e36600461025c565b610045565b005b73ffffffffffffffffffffffffffffffffffffffff84166100c6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4d7573742070726f76696465204c3120746f6b656e2061646472657373000000604482015260640160405180910390fd5b6000734200000000000000000000000000000000000010858585856040516100ed90610175565b6100fb95949392919061036f565b604051809103906000f080158015610117573d6000803e3d6000fd5b5060405160ff8416815290915073ffffffffffffffffffffffffffffffffffffffff80831691908716907f41e27481c6f764357db26ae29b68b9f3aafc40b87444459cbf50d338c75317329060200160405180910390a35050505050565b61146d806103d183390190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126101c257600080fd5b813567ffffffffffffffff808211156101dd576101dd610182565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561022357610223610182565b8160405283815286602085880101111561023c57600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806000806080858703121561027257600080fd5b843573ffffffffffffffffffffffffffffffffffffffff8116811461029657600080fd5b9350602085013567ffffffffffffffff808211156102b357600080fd5b6102bf888389016101b1565b945060408701359150808211156102d557600080fd5b506102e2878288016101b1565b925050606085013560ff811681146102f957600080fd5b939692955090935050565b6000815180845260005b8181101561032a5760208185018101518683018201520161030e565b8181111561033c576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b600073ffffffffffffffffffffffffffffffffffffffff808816835280871660208401525060a060408301526103a860a0830186610304565b82810360608401526103ba8186610304565b91505060ff83166080830152969550505050505056fe60806040523480156200001157600080fd5b506040516200146d3803806200146d833981016040819052620000349162000247565b8251839083906200004d906003906020850190620000b7565b50805162000063906004906020840190620000b7565b5050600580546001600160a01b039687166001600160a01b0319909116179055506006805460ff909216600160a01b026001600160a81b031990921695909416949094179390931790915550620003309050565b828054620000c590620002f3565b90600052602060002090601f016020900481019282620000e9576000855562000134565b82601f106200010457805160ff191683800117855562000134565b8280016001018555821562000134579182015b828111156200013457825182559160200191906001019062000117565b506200014292915062000146565b5090565b5b8082111562000142576000815560010162000147565b80516001600160a01b03811681146200017557600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620001a257600080fd5b81516001600160401b0380821115620001bf57620001bf6200017a565b604051601f8301601f19908116603f01168101908282118183101715620001ea57620001ea6200017a565b816040528381526020925086838588010111156200020757600080fd5b600091505b838210156200022b57858201830151818301840152908201906200020c565b838211156200023d5760008385830101525b9695505050505050565b600080600080600060a086880312156200026057600080fd5b6200026b866200015d565b94506200027b602087016200015d565b60408701519094506001600160401b03808211156200029957600080fd5b620002a789838a0162000190565b94506060880151915080821115620002be57600080fd5b50620002cd8882890162000190565b925050608086015160ff81168114620002e557600080fd5b809150509295509295909350565b600181811c908216806200030857607f821691505b602082108114156200032a57634e487b7160e01b600052602260045260246000fd5b50919050565b61112d80620003406000396000f3fe608060405234801561001057600080fd5b506004361061011b5760003560e01c806370a08231116100b2578063a457c2d711610081578063ae1f6aaf11610066578063ae1f6aaf1461028a578063c01e1bd6146102cf578063dd62ed3e146102ef57600080fd5b8063a457c2d714610264578063a9059cbb1461027757600080fd5b806370a08231146101ee57806376809ce31461022457806395d89b41146102495780639dc29fac1461025157600080fd5b806323b872dd116100ee57806323b872dd14610182578063313ce5671461019557806339509351146101c657806340c10f19146101d957600080fd5b806301ffc9a71461012057806306fdde0314610148578063095ea7b31461015d57806318160ddd14610170575b600080fd5b61013361012e366004610eac565b610335565b60405190151581526020015b60405180910390f35b6101506103f5565b60405161013f9190610ef5565b61013361016b366004610f91565b610487565b6002545b60405190815260200161013f565b610133610190366004610fbb565b61049d565b60065474010000000000000000000000000000000000000000900460ff165b60405160ff909116815260200161013f565b6101336101d4366004610f91565b61056e565b6101ec6101e7366004610f91565b6105b7565b005b6101746101fc366004610ff7565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6006546101b49074010000000000000000000000000000000000000000900460ff1681565b61015061067c565b6101ec61025f366004610f91565b61068b565b610133610272366004610f91565b610744565b610133610285366004610f91565b610802565b6006546102aa9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161013f565b6005546102aa9073ffffffffffffffffffffffffffffffffffffffff1681565b6101746102fd366004611012565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b60007f01ffc9a7a5cef8baa21ed3c5c0d7e23accb804b619e9333b597f47a0d84076e27f1d1d8b63000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000084167f01ffc9a70000000000000000000000000000000000000000000000000000000014806103ed57507fffffffff00000000000000000000000000000000000000000000000000000000848116908216145b949350505050565b60606003805461040490611045565b80601f016020809104026020016040519081016040528092919081815260200182805461043090611045565b801561047d5780601f106104525761010080835404028352916020019161047d565b820191906000526020600020905b81548152906001019060200180831161046057829003601f168201915b5050505050905090565b600061049433848461080f565b50600192915050565b60006104aa84848461098f565b73ffffffffffffffffffffffffffffffffffffffff84166000908152600160209081526040808320338452909152902054828110156105565760405162461bcd60e51b815260206004820152602860248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206160448201527f6c6c6f77616e636500000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b610563853385840361080f565b506001949350505050565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490916104949185906105b29086906110c8565b61080f565b60065473ffffffffffffffffffffffffffffffffffffffff16331461061e5760405162461bcd60e51b815260206004820181905260248201527f4f6e6c79204c32204272696467652063616e206d696e7420616e64206275726e604482015260640161054d565b6106288282610bf5565b8173ffffffffffffffffffffffffffffffffffffffff167f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d41213968858260405161067091815260200190565b60405180910390a25050565b60606004805461040490611045565b60065473ffffffffffffffffffffffffffffffffffffffff1633146106f25760405162461bcd60e51b815260206004820181905260248201527f4f6e6c79204c32204272696467652063616e206d696e7420616e64206275726e604482015260640161054d565b6106fc8282610cfb565b8173ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca58260405161067091815260200190565b33600090815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff86168452909152812054828110156107eb5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f000000000000000000000000000000000000000000000000000000606482015260840161054d565b6107f8338585840361080f565b5060019392505050565b600061049433848461098f565b73ffffffffffffffffffffffffffffffffffffffff83166108975760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f7265737300000000000000000000000000000000000000000000000000000000606482015260840161054d565b73ffffffffffffffffffffffffffffffffffffffff82166109205760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f7373000000000000000000000000000000000000000000000000000000000000606482015260840161054d565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8316610a185760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f6472657373000000000000000000000000000000000000000000000000000000606482015260840161054d565b73ffffffffffffffffffffffffffffffffffffffff8216610aa15760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f6573730000000000000000000000000000000000000000000000000000000000606482015260840161054d565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610b3d5760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e63650000000000000000000000000000000000000000000000000000606482015260840161054d565b73ffffffffffffffffffffffffffffffffffffffff808516600090815260208190526040808220858503905591851681529081208054849290610b819084906110c8565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610be791815260200190565b60405180910390a350505050565b73ffffffffffffffffffffffffffffffffffffffff8216610c585760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015260640161054d565b8060026000828254610c6a91906110c8565b909155505073ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604081208054839290610ca49084906110c8565b909155505060405181815273ffffffffffffffffffffffffffffffffffffffff8316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b73ffffffffffffffffffffffffffffffffffffffff8216610d845760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f7300000000000000000000000000000000000000000000000000000000000000606482015260840161054d565b73ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604090205481811015610e205760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f6365000000000000000000000000000000000000000000000000000000000000606482015260840161054d565b73ffffffffffffffffffffffffffffffffffffffff83166000908152602081905260408120838303905560028054849290610e5c9084906110e0565b909155505060405182815260009073ffffffffffffffffffffffffffffffffffffffff8516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001610982565b600060208284031215610ebe57600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610eee57600080fd5b9392505050565b600060208083528351808285015260005b81811015610f2257858101830151858201604001528201610f06565b81811115610f34576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610f8c57600080fd5b919050565b60008060408385031215610fa457600080fd5b610fad83610f68565b946020939093013593505050565b600080600060608486031215610fd057600080fd5b610fd984610f68565b9250610fe760208501610f68565b9150604084013590509250925092565b60006020828403121561100957600080fd5b610eee82610f68565b6000806040838503121561102557600080fd5b61102e83610f68565b915061103c60208401610f68565b90509250929050565b600181811c9082168061105957607f821691505b60208210811415611093577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156110db576110db611099565b500190565b6000828210156110f2576110f2611099565b50039056fea2646970667358221220ab7ddcc069894ab0c9603724acfbe497a2711b0082f18ecb2e7e55d7bdd7907864736f6c63430008090033a2646970667358221220a8284f3e8a840cded5a59b6bef46ebaa83af9494841c13131c3e2d32c9b5710064736f6c63430008090033" + "code": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c80630769a96914610030575b600080fd5b61004361003e3660046101e4565b610045565b005b6001600160a01b03841661009f5760405162461bcd60e51b815260206004820152601d60248201527f4d7573742070726f76696465204c3120746f6b656e2061646472657373000000604482015260640160405180910390fd5b60006010602160991b01858585856040516100b990610134565b6100c79594939291906102cc565b604051809103906000f0801580156100e3573d6000803e3d6000fd5b5060405160ff841681529091506001600160a01b0380831691908716907f41e27481c6f764357db26ae29b68b9f3aafc40b87444459cbf50d338c75317329060200160405180910390a35050505050565b6111178061032183390190565b634e487b7160e01b600052604160045260246000fd5b600082601f83011261016857600080fd5b813567ffffffffffffffff8082111561018357610183610141565b604051601f8301601f19908116603f011681019082821181831017156101ab576101ab610141565b816040528381528660208588010111156101c457600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080600080608085870312156101fa57600080fd5b84356001600160a01b038116811461021157600080fd5b9350602085013567ffffffffffffffff8082111561022e57600080fd5b61023a88838901610157565b9450604087013591508082111561025057600080fd5b5061025d87828801610157565b925050606085013560ff8116811461027457600080fd5b939692955090935050565b6000815180845260005b818110156102a557602081850181015186830182015201610289565b818111156102b7576000602083870101525b50601f01601f19169290920160200192915050565b6001600160a01b0386811682528516602082015260a0604082018190526000906102f89083018661027f565b828103606084015261030a818661027f565b91505060ff83166080830152969550505050505056fe60806040523480156200001157600080fd5b506040516200111738038062001117833981016040819052620000349162000247565b8251839083906200004d906003906020850190620000b7565b50805162000063906004906020840190620000b7565b5050600580546001600160a01b039687166001600160a01b0319909116179055506006805460ff909216600160a01b026001600160a81b031990921695909416949094179390931790915550620003309050565b828054620000c590620002f3565b90600052602060002090601f016020900481019282620000e9576000855562000134565b82601f106200010457805160ff191683800117855562000134565b8280016001018555821562000134579182015b828111156200013457825182559160200191906001019062000117565b506200014292915062000146565b5090565b5b8082111562000142576000815560010162000147565b80516001600160a01b03811681146200017557600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620001a257600080fd5b81516001600160401b0380821115620001bf57620001bf6200017a565b604051601f8301601f19908116603f01168101908282118183101715620001ea57620001ea6200017a565b816040528381526020925086838588010111156200020757600080fd5b600091505b838210156200022b57858201830151818301840152908201906200020c565b838211156200023d5760008385830101525b9695505050505050565b600080600080600060a086880312156200026057600080fd5b6200026b866200015d565b94506200027b602087016200015d565b60408701519094506001600160401b03808211156200029957600080fd5b620002a789838a0162000190565b94506060880151915080821115620002be57600080fd5b50620002cd8882890162000190565b925050608086015160ff81168114620002e557600080fd5b809150509295509295909350565b600181811c908216806200030857607f821691505b602082108114156200032a57634e487b7160e01b600052602260045260246000fd5b50919050565b610dd780620003406000396000f3fe608060405234801561001057600080fd5b506004361061010b5760003560e01c806370a08231116100a2578063a457c2d711610071578063a457c2d714610225578063a9059cbb14610238578063ae1f6aaf1461024b578063c01e1bd614610276578063dd62ed3e1461028957600080fd5b806370a08231146101cd57806376809ce3146101f657806395d89b411461020a5780639dc29fac1461021257600080fd5b806323b872dd116100de57806323b872dd14610172578063313ce5671461018557806339509351146101a557806340c10f19146101b857600080fd5b806301ffc9a71461011057806306fdde0314610138578063095ea7b31461014d57806318160ddd14610160575b600080fd5b61012361011e366004610bcb565b6102c2565b60405190151581526020015b60405180910390f35b610140610320565b60405161012f9190610bfc565b61012361015b366004610c6d565b6103b2565b6002545b60405190815260200161012f565b610123610180366004610c97565b6103c8565b600654600160a01b900460ff165b60405160ff909116815260200161012f565b6101236101b3366004610c6d565b610477565b6101cb6101c6366004610c6d565b6104b3565b005b6101646101db366004610cd3565b6001600160a01b031660009081526020819052604090205490565b60065461019390600160a01b900460ff1681565b61014061055e565b6101cb610220366004610c6d565b61056d565b610123610233366004610c6d565b61060c565b610123610246366004610c6d565b6106a5565b60065461025e906001600160a01b031681565b6040516001600160a01b03909116815260200161012f565b60055461025e906001600160a01b031681565b610164610297366004610cee565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b60007f01ffc9a7a5cef8baa21ed3c5c0d7e23accb804b619e9333b597f47a0d84076e2631d1d8b6360e01b6001600160e01b031984166301ffc9a760e01b148061031857506001600160e01b0319848116908216145b949350505050565b60606003805461032f90610d21565b80601f016020809104026020016040519081016040528092919081815260200182805461035b90610d21565b80156103a85780601f1061037d576101008083540402835291602001916103a8565b820191906000526020600020905b81548152906001019060200180831161038b57829003601f168201915b5050505050905090565b60006103bf3384846106b2565b50600192915050565b60006103d58484846107d7565b6001600160a01b03841660009081526001602090815260408083203384529091529020548281101561045f5760405162461bcd60e51b815260206004820152602860248201527f45524332303a207472616e7366657220616d6f756e74206578636565647320616044820152676c6c6f77616e636560c01b60648201526084015b60405180910390fd5b61046c85338584036106b2565b506001949350505050565b3360008181526001602090815260408083206001600160a01b038716845290915281205490916103bf9185906104ae908690610d72565b6106b2565b6006546001600160a01b0316331461050d5760405162461bcd60e51b815260206004820181905260248201527f4f6e6c79204c32204272696467652063616e206d696e7420616e64206275726e6044820152606401610456565b61051782826109a6565b816001600160a01b03167f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d41213968858260405161055291815260200190565b60405180910390a25050565b60606004805461032f90610d21565b6006546001600160a01b031633146105c75760405162461bcd60e51b815260206004820181905260248201527f4f6e6c79204c32204272696467652063616e206d696e7420616e64206275726e6044820152606401610456565b6105d18282610a85565b816001600160a01b03167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca58260405161055291815260200190565b3360009081526001602090815260408083206001600160a01b03861684529091528120548281101561068e5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152608401610456565b61069b33858584036106b2565b5060019392505050565b60006103bf3384846107d7565b6001600160a01b0383166107145760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610456565b6001600160a01b0382166107755760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610456565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b6001600160a01b03831661083b5760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610456565b6001600160a01b03821661089d5760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610456565b6001600160a01b038316600090815260208190526040902054818110156109155760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610456565b6001600160a01b0380851660009081526020819052604080822085850390559185168152908120805484929061094c908490610d72565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161099891815260200190565b60405180910390a350505050565b6001600160a01b0382166109fc5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610456565b8060026000828254610a0e9190610d72565b90915550506001600160a01b03821660009081526020819052604081208054839290610a3b908490610d72565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b6001600160a01b038216610ae55760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608401610456565b6001600160a01b03821660009081526020819052604090205481811015610b595760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b6064820152608401610456565b6001600160a01b0383166000908152602081905260408120838303905560028054849290610b88908490610d8a565b90915550506040518281526000906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020016107ca565b600060208284031215610bdd57600080fd5b81356001600160e01b031981168114610bf557600080fd5b9392505050565b600060208083528351808285015260005b81811015610c2957858101830151858201604001528201610c0d565b81811115610c3b576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b0381168114610c6857600080fd5b919050565b60008060408385031215610c8057600080fd5b610c8983610c51565b946020939093013593505050565b600080600060608486031215610cac57600080fd5b610cb584610c51565b9250610cc360208501610c51565b9150604084013590509250925092565b600060208284031215610ce557600080fd5b610bf582610c51565b60008060408385031215610d0157600080fd5b610d0a83610c51565b9150610d1860208401610c51565b90509250929050565b600181811c90821680610d3557607f821691505b60208210811415610d5657634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b60008219821115610d8557610d85610d5c565b500190565b600082821015610d9c57610d9c610d5c565b50039056fea2646970667358221220ed1c890f63fc0e27aceeab528a2838fcf26ba283b930f3ff95172ea75710515064736f6c63430008090033a2646970667358221220e63bdaf15255b8d173004360440570b26855dd560516e2f4be90363f6fc1701a64736f6c63430008090033" }, "0x4200000000000000000000000000000000000013": { "balance": "00", @@ -99,7 +95,7 @@ "0x0000000000000000000000000000000000000000000000000000000000000004": "0x4249540000000000000000000000000000000000000000000000000000000006", "0x0000000000000000000000000000000000000000000000000000000000000006": "0x0000000000000000000000124200000000000000000000000000000000000010" }, - "code": "0x608060405234801561001057600080fd5b506004361061011b5760003560e01c806370a08231116100b2578063a457c2d711610081578063ae1f6aaf11610066578063ae1f6aaf1461028a578063c01e1bd6146102cf578063dd62ed3e146102ef57600080fd5b8063a457c2d714610264578063a9059cbb1461027757600080fd5b806370a08231146101ee57806376809ce31461022457806395d89b41146102495780639dc29fac1461025157600080fd5b806323b872dd116100ee57806323b872dd14610182578063313ce5671461019557806339509351146101c657806340c10f19146101d957600080fd5b806301ffc9a71461012057806306fdde0314610148578063095ea7b31461015d57806318160ddd14610170575b600080fd5b61013361012e366004610ccf565b610335565b60405190151581526020015b60405180910390f35b6101506103f5565b60405161013f9190610d18565b61013361016b366004610db4565b610487565b6002545b60405190815260200161013f565b610133610190366004610dde565b61053d565b60065474010000000000000000000000000000000000000000900460ff165b60405160ff909116815260200161013f565b6101336101d4366004610db4565b6105ee565b6101ec6101e7366004610db4565b61069f565b005b6101746101fc366004610e1a565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6006546101b49074010000000000000000000000000000000000000000900460ff1681565b61015061077e565b6101ec61025f366004610db4565b61078d565b610133610272366004610db4565b610860565b610133610285366004610db4565b610911565b6006546102aa9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161013f565b6005546102aa9073ffffffffffffffffffffffffffffffffffffffff1681565b6101746102fd366004610e35565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b60007f01ffc9a7a5cef8baa21ed3c5c0d7e23accb804b619e9333b597f47a0d84076e27f1d1d8b63000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000084167f01ffc9a70000000000000000000000000000000000000000000000000000000014806103ed57507fffffffff00000000000000000000000000000000000000000000000000000000848116908216145b949350505050565b60606003805461040490610e68565b80601f016020809104026020016040519081016040528092919081815260200182805461043090610e68565b801561047d5780601f106104525761010080835404028352916020019161047d565b820191906000526020600020905b81548152906001019060200180831161046057829003601f168201915b5050505050905090565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604260248201527f42564d5f4249543a20617070726f76652069732064697361626c65642070656e60448201527f64696e67206675727468657220636f6d6d756e6974792064697363757373696f60648201527f6e2e000000000000000000000000000000000000000000000000000000000000608482015260009060a4015b60405180910390fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604760248201527f42564d5f4249543a207472616e7366657246726f6d2069732064697361626c6560448201527f642070656e64696e67206675727468657220636f6d6d756e697479206469736360648201527f757373696f6e2e00000000000000000000000000000000000000000000000000608482015260009060a401610534565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604c60248201527f42564d5f4249543a20696e637265617365416c6c6f77616e636520697320646960448201527f7361626c65642070656e64696e67206675727468657220636f6d6d756e69747960648201527f2064697363757373696f6e2e0000000000000000000000000000000000000000608482015260009060a401610534565b60065473ffffffffffffffffffffffffffffffffffffffff163314610720576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f6e6c79204c32204272696467652063616e206d696e7420616e64206275726e6044820152606401610534565b61072a82826109c2565b8173ffffffffffffffffffffffffffffffffffffffff167f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d41213968858260405161077291815260200190565b60405180910390a25050565b60606004805461040490610e68565b60065473ffffffffffffffffffffffffffffffffffffffff16331461080e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f6e6c79204c32204272696467652063616e206d696e7420616e64206275726e6044820152606401610534565b6108188282610ae2565b8173ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca58260405161077291815260200190565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604c60248201527f42564d5f4249543a206465637265617365416c6c6f77616e636520697320646960448201527f7361626c65642070656e64696e67206675727468657220636f6d6d756e69747960648201527f2064697363757373696f6e2e0000000000000000000000000000000000000000608482015260009060a401610534565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f42564d5f4249543a207472616e736665722069732064697361626c656420706560448201527f6e64696e67206675727468657220636f6d6d756e69747920646973637573736960648201527f6f6e2e0000000000000000000000000000000000000000000000000000000000608482015260009060a401610534565b73ffffffffffffffffffffffffffffffffffffffff8216610a3f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610534565b8060026000828254610a519190610eeb565b909155505073ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604081208054839290610a8b908490610eeb565b909155505060405181815273ffffffffffffffffffffffffffffffffffffffff8316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b73ffffffffffffffffffffffffffffffffffffffff8216610b85576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f73000000000000000000000000000000000000000000000000000000000000006064820152608401610534565b73ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604090205481811015610c3b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f63650000000000000000000000000000000000000000000000000000000000006064820152608401610534565b73ffffffffffffffffffffffffffffffffffffffff83166000908152602081905260408120838303905560028054849290610c77908490610f03565b909155505060405182815260009073ffffffffffffffffffffffffffffffffffffffff8516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a3505050565b600060208284031215610ce157600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610d1157600080fd5b9392505050565b600060208083528351808285015260005b81811015610d4557858101830151858201604001528201610d29565b81811115610d57576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610daf57600080fd5b919050565b60008060408385031215610dc757600080fd5b610dd083610d8b565b946020939093013593505050565b600080600060608486031215610df357600080fd5b610dfc84610d8b565b9250610e0a60208501610d8b565b9150604084013590509250925092565b600060208284031215610e2c57600080fd5b610d1182610d8b565b60008060408385031215610e4857600080fd5b610e5183610d8b565b9150610e5f60208401610d8b565b90509250929050565b600181811c90821680610e7c57607f821691505b60208210811415610eb6577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008219821115610efe57610efe610ebc565b500190565b600082821015610f1557610f15610ebc565b50039056fea264697066735822122050aa0c31bc8b8b99d2aae33c49266a48e1ba9a4df3c34e5b7224c213c6e3194064736f6c63430008090033" + "code": "0x608060405234801561001057600080fd5b506004361061010b5760003560e01c806370a08231116100a2578063a457c2d711610071578063a457c2d714610225578063a9059cbb14610238578063ae1f6aaf1461024b578063c01e1bd614610276578063dd62ed3e1461028957600080fd5b806370a08231146101cd57806376809ce3146101f657806395d89b411461020a5780639dc29fac1461021257600080fd5b806323b872dd116100de57806323b872dd14610172578063313ce5671461018557806339509351146101a557806340c10f19146101b857600080fd5b806301ffc9a71461011057806306fdde0314610138578063095ea7b31461014d57806318160ddd14610160575b600080fd5b61012361011e3660046109c3565b6102c2565b60405190151581526020015b60405180910390f35b610140610320565b60405161012f91906109f4565b61012361015b366004610a65565b6103b2565b6002545b60405190815260200161012f565b610123610180366004610a8f565b610433565b600654600160a01b900460ff165b60405160ff909116815260200161012f565b6101236101b3366004610a65565b6104b4565b6101cb6101c6366004610a65565b61053a565b005b6101646101db366004610acb565b6001600160a01b031660009081526020819052604090205490565b60065461019390600160a01b900460ff1681565b6101406105e5565b6101cb610220366004610a65565b6105f4565b610123610233366004610a65565b610693565b610123610246366004610a65565b610719565b60065461025e906001600160a01b031681565b6040516001600160a01b03909116815260200161012f565b60055461025e906001600160a01b031681565b610164610297366004610ae6565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b60007f01ffc9a7a5cef8baa21ed3c5c0d7e23accb804b619e9333b597f47a0d84076e2631d1d8b6360e01b6001600160e01b031984166301ffc9a760e01b148061031857506001600160e01b0319848116908216145b949350505050565b60606003805461032f90610b19565b80601f016020809104026020016040519081016040528092919081815260200182805461035b90610b19565b80156103a85780601f1061037d576101008083540402835291602001916103a8565b820191906000526020600020905b81548152906001019060200180831161038b57829003601f168201915b5050505050905090565b60405162461bcd60e51b815260206004820152604260248201527f42564d5f4249543a20617070726f76652069732064697361626c65642070656e60448201527f64696e67206675727468657220636f6d6d756e6974792064697363757373696f606482015261371760f11b608482015260009060a4015b60405180910390fd5b60405162461bcd60e51b815260206004820152604760248201527f42564d5f4249543a207472616e7366657246726f6d2069732064697361626c6560448201527f642070656e64696e67206675727468657220636f6d6d756e69747920646973636064820152663ab9b9b4b7b71760c91b608482015260009060a40161042a565b60405162461bcd60e51b815260206004820152604c60248201527f42564d5f4249543a20696e637265617365416c6c6f77616e636520697320646960448201527f7361626c65642070656e64696e67206675727468657220636f6d6d756e69747960648201526b103234b9b1bab9b9b4b7b71760a11b608482015260009060a40161042a565b6006546001600160a01b031633146105945760405162461bcd60e51b815260206004820181905260248201527f4f6e6c79204c32204272696467652063616e206d696e7420616e64206275726e604482015260640161042a565b61059e8282610796565b816001600160a01b03167f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d4121396885826040516105d991815260200190565b60405180910390a25050565b60606004805461032f90610b19565b6006546001600160a01b0316331461064e5760405162461bcd60e51b815260206004820181905260248201527f4f6e6c79204c32204272696467652063616e206d696e7420616e64206275726e604482015260640161042a565b6106588282610875565b816001600160a01b03167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5826040516105d991815260200190565b60405162461bcd60e51b815260206004820152604c60248201527f42564d5f4249543a206465637265617365416c6c6f77616e636520697320646960448201527f7361626c65642070656e64696e67206675727468657220636f6d6d756e69747960648201526b103234b9b1bab9b9b4b7b71760a11b608482015260009060a40161042a565b60405162461bcd60e51b815260206004820152604360248201527f42564d5f4249543a207472616e736665722069732064697361626c656420706560448201527f6e64696e67206675727468657220636f6d6d756e69747920646973637573736960648201526237b71760e91b608482015260009060a40161042a565b6001600160a01b0382166107ec5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015260640161042a565b80600260008282546107fe9190610b6a565b90915550506001600160a01b0382166000908152602081905260408120805483929061082b908490610b6a565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b6001600160a01b0382166108d55760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b606482015260840161042a565b6001600160a01b038216600090815260208190526040902054818110156109495760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b606482015260840161042a565b6001600160a01b0383166000908152602081905260408120838303905560028054849290610978908490610b82565b90915550506040518281526000906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a3505050565b6000602082840312156109d557600080fd5b81356001600160e01b0319811681146109ed57600080fd5b9392505050565b600060208083528351808285015260005b81811015610a2157858101830151858201604001528201610a05565b81811115610a33576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b0381168114610a6057600080fd5b919050565b60008060408385031215610a7857600080fd5b610a8183610a49565b946020939093013593505050565b600080600060608486031215610aa457600080fd5b610aad84610a49565b9250610abb60208501610a49565b9150604084013590509250925092565b600060208284031215610add57600080fd5b6109ed82610a49565b60008060408385031215610af957600080fd5b610b0283610a49565b9150610b1060208401610a49565b90509250929050565b600181811c90821680610b2d57607f821691505b60208210811415610b4e57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b60008219821115610b7d57610b7d610b54565b500190565b600082821015610b9457610b94610b54565b50039056fea26469706673582212201959bd6e2d63380ecfd7deaa6b17ccc19c819a81ee3b91e93fcac6625d99493e64736f6c63430008090033" }, "0xdEAddEaDdeadDEadDEADDEAddEADDEAddead1111": { "balance": "00", @@ -109,7 +105,7 @@ "0x0000000000000000000000000000000000000000000000000000000000000004": "0x5745544800000000000000000000000000000000000000000000000000000008", "0x0000000000000000000000000000000000000000000000000000000000000006": "0x0000000000000000000000124200000000000000000000000000000000000010" }, - "code": "0x608060405234801561001057600080fd5b506004361061011b5760003560e01c806370a08231116100b2578063a457c2d711610081578063ae1f6aaf11610066578063ae1f6aaf1461028a578063c01e1bd6146102cf578063dd62ed3e146102ef57600080fd5b8063a457c2d714610264578063a9059cbb1461027757600080fd5b806370a08231146101ee57806376809ce31461022457806395d89b41146102495780639dc29fac1461025157600080fd5b806323b872dd116100ee57806323b872dd14610182578063313ce5671461019557806339509351146101c657806340c10f19146101d957600080fd5b806301ffc9a71461012057806306fdde0314610148578063095ea7b31461015d57806318160ddd14610170575b600080fd5b61013361012e366004610eac565b610335565b60405190151581526020015b60405180910390f35b6101506103f5565b60405161013f9190610ef5565b61013361016b366004610f91565b610487565b6002545b60405190815260200161013f565b610133610190366004610fbb565b61049d565b60065474010000000000000000000000000000000000000000900460ff165b60405160ff909116815260200161013f565b6101336101d4366004610f91565b61056e565b6101ec6101e7366004610f91565b6105b7565b005b6101746101fc366004610ff7565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6006546101b49074010000000000000000000000000000000000000000900460ff1681565b61015061067c565b6101ec61025f366004610f91565b61068b565b610133610272366004610f91565b610744565b610133610285366004610f91565b610802565b6006546102aa9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161013f565b6005546102aa9073ffffffffffffffffffffffffffffffffffffffff1681565b6101746102fd366004611012565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b60007f01ffc9a7a5cef8baa21ed3c5c0d7e23accb804b619e9333b597f47a0d84076e27f1d1d8b63000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000084167f01ffc9a70000000000000000000000000000000000000000000000000000000014806103ed57507fffffffff00000000000000000000000000000000000000000000000000000000848116908216145b949350505050565b60606003805461040490611045565b80601f016020809104026020016040519081016040528092919081815260200182805461043090611045565b801561047d5780601f106104525761010080835404028352916020019161047d565b820191906000526020600020905b81548152906001019060200180831161046057829003601f168201915b5050505050905090565b600061049433848461080f565b50600192915050565b60006104aa84848461098f565b73ffffffffffffffffffffffffffffffffffffffff84166000908152600160209081526040808320338452909152902054828110156105565760405162461bcd60e51b815260206004820152602860248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206160448201527f6c6c6f77616e636500000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b610563853385840361080f565b506001949350505050565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490916104949185906105b29086906110c8565b61080f565b60065473ffffffffffffffffffffffffffffffffffffffff16331461061e5760405162461bcd60e51b815260206004820181905260248201527f4f6e6c79204c32204272696467652063616e206d696e7420616e64206275726e604482015260640161054d565b6106288282610bf5565b8173ffffffffffffffffffffffffffffffffffffffff167f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d41213968858260405161067091815260200190565b60405180910390a25050565b60606004805461040490611045565b60065473ffffffffffffffffffffffffffffffffffffffff1633146106f25760405162461bcd60e51b815260206004820181905260248201527f4f6e6c79204c32204272696467652063616e206d696e7420616e64206275726e604482015260640161054d565b6106fc8282610cfb565b8173ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca58260405161067091815260200190565b33600090815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff86168452909152812054828110156107eb5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f000000000000000000000000000000000000000000000000000000606482015260840161054d565b6107f8338585840361080f565b5060019392505050565b600061049433848461098f565b73ffffffffffffffffffffffffffffffffffffffff83166108975760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f7265737300000000000000000000000000000000000000000000000000000000606482015260840161054d565b73ffffffffffffffffffffffffffffffffffffffff82166109205760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f7373000000000000000000000000000000000000000000000000000000000000606482015260840161054d565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8316610a185760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f6472657373000000000000000000000000000000000000000000000000000000606482015260840161054d565b73ffffffffffffffffffffffffffffffffffffffff8216610aa15760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f6573730000000000000000000000000000000000000000000000000000000000606482015260840161054d565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610b3d5760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e63650000000000000000000000000000000000000000000000000000606482015260840161054d565b73ffffffffffffffffffffffffffffffffffffffff808516600090815260208190526040808220858503905591851681529081208054849290610b819084906110c8565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610be791815260200190565b60405180910390a350505050565b73ffffffffffffffffffffffffffffffffffffffff8216610c585760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015260640161054d565b8060026000828254610c6a91906110c8565b909155505073ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604081208054839290610ca49084906110c8565b909155505060405181815273ffffffffffffffffffffffffffffffffffffffff8316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b73ffffffffffffffffffffffffffffffffffffffff8216610d845760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f7300000000000000000000000000000000000000000000000000000000000000606482015260840161054d565b73ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604090205481811015610e205760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f6365000000000000000000000000000000000000000000000000000000000000606482015260840161054d565b73ffffffffffffffffffffffffffffffffffffffff83166000908152602081905260408120838303905560028054849290610e5c9084906110e0565b909155505060405182815260009073ffffffffffffffffffffffffffffffffffffffff8516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001610982565b600060208284031215610ebe57600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610eee57600080fd5b9392505050565b600060208083528351808285015260005b81811015610f2257858101830151858201604001528201610f06565b81811115610f34576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610f8c57600080fd5b919050565b60008060408385031215610fa457600080fd5b610fad83610f68565b946020939093013593505050565b600080600060608486031215610fd057600080fd5b610fd984610f68565b9250610fe760208501610f68565b9150604084013590509250925092565b60006020828403121561100957600080fd5b610eee82610f68565b6000806040838503121561102557600080fd5b61102e83610f68565b915061103c60208401610f68565b90509250929050565b600181811c9082168061105957607f821691505b60208210811415611093577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156110db576110db611099565b500190565b6000828210156110f2576110f2611099565b50039056fea264697066735822122067ad8264b2307edf22081cc5f4616ebe296b49743b70a63a727a79897bad3ecb64736f6c63430008090033" + "code": "0x608060405234801561001057600080fd5b506004361061010b5760003560e01c806370a08231116100a2578063a457c2d711610071578063a457c2d714610225578063a9059cbb14610238578063ae1f6aaf1461024b578063c01e1bd614610276578063dd62ed3e1461028957600080fd5b806370a08231146101cd57806376809ce3146101f657806395d89b411461020a5780639dc29fac1461021257600080fd5b806323b872dd116100de57806323b872dd14610172578063313ce5671461018557806339509351146101a557806340c10f19146101b857600080fd5b806301ffc9a71461011057806306fdde0314610138578063095ea7b31461014d57806318160ddd14610160575b600080fd5b61012361011e366004610bcb565b6102c2565b60405190151581526020015b60405180910390f35b610140610320565b60405161012f9190610bfc565b61012361015b366004610c6d565b6103b2565b6002545b60405190815260200161012f565b610123610180366004610c97565b6103c8565b600654600160a01b900460ff165b60405160ff909116815260200161012f565b6101236101b3366004610c6d565b610477565b6101cb6101c6366004610c6d565b6104b3565b005b6101646101db366004610cd3565b6001600160a01b031660009081526020819052604090205490565b60065461019390600160a01b900460ff1681565b61014061055e565b6101cb610220366004610c6d565b61056d565b610123610233366004610c6d565b61060c565b610123610246366004610c6d565b6106a5565b60065461025e906001600160a01b031681565b6040516001600160a01b03909116815260200161012f565b60055461025e906001600160a01b031681565b610164610297366004610cee565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b60007f01ffc9a7a5cef8baa21ed3c5c0d7e23accb804b619e9333b597f47a0d84076e2631d1d8b6360e01b6001600160e01b031984166301ffc9a760e01b148061031857506001600160e01b0319848116908216145b949350505050565b60606003805461032f90610d21565b80601f016020809104026020016040519081016040528092919081815260200182805461035b90610d21565b80156103a85780601f1061037d576101008083540402835291602001916103a8565b820191906000526020600020905b81548152906001019060200180831161038b57829003601f168201915b5050505050905090565b60006103bf3384846106b2565b50600192915050565b60006103d58484846107d7565b6001600160a01b03841660009081526001602090815260408083203384529091529020548281101561045f5760405162461bcd60e51b815260206004820152602860248201527f45524332303a207472616e7366657220616d6f756e74206578636565647320616044820152676c6c6f77616e636560c01b60648201526084015b60405180910390fd5b61046c85338584036106b2565b506001949350505050565b3360008181526001602090815260408083206001600160a01b038716845290915281205490916103bf9185906104ae908690610d72565b6106b2565b6006546001600160a01b0316331461050d5760405162461bcd60e51b815260206004820181905260248201527f4f6e6c79204c32204272696467652063616e206d696e7420616e64206275726e6044820152606401610456565b61051782826109a6565b816001600160a01b03167f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d41213968858260405161055291815260200190565b60405180910390a25050565b60606004805461032f90610d21565b6006546001600160a01b031633146105c75760405162461bcd60e51b815260206004820181905260248201527f4f6e6c79204c32204272696467652063616e206d696e7420616e64206275726e6044820152606401610456565b6105d18282610a85565b816001600160a01b03167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca58260405161055291815260200190565b3360009081526001602090815260408083206001600160a01b03861684529091528120548281101561068e5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152608401610456565b61069b33858584036106b2565b5060019392505050565b60006103bf3384846107d7565b6001600160a01b0383166107145760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610456565b6001600160a01b0382166107755760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610456565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b6001600160a01b03831661083b5760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610456565b6001600160a01b03821661089d5760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610456565b6001600160a01b038316600090815260208190526040902054818110156109155760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610456565b6001600160a01b0380851660009081526020819052604080822085850390559185168152908120805484929061094c908490610d72565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161099891815260200190565b60405180910390a350505050565b6001600160a01b0382166109fc5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610456565b8060026000828254610a0e9190610d72565b90915550506001600160a01b03821660009081526020819052604081208054839290610a3b908490610d72565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b6001600160a01b038216610ae55760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608401610456565b6001600160a01b03821660009081526020819052604090205481811015610b595760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b6064820152608401610456565b6001600160a01b0383166000908152602081905260408120838303905560028054849290610b88908490610d8a565b90915550506040518281526000906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020016107ca565b600060208284031215610bdd57600080fd5b81356001600160e01b031981168114610bf557600080fd5b9392505050565b600060208083528351808285015260005b81811015610c2957858101830151858201604001528201610c0d565b81811115610c3b576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b0381168114610c6857600080fd5b919050565b60008060408385031215610c8057600080fd5b610c8983610c51565b946020939093013593505050565b600080600060608486031215610cac57600080fd5b610cb584610c51565b9250610cc360208501610c51565b9150604084013590509250925092565b600060208284031215610ce557600080fd5b610bf582610c51565b60008060408385031215610d0157600080fd5b610d0a83610c51565b9150610d1860208401610c51565b90509250929050565b600181811c90821680610d3557607f821691505b60208210811415610d5657634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b60008219821115610d8557610d85610d5c565b500190565b600082821015610d9c57610d9c610d5c565b50039056fea2646970667358221220f789dc8b2639a060e5131ee99aa91f5abc88a63a15720481d58aa30fea1b1da064736f6c63430008090033" }, "0x4200000000000000000000000000000000000006": { "balance": "00", @@ -118,7 +114,7 @@ "0x0000000000000000000000000000000000000000000000000000000000000001": "0x5745544800000000000000000000000000000000000000000000000000000008", "0x0000000000000000000000000000000000000000000000000000000000000002": "0x0000000000000000000000000000000000000000000000000000000000000012" }, - "code": "0x6080604052600436106100bc5760003560e01c8063313ce56711610074578063a9059cbb1161004e578063a9059cbb146102cb578063d0e30db0146100bc578063dd62ed3e14610311576100bc565b8063313ce5671461024b57806370a082311461027657806395d89b41146102b6576100bc565b806318160ddd116100a557806318160ddd146101aa57806323b872dd146101d15780632e1a7d4d14610221576100bc565b806306fdde03146100c6578063095ea7b314610150575b6100c4610359565b005b3480156100d257600080fd5b506100db6103a8565b6040805160208082528351818301528351919283929083019185019080838360005b838110156101155781810151838201526020016100fd565b50505050905090810190601f1680156101425780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561015c57600080fd5b506101966004803603604081101561017357600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135610454565b604080519115158252519081900360200190f35b3480156101b657600080fd5b506101bf6104c7565b60408051918252519081900360200190f35b3480156101dd57600080fd5b50610196600480360360608110156101f457600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135811691602081013590911690604001356104cb565b34801561022d57600080fd5b506100c46004803603602081101561024457600080fd5b503561066b565b34801561025757600080fd5b50610260610700565b6040805160ff9092168252519081900360200190f35b34801561028257600080fd5b506101bf6004803603602081101561029957600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610709565b3480156102c257600080fd5b506100db61071b565b3480156102d757600080fd5b50610196600480360360408110156102ee57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135610793565b34801561031d57600080fd5b506101bf6004803603604081101561033457600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160200135166107a7565b33600081815260036020908152604091829020805434908101909155825190815291517fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9281900390910190a2565b6000805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f8101849004840282018401909252818152929183018282801561044c5780601f106104215761010080835404028352916020019161044c565b820191906000526020600020905b81548152906001019060200180831161042f57829003601f168201915b505050505081565b33600081815260046020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716808552908352818420869055815186815291519394909390927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925928290030190a350600192915050565b4790565b73ffffffffffffffffffffffffffffffffffffffff83166000908152600360205260408120548211156104fd57600080fd5b73ffffffffffffffffffffffffffffffffffffffff84163314801590610573575073ffffffffffffffffffffffffffffffffffffffff841660009081526004602090815260408083203384529091529020547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff14155b156105ed5773ffffffffffffffffffffffffffffffffffffffff841660009081526004602090815260408083203384529091529020548211156105b557600080fd5b73ffffffffffffffffffffffffffffffffffffffff841660009081526004602090815260408083203384529091529020805483900390555b73ffffffffffffffffffffffffffffffffffffffff808516600081815260036020908152604080832080548890039055938716808352918490208054870190558351868152935191937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929081900390910190a35060019392505050565b3360009081526003602052604090205481111561068757600080fd5b33600081815260036020526040808220805485900390555183156108fc0291849190818181858888f193505050501580156106c6573d6000803e3d6000fd5b5060408051828152905133917f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65919081900360200190a250565b60025460ff1681565b60036020526000908152604090205481565b60018054604080516020600284861615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f8101849004840282018401909252818152929183018282801561044c5780601f106104215761010080835404028352916020019161044c565b60006107a03384846104cb565b9392505050565b60046020908152600092835260408084209091529082529020548156fea265627a7a7231582091c18790e0cca5011d2518024840ee00fecc67e11f56fd746f2cf84d5b583e0064736f6c63430005110032" + "code": "0x60806040526004361061009c5760003560e01c8063313ce56711610064578063313ce5671461021157806370a082311461023c57806395d89b411461026f578063a9059cbb14610284578063d0e30db01461009c578063dd62ed3e146102bd5761009c565b806306fdde03146100a6578063095ea7b31461013057806318160ddd1461017d57806323b872dd146101a45780632e1a7d4d146101e7575b6100a46102f8565b005b3480156100b257600080fd5b506100bb610347565b6040805160208082528351818301528351919283929083019185019080838360005b838110156100f55781810151838201526020016100dd565b50505050905090810190601f1680156101225780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561013c57600080fd5b506101696004803603604081101561015357600080fd5b506001600160a01b0381351690602001356103d5565b604080519115158252519081900360200190f35b34801561018957600080fd5b5061019261043b565b60408051918252519081900360200190f35b3480156101b057600080fd5b50610169600480360360608110156101c757600080fd5b506001600160a01b0381358116916020810135909116906040013561043f565b3480156101f357600080fd5b506100a46004803603602081101561020a57600080fd5b5035610573565b34801561021d57600080fd5b50610226610608565b6040805160ff9092168252519081900360200190f35b34801561024857600080fd5b506101926004803603602081101561025f57600080fd5b50356001600160a01b0316610611565b34801561027b57600080fd5b506100bb610623565b34801561029057600080fd5b50610169600480360360408110156102a757600080fd5b506001600160a01b03813516906020013561067d565b3480156102c957600080fd5b50610192600480360360408110156102e057600080fd5b506001600160a01b0381358116916020013516610691565b33600081815260036020908152604091829020805434908101909155825190815291517fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9281900390910190a2565b6000805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156103cd5780601f106103a2576101008083540402835291602001916103cd565b820191906000526020600020905b8154815290600101906020018083116103b057829003601f168201915b505050505081565b3360008181526004602090815260408083206001600160a01b038716808552908352818420869055815186815291519394909390927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925928290030190a350600192915050565b4790565b6001600160a01b03831660009081526003602052604081205482111561046457600080fd5b6001600160a01b03841633148015906104a257506001600160a01b038416600090815260046020908152604080832033845290915290205460001914155b15610502576001600160a01b03841660009081526004602090815260408083203384529091529020548211156104d757600080fd5b6001600160a01b03841660009081526004602090815260408083203384529091529020805483900390555b6001600160a01b03808516600081815260036020908152604080832080548890039055938716808352918490208054870190558351868152935191937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929081900390910190a35060019392505050565b3360009081526003602052604090205481111561058f57600080fd5b33600081815260036020526040808220805485900390555183156108fc0291849190818181858888f193505050501580156105ce573d6000803e3d6000fd5b5060408051828152905133917f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65919081900360200190a250565b60025460ff1681565b60036020526000908152604090205481565b60018054604080516020600284861615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156103cd5780601f106103a2576101008083540402835291602001916103cd565b600061068a33848461043f565b9392505050565b60046020908152600092835260408084209091529082529020548156fea265627a7a723158203a20a42ecfa42be2e74e4ae807d829fdcf12083ea8a3f6392d9de06662bdc10964736f6c63430005110032" }, "0x4200000000000000000000000000000000000020": { "balance": "00", @@ -130,7 +126,7 @@ "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000004200000000000000000000000000000000000007", "0x000000000000000000000000000000000000000000000000000000000000000a": "0x0000000000000000000000008baccff561fde61d6bc8b6f299ffba561d2189b9" }, - "code": "0x6080604052600436106101635760003560e01c80633cb747bf116100c0578063d8111a5711610074578063ea01cd3611610059578063ea01cd36146103b9578063f2fde38b146103e6578063fad9aba31461040657600080fd5b8063d8111a571461038d578063e5efd585146103a357600080fd5b8063715018a6116100a5578063715018a6146103385780638da5cb5b1461034d578063cfb550f11461037857600080fd5b80633cb747bf146102f65780633ccfd60b1461032357600080fd5b806319d509a11161011757806327c8f835116100fc57806327c8f835146102945780632c79db11146102c15780633b52c31e146102d657600080fd5b806319d509a1146102685780631a39d8ef1461027e57600080fd5b806310a7fd7b1161014857806310a7fd7b146101c6578063110b7eb01461020157806315c6f1661461025357600080fd5b80630b50cd3e1461016f5780630fae75d9146101a457600080fd5b3661016a57005b600080fd5b34801561017b57600080fd5b5061018f61018a3660046111bc565b61041c565b60405190151581526020015b60405180910390f35b3480156101b057600080fd5b506101c46101bf3660046111de565b6105b0565b005b3480156101d257600080fd5b506101f36101e1366004611280565b60026020526000908152604090205481565b60405190815260200161019b565b34801561020d57600080fd5b5060035461022e9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161019b565b34801561025f57600080fd5b506101f3610a63565b34801561027457600080fd5b506101f360065481565b34801561028a57600080fd5b506101f360075481565b3480156102a057600080fd5b5060045461022e9073ffffffffffffffffffffffffffffffffffffffff1681565b3480156102cd57600080fd5b506101f3610a8e565b3480156102e257600080fd5b506101c46102f1366004611280565b610b0d565b34801561030257600080fd5b5060015461022e9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561032f57600080fd5b506101c4610b79565b34801561034457600080fd5b506101c4610cae565b34801561035957600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff1661022e565b34801561038457600080fd5b506101c4610d1f565b34801561039957600080fd5b506101f360095481565b3480156103af57600080fd5b506101f360085481565b3480156103c557600080fd5b50600a5461022e9073ffffffffffffffffffffffffffffffffffffffff1681565b3480156103f257600080fd5b506101c46104013660046112bb565b610e68565b34801561041257600080fd5b506101f360055481565b60045460009073ffffffffffffffffffffffffffffffffffffffff1633146104b15760405162461bcd60e51b815260206004820152602760248201527f747373207265776172642063616c6c206d65737361676520756e61757468656e60448201527f746963617465640000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6007544710156105295760405162461bcd60e51b815260206004820152603160248201527f62616c616e6365207265636f726420616e6420636f6e74726163742062616c6160448201527f6e636520617265206e6f7420657175616c00000000000000000000000000000060648201526084016104a8565b600654610537906001611307565b83146105855760405162461bcd60e51b815260206004820152601760248201527f626c6f636b2069642075706461746520696c6c6567616c00000000000000000060448201526064016104a8565b60068390556007546105979083610f61565b6007555060009182526002602052604090912055600190565b600a5473ffffffffffffffffffffffffffffffffffffffff166105e860015473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146106885760405162461bcd60e51b815260206004820152602e60248201527f42564d5f58434841494e3a206d657373656e67657220636f6e7472616374207560448201527f6e61757468656e7469636174656400000000000000000000000000000000000060648201526084016104a8565b8073ffffffffffffffffffffffffffffffffffffffff166106be60015473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff16636e296e456040518163ffffffff1660e01b815260040160206040518083038186803b15801561070357600080fd5b505afa158015610717573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061073b919061131f565b73ffffffffffffffffffffffffffffffffffffffff16146107c45760405162461bcd60e51b815260206004820152603060248201527f42564d5f58434841494e3a2077726f6e672073656e646572206f662063726f7360448201527f732d646f6d61696e206d6573736167650000000000000000000000000000000060648201526084016104a8565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16630d1e43a06040518163ffffffff1660e01b815260040160206040518083038186803b15801561082c57600080fd5b505afa158015610840573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610864919061133c565b60011461087c5761087786868585610f74565b610a5b565b600080600060085460001415610899575050506008849055610a5b565b60085487116109105760405162461bcd60e51b815260206004820152603260248201527f61726773205f626174636854696d65206d757374206774686572207468616e2060448201527f6c617374206c617374426174636854696d65000000000000000000000000000060648201526084016104a8565b60055461091b610a63565b600854610928908a611355565b610932919061136c565b61093c9190611307565b6000600555915061094d828661112f565b925060005b858110156109ea57600087878381811061096e5761096e6113a9565b905060200201602081019061098391906112bb565b905061098f8386610f61565b60405190935073ffffffffffffffffffffffffffffffffffffffff82169086156108fc029087906000818181858888f193505050501580156109d5573d6000803e3d6000fd5b505080806109e2906113d8565b915050610952565b5060006109f7838361113b565b90508015610a1057600554610a0c9082610f61565b6005555b7ff533ef50019763ee9d95ad46e28350b533c11edd472ae7be93e8fae83c1b6d9960085489868a8a604051610a49959493929190611467565b60405180910390a15050506008859055505b505050505050565b6000610a896301e13380600954670de0b6b3a7640000610a83919061136c565b9061112f565b905090565b6000600754471015610b085760405162461bcd60e51b815260206004820152603160248201527f62616c616e6365207265636f726420616e6420636f6e74726163742062616c6160448201527f6e636520617265206e6f7420657175616c00000000000000000000000000000060648201526084016104a8565b504790565b60005473ffffffffffffffffffffffffffffffffffffffff163314610b745760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016104a8565b600955565b60005473ffffffffffffffffffffffffffffffffffffffff163314610be05760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016104a8565b600754471015610c585760405162461bcd60e51b815260206004820152603160248201527f62616c616e6365207265636f726420616e6420636f6e74726163742062616c6160448201527f6e636520617265206e6f7420657175616c00000000000000000000000000000060648201526084016104a8565b60006007554715610cac576000805460405173ffffffffffffffffffffffffffffffffffffffff909116914780156108fc02929091818181858888f19350505050158015610caa573d6000803e3d6000fd5b505b565b60005473ffffffffffffffffffffffffffffffffffffffff163314610d155760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016104a8565b610cac6000611147565b60005473ffffffffffffffffffffffffffffffffffffffff163314610d865760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016104a8565b600754471015610dfe5760405162461bcd60e51b815260206004820152603160248201527f62616c616e6365207265636f726420616e6420636f6e74726163742062616c6160448201527f6e636520617265206e6f7420657175616c00000000000000000000000000000060648201526084016104a8565b600554600754610e0e908261113b565b60075560006005558015610caa576000805460055460405173ffffffffffffffffffffffffffffffffffffffff9092169281156108fc029290818181858888f19350505050158015610e64573d6000803e3d6000fd5b5050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610ecf5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016104a8565b73ffffffffffffffffffffffffffffffffffffffff8116610f585760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016104a8565b610caa81611147565b6000610f6d8284611307565b9392505050565b6000806000805b8663ffffffff16811015610fed57610fb860026000610f9a848c611307565b81526020019081526020016000205484610f6190919063ffffffff16565b925060026000610fc8838b611307565b8152602001908152602001600020600090558080610fe5906113d8565b915050610f7b565b5081156110e7576005546110019083611307565b60006005559150611012828561112f565b925060005b848110156110bf576000868683818110611033576110336113a9565b905060200201602081019061104891906112bb565b90506110548386610f61565b600754909350611064908661113b565b60075560405173ffffffffffffffffffffffffffffffffffffffff82169086156108fc029087906000818181858888f193505050501580156110aa573d6000803e3d6000fd5b505080806110b7906113d8565b915050611017565b5060006110cc838361113b565b905080156110e5576005546110e19082610f61565b6005555b505b7f2dae6f3d42a2c50d6baa3ea3f2423a9e1ff0ba26875f8ba6ba25c40df98009fe878785888860405161111e959493929190611498565b60405180910390a150505050505050565b6000610f6d82846114c4565b6000610f6d8284611355565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600080604083850312156111cf57600080fd5b50508035926020909101359150565b6000806000806000608086880312156111f657600080fd5b85359450602086013563ffffffff8116811461121157600080fd5b935060408601359250606086013567ffffffffffffffff8082111561123557600080fd5b818801915088601f83011261124957600080fd5b81358181111561125857600080fd5b8960208260051b850101111561126d57600080fd5b9699959850939650602001949392505050565b60006020828403121561129257600080fd5b5035919050565b73ffffffffffffffffffffffffffffffffffffffff81168114610caa57600080fd5b6000602082840312156112cd57600080fd5b8135610f6d81611299565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561131a5761131a6112d8565b500190565b60006020828403121561133157600080fd5b8151610f6d81611299565b60006020828403121561134e57600080fd5b5051919050565b600082821015611367576113676112d8565b500390565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156113a4576113a46112d8565b500290565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561140a5761140a6112d8565b5060010190565b8183526000602080850194508260005b8581101561145c57813561143481611299565b73ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101611421565b509495945050505050565b85815284602082015283604082015260806060820152600061148d608083018486611411565b979650505050505050565b85815263ffffffff8516602082015283604082015260806060820152600061148d608083018486611411565b6000826114fa577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b50049056fea2646970667358221220966ea09f223dafcdbfd297d1a3f61aa7ad3d4c160e609139751d66b36b653a0864736f6c63430008090033" + "code": "0x6080604052600436106101235760003560e01c80633cb747bf116100a0578063d8111a5711610064578063d8111a571461030c578063e5efd58514610322578063ea01cd3614610338578063f2fde38b14610358578063fad9aba31461037857600080fd5b80633cb747bf1461028f5780633ccfd60b146102af578063715018a6146102c45780638da5cb5b146102d9578063cfb550f1146102f757600080fd5b806319d509a1116100e757806319d509a11461020e5780631a39d8ef1461022457806327c8f8351461023a5780632c79db111461025a5780633b52c31e1461026f57600080fd5b80630b50cd3e1461012f5780630fae75d91461016457806310a7fd7b14610186578063110b7eb0146101c157806315c6f166146101f957600080fd5b3661012a57005b600080fd5b34801561013b57600080fd5b5061014f61014a366004610d5c565b61038e565b60405190151581526020015b60405180910390f35b34801561017057600080fd5b5061018461017f366004610d7e565b6104a9565b005b34801561019257600080fd5b506101b36101a1366004610e20565b60026020526000908152604090205481565b60405190815260200161015b565b3480156101cd57600080fd5b506003546101e1906001600160a01b031681565b6040516001600160a01b03909116815260200161015b565b34801561020557600080fd5b506101b36108a6565b34801561021a57600080fd5b506101b360065481565b34801561023057600080fd5b506101b360075481565b34801561024657600080fd5b506004546101e1906001600160a01b031681565b34801561026657600080fd5b506101b36108d1565b34801561027b57600080fd5b5061018461028a366004610e20565b6108fa565b34801561029b57600080fd5b506001546101e1906001600160a01b031681565b3480156102bb57600080fd5b50610184610929565b3480156102d057600080fd5b506101846109be565b3480156102e557600080fd5b506000546001600160a01b03166101e1565b34801561030357600080fd5b506101846109f2565b34801561031857600080fd5b506101b360095481565b34801561032e57600080fd5b506101b360085481565b34801561034457600080fd5b50600a546101e1906001600160a01b031681565b34801561036457600080fd5b50610184610373366004610e4e565b610a9b565b34801561038457600080fd5b506101b360055481565b6004546000906001600160a01b031633146104005760405162461bcd60e51b815260206004820152602760248201527f747373207265776172642063616c6c206d65737361676520756e61757468656e6044820152661d1a58d85d195960ca1b60648201526084015b60405180910390fd5b6007544710156104225760405162461bcd60e51b81526004016103f790610e6b565b600654610430906001610ed2565b831461047e5760405162461bcd60e51b815260206004820152601760248201527f626c6f636b2069642075706461746520696c6c6567616c00000000000000000060448201526064016103f7565b60068390556007546104909083610b33565b6007555060009182526002602052604090912055600190565b600a546001600160a01b03166104c76001546001600160a01b031690565b6001600160a01b0316336001600160a01b03161461053e5760405162461bcd60e51b815260206004820152602e60248201527f42564d5f58434841494e3a206d657373656e67657220636f6e7472616374207560448201526d1b985d5d1a195b9d1a58d85d195960921b60648201526084016103f7565b806001600160a01b031661055a6001546001600160a01b031690565b6001600160a01b0316636e296e456040518163ffffffff1660e01b815260040160206040518083038186803b15801561059257600080fd5b505afa1580156105a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ca9190610eea565b6001600160a01b0316146106395760405162461bcd60e51b815260206004820152603060248201527f42564d5f58434841494e3a2077726f6e672073656e646572206f662063726f7360448201526f732d646f6d61696e206d65737361676560801b60648201526084016103f7565b600360009054906101000a90046001600160a01b03166001600160a01b0316630d1e43a06040518163ffffffff1660e01b815260040160206040518083038186803b15801561068757600080fd5b505afa15801561069b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106bf9190610f07565b6001146106d7576106d286868585610b46565b61089e565b6000806000600854600014156106f457505050600884905561089e565b60085487116107605760405162461bcd60e51b815260206004820152603260248201527f61726773205f626174636854696d65206d757374206774686572207468616e206044820152716c617374206c617374426174636854696d6560701b60648201526084016103f7565b60055461076b6108a6565b600854610778908a610f20565b6107829190610f37565b61078c9190610ed2565b6000600555915061079d8286610cf4565b925060005b8581101561082d5760008787838181106107be576107be610f56565b90506020020160208101906107d39190610e4e565b90506107df8386610b33565b6040519093506001600160a01b0382169086156108fc029087906000818181858888f19350505050158015610818573d6000803e3d6000fd5b5050808061082590610f6c565b9150506107a2565b50600061083a8383610d00565b905080156108535760055461084f9082610b33565b6005555b7ff533ef50019763ee9d95ad46e28350b533c11edd472ae7be93e8fae83c1b6d9960085489868a8a60405161088c959493929190610fd0565b60405180910390a15050506008859055505b505050505050565b60006108cc6301e13380600954670de0b6b3a76400006108c69190610f37565b90610cf4565b905090565b60006007544710156108f55760405162461bcd60e51b81526004016103f790610e6b565b504790565b6000546001600160a01b031633146109245760405162461bcd60e51b81526004016103f790611001565b600955565b6000546001600160a01b031633146109535760405162461bcd60e51b81526004016103f790611001565b6007544710156109755760405162461bcd60e51b81526004016103f790610e6b565b600060075547156109bc57600080546040516001600160a01b03909116914780156108fc02929091818181858888f193505050501580156109ba573d6000803e3d6000fd5b505b565b6000546001600160a01b031633146109e85760405162461bcd60e51b81526004016103f790611001565b6109bc6000610d0c565b6000546001600160a01b03163314610a1c5760405162461bcd60e51b81526004016103f790611001565b600754471015610a3e5760405162461bcd60e51b81526004016103f790610e6b565b600554600754610a4e9082610d00565b600755600060055580156109ba57600080546005546040516001600160a01b039092169281156108fc029290818181858888f19350505050158015610a97573d6000803e3d6000fd5b5050565b6000546001600160a01b03163314610ac55760405162461bcd60e51b81526004016103f790611001565b6001600160a01b038116610b2a5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016103f7565b6109ba81610d0c565b6000610b3f8284610ed2565b9392505050565b6000806000805b8663ffffffff16811015610bbf57610b8a60026000610b6c848c610ed2565b81526020019081526020016000205484610b3390919063ffffffff16565b925060026000610b9a838b610ed2565b8152602001908152602001600020600090558080610bb790610f6c565b915050610b4d565b508115610cac57600554610bd39083610ed2565b60006005559150610be48285610cf4565b925060005b84811015610c84576000868683818110610c0557610c05610f56565b9050602002016020810190610c1a9190610e4e565b9050610c268386610b33565b600754909350610c369086610d00565b6007556040516001600160a01b0382169086156108fc029087906000818181858888f19350505050158015610c6f573d6000803e3d6000fd5b50508080610c7c90610f6c565b915050610be9565b506000610c918383610d00565b90508015610caa57600554610ca69082610b33565b6005555b505b7f2dae6f3d42a2c50d6baa3ea3f2423a9e1ff0ba26875f8ba6ba25c40df98009fe8787858888604051610ce3959493929190611036565b60405180910390a150505050505050565b6000610b3f8284611062565b6000610b3f8284610f20565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60008060408385031215610d6f57600080fd5b50508035926020909101359150565b600080600080600060808688031215610d9657600080fd5b85359450602086013563ffffffff81168114610db157600080fd5b935060408601359250606086013567ffffffffffffffff80821115610dd557600080fd5b818801915088601f830112610de957600080fd5b813581811115610df857600080fd5b8960208260051b8501011115610e0d57600080fd5b9699959850939650602001949392505050565b600060208284031215610e3257600080fd5b5035919050565b6001600160a01b03811681146109ba57600080fd5b600060208284031215610e6057600080fd5b8135610b3f81610e39565b60208082526031908201527f62616c616e6365207265636f726420616e6420636f6e74726163742062616c616040820152701b98d948185c99481b9bdd08195c5d585b607a1b606082015260800190565b634e487b7160e01b600052601160045260246000fd5b60008219821115610ee557610ee5610ebc565b500190565b600060208284031215610efc57600080fd5b8151610b3f81610e39565b600060208284031215610f1957600080fd5b5051919050565b600082821015610f3257610f32610ebc565b500390565b6000816000190483118215151615610f5157610f51610ebc565b500290565b634e487b7160e01b600052603260045260246000fd5b6000600019821415610f8057610f80610ebc565b5060010190565b8183526000602080850194508260005b85811015610fc5578135610faa81610e39565b6001600160a01b031687529582019590820190600101610f97565b509495945050505050565b858152846020820152836040820152608060608201526000610ff6608083018486610f87565b979650505050505050565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b85815263ffffffff85166020820152836040820152608060608201526000610ff6608083018486610f87565b60008261107f57634e487b7160e01b600052601260045260246000fd5b50049056fea2646970667358221220796ffabdfbad4bc4abcc71948bad22b7a53f5250cc041d698f8f6ba035dd424f64736f6c63430008090033" }, "0x63EB358137cd06290544e71210c140B345C6FF10": { "balance": "100000000000000000000000" diff --git a/packages/contracts/hardhat.config.ts b/packages/contracts/hardhat.config.ts index f1edced5c..fdba814ce 100644 --- a/packages/contracts/hardhat.config.ts +++ b/packages/contracts/hardhat.config.ts @@ -14,6 +14,7 @@ import '@typechain/hardhat' import 'hardhat-deploy' import 'hardhat-gas-reporter' import 'hardhat-output-validator' +import 'hardhat-abi-exporter' // Hardhat tasks import './tasks' @@ -71,6 +72,8 @@ subtask(TASK_COMPILE_SOLIDITY_LOG_NOTHING_TO_COMPILE).setAction( } ) +// @ts-ignore +// @ts-ignore const config: HardhatUserConfig = { networks: { hardhat: { @@ -154,13 +157,13 @@ const config: HardhatUserConfig = { { version: '0.8.9', settings: { - optimizer: { enabled: true, runs: 10_000 }, + optimizer: { enabled: true, runs: 200 }, }, }, { version: '0.5.17', // Required for WETH9 settings: { - optimizer: { enabled: true, runs: 10_000 }, + optimizer: { enabled: true, runs: 200 }, }, }, ], @@ -184,6 +187,11 @@ const config: HardhatUserConfig = { deployments: './deployments', deployConfig: './deploy-config', }, + abiExporter: { + path: './abi', + runOnCompile: true, + clear: true, + }, namedAccounts: { deployer: { default: 0, @@ -230,6 +238,10 @@ const config: HardhatUserConfig = { exclude: ['contracts/test-helpers', 'contracts/test-libraries'], }, deployConfigSpec: { + allowUnlimitedContractSize: { + type: 'boolean', + default: true, + }, isForkedNetwork: { type: 'boolean', default: false, diff --git a/packages/contracts/package.json b/packages/contracts/package.json index ff54a015b..9cc9cbd6f 100644 --- a/packages/contracts/package.json +++ b/packages/contracts/package.json @@ -95,6 +95,7 @@ "hardhat-deploy": "^0.11.10", "hardhat-gas-reporter": "^1.0.4", "hardhat-output-validator": "^0.1.18", + "hardhat-abi-exporter": "^2.10.0", "istanbul": "^0.4.5", "lint-staged": "11.0.0", "lodash": "^4.17.21", diff --git a/packages/contracts/src/address-names.ts b/packages/contracts/src/address-names.ts index cd7ca5ece..e1e9f901c 100644 --- a/packages/contracts/src/address-names.ts +++ b/packages/contracts/src/address-names.ts @@ -21,7 +21,30 @@ export const names = { BVM_EigenDataLayrChain: 'BVM_EigenDataLayrChain', Proxy__BVM_EigenDataLayrChain: 'Proxy__BVM_EigenDataLayrChain', }, - accounts: { BVM_Sequencer: 'BVM_Sequencer', BVM_Proposer: 'BVM_Proposer' }, + fraud_proof: { + AssertionMap: 'AssertionMap', + VerifierEntry: 'VerifierEntry', + Rollup: 'Rollup', + Proxy__AssertionMap: 'Proxy__AssertionMap', + Proxy__Verifier: 'Proxy__Verifier', + Proxy__Rollup: 'Proxy__Rollup', + SubVerifiers: { + BlockInitiationVerifier: 'BlockInitiationVerifier', + BlockFinalizationVerifier: 'BlockFinalizationVerifier', + InterTxVerifier: 'InterTxVerifier', + StackOpVerifier: 'StackOpVerifier', + EnvironmentalOpVerifier: 'EnvironmentalOpVerifier', + MemoryOpVerifier: 'MemoryOpVerifier', + StorageOpVerifier: 'StorageOpVerifier', + CallOpVerifier: 'CallOpVerifier', + InvalidOpVerifier: 'InvalidOpVerifier', + }, + }, + accounts: { + BVM_Sequencer: 'BVM_Sequencer', + BVM_Proposer: 'BVM_Proposer', + BVM_Rolluper: 'BVM_Rolluper', + }, configs: { L1_BIT_ADDRESS: 'L1_BitAddress', Local_Bit_Token: 'TestBitToken', diff --git a/packages/contracts/src/deploy-config.ts b/packages/contracts/src/deploy-config.ts index fd25c0fce..fb7d62259 100644 --- a/packages/contracts/src/deploy-config.ts +++ b/packages/contracts/src/deploy-config.ts @@ -79,6 +79,11 @@ export interface DeployConfig { */ bvmProposerAddress: string + /** + * Address of the Rolluper (publishes to Rollup). + */ + bvmRolluperAddress: string + /** * Address of the account that will sign blocks. */ @@ -222,6 +227,9 @@ const configSpec: { bvmProposerAddress: { type: 'address', }, + bvmRolluperAddress: { + type: 'address', + }, bvmBlockSignerAddress: { type: 'address', }, diff --git a/packages/contracts/tasks/fraud-proof-tasks.ts b/packages/contracts/tasks/fraud-proof-tasks.ts new file mode 100644 index 000000000..df878370c --- /dev/null +++ b/packages/contracts/tasks/fraud-proof-tasks.ts @@ -0,0 +1,398 @@ +import { task } from 'hardhat/config' +import { ethers } from 'ethers' +import { hexStringEquals } from '@mantleio/core-utils' + +// @ts-ignore +import { getContractFactory } from '../src' +// @ts-ignore +import { names } from '../src/address-names' + +// eslint-disable-next-line @typescript-eslint/no-var-requires +const fs = require('fs') + +task('setAddress') + .addParam('addressmanager', 'Lib_AddressManager contract address') + .addParam('name', 'contract name') + .addParam('address', 'contract address') + .setAction(async (taskArgs) => { + const provider = new ethers.providers.JsonRpcProvider( + 'http://localhost:9545' + ) + const addressManagerKey = process.env.BVM_ADDRESS_MANAGER_KEY + const managerWallet = new ethers.Wallet(addressManagerKey, provider) + const lib_AddressManager = await getContractFactory( + 'Lib_AddressManager' + ).attach(taskArgs.addressmanager) + + console.log( + 'Lib_AddressManager owner:', + await lib_AddressManager.connect(managerWallet).owner() + ) + console.log( + 'The name has address before set', + await lib_AddressManager.connect(managerWallet).getAddress(taskArgs.name) + ) + await lib_AddressManager + .connect(managerWallet) + .setAddress(taskArgs.name, taskArgs.address) + console.log( + 'The name has address after set', + await lib_AddressManager.connect(managerWallet).getAddress(taskArgs.name) + ) + }) + +task('whiteListInit') + .addParam('rollup', 'Rollup contract address') + .setAction(async (taskArgs) => { + const provider = new ethers.providers.JsonRpcProvider( + 'http://localhost:9545' + ) + const deployerKey = process.env.CONTRACTS_DEPLOYER_KEY + const proposerAddr = process.env.BVM_ROLLUPER_ADDRESS + const entryOwner = new ethers.Wallet(deployerKey, provider) + + console.log( + 'balance: ', + entryOwner.address, + (await entryOwner.getBalance()).toString() + ) + const SequencerENV = process.env.BVM_ROLLUPER_ADDRESS + const Validator1ENV = process.env.BVM_VERIFIER1_ADDRESS + // const Validator2ENV = process.env.BVM_VERIFIER2_ADDRESS + const whiteListToAdd = [SequencerENV, Validator1ENV] + console.log('whiteList:', whiteListToAdd) + const rollup = await getContractFactory('Rollup').attach(taskArgs.rollup) + await rollup.connect(entryOwner).addToWhitelist(whiteListToAdd) + console.log('transferOwnerShip') + await rollup.connect(entryOwner).transferOwnership(proposerAddr) + }) + +task('rollupStake') + .addParam('rollup', 'Rollup contract address') + .addParam('amount', 'amount to stake', '0.1') + .setAction(async (taskArgs) => { + const provider = new ethers.providers.JsonRpcProvider( + 'http://localhost:9545' + ) + const verifier1Key = process.env.BVM_VERIFIER1_KEY + const verifier2Key = process.env.BVM_VERIFIER2_KEY + const proposerKey = process.env.BVM_PROPOSER_KEY + + const proposerWallet = new ethers.Wallet(proposerKey, provider) + const verifier1Wallet = new ethers.Wallet(verifier1Key, provider) + const verifier2Wallet = new ethers.Wallet(verifier2Key, provider) + + const wallets = [proposerWallet, verifier1Wallet, verifier2Wallet] + const rollup = await getContractFactory('Rollup').attach(taskArgs.rollup) + + for (const w of wallets) { + console.log('balance: ', w.address, (await w.getBalance()).toString()) + await rollup + .connect(w) + .stake({ value: ethers.utils.parseEther(taskArgs.amount) }) + } + }) + +task(`deployVerifier`) + .addParam('verifier', 'verifier entry address') + .setAction(async (taskArgs) => { + const provider = new ethers.providers.JsonRpcProvider( + 'http://localhost:9545' + ) + const deployerKey = process.env.CONTRACTS_DEPLOYER_KEY + const entryOwner = new ethers.Wallet(deployerKey, provider) + const BlockInitiationVerifier = getContractFactory( + names.managed.fraud_proof.SubVerifiers.BlockInitiationVerifier + ) + const blockInitiationVerifier = await BlockInitiationVerifier.connect( + entryOwner + ).deploy() + await blockInitiationVerifier.deployed() + console.log('blockInitiationVerifier : ', blockInitiationVerifier.address) + + const BlockFinalizationVerifier = getContractFactory( + names.managed.fraud_proof.SubVerifiers.BlockFinalizationVerifier + ) + const blockFinalizationVerifier = await BlockFinalizationVerifier.connect( + entryOwner + ).deploy() + await blockFinalizationVerifier.deployed() + console.log( + 'blockFinalizationVerifier : ', + blockFinalizationVerifier.address + ) + + const InterTxVerifier = getContractFactory( + names.managed.fraud_proof.SubVerifiers.BlockInitiationVerifier + ) + const interTxVerifier = await InterTxVerifier.connect(entryOwner).deploy() + await interTxVerifier.deployed() + console.log('interTxVerifier : ', interTxVerifier.address) + + const StackOpVerifier = getContractFactory( + names.managed.fraud_proof.SubVerifiers.StackOpVerifier + ) + const stackOpVerifier = await StackOpVerifier.connect(entryOwner).deploy() + await stackOpVerifier.deployed() + console.log('stackOpVerifier : ', stackOpVerifier.address) + + const EnvironmentalOpVerifier = getContractFactory( + names.managed.fraud_proof.SubVerifiers.EnvironmentalOpVerifier + ) + const environmentalOpVerifier = await EnvironmentalOpVerifier.connect( + entryOwner + ).deploy() + await environmentalOpVerifier.deployed() + console.log('environmentalOpVerifier : ', environmentalOpVerifier.address) + + const MemoryOpVerifier = getContractFactory( + names.managed.fraud_proof.SubVerifiers.MemoryOpVerifier + ) + const memoryOpVerifier = await MemoryOpVerifier.connect( + entryOwner + ).deploy() + await memoryOpVerifier.deployed() + console.log('memoryOpVerifier : ', memoryOpVerifier.address) + + const StorageOpVerifier = getContractFactory( + names.managed.fraud_proof.SubVerifiers.StorageOpVerifier + ) + const storageOpVerifier = await StorageOpVerifier.connect( + entryOwner + ).deploy() + await storageOpVerifier.deployed() + console.log('storageOpVerifier : ', storageOpVerifier.address) + + const CallOpVerifier = getContractFactory( + names.managed.fraud_proof.SubVerifiers.CallOpVerifier + ) + const callOpVerifier = await CallOpVerifier.connect(entryOwner).deploy() + await callOpVerifier.deployed() + console.log('callOpVerifier : ', callOpVerifier.address) + + const InvalidOpVerifier = getContractFactory( + names.managed.fraud_proof.SubVerifiers.InvalidOpVerifier + ) + const invalidOpVerifier = await InvalidOpVerifier.connect( + entryOwner + ).deploy() + await invalidOpVerifier.deployed() + console.log('invalidOpVerifier : ', invalidOpVerifier.address) + + const Proxy__Verifier = getContractFactory( + names.managed.fraud_proof.VerifierEntry + ).attach(taskArgs.verifier) + await Proxy__Verifier.connect(entryOwner).setVerifier( + 0, + await stackOpVerifier.address + ) + await Proxy__Verifier.connect(entryOwner).setVerifier( + 1, + await environmentalOpVerifier.address + ) + await Proxy__Verifier.connect(entryOwner).setVerifier( + 2, + await memoryOpVerifier.address + ) + await Proxy__Verifier.connect(entryOwner).setVerifier( + 3, + await storageOpVerifier.address + ) + await Proxy__Verifier.connect(entryOwner).setVerifier( + 4, + await callOpVerifier.address + ) + await Proxy__Verifier.connect(entryOwner).setVerifier( + 5, + await invalidOpVerifier.address + ) + await Proxy__Verifier.connect(entryOwner).setVerifier( + 6, + await interTxVerifier.address + ) + await Proxy__Verifier.connect(entryOwner).setVerifier( + 7, + await blockInitiationVerifier.address + ) + await Proxy__Verifier.connect(entryOwner).setVerifier( + 8, + await blockFinalizationVerifier.address + ) + + if ( + !hexStringEquals( + await Proxy__Verifier.connect(entryOwner).blockInitiationVerifier(), + blockInitiationVerifier.address + ) + ) { + console.log('blockInitiationVerifier address not equal') + } + + if ( + !hexStringEquals( + await Proxy__Verifier.connect(entryOwner).blockFinalizationVerifier(), + blockFinalizationVerifier.address + ) + ) { + console.log('blockFinalizationVerifier address not equal') + } + + if ( + !hexStringEquals( + await Proxy__Verifier.connect(entryOwner).interTxVerifier(), + interTxVerifier.address + ) + ) { + console.log('interTxVerifier address not equal') + } + + if ( + !hexStringEquals( + await Proxy__Verifier.connect(entryOwner).stackOpVerifier(), + stackOpVerifier.address + ) + ) { + console.log('stackOpVerifier address not equal') + } + + if ( + !hexStringEquals( + await Proxy__Verifier.connect(entryOwner).environmentalOpVerifier(), + environmentalOpVerifier.address + ) + ) { + console.log('environmentalOpVerifier address not equal') + } + + if ( + !hexStringEquals( + await Proxy__Verifier.connect(entryOwner).memoryOpVerifier(), + memoryOpVerifier.address + ) + ) { + console.log('memoryOpVerifier address not equal') + } + + if ( + !hexStringEquals( + await Proxy__Verifier.connect(entryOwner).storageOpVerifier(), + storageOpVerifier.address + ) + ) { + console.log('storageOpVerifier address not equal') + } + + if ( + !hexStringEquals( + await Proxy__Verifier.connect(entryOwner).callOpVerifier(), + callOpVerifier.address + ) + ) { + console.log('callOpVerifier address not equal') + } + + if ( + !hexStringEquals( + await Proxy__Verifier.connect(entryOwner).invalidOpVerifier(), + invalidOpVerifier.address + ) + ) { + console.log('invalidOpVerifier address not equal') + } + + const VerifierTestDriver = await getContractFactory('VerifierTestDriver') + const verifierTestDriver = await VerifierTestDriver.connect( + entryOwner + ).deploy( + blockInitiationVerifier.address, + blockFinalizationVerifier.address, + interTxVerifier.address, + stackOpVerifier.address, + environmentalOpVerifier.address, + memoryOpVerifier.address, + storageOpVerifier.address, + callOpVerifier.address, + invalidOpVerifier.address + ) + await verifierTestDriver.deployed() + + console.log('verifierTestDriver deployed to:', verifierTestDriver.address) + }) + +task(`genOsp`) + .addParam('hash', 'the transaction hash to prove') + .addParam('step', 'the step to prove') + .setAction(async (taskArgs) => { + const provider = new ethers.providers.JsonRpcProvider( + 'http://localhost:8545' + ) + const res = await provider.send('debug_generateProofForTest', [ + taskArgs.hash, + 0, + 0, + parseInt(taskArgs.step, 10), + ]) + fs.writeFileSync( + './test/data/json/fraud-proof/osp.json', + JSON.stringify(res) + ) + console.log('wrote proof to ./test/data/json/fraud-proof/osp.json') + }) + +task(`verifyOsp`) + // .addParam('addr', 'VerifierTestDriver contract address') + .setAction(async () => { + const provider = new ethers.providers.JsonRpcProvider( + 'http://localhost:9545' + ) + const ownerWallet = new ethers.Wallet( + '0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80', + provider + ) + const verifierTestDriver = await getContractFactory( + 'VerifierTestDriver' + ).attach('0xc6e7DF5E7b4f2A278906862b61205850344D4e7d') + const { ctx, proof } = JSON.parse( + fs.readFileSync('./test/data/json/fraud-proof/osp.json') + ) + console.log(`processing tx ${ctx.txnHash}`) + + const transaction = [ + ctx.txNonce, + ctx.gasPrice, + ctx.gas, + ctx.recipient, + ctx.value, + ctx.input, + ctx.txV, + ctx.txR, + ctx.txS, + ] + + const res = await verifierTestDriver + .connect(ownerWallet) + .verifyProof( + ctx.coinbase, + ctx.timestamp, + ctx.blockNumber, + ctx.origin, + ctx.txnHash, + transaction, + proof.verifier, + proof.currHash, + proof.proof + ) + + if (!hexStringEquals(proof.nextHash, res)) { + console.log( + 'next hash not equal with proof: ', + proof.nextHash, + ' res: ', + res + ) + } else { + console.log('verify success') + } + }) + +module.exports = {} diff --git a/packages/contracts/tasks/index.ts b/packages/contracts/tasks/index.ts index 706fbc116..c7d60e749 100644 --- a/packages/contracts/tasks/index.ts +++ b/packages/contracts/tasks/index.ts @@ -7,3 +7,4 @@ export * from './withdraw-fees' export * from './fetch-batches' export * from './tss-tasks' export * from './upgrade-task' +export * from './fraud-proof-tasks' diff --git a/packages/contracts/tasks/upgrade-task.ts b/packages/contracts/tasks/upgrade-task.ts index 51ddf9a6f..2b9887f74 100644 --- a/packages/contracts/tasks/upgrade-task.ts +++ b/packages/contracts/tasks/upgrade-task.ts @@ -38,23 +38,21 @@ task('getImp') task('setCode') .addParam('contract', 'proxy address') - .setAction(async (taskArgs, hre) => { - const accounts = await hre.ethers.getSigners() - const ownerWallet = new ethers.Wallet( - '0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80', - accounts[0].provider + .setAction(async (taskArgs) => { + const provider = new ethers.providers.JsonRpcProvider( + 'http://localhost:9545' ) + const proposerKey = process.env.BVM_ADDRESS_MANAGER_KEY + const ownerWallet = new ethers.Wallet(proposerKey, provider) const l1ChugSplashProxy = getContractFactory('L1ChugSplashProxy').attach( taskArgs.contract ) console.log('Query before setCode') console.log( 'Implementation :', - await l1ChugSplashProxy - .connect(accounts[0].provider) - .callStatic.getImplementation({ - from: ethers.constants.AddressZero, - }) + await l1ChugSplashProxy.connect(provider).callStatic.getImplementation({ + from: ethers.constants.AddressZero, + }) ) const upgrade = getContractDefinition('L1StandardBridgeUpgrade') @@ -70,16 +68,16 @@ task('setCode') console.log('Query after setCode') console.log( 'Implementation :', - await l1ChugSplashProxy - .connect(accounts[0].provider) - .callStatic.getImplementation({ - from: ethers.constants.AddressZero, - }) + await l1ChugSplashProxy.connect(provider).callStatic.getImplementation({ + from: ethers.constants.AddressZero, + }) ) console.log( 'version: ', - await upgradeContract.connect(accounts[0]).getVersion() + await upgradeContract.connect(ownerWallet.provider).getVersion({ + from: ethers.constants.AddressZero, + }) ) }) diff --git a/packages/contracts/test/contracts/L1/fraud-proof/RollUp.spec.ts b/packages/contracts/test/contracts/L1/fraud-proof/RollUp.spec.ts new file mode 100644 index 000000000..070ae3f39 --- /dev/null +++ b/packages/contracts/test/contracts/L1/fraud-proof/RollUp.spec.ts @@ -0,0 +1,267 @@ +import { Signer, Contract, constants } from 'ethers' +import chai from 'chai' + +// @ts-ignore +import { deploy } from '../../../helpers' +import { ctx, proof } from '../../../data/json/fraud-proof/fp_challenge.json' + +const { expect } = chai +// eslint-disable-next-line @typescript-eslint/no-var-requires +const { ethers } = require('hardhat') + +describe('RollUp', () => { + let accounts: Signer[] + let rollUp: Contract + let verifier: Contract + let token: Contract + let assertionMap: Contract + let addressManager: Contract + + const tx = [ + ctx.txNonce, + ctx.gasPrice, + ctx.gas, + ctx.recipient, + ctx.value, + ctx.input, + ctx.txV, + ctx.txR, + ctx.txS, + ] + + const ctxCall = { + coinbase: ctx.coinbase, + timestamp: ctx.timestamp, + number: ctx.blockNumber, + origin: ctx.origin, + transaction: tx, + inputRoot: + '0x0000000000000000000000000000000000000000000000000000000000000000', + txHash: ctx.txnHash, + } + + before('setup', async () => { + accounts = await ethers.getSigners() + await deployAddressManager() + await deploySCC() + await deployToken() + await deployVerifier() + await deployRollUp() + }) + + it('stake', async () => { + const amountStake = 1000 + expect(await rollUp.isStaked(await accounts[0].getAddress())).to.eq(false) + expect(await rollUp.numStakers()).to.eq(0) + + await rollUp.stake({ value: amountStake }) + expect(await rollUp.isStaked(await accounts[0].getAddress())).to.eq(true) + expect(await rollUp.numStakers()).to.eq(1) + const staker = await rollUp.stakers(await accounts[0].getAddress()) + expect(staker.isStaked).to.eq(true) + expect(staker.amountStaked.toNumber()).to.eq(amountStake) + expect(staker.assertionID.toNumber()).to.eq(0) + expect(staker.currentChallenge).to.eq(constants.AddressZero) + }) + + it('unstake', async () => { + const amountUnStake = 100 + let staker = await rollUp.stakers(await accounts[0].getAddress()) + const amountStake = staker.amountStaked.toNumber() + const baseStakeAmount = await rollUp.baseStakeAmount() + + await rollUp.unstake(amountUnStake) + + staker = await rollUp.stakers(await accounts[0].getAddress()) + expect(staker.amountStaked.toNumber()).to.eq(amountStake - baseStakeAmount) + }) + + it('removeStake', async () => { + expect(await rollUp.isStaked(await accounts[0].getAddress())).to.eq(true) + await rollUp.removeStake(await accounts[0].getAddress()) + expect(await rollUp.isStaked(await accounts[0].getAddress())).to.eq(false) + }) + + it('createAssertion', async () => { + const amountStake = 10000 + await rollUp.stake({ value: amountStake }) + + await rollUp.createAssertion( + '0x0000000000000000000000000000000000000000000000000000000000000001', + 1 + ) + expect(await rollUp.lastCreatedAssertionID()).to.eq(1) + + await rollUp.createAssertion(proof.currHash, 2) + expect(await rollUp.lastCreatedAssertionID()).to.eq(2) + + await rollUp.createAssertion(proof.nextHash, 3) + + expect(await rollUp.lastCreatedAssertionID()).to.eq(3) + + await rollUp.createAssertion( + '0x0000000000000000000000000000000000000000000000000000000000000001', + 4 + ) + expect(await rollUp.lastCreatedAssertionID()).to.eq(4) + await rollUp.connect(await accounts[3]).stake({ value: 100000 }) + await rollUp.connect(await accounts[3]).advanceStake(1) + await rollUp.connect(await accounts[3]).advanceStake(2) + await rollUp + .connect(await accounts[3]) + .createAssertion( + '0x0000000000000000000000000000000000000000000000000000000000000001', + 3 + ) + expect(await rollUp.lastCreatedAssertionID()).to.eq(5) + }) + + it('confirmFirstUnresolvedAssertion', async () => { + expect(await rollUp.lastResolvedAssertionID()).to.eq(0) + expect(await rollUp.lastConfirmedAssertionID()).to.eq(0) + + await rollUp.confirmFirstUnresolvedAssertion() + expect(await rollUp.lastResolvedAssertionID()).to.eq(1) + expect(await rollUp.lastConfirmedAssertionID()).to.eq(1) + + await rollUp.confirmFirstUnresolvedAssertion() + expect(await rollUp.lastResolvedAssertionID()).to.eq(2) + expect(await rollUp.lastConfirmedAssertionID()).to.eq(2) + }) + + it('challengeAssertion', async () => { + const players = [ + await accounts[0].getAddress(), + await accounts[3].getAddress(), + ] + const assertionIDs = [3, 5] + await rollUp.challengeAssertion(players, assertionIDs) + expect( + (await rollUp.stakers(await accounts[0].getAddress())).currentChallenge + ).to.eq( + (await rollUp.stakers(await accounts[3].getAddress())).currentChallenge + ) + }) + + it('verifyOneStepProof', async () => { + const winnerAddr = await accounts[0].getAddress() + const loserAddr = await accounts[3].getAddress() + + const challengeImp = await deploy('Challenge') + const challengeAddr = (await rollUp.stakers(winnerAddr)).currentChallenge + const challenge = new Contract( + challengeAddr, + challengeImp.interface, + accounts[0] + ) + await challenge.initializeChallengeLength( + '0x0000000000000000000000000000000000000000000000000000000000000011', + 2 + ) + const loserAmount = ( + await rollUp.stakers(loserAddr) + ).amountStaked.toNumber() + + await challenge.connect(accounts[3]).verifyOneStepProof( + ctxCall, + proof.verifier, + proof.proof, // proof + 1, // challengedStepIndex + 0, // prevChallengedSegmentStart + 2 // prevChallengedSegmentLength + ) + await challenge.completeChallenge(true) + // check amount + expect(await rollUp.withdrawableFunds(loserAddr)).to.eq(loserAmount - 100) + expect(await rollUp.isStaked(loserAddr)).to.eq(false) + expect((await rollUp.zombies(0)).stakerAddress).to.eq(loserAddr) + expect((await rollUp.zombies(0)).lastAssertionID.toNumber()).to.eq(5) + }) + + const deployToken = async () => { + token = await deploy('TestERC20') + } + + const deployRollUp = async () => { + const rollUpImp = await deploy('Rollup') + assertionMap = await deploy('AssertionMap') + + const whitelists = [ + await accounts[0].getAddress(), + await accounts[1].getAddress(), + await accounts[2].getAddress(), + await accounts[3].getAddress(), + ] + const rollupArgs = [ + await accounts[1].getAddress(), // roll up owner + verifier.address, // verifier + token.address, // stake token + addressManager.address, // address manager + assertionMap.address, // assertionMap + 0, // confirmation period + 0, // challenge period + 0, // minimum assertion period + 100, // baseStakeAmount + '0x0000000000000000000000000000000000000000000000000000000000000000', // initialVMhash + whitelists, + ] + + const callData = rollUpImp.interface.encodeFunctionData( + 'initialize', + rollupArgs + ) + const rollUpProxy = await deploy('TransparentUpgradeableProxy', { + args: [ + rollUpImp.address, // logic + await accounts[2].getAddress(), // admin + callData, // call data + ], + }) + + expect(await assertionMap.rollupAddress()).to.eq(rollUpProxy.address) + + rollUp = new Contract(rollUpProxy.address, rollUpImp.interface, accounts[0]) + expect(await rollUp.owner()).to.eq(rollupArgs[0]) + expect(await rollUp.verifier()).to.eq(rollupArgs[1]) + expect(await rollUp.stakeToken()).to.eq(rollupArgs[2]) + expect(await rollUp.libAddressManager()).to.eq(rollupArgs[3]) + expect(await rollUp.assertions()).to.eq(rollupArgs[4]) + expect(await rollUp.confirmationPeriod()).to.eq(rollupArgs[5]) + expect(await rollUp.challengePeriod()).to.eq(rollupArgs[6]) + expect(await rollUp.minimumAssertionPeriod()).to.eq(rollupArgs[7]) + expect(await rollUp.baseStakeAmount()).to.eq(rollupArgs[8]) + } + + const deployVerifier = async () => { + const stackOpVerifier = await deploy('StackOpVerifier') + const verifierEntry = await deploy('VerifierEntry') + const callData = verifierEntry.interface.encodeFunctionData('initialize') + const verifierProxy = await deploy('TransparentUpgradeableProxy', { + args: [ + verifierEntry.address, // logic + await accounts[2].getAddress(), // admin + callData, // call data + ], + }) + + verifier = new Contract( + verifierProxy.address, + verifierEntry.interface, + accounts[0] + ) + await verifier.setVerifier(0, stackOpVerifier.address) + } + + const deployAddressManager = async () => { + addressManager = await deploy('Lib_AddressManager') + await addressManager.setAddress( + 'BVM_Rolluper', + await accounts[0].getAddress() + ) + } + + const deploySCC = async () => { + const scc = await deploy('MockStateCommitmentChain') + await addressManager.setAddress('StateCommitmentChain', scc.address) + } +}) diff --git a/packages/contracts/test/contracts/L1/fraud-proof/Verifier.spec.ts b/packages/contracts/test/contracts/L1/fraud-proof/Verifier.spec.ts new file mode 100644 index 000000000..106008806 --- /dev/null +++ b/packages/contracts/test/contracts/L1/fraud-proof/Verifier.spec.ts @@ -0,0 +1,105 @@ +// eslint-disable-next-line import/order +import { Contract, Signer } from 'ethers' + +// @ts-ignore +import { ethers } from 'hardhat' + +// @ts-ignore +import { deploy } from '../../../helpers' +import { ctx, proof } from '../../../data/json/fraud-proof/fp_challenge.json' + +describe('RollUp', () => { + let accounts: Signer[] + let verifierTestDriver: Contract + let stackOpVerifier: Contract + let verifier: Contract + + const tx = [ + ctx.txNonce, + ctx.gasPrice, + ctx.gas, + ctx.recipient, + ctx.value, + ctx.input, + ctx.txV, + ctx.txR, + ctx.txS, + ] + + before('setup', async () => { + accounts = await ethers.getSigners() + await deployVerifier() + await deployVerifierEntry() + }) + + it('verifierEntry verifyProof', async () => { + const ctxCall = { + coinbase: ctx.coinbase, + timestamp: ctx.timestamp, + number: ctx.blockNumber, + origin: ctx.origin, + transaction: tx, + inputRoot: + '0x0000000000000000000000000000000000000000000000000000000000000000', + txHash: ctx.txnHash, + } + + await verifier.verifyOneStepProof( + ctxCall, + proof.verifier, + proof.currHash, + proof.proof + ) + }) + + it('VerifierTestDriver verifyProof', async () => { + await verifierTestDriver.verifyProof( + ctx.coinbase, + ctx.timestamp, + ctx.blockNumber, + ctx.origin, + ctx.txnHash, + tx, + proof.verifier, + proof.currHash, + proof.proof + ) + }) + + const deployVerifier = async () => { + stackOpVerifier = await deploy('StackOpVerifier') + // eslint-disable-next-line @typescript-eslint/no-unused-vars + verifierTestDriver = await deploy('VerifierTestDriver', { + args: [ + stackOpVerifier.address, + stackOpVerifier.address, + stackOpVerifier.address, + stackOpVerifier.address, + stackOpVerifier.address, + stackOpVerifier.address, + stackOpVerifier.address, + stackOpVerifier.address, + stackOpVerifier.address, + ], + }) + } + + const deployVerifierEntry = async () => { + const verifierEntry = await deploy('VerifierEntry') + const callData = verifierEntry.interface.encodeFunctionData('initialize') + const verifierProxy = await deploy('TransparentUpgradeableProxy', { + args: [ + verifierEntry.address, // logic + await accounts[2].getAddress(), // admin + callData, // call data + ], + }) + + verifier = new Contract( + verifierProxy.address, + verifierEntry.interface, + accounts[0] + ) + await verifier.setVerifier(0, stackOpVerifier.address) + } +}) diff --git a/packages/contracts/test/data/json/fraud-proof/fp_challenge.json b/packages/contracts/test/data/json/fraud-proof/fp_challenge.json new file mode 100644 index 000000000..66f68a0fc --- /dev/null +++ b/packages/contracts/test/data/json/fraud-proof/fp_challenge.json @@ -0,0 +1 @@ +{"ctx":{"txnHash":"0x73ea1d2ee379cd800d4006953888d2e23a57675dfc44de09e1d0194fcd866b1f","txNonce":"0x0","txV":"0x69d2","txR":"0xd4cb56830de320028fc55988eb0102257955519d9dc062d80a485abb122e9e67","txS":"0x30cd3a7bdef20deae43d760be21f524a8bbec4f97a59b07d6779da50a2a1af5f","coinbase":"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266","timestamp":"0x63b7e9c1","blockNumber":"0x1","difficulty":"0x1","gasLimit":"0x7a3083","chainID":"0x34d7","baseFee":"0x0","origin":"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266","recipient":"0x0000000000000000000000000000000000000000","value":"0x0","gas":"0x1eaed","gasPrice":"0x3b9aca00","input":"0x608060405234801561001057600080fd5b50610150806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80632e64cec11461003b5780636057361d14610059575b600080fd5b610043610075565b60405161005091906100d9565b60405180910390f35b610073600480360381019061006e919061009d565b61007e565b005b60008054905090565b8060008190555050565b60008135905061009781610103565b92915050565b6000602082840312156100b3576100b26100fe565b5b60006100c184828501610088565b91505092915050565b6100d3816100f4565b82525050565b60006020820190506100ee60008301846100ca565b92915050565b6000819050919050565b600080fd5b61010c816100f4565b811461011757600080fd5b5056fea2646970667358221220404e37f487a89a932dca5e77faaf6ca2de3b991f93d230604b1b8daaef64766264736f6c63430008070033","inputSize":"0x170"},"proof":{"opcode":"PUSH1","verifier":0,"currHash":"0xea576c527587e9781b29f73d5f0c3790bb6690bd1b3b080e4b1b213f53e9f872","nextHash":"0x593eedc374701325ac268ad9701765147e200b736b55626323cf9921db5b8a61","proofSize":"0x2bb","codeSize":"0x170","proof":"0x00000000000000010000000000000000000100000000000106f500000000000000004262f14003fcb1c7a13c958a3cd20818d6a5e3d7777745b13c05f14385c19e6d000000000000000060c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470000000000000000000000000000000000000000000000000744c19d2e8593c97867b3b6a3588f51cd9dbc5010a395cf199be4bbb353848b8c549a82442ec9d279699caa0abffb15160db5a18e264622fc440b66cff66bf3f0000000000000000000000000000000000000000000000000000000000000000cdc5a830e025de132066c7f43de48570407bfaebc30b96f499fc06d42f5602dfac5def5a7a8b39addbb94d47a566bd1900fb621a43073880e10d6c739ae503eb00000000000000000000000000000000000000000000000000000000000000000000000000000170608060405234801561001057600080fd5b50610150806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80632e64cec11461003b5780636057361d14610059575b600080fd5b610043610075565b60405161005091906100d9565b60405180910390f35b610073600480360381019061006e919061009d565b61007e565b005b60008054905090565b8060008190555050565b60008135905061009781610103565b92915050565b6000602082840312156100b3576100b26100fe565b5b60006100c184828501610088565b91505092915050565b6100d3816100f4565b82525050565b60006020820190506100ee60008301846100ca565b92915050565b6000819050919050565b600080fd5b61010c816100f4565b811461011757600080fd5b5056fea2646970667358221220404e37f487a89a932dca5e77faaf6ca2de3b991f93d230604b1b8daaef64766264736f6c63430008070033","idx":1}} diff --git a/state-surgery/cli.go b/state-surgery/cli.go index 51c2735f8..1fd502292 100644 --- a/state-surgery/cli.go +++ b/state-surgery/cli.go @@ -49,14 +49,14 @@ func DumpAddresses(dataDir string, outFile string) error { // Migrate performs the actual state migration. It does quite a lot: // -// 1. It uses address lists, allowance lists, Mint events, and address preimages in -// the input state database to create a comprehensive list of storage slots in the -// BVM ETH contract. -// 2. It iterates over the slots in BVM ETH, and compares then against the list in (1). -// If the list doesn't match, or the total supply of BVM ETH doesn't match the sum of -// all balance storage slots, it panics. -// 3. It performs the actual migration by copying the input state DB into a new state DB. -// 4. It imports the provided genesis into the new state DB like Geth would during geth init. +// 1. It uses address lists, allowance lists, Mint events, and address preimages in +// the input state database to create a comprehensive list of storage slots in the +// BVM ETH contract. +// 2. It iterates over the slots in BVM ETH, and compares then against the list in (1). +// If the list doesn't match, or the total supply of BVM ETH doesn't match the sum of +// all balance storage slots, it panics. +// 3. It performs the actual migration by copying the input state DB into a new state DB. +// 4. It imports the provided genesis into the new state DB like Geth would during geth init. // // It takes the following arguments: // @@ -64,9 +64,9 @@ func DumpAddresses(dataDir string, outFile string) error { // - outDir: A directory to output the migrated database to. // - genesis: The new chain's genesis configuration. // - addrLists: A list of address list file paths. These address lists are used to populate -// balances from previous regenesis events. +// balances from previous regenesis events. // - allowanceLists: A list of allowance list file paths. These allowance lists are used -// to calculate allowance storage slots from previous regenesis events. +// to calculate allowance storage slots from previous regenesis events. // - chainID: The chain ID of the chain being migrated. func Migrate(dataDir, outDir string, genesis *core.Genesis, addrLists, allowanceLists []string, chainID, levelDBCacheSize, levelDBHandles int) error { db := MustOpenDBWithCacheOpts(dataDir, levelDBCacheSize, levelDBHandles) @@ -359,7 +359,7 @@ func Migrate(dataDir, outDir string, genesis *core.Genesis, addrLists, allowance // // Unlike regular Geth (which panics if you try to import a genesis state with a nonzero // block number), the block number can be anything. - block := genesis.ToBlock(nil) + block := genesis.ToBlock() // Geth block headers are immutable, so swap the root and make a new block with the // updated root. diff --git a/tss/bindings/fp/Challenge.go b/tss/bindings/fp/Challenge.go new file mode 100644 index 000000000..ef9cebc4a --- /dev/null +++ b/tss/bindings/fp/Challenge.go @@ -0,0 +1,1100 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package bindings + +import ( + "errors" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" +) + +// Reference imports to suppress errors if they are not otherwise used. +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription +) + +// EVMTypesLibTransaction is an auto generated low-level Go binding around an user-defined struct. +type EVMTypesLibTransaction struct { + Nonce uint64 + GasPrice *big.Int + Gas uint64 + To common.Address + Value *big.Int + Data []byte + V *big.Int + R *big.Int + S *big.Int +} + +// VerificationContextContext is an auto generated low-level Go binding around an user-defined struct. +type VerificationContextContext struct { + Coinbase common.Address + Timestamp *big.Int + Number *big.Int + Origin common.Address + Transaction EVMTypesLibTransaction + InputRoot [32]byte + TxHash [32]byte +} + +// ChallengeMetaData contains all meta data concerning the Challenge contract. +var ChallengeMetaData = &bind.MetaData{ + ABI: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"startState\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"midState\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"endState\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"blockNum\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"blockTime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"challengedSegmentStart\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"challengedSegmentLength\",\"type\":\"uint256\"}],\"name\":\"Bisected\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"winner\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"loser\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"enumIChallenge.CompletionReason\",\"name\":\"reason\",\"type\":\"uint8\"}],\"name\":\"ChallengeCompleted\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"bisection\",\"type\":\"bytes32[3]\"},{\"internalType\":\"uint256\",\"name\":\"challengedSegmentIndex\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"challengedSegmentStart\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"challengedSegmentLength\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"prevChallengedSegmentStart\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"prevChallengedSegmentLength\",\"type\":\"uint256\"}],\"name\":\"bisectExecution\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bisectionHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"challenger\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"challengerTimeLeft\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"result\",\"type\":\"bool\"}],\"name\":\"completeChallenge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"currentBisected\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"startState\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"midState\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"endState\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"blockNum\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"blockTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"challengedSegmentStart\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"challengedSegmentLength\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"currentResponder\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"currentResponderTimeLeft\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"defender\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"defenderTimeLeft\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_defender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_challenger\",\"type\":\"address\"},{\"internalType\":\"contractIVerifierEntry\",\"name\":\"_verifier\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_resultReceiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_startInboxSize\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_startStateHash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"_endStateHash\",\"type\":\"bytes32\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"checkStateHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_numSteps\",\"type\":\"uint256\"}],\"name\":\"initializeChallengeLength\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastMoveBlockTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"prevBisection\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"rollback\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"setRollback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"startInboxSize\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"timeout\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"turn\",\"outputs\":[{\"internalType\":\"enumChallenge.Turn\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"coinbase\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"number\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"origin\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"gasPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"gas\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"v\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"r\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"s\",\"type\":\"uint256\"}],\"internalType\":\"structEVMTypesLib.Transaction\",\"name\":\"transaction\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"inputRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"txHash\",\"type\":\"bytes32\"}],\"internalType\":\"structVerificationContext.Context\",\"name\":\"ctx\",\"type\":\"tuple\"},{\"internalType\":\"uint8\",\"name\":\"verifyType\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"proof\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"challengedStepIndex\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"prevChallengedSegmentStart\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"prevChallengedSegmentLength\",\"type\":\"uint256\"}],\"name\":\"verifyOneStepProof\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"winner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", +} + +// ChallengeABI is the input ABI used to generate the binding from. +// Deprecated: Use ChallengeMetaData.ABI instead. +var ChallengeABI = ChallengeMetaData.ABI + +// Challenge is an auto generated Go binding around an Ethereum contract. +type Challenge struct { + ChallengeCaller // Read-only binding to the contract + ChallengeTransactor // Write-only binding to the contract + ChallengeFilterer // Log filterer for contract events +} + +// ChallengeCaller is an auto generated read-only Go binding around an Ethereum contract. +type ChallengeCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ChallengeTransactor is an auto generated write-only Go binding around an Ethereum contract. +type ChallengeTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ChallengeFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type ChallengeFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ChallengeSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type ChallengeSession struct { + Contract *Challenge // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// ChallengeCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type ChallengeCallerSession struct { + Contract *ChallengeCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// ChallengeTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type ChallengeTransactorSession struct { + Contract *ChallengeTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// ChallengeRaw is an auto generated low-level Go binding around an Ethereum contract. +type ChallengeRaw struct { + Contract *Challenge // Generic contract binding to access the raw methods on +} + +// ChallengeCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type ChallengeCallerRaw struct { + Contract *ChallengeCaller // Generic read-only contract binding to access the raw methods on +} + +// ChallengeTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type ChallengeTransactorRaw struct { + Contract *ChallengeTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewChallenge creates a new instance of Challenge, bound to a specific deployed contract. +func NewChallenge(address common.Address, backend bind.ContractBackend) (*Challenge, error) { + contract, err := bindChallenge(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &Challenge{ChallengeCaller: ChallengeCaller{contract: contract}, ChallengeTransactor: ChallengeTransactor{contract: contract}, ChallengeFilterer: ChallengeFilterer{contract: contract}}, nil +} + +// NewChallengeCaller creates a new read-only instance of Challenge, bound to a specific deployed contract. +func NewChallengeCaller(address common.Address, caller bind.ContractCaller) (*ChallengeCaller, error) { + contract, err := bindChallenge(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &ChallengeCaller{contract: contract}, nil +} + +// NewChallengeTransactor creates a new write-only instance of Challenge, bound to a specific deployed contract. +func NewChallengeTransactor(address common.Address, transactor bind.ContractTransactor) (*ChallengeTransactor, error) { + contract, err := bindChallenge(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &ChallengeTransactor{contract: contract}, nil +} + +// NewChallengeFilterer creates a new log filterer instance of Challenge, bound to a specific deployed contract. +func NewChallengeFilterer(address common.Address, filterer bind.ContractFilterer) (*ChallengeFilterer, error) { + contract, err := bindChallenge(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &ChallengeFilterer{contract: contract}, nil +} + +// bindChallenge binds a generic wrapper to an already deployed contract. +func bindChallenge(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := abi.JSON(strings.NewReader(ChallengeABI)) + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Challenge *ChallengeRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Challenge.Contract.ChallengeCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Challenge *ChallengeRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Challenge.Contract.ChallengeTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Challenge *ChallengeRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Challenge.Contract.ChallengeTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Challenge *ChallengeCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Challenge.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Challenge *ChallengeTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Challenge.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Challenge *ChallengeTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Challenge.Contract.contract.Transact(opts, method, params...) +} + +// BisectionHash is a free data retrieval call binding the contract method 0x2a51f6f7. +// +// Solidity: function bisectionHash() view returns(bytes32) +func (_Challenge *ChallengeCaller) BisectionHash(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _Challenge.contract.Call(opts, &out, "bisectionHash") + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +// BisectionHash is a free data retrieval call binding the contract method 0x2a51f6f7. +// +// Solidity: function bisectionHash() view returns(bytes32) +func (_Challenge *ChallengeSession) BisectionHash() ([32]byte, error) { + return _Challenge.Contract.BisectionHash(&_Challenge.CallOpts) +} + +// BisectionHash is a free data retrieval call binding the contract method 0x2a51f6f7. +// +// Solidity: function bisectionHash() view returns(bytes32) +func (_Challenge *ChallengeCallerSession) BisectionHash() ([32]byte, error) { + return _Challenge.Contract.BisectionHash(&_Challenge.CallOpts) +} + +// Challenger is a free data retrieval call binding the contract method 0x534db0e2. +// +// Solidity: function challenger() view returns(address) +func (_Challenge *ChallengeCaller) Challenger(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _Challenge.contract.Call(opts, &out, "challenger") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// Challenger is a free data retrieval call binding the contract method 0x534db0e2. +// +// Solidity: function challenger() view returns(address) +func (_Challenge *ChallengeSession) Challenger() (common.Address, error) { + return _Challenge.Contract.Challenger(&_Challenge.CallOpts) +} + +// Challenger is a free data retrieval call binding the contract method 0x534db0e2. +// +// Solidity: function challenger() view returns(address) +func (_Challenge *ChallengeCallerSession) Challenger() (common.Address, error) { + return _Challenge.Contract.Challenger(&_Challenge.CallOpts) +} + +// ChallengerTimeLeft is a free data retrieval call binding the contract method 0x41e8510c. +// +// Solidity: function challengerTimeLeft() view returns(uint256) +func (_Challenge *ChallengeCaller) ChallengerTimeLeft(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Challenge.contract.Call(opts, &out, "challengerTimeLeft") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// ChallengerTimeLeft is a free data retrieval call binding the contract method 0x41e8510c. +// +// Solidity: function challengerTimeLeft() view returns(uint256) +func (_Challenge *ChallengeSession) ChallengerTimeLeft() (*big.Int, error) { + return _Challenge.Contract.ChallengerTimeLeft(&_Challenge.CallOpts) +} + +// ChallengerTimeLeft is a free data retrieval call binding the contract method 0x41e8510c. +// +// Solidity: function challengerTimeLeft() view returns(uint256) +func (_Challenge *ChallengeCallerSession) ChallengerTimeLeft() (*big.Int, error) { + return _Challenge.Contract.ChallengerTimeLeft(&_Challenge.CallOpts) +} + +// CurrentBisected is a free data retrieval call binding the contract method 0x732e6961. +// +// Solidity: function currentBisected() view returns(bytes32 startState, bytes32 midState, bytes32 endState, uint256 blockNum, uint256 blockTime, uint256 challengedSegmentStart, uint256 challengedSegmentLength) +func (_Challenge *ChallengeCaller) CurrentBisected(opts *bind.CallOpts) (struct { + StartState [32]byte + MidState [32]byte + EndState [32]byte + BlockNum *big.Int + BlockTime *big.Int + ChallengedSegmentStart *big.Int + ChallengedSegmentLength *big.Int +}, error) { + var out []interface{} + err := _Challenge.contract.Call(opts, &out, "currentBisected") + + outstruct := new(struct { + StartState [32]byte + MidState [32]byte + EndState [32]byte + BlockNum *big.Int + BlockTime *big.Int + ChallengedSegmentStart *big.Int + ChallengedSegmentLength *big.Int + }) + if err != nil { + return *outstruct, err + } + + outstruct.StartState = *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + outstruct.MidState = *abi.ConvertType(out[1], new([32]byte)).(*[32]byte) + outstruct.EndState = *abi.ConvertType(out[2], new([32]byte)).(*[32]byte) + outstruct.BlockNum = *abi.ConvertType(out[3], new(*big.Int)).(**big.Int) + outstruct.BlockTime = *abi.ConvertType(out[4], new(*big.Int)).(**big.Int) + outstruct.ChallengedSegmentStart = *abi.ConvertType(out[5], new(*big.Int)).(**big.Int) + outstruct.ChallengedSegmentLength = *abi.ConvertType(out[6], new(*big.Int)).(**big.Int) + + return *outstruct, err + +} + +// CurrentBisected is a free data retrieval call binding the contract method 0x732e6961. +// +// Solidity: function currentBisected() view returns(bytes32 startState, bytes32 midState, bytes32 endState, uint256 blockNum, uint256 blockTime, uint256 challengedSegmentStart, uint256 challengedSegmentLength) +func (_Challenge *ChallengeSession) CurrentBisected() (struct { + StartState [32]byte + MidState [32]byte + EndState [32]byte + BlockNum *big.Int + BlockTime *big.Int + ChallengedSegmentStart *big.Int + ChallengedSegmentLength *big.Int +}, error) { + return _Challenge.Contract.CurrentBisected(&_Challenge.CallOpts) +} + +// CurrentBisected is a free data retrieval call binding the contract method 0x732e6961. +// +// Solidity: function currentBisected() view returns(bytes32 startState, bytes32 midState, bytes32 endState, uint256 blockNum, uint256 blockTime, uint256 challengedSegmentStart, uint256 challengedSegmentLength) +func (_Challenge *ChallengeCallerSession) CurrentBisected() (struct { + StartState [32]byte + MidState [32]byte + EndState [32]byte + BlockNum *big.Int + BlockTime *big.Int + ChallengedSegmentStart *big.Int + ChallengedSegmentLength *big.Int +}, error) { + return _Challenge.Contract.CurrentBisected(&_Challenge.CallOpts) +} + +// CurrentResponder is a free data retrieval call binding the contract method 0x8a8cd218. +// +// Solidity: function currentResponder() view returns(address) +func (_Challenge *ChallengeCaller) CurrentResponder(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _Challenge.contract.Call(opts, &out, "currentResponder") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// CurrentResponder is a free data retrieval call binding the contract method 0x8a8cd218. +// +// Solidity: function currentResponder() view returns(address) +func (_Challenge *ChallengeSession) CurrentResponder() (common.Address, error) { + return _Challenge.Contract.CurrentResponder(&_Challenge.CallOpts) +} + +// CurrentResponder is a free data retrieval call binding the contract method 0x8a8cd218. +// +// Solidity: function currentResponder() view returns(address) +func (_Challenge *ChallengeCallerSession) CurrentResponder() (common.Address, error) { + return _Challenge.Contract.CurrentResponder(&_Challenge.CallOpts) +} + +// CurrentResponderTimeLeft is a free data retrieval call binding the contract method 0xe87e3589. +// +// Solidity: function currentResponderTimeLeft() view returns(uint256) +func (_Challenge *ChallengeCaller) CurrentResponderTimeLeft(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Challenge.contract.Call(opts, &out, "currentResponderTimeLeft") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// CurrentResponderTimeLeft is a free data retrieval call binding the contract method 0xe87e3589. +// +// Solidity: function currentResponderTimeLeft() view returns(uint256) +func (_Challenge *ChallengeSession) CurrentResponderTimeLeft() (*big.Int, error) { + return _Challenge.Contract.CurrentResponderTimeLeft(&_Challenge.CallOpts) +} + +// CurrentResponderTimeLeft is a free data retrieval call binding the contract method 0xe87e3589. +// +// Solidity: function currentResponderTimeLeft() view returns(uint256) +func (_Challenge *ChallengeCallerSession) CurrentResponderTimeLeft() (*big.Int, error) { + return _Challenge.Contract.CurrentResponderTimeLeft(&_Challenge.CallOpts) +} + +// Defender is a free data retrieval call binding the contract method 0x7f4c91c5. +// +// Solidity: function defender() view returns(address) +func (_Challenge *ChallengeCaller) Defender(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _Challenge.contract.Call(opts, &out, "defender") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// Defender is a free data retrieval call binding the contract method 0x7f4c91c5. +// +// Solidity: function defender() view returns(address) +func (_Challenge *ChallengeSession) Defender() (common.Address, error) { + return _Challenge.Contract.Defender(&_Challenge.CallOpts) +} + +// Defender is a free data retrieval call binding the contract method 0x7f4c91c5. +// +// Solidity: function defender() view returns(address) +func (_Challenge *ChallengeCallerSession) Defender() (common.Address, error) { + return _Challenge.Contract.Defender(&_Challenge.CallOpts) +} + +// DefenderTimeLeft is a free data retrieval call binding the contract method 0x5f41e3d6. +// +// Solidity: function defenderTimeLeft() view returns(uint256) +func (_Challenge *ChallengeCaller) DefenderTimeLeft(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Challenge.contract.Call(opts, &out, "defenderTimeLeft") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// DefenderTimeLeft is a free data retrieval call binding the contract method 0x5f41e3d6. +// +// Solidity: function defenderTimeLeft() view returns(uint256) +func (_Challenge *ChallengeSession) DefenderTimeLeft() (*big.Int, error) { + return _Challenge.Contract.DefenderTimeLeft(&_Challenge.CallOpts) +} + +// DefenderTimeLeft is a free data retrieval call binding the contract method 0x5f41e3d6. +// +// Solidity: function defenderTimeLeft() view returns(uint256) +func (_Challenge *ChallengeCallerSession) DefenderTimeLeft() (*big.Int, error) { + return _Challenge.Contract.DefenderTimeLeft(&_Challenge.CallOpts) +} + +// LastMoveBlockTime is a free data retrieval call binding the contract method 0xed5b1303. +// +// Solidity: function lastMoveBlockTime() view returns(uint256) +func (_Challenge *ChallengeCaller) LastMoveBlockTime(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Challenge.contract.Call(opts, &out, "lastMoveBlockTime") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// LastMoveBlockTime is a free data retrieval call binding the contract method 0xed5b1303. +// +// Solidity: function lastMoveBlockTime() view returns(uint256) +func (_Challenge *ChallengeSession) LastMoveBlockTime() (*big.Int, error) { + return _Challenge.Contract.LastMoveBlockTime(&_Challenge.CallOpts) +} + +// LastMoveBlockTime is a free data retrieval call binding the contract method 0xed5b1303. +// +// Solidity: function lastMoveBlockTime() view returns(uint256) +func (_Challenge *ChallengeCallerSession) LastMoveBlockTime() (*big.Int, error) { + return _Challenge.Contract.LastMoveBlockTime(&_Challenge.CallOpts) +} + +// PrevBisection is a free data retrieval call binding the contract method 0xafeae965. +// +// Solidity: function prevBisection(uint256 ) view returns(bytes32) +func (_Challenge *ChallengeCaller) PrevBisection(opts *bind.CallOpts, arg0 *big.Int) ([32]byte, error) { + var out []interface{} + err := _Challenge.contract.Call(opts, &out, "prevBisection", arg0) + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +// PrevBisection is a free data retrieval call binding the contract method 0xafeae965. +// +// Solidity: function prevBisection(uint256 ) view returns(bytes32) +func (_Challenge *ChallengeSession) PrevBisection(arg0 *big.Int) ([32]byte, error) { + return _Challenge.Contract.PrevBisection(&_Challenge.CallOpts, arg0) +} + +// PrevBisection is a free data retrieval call binding the contract method 0xafeae965. +// +// Solidity: function prevBisection(uint256 ) view returns(bytes32) +func (_Challenge *ChallengeCallerSession) PrevBisection(arg0 *big.Int) ([32]byte, error) { + return _Challenge.Contract.PrevBisection(&_Challenge.CallOpts, arg0) +} + +// Rollback is a free data retrieval call binding the contract method 0x9afd9d78. +// +// Solidity: function rollback() view returns(bool) +func (_Challenge *ChallengeCaller) Rollback(opts *bind.CallOpts) (bool, error) { + var out []interface{} + err := _Challenge.contract.Call(opts, &out, "rollback") + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// Rollback is a free data retrieval call binding the contract method 0x9afd9d78. +// +// Solidity: function rollback() view returns(bool) +func (_Challenge *ChallengeSession) Rollback() (bool, error) { + return _Challenge.Contract.Rollback(&_Challenge.CallOpts) +} + +// Rollback is a free data retrieval call binding the contract method 0x9afd9d78. +// +// Solidity: function rollback() view returns(bool) +func (_Challenge *ChallengeCallerSession) Rollback() (bool, error) { + return _Challenge.Contract.Rollback(&_Challenge.CallOpts) +} + +// StartInboxSize is a free data retrieval call binding the contract method 0xfaeff41b. +// +// Solidity: function startInboxSize() view returns(uint256) +func (_Challenge *ChallengeCaller) StartInboxSize(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Challenge.contract.Call(opts, &out, "startInboxSize") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// StartInboxSize is a free data retrieval call binding the contract method 0xfaeff41b. +// +// Solidity: function startInboxSize() view returns(uint256) +func (_Challenge *ChallengeSession) StartInboxSize() (*big.Int, error) { + return _Challenge.Contract.StartInboxSize(&_Challenge.CallOpts) +} + +// StartInboxSize is a free data retrieval call binding the contract method 0xfaeff41b. +// +// Solidity: function startInboxSize() view returns(uint256) +func (_Challenge *ChallengeCallerSession) StartInboxSize() (*big.Int, error) { + return _Challenge.Contract.StartInboxSize(&_Challenge.CallOpts) +} + +// Turn is a free data retrieval call binding the contract method 0x8b299903. +// +// Solidity: function turn() view returns(uint8) +func (_Challenge *ChallengeCaller) Turn(opts *bind.CallOpts) (uint8, error) { + var out []interface{} + err := _Challenge.contract.Call(opts, &out, "turn") + + if err != nil { + return *new(uint8), err + } + + out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8) + + return out0, err + +} + +// Turn is a free data retrieval call binding the contract method 0x8b299903. +// +// Solidity: function turn() view returns(uint8) +func (_Challenge *ChallengeSession) Turn() (uint8, error) { + return _Challenge.Contract.Turn(&_Challenge.CallOpts) +} + +// Turn is a free data retrieval call binding the contract method 0x8b299903. +// +// Solidity: function turn() view returns(uint8) +func (_Challenge *ChallengeCallerSession) Turn() (uint8, error) { + return _Challenge.Contract.Turn(&_Challenge.CallOpts) +} + +// Winner is a free data retrieval call binding the contract method 0xdfbf53ae. +// +// Solidity: function winner() view returns(address) +func (_Challenge *ChallengeCaller) Winner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _Challenge.contract.Call(opts, &out, "winner") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// Winner is a free data retrieval call binding the contract method 0xdfbf53ae. +// +// Solidity: function winner() view returns(address) +func (_Challenge *ChallengeSession) Winner() (common.Address, error) { + return _Challenge.Contract.Winner(&_Challenge.CallOpts) +} + +// Winner is a free data retrieval call binding the contract method 0xdfbf53ae. +// +// Solidity: function winner() view returns(address) +func (_Challenge *ChallengeCallerSession) Winner() (common.Address, error) { + return _Challenge.Contract.Winner(&_Challenge.CallOpts) +} + +// BisectExecution is a paid mutator transaction binding the contract method 0x8f2400a8. +// +// Solidity: function bisectExecution(bytes32[3] bisection, uint256 challengedSegmentIndex, uint256 challengedSegmentStart, uint256 challengedSegmentLength, uint256 prevChallengedSegmentStart, uint256 prevChallengedSegmentLength) returns() +func (_Challenge *ChallengeTransactor) BisectExecution(opts *bind.TransactOpts, bisection [3][32]byte, challengedSegmentIndex *big.Int, challengedSegmentStart *big.Int, challengedSegmentLength *big.Int, prevChallengedSegmentStart *big.Int, prevChallengedSegmentLength *big.Int) (*types.Transaction, error) { + return _Challenge.contract.Transact(opts, "bisectExecution", bisection, challengedSegmentIndex, challengedSegmentStart, challengedSegmentLength, prevChallengedSegmentStart, prevChallengedSegmentLength) +} + +// BisectExecution is a paid mutator transaction binding the contract method 0x8f2400a8. +// +// Solidity: function bisectExecution(bytes32[3] bisection, uint256 challengedSegmentIndex, uint256 challengedSegmentStart, uint256 challengedSegmentLength, uint256 prevChallengedSegmentStart, uint256 prevChallengedSegmentLength) returns() +func (_Challenge *ChallengeSession) BisectExecution(bisection [3][32]byte, challengedSegmentIndex *big.Int, challengedSegmentStart *big.Int, challengedSegmentLength *big.Int, prevChallengedSegmentStart *big.Int, prevChallengedSegmentLength *big.Int) (*types.Transaction, error) { + return _Challenge.Contract.BisectExecution(&_Challenge.TransactOpts, bisection, challengedSegmentIndex, challengedSegmentStart, challengedSegmentLength, prevChallengedSegmentStart, prevChallengedSegmentLength) +} + +// BisectExecution is a paid mutator transaction binding the contract method 0x8f2400a8. +// +// Solidity: function bisectExecution(bytes32[3] bisection, uint256 challengedSegmentIndex, uint256 challengedSegmentStart, uint256 challengedSegmentLength, uint256 prevChallengedSegmentStart, uint256 prevChallengedSegmentLength) returns() +func (_Challenge *ChallengeTransactorSession) BisectExecution(bisection [3][32]byte, challengedSegmentIndex *big.Int, challengedSegmentStart *big.Int, challengedSegmentLength *big.Int, prevChallengedSegmentStart *big.Int, prevChallengedSegmentLength *big.Int) (*types.Transaction, error) { + return _Challenge.Contract.BisectExecution(&_Challenge.TransactOpts, bisection, challengedSegmentIndex, challengedSegmentStart, challengedSegmentLength, prevChallengedSegmentStart, prevChallengedSegmentLength) +} + +// CompleteChallenge is a paid mutator transaction binding the contract method 0xf2858aa3. +// +// Solidity: function completeChallenge(bool result) returns() +func (_Challenge *ChallengeTransactor) CompleteChallenge(opts *bind.TransactOpts, result bool) (*types.Transaction, error) { + return _Challenge.contract.Transact(opts, "completeChallenge", result) +} + +// CompleteChallenge is a paid mutator transaction binding the contract method 0xf2858aa3. +// +// Solidity: function completeChallenge(bool result) returns() +func (_Challenge *ChallengeSession) CompleteChallenge(result bool) (*types.Transaction, error) { + return _Challenge.Contract.CompleteChallenge(&_Challenge.TransactOpts, result) +} + +// CompleteChallenge is a paid mutator transaction binding the contract method 0xf2858aa3. +// +// Solidity: function completeChallenge(bool result) returns() +func (_Challenge *ChallengeTransactorSession) CompleteChallenge(result bool) (*types.Transaction, error) { + return _Challenge.Contract.CompleteChallenge(&_Challenge.TransactOpts, result) +} + +// Initialize is a paid mutator transaction binding the contract method 0xabf48013. +// +// Solidity: function initialize(address _defender, address _challenger, address _verifier, address _resultReceiver, uint256 _startInboxSize, bytes32 _startStateHash, bytes32 _endStateHash) returns() +func (_Challenge *ChallengeTransactor) Initialize(opts *bind.TransactOpts, _defender common.Address, _challenger common.Address, _verifier common.Address, _resultReceiver common.Address, _startInboxSize *big.Int, _startStateHash [32]byte, _endStateHash [32]byte) (*types.Transaction, error) { + return _Challenge.contract.Transact(opts, "initialize", _defender, _challenger, _verifier, _resultReceiver, _startInboxSize, _startStateHash, _endStateHash) +} + +// Initialize is a paid mutator transaction binding the contract method 0xabf48013. +// +// Solidity: function initialize(address _defender, address _challenger, address _verifier, address _resultReceiver, uint256 _startInboxSize, bytes32 _startStateHash, bytes32 _endStateHash) returns() +func (_Challenge *ChallengeSession) Initialize(_defender common.Address, _challenger common.Address, _verifier common.Address, _resultReceiver common.Address, _startInboxSize *big.Int, _startStateHash [32]byte, _endStateHash [32]byte) (*types.Transaction, error) { + return _Challenge.Contract.Initialize(&_Challenge.TransactOpts, _defender, _challenger, _verifier, _resultReceiver, _startInboxSize, _startStateHash, _endStateHash) +} + +// Initialize is a paid mutator transaction binding the contract method 0xabf48013. +// +// Solidity: function initialize(address _defender, address _challenger, address _verifier, address _resultReceiver, uint256 _startInboxSize, bytes32 _startStateHash, bytes32 _endStateHash) returns() +func (_Challenge *ChallengeTransactorSession) Initialize(_defender common.Address, _challenger common.Address, _verifier common.Address, _resultReceiver common.Address, _startInboxSize *big.Int, _startStateHash [32]byte, _endStateHash [32]byte) (*types.Transaction, error) { + return _Challenge.Contract.Initialize(&_Challenge.TransactOpts, _defender, _challenger, _verifier, _resultReceiver, _startInboxSize, _startStateHash, _endStateHash) +} + +// InitializeChallengeLength is a paid mutator transaction binding the contract method 0x18ef160d. +// +// Solidity: function initializeChallengeLength(bytes32 checkStateHash, uint256 _numSteps) returns() +func (_Challenge *ChallengeTransactor) InitializeChallengeLength(opts *bind.TransactOpts, checkStateHash [32]byte, _numSteps *big.Int) (*types.Transaction, error) { + return _Challenge.contract.Transact(opts, "initializeChallengeLength", checkStateHash, _numSteps) +} + +// InitializeChallengeLength is a paid mutator transaction binding the contract method 0x18ef160d. +// +// Solidity: function initializeChallengeLength(bytes32 checkStateHash, uint256 _numSteps) returns() +func (_Challenge *ChallengeSession) InitializeChallengeLength(checkStateHash [32]byte, _numSteps *big.Int) (*types.Transaction, error) { + return _Challenge.Contract.InitializeChallengeLength(&_Challenge.TransactOpts, checkStateHash, _numSteps) +} + +// InitializeChallengeLength is a paid mutator transaction binding the contract method 0x18ef160d. +// +// Solidity: function initializeChallengeLength(bytes32 checkStateHash, uint256 _numSteps) returns() +func (_Challenge *ChallengeTransactorSession) InitializeChallengeLength(checkStateHash [32]byte, _numSteps *big.Int) (*types.Transaction, error) { + return _Challenge.Contract.InitializeChallengeLength(&_Challenge.TransactOpts, checkStateHash, _numSteps) +} + +// SetRollback is a paid mutator transaction binding the contract method 0x631acced. +// +// Solidity: function setRollback() returns() +func (_Challenge *ChallengeTransactor) SetRollback(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Challenge.contract.Transact(opts, "setRollback") +} + +// SetRollback is a paid mutator transaction binding the contract method 0x631acced. +// +// Solidity: function setRollback() returns() +func (_Challenge *ChallengeSession) SetRollback() (*types.Transaction, error) { + return _Challenge.Contract.SetRollback(&_Challenge.TransactOpts) +} + +// SetRollback is a paid mutator transaction binding the contract method 0x631acced. +// +// Solidity: function setRollback() returns() +func (_Challenge *ChallengeTransactorSession) SetRollback() (*types.Transaction, error) { + return _Challenge.Contract.SetRollback(&_Challenge.TransactOpts) +} + +// Timeout is a paid mutator transaction binding the contract method 0x70dea79a. +// +// Solidity: function timeout() returns() +func (_Challenge *ChallengeTransactor) Timeout(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Challenge.contract.Transact(opts, "timeout") +} + +// Timeout is a paid mutator transaction binding the contract method 0x70dea79a. +// +// Solidity: function timeout() returns() +func (_Challenge *ChallengeSession) Timeout() (*types.Transaction, error) { + return _Challenge.Contract.Timeout(&_Challenge.TransactOpts) +} + +// Timeout is a paid mutator transaction binding the contract method 0x70dea79a. +// +// Solidity: function timeout() returns() +func (_Challenge *ChallengeTransactorSession) Timeout() (*types.Transaction, error) { + return _Challenge.Contract.Timeout(&_Challenge.TransactOpts) +} + +// VerifyOneStepProof is a paid mutator transaction binding the contract method 0xf03a7fcb. +// +// Solidity: function verifyOneStepProof((address,uint256,uint256,address,(uint64,uint256,uint64,address,uint256,bytes,uint256,uint256,uint256),bytes32,bytes32) ctx, uint8 verifyType, bytes proof, uint256 challengedStepIndex, uint256 prevChallengedSegmentStart, uint256 prevChallengedSegmentLength) returns() +func (_Challenge *ChallengeTransactor) VerifyOneStepProof(opts *bind.TransactOpts, ctx VerificationContextContext, verifyType uint8, proof []byte, challengedStepIndex *big.Int, prevChallengedSegmentStart *big.Int, prevChallengedSegmentLength *big.Int) (*types.Transaction, error) { + return _Challenge.contract.Transact(opts, "verifyOneStepProof", ctx, verifyType, proof, challengedStepIndex, prevChallengedSegmentStart, prevChallengedSegmentLength) +} + +// VerifyOneStepProof is a paid mutator transaction binding the contract method 0xf03a7fcb. +// +// Solidity: function verifyOneStepProof((address,uint256,uint256,address,(uint64,uint256,uint64,address,uint256,bytes,uint256,uint256,uint256),bytes32,bytes32) ctx, uint8 verifyType, bytes proof, uint256 challengedStepIndex, uint256 prevChallengedSegmentStart, uint256 prevChallengedSegmentLength) returns() +func (_Challenge *ChallengeSession) VerifyOneStepProof(ctx VerificationContextContext, verifyType uint8, proof []byte, challengedStepIndex *big.Int, prevChallengedSegmentStart *big.Int, prevChallengedSegmentLength *big.Int) (*types.Transaction, error) { + return _Challenge.Contract.VerifyOneStepProof(&_Challenge.TransactOpts, ctx, verifyType, proof, challengedStepIndex, prevChallengedSegmentStart, prevChallengedSegmentLength) +} + +// VerifyOneStepProof is a paid mutator transaction binding the contract method 0xf03a7fcb. +// +// Solidity: function verifyOneStepProof((address,uint256,uint256,address,(uint64,uint256,uint64,address,uint256,bytes,uint256,uint256,uint256),bytes32,bytes32) ctx, uint8 verifyType, bytes proof, uint256 challengedStepIndex, uint256 prevChallengedSegmentStart, uint256 prevChallengedSegmentLength) returns() +func (_Challenge *ChallengeTransactorSession) VerifyOneStepProof(ctx VerificationContextContext, verifyType uint8, proof []byte, challengedStepIndex *big.Int, prevChallengedSegmentStart *big.Int, prevChallengedSegmentLength *big.Int) (*types.Transaction, error) { + return _Challenge.Contract.VerifyOneStepProof(&_Challenge.TransactOpts, ctx, verifyType, proof, challengedStepIndex, prevChallengedSegmentStart, prevChallengedSegmentLength) +} + +// ChallengeBisectedIterator is returned from FilterBisected and is used to iterate over the raw logs and unpacked data for Bisected events raised by the Challenge contract. +type ChallengeBisectedIterator struct { + Event *ChallengeBisected // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *ChallengeBisectedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(ChallengeBisected) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(ChallengeBisected) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *ChallengeBisectedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *ChallengeBisectedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// ChallengeBisected represents a Bisected event raised by the Challenge contract. +type ChallengeBisected struct { + StartState [32]byte + MidState [32]byte + EndState [32]byte + BlockNum *big.Int + BlockTime *big.Int + ChallengedSegmentStart *big.Int + ChallengedSegmentLength *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterBisected is a free log retrieval operation binding the contract event 0x71809f4d4f7bf3c208a85ccd3c922c984024f8e3cef51e3d03ae677e4217097d. +// +// Solidity: event Bisected(bytes32 startState, bytes32 midState, bytes32 endState, uint256 blockNum, uint256 blockTime, uint256 challengedSegmentStart, uint256 challengedSegmentLength) +func (_Challenge *ChallengeFilterer) FilterBisected(opts *bind.FilterOpts) (*ChallengeBisectedIterator, error) { + + logs, sub, err := _Challenge.contract.FilterLogs(opts, "Bisected") + if err != nil { + return nil, err + } + return &ChallengeBisectedIterator{contract: _Challenge.contract, event: "Bisected", logs: logs, sub: sub}, nil +} + +// WatchBisected is a free log subscription operation binding the contract event 0x71809f4d4f7bf3c208a85ccd3c922c984024f8e3cef51e3d03ae677e4217097d. +// +// Solidity: event Bisected(bytes32 startState, bytes32 midState, bytes32 endState, uint256 blockNum, uint256 blockTime, uint256 challengedSegmentStart, uint256 challengedSegmentLength) +func (_Challenge *ChallengeFilterer) WatchBisected(opts *bind.WatchOpts, sink chan<- *ChallengeBisected) (event.Subscription, error) { + + logs, sub, err := _Challenge.contract.WatchLogs(opts, "Bisected") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(ChallengeBisected) + if err := _Challenge.contract.UnpackLog(event, "Bisected", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseBisected is a log parse operation binding the contract event 0x71809f4d4f7bf3c208a85ccd3c922c984024f8e3cef51e3d03ae677e4217097d. +// +// Solidity: event Bisected(bytes32 startState, bytes32 midState, bytes32 endState, uint256 blockNum, uint256 blockTime, uint256 challengedSegmentStart, uint256 challengedSegmentLength) +func (_Challenge *ChallengeFilterer) ParseBisected(log types.Log) (*ChallengeBisected, error) { + event := new(ChallengeBisected) + if err := _Challenge.contract.UnpackLog(event, "Bisected", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// ChallengeChallengeCompletedIterator is returned from FilterChallengeCompleted and is used to iterate over the raw logs and unpacked data for ChallengeCompleted events raised by the Challenge contract. +type ChallengeChallengeCompletedIterator struct { + Event *ChallengeChallengeCompleted // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *ChallengeChallengeCompletedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(ChallengeChallengeCompleted) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(ChallengeChallengeCompleted) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *ChallengeChallengeCompletedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *ChallengeChallengeCompletedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// ChallengeChallengeCompleted represents a ChallengeCompleted event raised by the Challenge contract. +type ChallengeChallengeCompleted struct { + Winner common.Address + Loser common.Address + Reason uint8 + Raw types.Log // Blockchain specific contextual infos +} + +// FilterChallengeCompleted is a free log retrieval operation binding the contract event 0x03f929a9a6b1f0aef5e43cb12b56f862da97ec3de3fda02a52e85f9f3974fb6a. +// +// Solidity: event ChallengeCompleted(address winner, address loser, uint8 reason) +func (_Challenge *ChallengeFilterer) FilterChallengeCompleted(opts *bind.FilterOpts) (*ChallengeChallengeCompletedIterator, error) { + + logs, sub, err := _Challenge.contract.FilterLogs(opts, "ChallengeCompleted") + if err != nil { + return nil, err + } + return &ChallengeChallengeCompletedIterator{contract: _Challenge.contract, event: "ChallengeCompleted", logs: logs, sub: sub}, nil +} + +// WatchChallengeCompleted is a free log subscription operation binding the contract event 0x03f929a9a6b1f0aef5e43cb12b56f862da97ec3de3fda02a52e85f9f3974fb6a. +// +// Solidity: event ChallengeCompleted(address winner, address loser, uint8 reason) +func (_Challenge *ChallengeFilterer) WatchChallengeCompleted(opts *bind.WatchOpts, sink chan<- *ChallengeChallengeCompleted) (event.Subscription, error) { + + logs, sub, err := _Challenge.contract.WatchLogs(opts, "ChallengeCompleted") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(ChallengeChallengeCompleted) + if err := _Challenge.contract.UnpackLog(event, "ChallengeCompleted", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseChallengeCompleted is a log parse operation binding the contract event 0x03f929a9a6b1f0aef5e43cb12b56f862da97ec3de3fda02a52e85f9f3974fb6a. +// +// Solidity: event ChallengeCompleted(address winner, address loser, uint8 reason) +func (_Challenge *ChallengeFilterer) ParseChallengeCompleted(log types.Log) (*ChallengeChallengeCompleted, error) { + event := new(ChallengeChallengeCompleted) + if err := _Challenge.contract.UnpackLog(event, "ChallengeCompleted", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} diff --git a/tss/common/types.go b/tss/common/types.go index 15df15114..ffb5db02a 100644 --- a/tss/common/types.go +++ b/tss/common/types.go @@ -15,6 +15,7 @@ const ( AskSlash Method = "askSlash" SignSlash Method = "signSlash" SignRollBack Method = "signRollBack" + AskRollBack Method = "askRollBack" SlashTypeLiveness byte = 1 SlashTypeCulprit byte = 2 @@ -27,8 +28,10 @@ func (m Method) String() string { } type SignStateRequest struct { + Type uint64 `json:"type"` StartBlock string `json:"start_block"` OffsetStartsAtIndex string `json:"offset_starts_at_index"` + Challenge string `json:"challenge"` StateRoots [][32]byte `json:"state_roots"` ElectionId uint64 `json:"election_id"` } diff --git a/tss/manager/manage.go b/tss/manager/manage.go index 05fbd34ad..39d73ac85 100644 --- a/tss/manager/manage.go +++ b/tss/manager/manage.go @@ -252,6 +252,60 @@ func (m Manager) SignStateBatch(request tss.SignStateRequest) ([]byte, error) { return responseBytes, nil } +func (m Manager) SignRollBack(request tss.SignStateRequest) ([]byte, error) { + log.Info("received roll back request", "request", request.String()) + + tssInfo, err := m.tssQueryService.QueryActiveInfo() + if err != nil { + return nil, err + } + availableNodes := m.availableNodes(tssInfo.TssMembers) + if len(availableNodes) < tssInfo.Threshold+1 { + return nil, errors.New("not enough available nodes to sign state") + } + + ctx := types.NewContext(). + WithAvailableNodes(availableNodes). + WithTssInfo(tssInfo). + WithRequestId(randomRequestId()). + WithElectionId(tssInfo.ElectionId) + + // ask tss nodes for the agreement + ctx, err = m.agreement(ctx, request, tss.AskRollBack) + if err != nil { + return nil, err + } + + if len(ctx.Approvers()) < ctx.TssInfos().Threshold+1 { + return nil, errors.New("failed to sign roll back, not enough approvals from tss nodes") + } + + var resp tss.SignResponse + + startBlock, _ := new(big.Int).SetString(request.StartBlock, 10) + rollBackRequest := tss.RollBackRequest{StartBlock: request.StartBlock} + rollBackBz, err := tss.RollBackHash(startBlock) + if err != nil { + return nil, err + } + resp, _, err = m.sign(ctx, rollBackRequest, rollBackBz, tss.SignRollBack) + + if err != nil { + return nil, err + } + + response := tss.BatchSubmitterResponse{ + Signature: resp.Signature, + RollBack: true, + } + responseBytes, err := json.Marshal(response) + if err != nil { + log.Error("batch submitter response failed to marshal !") + return nil, err + } + return responseBytes, nil +} + func (m Manager) SignTxBatch() error { return errors.New("not support for now") } diff --git a/tss/manager/router/registry.go b/tss/manager/router/registry.go index a71e2433e..8fd6bf416 100644 --- a/tss/manager/router/registry.go +++ b/tss/manager/router/registry.go @@ -43,13 +43,22 @@ func (registry *Registry) SignStateHandler() gin.HandlerFunc { c.JSON(http.StatusBadRequest, errors.New("wrong OffsetStartsAtIndex, can not be converted to number")) return } - signature, err := registry.signService.SignStateBatch(request) + var signature []byte + var err error + if request.Type == 0 { + signature, err = registry.signService.SignStateBatch(request) + } else if request.Type == 1 { + if !common.IsHexAddress(request.Challenge) { + c.JSON(http.StatusBadRequest, errors.New("wrong challenge address, can not be converted to hex address")) + return + } + signature, err = registry.signService.SignRollBack(request) + } if err != nil { c.String(http.StatusInternalServerError, "failed to sign state") log.Error("failed to sign state", "error", err) return } - if _, err = c.Writer.Write(signature); err != nil { log.Error("failed to write signature to response writer", "error", err) } diff --git a/tss/manager/types/interface.go b/tss/manager/types/interface.go index a697f3117..9826e0f81 100644 --- a/tss/manager/types/interface.go +++ b/tss/manager/types/interface.go @@ -9,6 +9,7 @@ import ( type SignService interface { SignStateBatch(request tss.SignStateRequest) ([]byte, error) + SignRollBack(request tss.SignStateRequest) ([]byte, error) SignTxBatch() error } diff --git a/tss/node/signer/deal_msg.go b/tss/node/signer/deal_msg.go index fc06ef488..b71a5b08e 100644 --- a/tss/node/signer/deal_msg.go +++ b/tss/node/signer/deal_msg.go @@ -2,6 +2,7 @@ package signer import ( "errors" + "github.com/mantlenetworkio/mantle/tss/common" tdtypes "github.com/tendermint/tendermint/rpc/jsonrpc/types" tmtypes "github.com/tendermint/tendermint/rpc/jsonrpc/types" @@ -47,9 +48,13 @@ func (p *Processor) ProcessMessage() { logger.Err(err).Msg("failed to write msg to sign slash channel,channel blocked") } } else if rpcReq.Method == common.SignRollBack.String() { - if err := p.writeChan(p.signRollBachChan, rpcReq); err != nil { + if err := p.writeChan(p.signRollBackChan, rpcReq); err != nil { logger.Err(err).Msg("failed to write msg to sign roll back channel,channel blocked") } + } else if rpcReq.Method == common.AskRollBack.String() { + if err := p.writeChan(p.askRollBackChan, rpcReq); err != nil { + logger.Err(err).Msg("failed to write msg to ask roll back channel,channel blocked") + } } else { logger.Error().Msgf("unknown rpc request method : %s ", rpcReq.Method) } diff --git a/tss/node/signer/delete_slash.go b/tss/node/signer/delete_slash.go index 9ff325420..32dc7bda1 100644 --- a/tss/node/signer/delete_slash.go +++ b/tss/node/signer/delete_slash.go @@ -2,12 +2,12 @@ package signer import ( "context" + "math/big" + "time" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/mantlenetworkio/mantle/l2geth/log" "github.com/mantlenetworkio/mantle/tss/slash" - "math/big" - "time" ) func (p *Processor) deleteSlashing() { diff --git a/tss/node/signer/dial_le_client.go b/tss/node/signer/dial_le_client.go index 5260a810b..a4966c5fe 100644 --- a/tss/node/signer/dial_le_client.go +++ b/tss/node/signer/dial_le_client.go @@ -3,12 +3,13 @@ package signer import ( "context" "crypto/tls" + "net/http" + "strings" + "github.com/mantlenetworkio/mantle/bss-core/dial" "github.com/mantlenetworkio/mantle/l2geth/ethclient" "github.com/mantlenetworkio/mantle/l2geth/log" "github.com/mantlenetworkio/mantle/l2geth/rpc" - "net/http" - "strings" ) // DialL2EthClientWithTimeout attempts to dial the L2 provider using the diff --git a/tss/node/signer/keygen.go b/tss/node/signer/keygen.go index 7cb04cd3b..7a87c5f14 100644 --- a/tss/node/signer/keygen.go +++ b/tss/node/signer/keygen.go @@ -4,6 +4,10 @@ import ( "context" "encoding/json" "errors" + "math/big" + "strings" + "time" + "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -16,10 +20,6 @@ import ( "github.com/mantlenetworkio/mantle/tss/node/tsslib/common" "github.com/mantlenetworkio/mantle/tss/node/tsslib/keygen" tdtypes "github.com/tendermint/tendermint/rpc/jsonrpc/types" - "math/big" - "strings" - - "time" ) const ( diff --git a/tss/node/signer/process.go b/tss/node/signer/process.go index ad8d2992c..e32639a63 100644 --- a/tss/node/signer/process.go +++ b/tss/node/signer/process.go @@ -4,26 +4,23 @@ import ( "context" "crypto/ecdsa" "math/big" + "sync" + "time" ethc "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethclient" "github.com/mantlenetworkio/mantle/bss-core/dial" l2ethclient "github.com/mantlenetworkio/mantle/l2geth/ethclient" "github.com/mantlenetworkio/mantle/tss/bindings/tsh" "github.com/mantlenetworkio/mantle/tss/common" "github.com/mantlenetworkio/mantle/tss/manager/l1chain" managertypes "github.com/mantlenetworkio/mantle/tss/manager/types" - - "time" - - "github.com/ethereum/go-ethereum/ethclient" "github.com/mantlenetworkio/mantle/tss/node/tsslib" "github.com/mantlenetworkio/mantle/tss/node/types" "github.com/mantlenetworkio/mantle/tss/ws/client" "github.com/rs/zerolog" "github.com/rs/zerolog/log" tdtypes "github.com/tendermint/tendermint/rpc/jsonrpc/types" - - "sync" ) type Processor struct { @@ -45,7 +42,8 @@ type Processor struct { askSlashChan chan tdtypes.RPCRequest signSlashChan chan tdtypes.RPCRequest keygenRequestChan chan tdtypes.RPCRequest - signRollBachChan chan tdtypes.RPCRequest + askRollBackChan chan tdtypes.RPCRequest + signRollBackChan chan tdtypes.RPCRequest waitSignLock *sync.RWMutex waitSignMsgs map[string]common.SignStateRequest waitSignSlashLock *sync.RWMutex @@ -119,7 +117,8 @@ func NewProcessor(cfg common.Configuration, contx context.Context, tssInstance t askSlashChan: make(chan tdtypes.RPCRequest, 1), signSlashChan: make(chan tdtypes.RPCRequest, 1), keygenRequestChan: make(chan tdtypes.RPCRequest, 1), - signRollBachChan: make(chan tdtypes.RPCRequest, 1), + askRollBackChan: make(chan tdtypes.RPCRequest, 1), + signRollBackChan: make(chan tdtypes.RPCRequest, 1), waitSignLock: &sync.RWMutex{}, waitSignMsgs: make(map[string]common.SignStateRequest), waitSignSlashLock: &sync.RWMutex{}, @@ -143,7 +142,7 @@ func NewProcessor(cfg common.Configuration, contx context.Context, tssInstance t func (p *Processor) Start() { p.logger.Info().Msg("Signer is starting") - p.wg.Add(8) + p.wg.Add(9) p.run() } @@ -167,4 +166,5 @@ func (p *Processor) run() { go p.Keygen() go p.deleteSlashing() go p.SignRollBack() + go p.VerifyRollBack() } diff --git a/tss/node/signer/sign_rollback.go b/tss/node/signer/sign_rollback.go index a0ba32aa4..c2678b870 100644 --- a/tss/node/signer/sign_rollback.go +++ b/tss/node/signer/sign_rollback.go @@ -24,7 +24,7 @@ func (p *Processor) SignRollBack() { select { case <-p.stopChan: return - case req := <-p.signRollBachChan: + case req := <-p.signRollBackChan: var resId = req.ID.(tdtypes.JSONRPCStringID).String() logger.Info().Msgf("dealing resId (%s) ", resId) diff --git a/tss/node/signer/sign_slash.go b/tss/node/signer/sign_slash.go index aaf3109ed..7d42ff148 100644 --- a/tss/node/signer/sign_slash.go +++ b/tss/node/signer/sign_slash.go @@ -8,11 +8,10 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/rs/zerolog" - ethc "github.com/ethereum/go-ethereum/common" "github.com/mantlenetworkio/mantle/tss/bindings/tsh" tsscommon "github.com/mantlenetworkio/mantle/tss/common" + "github.com/rs/zerolog" tdtypes "github.com/tendermint/tendermint/rpc/jsonrpc/types" ) diff --git a/tss/node/signer/verify.go b/tss/node/signer/verify.go index b33c06c09..f73b42a55 100644 --- a/tss/node/signer/verify.go +++ b/tss/node/signer/verify.go @@ -5,10 +5,12 @@ import ( "math/big" "sync" + "github.com/rs/zerolog" + "github.com/mantlenetworkio/mantle/l2geth/common/hexutil" "github.com/mantlenetworkio/mantle/l2geth/core/types" "github.com/mantlenetworkio/mantle/tss/common" - "github.com/rs/zerolog" + tdtypes "github.com/tendermint/tendermint/rpc/jsonrpc/types" ) diff --git a/tss/node/signer/verify_rollback.go b/tss/node/signer/verify_rollback.go new file mode 100644 index 000000000..5a4ce570b --- /dev/null +++ b/tss/node/signer/verify_rollback.go @@ -0,0 +1,88 @@ +package signer + +import ( + "context" + "encoding/json" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + ethcommon "github.com/ethereum/go-ethereum/common" + + bindings "github.com/mantlenetworkio/mantle/tss/bindings/fp" + "github.com/mantlenetworkio/mantle/tss/common" + tdtypes "github.com/tendermint/tendermint/rpc/jsonrpc/types" +) + +func (p *Processor) VerifyRollBack() { + defer p.wg.Done() + logger := p.logger.With().Str("step", "verify slash event").Logger() + logger.Info().Msg("start to verify slash events ") + + go func() { + defer func() { + logger.Info().Msg("exit verify slash event process") + }() + for { + select { + case <-p.stopChan: + return + case req := <-p.askRollBackChan: + var RpcResponse tdtypes.RPCResponse + + var resId = req.ID + + ret, err := p.doVerify(req) + + if err != nil { + logger.Error().Msgf("failed to do verify for rollback, %s", err.Error()) + RpcResponse = tdtypes.NewRPCErrorResponse(req.ID, 201, "failed to do verify for rollback ", err.Error()) + p.wsClient.SendMsg(RpcResponse) + continue + } + askResponse := common.AskResponse{ + Result: ret, + } + RpcResponse = tdtypes.NewRPCSuccessResponse(resId, askResponse) + p.wsClient.SendMsg(RpcResponse) + } + } + }() + +} + +func (p *Processor) doVerify(req tdtypes.RPCRequest) (bool, error) { + var askRequest common.SignStateRequest + if err := json.Unmarshal(req.Params, &askRequest); err != nil { + return false, err + } + + challengeAddr := ethcommon.HexToAddress(askRequest.Challenge) + challengeContract, err := bindings.NewChallenge(challengeAddr, p.l1Client) + if err != nil { + return false, err + } + winner, err := challengeContract.Winner(&bind.CallOpts{ + Context: context.Background(), + }) + if err != nil { + return false, err + } + defender, err := challengeContract.Defender(&bind.CallOpts{ + Context: context.Background(), + }) + if err != nil { + return false, err + } + rollback, err := challengeContract.Rollback(&bind.CallOpts{ + Context: context.Background(), + }) + if err != nil { + return false, err + } + + if winner.String() == defender.String() && !rollback { + return true, nil + } else { + return false, nil + } + +} diff --git a/tss/node/signer/verify_slash.go b/tss/node/signer/verify_slash.go index 33edf4709..99079f375 100644 --- a/tss/node/signer/verify_slash.go +++ b/tss/node/signer/verify_slash.go @@ -3,6 +3,7 @@ package signer import ( "bytes" "encoding/json" + "github.com/mantlenetworkio/mantle/tss/common" tdtypes "github.com/tendermint/tendermint/rpc/jsonrpc/types" ) diff --git a/yarn.lock b/yarn.lock index 907654548..5bf4e9a17 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4275,6 +4275,11 @@ ansi-colors@4.1.1, ansi-colors@^4.1.1: resolved "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz" integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== +ansi-colors@^4.1.0: + version "4.1.3" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.3.tgz#37611340eb2243e70cc604cad35d63270d48781b" + integrity sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw== + ansi-escapes@^3.1.0, ansi-escapes@^3.2.0: version "3.2.0" resolved "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz" @@ -7008,6 +7013,16 @@ delegates@^1.0.0: resolved "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz" integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= +delete-empty@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/delete-empty/-/delete-empty-3.0.0.tgz#f8040f2669f26fa7060bc2304e9859c593b685e8" + integrity sha512-ZUyiwo76W+DYnKsL3Kim6M/UOavPdBJgDYWOmuQhYaZvJH0AXAHbUNyEDtRbBra8wqqr686+63/0azfEk1ebUQ== + dependencies: + ansi-colors "^4.1.0" + minimist "^1.2.0" + path-starts-with "^2.0.0" + rimraf "^2.6.2" + depcheck@^1.4.3: version "1.4.3" resolved "https://registry.npmjs.org/depcheck/-/depcheck-1.4.3.tgz" @@ -9756,6 +9771,14 @@ hard-rejection@^2.1.0: resolved "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz" integrity sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA== +hardhat-abi-exporter@^2.10.0: + version "2.10.1" + resolved "https://registry.yarnpkg.com/hardhat-abi-exporter/-/hardhat-abi-exporter-2.10.1.tgz#b14884e233c73fe3f43360f014ad7fd6df4b6d25" + integrity sha512-X8GRxUTtebMAd2k4fcPyVnCdPa6dYK4lBsrwzKP5yiSq4i+WadWPIumaLfce53TUf/o2TnLpLOduyO1ylE2NHQ== + dependencies: + "@ethersproject/abi" "^5.5.0" + delete-empty "^3.0.0" + hardhat-deploy@^0.11.10, hardhat-deploy@^0.11.4: version "0.11.10" resolved "https://registry.npmjs.org/hardhat-deploy/-/hardhat-deploy-0.11.10.tgz" @@ -14100,6 +14123,11 @@ path-parse@^1.0.6, path-parse@^1.0.7: resolved "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== +path-starts-with@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/path-starts-with/-/path-starts-with-2.0.0.tgz#ffd6d51926cd497022b44d392196033d5451892f" + integrity sha512-3UHTHbJz5+NLkPafFR+2ycJOjoc4WV2e9qCZCnm71zHiWaFrm1XniLVTkZXvaRgxr1xFh9JsTdicpH2yM03nLA== + path-to-regexp@0.1.7: version "0.1.7" resolved "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz" @@ -15369,7 +15397,7 @@ rimraf@2.6.3: dependencies: glob "^7.1.3" -rimraf@^2.2.8, rimraf@^2.6.3: +rimraf@^2.2.8, rimraf@^2.6.2, rimraf@^2.6.3: version "2.7.1" resolved "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz" integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==