diff --git a/consensus/dbft/dbft.go b/consensus/dbft/dbft.go index 1f9528197b..b2a4b3da0b 100644 --- a/consensus/dbft/dbft.go +++ b/consensus/dbft/dbft.go @@ -25,16 +25,15 @@ import ( "errors" "fmt" "io" - "math" "math/big" "sort" "sync" "sync/atomic" "time" - "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/common/lru" "github.com/ethereum/go-ethereum/consensus" "github.com/ethereum/go-ethereum/consensus/dbft/dbftutil" "github.com/ethereum/go-ethereum/consensus/misc" @@ -81,6 +80,11 @@ const ( // msgsChCap is a capacity of channel that accepts consensus messages from // dBFT protocol. msgsChCap = 100 + // validatorsCacheCap is a capacity of validators cache. It's enough to store + // validators for only three potentially subsequent heights, i.e. three latest + // blocks to effectivaly verify dBFT payloads travelling through the network and + // properly initialize dBFT at the latest height. + validatorsCacheCap = 3 ) // Various error messages to mark blocks invalid. These should be private to @@ -194,12 +198,11 @@ type DBFT struct { // lastTimestamp, lastIndex and lastBlockHash are updated on every new header // received from dBFT or from chain. These fields have exactly those type // that Eth offers, thus, they need to be converted before feeding to dBFT. - lastTimestamp uint64 // in seconds, like Eth requires. - lastIndex uint64 - lastBlockHash common.Hash - lastBlockSealHash common.Hash - lastBlockExtra []byte - lastBlockNextNextConsensus common.Hash // ready-to-use NextConsensus field for the next accepted block. + lastTimestamp uint64 // in seconds, like Eth requires. + lastIndex uint64 + lastBlockHash common.Hash + lastBlockSealHash common.Hash + lastBlockExtra []byte // lastProposal holds the latest proposal submitted to dBFT by miner. It is updated // irrespectively and concurrently to dBFT process, thus, access should be protected @@ -219,8 +222,8 @@ type DBFT struct { finished chan struct{} // various native contract APIs that dBFT uses. - ethAPI *ethapi.BlockChainAPI - governanceABI abi.ABI + ethAPI *ethapi.BlockChainAPI + validatorsCache *lru.Cache[uint64, []common.Address] // The fields below are for testing only fakeDiff bool // Skip difficulty verifications @@ -253,6 +256,8 @@ func New(config *params.DBFTConfig, _ ethdb.Database) (*DBFT, error) { quit: make(chan struct{}), finished: make(chan struct{}), + + validatorsCache: lru.NewCache[uint64, []common.Address](validatorsCacheCap), } logger, _ := zap.NewDevelopment() @@ -301,7 +306,7 @@ func New(config *params.DBFTConfig, _ ethdb.Database) (*DBFT, error) { // getValidators with empty args is used by dbft to fill the list of // block's validators, thus should return validators from the current // epoch without recalculation. - pKeys, err = c.getNextBlockValidators(c.lastBlockHash, c.lastIndex, false) + pKeys, err = c.getValidators(&c.lastIndex, nil, nil) } // getValidators with non-empty args is used by dbft to fill block's // NextConsensus field, but DBFT doesn't provide WithGetConsensusAddress @@ -340,10 +345,6 @@ func New(config *params.DBFTConfig, _ ethdb.Database) (*DBFT, error) { log.Warn("error on enqueue block", "error", err.Error()) } } - - // After that, update last block cached information. Do not reset sealing - // proposal, it will be done once new block arrives to eventLoop. - c.postBlock(res) }), dbft.WithNewBlockFromContext(func(ctx *dbft.Context) block.Block { prepareReq := ctx.PreparationPayloads[ctx.PrimaryIndex] @@ -420,42 +421,43 @@ func New(config *params.DBFTConfig, _ ethdb.Database) (*DBFT, error) { panic("bug: sealing proposal is not initialized") } - // NextConsensus -> MixHash - c.sealingProposal.MixDigest = c.lastBlockNextNextConsensus - - // Recalculate block state provided by miner and update sealing proposal if CV happened and context-related + // Recalculate block state provided by miner and update sealing proposal if context-related // block fields were changed. - if c.dbft.Context.ViewNumber != 0 { - dbftBlock := c.newBlockFromContext(c.sealingProposal) - dbftBlock.transactions = c.sealingTransactions - ethBlock := dbftBlock.ToEthBlock() + dbftBlock := c.newBlockFromContext(c.sealingProposal) + dbftBlock.transactions = c.sealingTransactions + ethBlock := dbftBlock.ToEthBlock() - state, receipts, _, _, err := c.chain.ProcessState(ethBlock) - if err != nil { - log.Crit("failed to process state from proposal", - "err", err, - "number", ethBlock.NumberU64(), - "seal hash", c.SealHash(ethBlock.Header()), - "parent hash", ethBlock.ParentHash().String(), - "intermediate merkle root", ethBlock.Root(), - "coinbase", ethBlock.Coinbase().String(), - "gas limit", ethBlock.GasLimit(), - "gas used", ethBlock.GasUsed(), - "difficulty", ethBlock.Difficulty().String(), - "mix digest", ethBlock.MixDigest().String(), - "nonce", ethBlock.Nonce(), - "time", ethBlock.Time(), - "uncle hash", ethBlock.UncleHash().String(), - "txs", len(ethBlock.Transactions())) - } - b, err := c.FinalizeAndAssemble(c.chain, dbftBlock.header, state, dbftBlock.transactions, nil, receipts, dbftBlock.withdrawals) - if err != nil { - log.Crit("failed to finalize and assemble proposal", - "err", err) - } + state, _, _, _, err := c.chain.ProcessState(ethBlock) + if err != nil { + log.Crit("failed to process state from proposal", + "err", err, + "number", ethBlock.NumberU64(), + "seal hash", c.SealHash(ethBlock.Header()), + "parent hash", ethBlock.ParentHash().String(), + "intermediate merkle root", ethBlock.Root(), + "coinbase", ethBlock.Coinbase().String(), + "gas limit", ethBlock.GasLimit(), + "gas used", ethBlock.GasUsed(), + "difficulty", ethBlock.Difficulty().String(), + "mix digest", ethBlock.MixDigest().String(), + "nonce", ethBlock.Nonce(), + "time", ethBlock.Time(), + "uncle hash", ethBlock.UncleHash().String(), + "txs", len(ethBlock.Transactions())) + } - c.sealingProposal = b.Header() + header := ethBlock.Header() + header.Root = state.IntermediateRoot(c.chain.Config().IsEIP158(header.Number)) + + c.sealingProposal = header + + // Fill NextConsensus based on the currently accepting block state and update MixDigest. + nextVals, err := c.getValidators(nil, state, c.sealingProposal) + if err != nil { + log.Crit("Failed to compute next block validators", + "err", err) } + c.sealingProposal.MixDigest = dbftutil.GetNextConsensusHash(nextVals) // Fill in only proposal and last block info, transactions will be properly // set from context later in SetTransactionHashes callback. @@ -476,11 +478,8 @@ func New(config *params.DBFTConfig, _ ethdb.Database) (*DBFT, error) { if req.SealingProposal == nil { return errors.New("failed to verify PrepareRequest: sealing proposal is nil") } - // Verify MixDigest separately from header verification below since header verification - // doesn't check the correctness of NextConsensus wrt storage state. - if req.SealingProposal.MixDigest != c.lastBlockNextNextConsensus { - return fmt.Errorf("invalid MixDigest (NextConsensus): expected %s, got %s", c.lastBlockNextNextConsensus, req.SealingProposal.MixDigest) - } + // Do not verify MixDigest since it depends on block state and will be verified once all transactions + // are fetched. parent := c.chain.GetBlockByNumber(req.SealingProposal.Number.Uint64() - 1) if parent == nil { return fmt.Errorf("no parent found for height %d", req.SealingProposal.Number.Uint64()-1) @@ -572,6 +571,23 @@ func New(config *params.DBFTConfig, _ ethdb.Database) (*DBFT, error) { "err", err.Error()) return false } + + // Verify NextConsensus based on the state got after in-block transactions processing. Make a + // state copy in order to avoid state modifications potentially made by getValidators call. + // The original state will be committed if block is accepted. + nextVals, err := c.getValidators(nil, state.Copy(), dbftBlock.header) + if err != nil { + log.Crit("Failed to compute next block validators", + "err", err) + } + expectedMixDigest := dbftutil.GetNextConsensusHash(nextVals) + if dbftBlock.header.MixDigest != expectedMixDigest { + log.Warn("Invalid NextConsensus in the proposed block", + "expected", expectedMixDigest.String(), + "actual", dbftBlock.header.MixDigest.String()) + return false + } + dbftBlock.state = state dbftBlock.receipts = receipts @@ -692,14 +708,6 @@ func (c *DBFT) postBlock(b *types.Block) { c.lastBlockExtra = h.Extra c.blockQueue.ClearStaleTasks(b.NumberU64()) - - // Calculate NextConsensus field for the next block based on the accepted lastBlock state. - nextVals, err := c.getNextBlockValidators(c.lastBlockHash, c.lastIndex, true) // always compute as it's NextConsensus. - if err != nil { - log.Crit("failed to compute next block validators", - "err", err.Error()) - } - c.lastBlockNextNextConsensus = dbftutil.GetNextConsensusHash(nextVals) } } @@ -1079,17 +1087,10 @@ func (c *DBFT) Start(chain ChainHeaderWriter) { c.lastBlockHash = currHeader.Hash() c.lastBlockSealHash = HonestSealHash(currHeader) c.lastBlockExtra = currHeader.Extra - nextVals, err := c.getNextBlockValidators(c.lastBlockHash, c.lastIndex, true) // always compute as it's NextConsensus. - if err != nil { - log.Warn("failed to compute next block validators while initializing dBFT", - "err", err.Error()) - return - } - c.lastBlockNextNextConsensus = dbftutil.GetNextConsensusHash(nextVals) // Before consensus start we should wait for initial sealing proposal to be // initialised by miner. Start consensus once we have new sealing work in Seal. - err = c.waitForNewSealingProposal(c.lastIndex+1, false) + err := c.waitForNewSealingProposal(c.lastIndex+1, false) if err != nil { log.Warn("Failed to fetch latest sealing proposal", "index", c.lastIndex+1, @@ -1338,8 +1339,8 @@ func (c *DBFT) OnPayload(cp *dbftproto.Message) error { return nil } - if !c.validatePayload(p) { - log.Info("can't validate payload", "hash", cp.Hash()) + if err := c.validatePayload(p); err != nil { + log.Info("Can't validate payload", "hash", cp.Hash(), "err", err) return nil } @@ -1377,18 +1378,22 @@ func payloadFromMessage(ep *dbftproto.Message) *Payload { } } -func (c *DBFT) validatePayload(p *Payload) bool { - h := c.chain.CurrentBlock() - validators, err := c.getNextBlockValidators(h.Hash(), h.Number.Uint64(), false) +func (c *DBFT) validatePayload(p *Payload) error { + h := c.chain.CurrentBlock().Number.Uint64() + validators, err := c.getValidators(&h, nil, nil) if err != nil { - return false + return fmt.Errorf("failed to get next block validators: %w", err) } if int(p.message.ValidatorIndex) >= len(validators) { - return false + return fmt.Errorf("invalid message validator index: validators count is %d, requested %d", len(validators), p.message.ValidatorIndex) } val := validators[p.message.ValidatorIndex] - return p.Sender == val + if p.Sender != val { + return fmt.Errorf("message sender is not a validator: expected %s, got %s", val, p.Sender) + } + + return nil } func (c *DBFT) newPayload(ctx *dbft.Context, t payload.MessageType, msg any) payload.ConsensusPayload { @@ -1415,7 +1420,8 @@ func (c *DBFT) handleChainBlock(b *types.Block) error { "hash", b.Hash().String(), "parent hash", b.ParentHash().String(), "primary", b.Primary(), - "coinbase", b.Coinbase()) + "coinbase", b.Coinbase(), + "mix digest", b.MixDigest().String()) c.postBlock(b) err := c.waitForNewSealingProposal(c.lastIndex+1, false) @@ -1445,7 +1451,8 @@ func (c *DBFT) CalcDifficulty(chain consensus.ChainHeaderReader, time uint64, pa } func (c *DBFT) calcDifficulty(signer common.Address, parent *types.Header) *big.Int { - vals, err := c.getNextBlockValidators(parent.Hash(), parent.Number.Uint64(), false) + h := parent.Number.Uint64() + vals, err := c.getValidators(&h, nil, nil) if err != nil { return nil } @@ -1589,56 +1596,68 @@ func (c *DBFT) APIs(chain consensus.ChainHeaderReader) []rpc.API { }} } -// getNextBlockValidators returns next block validators that should be set as -// a NextConsensus address for the next block accepted after block with blockHash -// hash and blockNum height (if compute is true). It also returns validators of -// the currently processing blocks to properly initialize dBFT context's Validators -// field (if compute is false). Validators returned from this method are always expected -// to be sorted by bytes order (even if returned from governance contract). -func (c *DBFT) getNextBlockValidators(blockHash common.Hash, blockNum uint64, compute bool) ([]common.Address, error) { - // Currently we don't have governance contract, thus, always return standby set. - if true { - return c.config.StandByValidators, nil - } - +// getValidators returns validators chosen in the result of the latest +// finalized voting epoch. It calls Governance contract under the hood. The call +// is based on the provided state or (if not provided) on the state of the block +// with the specified height. Validators returned from this method are always +// sorted by bytes order (even if the list returned from governance contract is +// sorted in another way). This method uses cached values in case of validators +// requested by block height. +func (c *DBFT) getValidators(blockNum *uint64, state *state.StateDB, header *types.Header) ([]common.Address, error) { if c.ethAPI == nil { return nil, errors.New("eth blockchain API is not initialized, dBFT can't function properly") } - // Once we have governance contract, we don't need StandByValidators in the dBFT's - // config, governance contract will handle it internally. - blockNr := rpc.BlockNumberOrHashWithHash(blockHash, false) + if state == nil && blockNum != nil { + vals, ok := c.validatorsCache.Get(*blockNum) + if ok { + return vals, nil + } + } - // Different values depending on dBFT epoch. - method := "getNextBlockValidators" // current epoch validators - if compute { - method = "computeNextBlockValidators" // current epoch validators for the middle of dBFT epoch and next epoch validators for the last block in epoch + // Perform smart contract call. + method := "getCurrentConsensus" // latest finalized epoch validators. + data, err := systemcontracts.GovernanceABI.Pack(method) + if err != nil { + return nil, fmt.Errorf("failed to pack '%s': %w", method, err) + } + msgData := hexutil.Bytes(data) + gas := hexutil.Uint64(50_000_000) // more than enough for validators call processing. + args := ethapi.TransactionArgs{ + Gas: &gas, + To: &systemcontracts.GovernanceProxyHash, + Data: &msgData, } ctx, cancel := context.WithCancel(context.Background()) - // Cancel when we are finished consuming integers + // Cancel when we are finished consuming integers. defer cancel() - data, err := c.governanceABI.Pack(method) + var result hexutil.Bytes + if state != nil { + result, err = c.ethAPI.CallAtState(ctx, args, state, header) + } else if blockNum != nil { + blockNr := rpc.BlockNumberOrHashWithNumber(rpc.BlockNumber(*blockNum)) + result, err = c.ethAPI.Call(ctx, args, &blockNr, nil, nil) + } else { + return nil, fmt.Errorf("failed to compute validators: both block number and state are nil") + } if err != nil { - log.Error("Unable to pack tx to retrieve next block validators", "error", err) - return nil, err - } - // do smart contract call - msgData := (hexutil.Bytes)(data) - toAddress := common.HexToAddress(systemcontracts.GovernanceContract) - gas := (hexutil.Uint64)(uint64(math.MaxUint64 / 2)) - result, err := c.ethAPI.Call(ctx, ethapi.TransactionArgs{ - Gas: &gas, - To: &toAddress, - Data: &msgData, - }, &blockNr, nil, nil) + return nil, fmt.Errorf("failed to perform '%s' call: %w", method, err) + } + + var res []common.Address + err = systemcontracts.GovernanceABI.UnpackIntoInterface(&res, method, result) if err != nil { - return nil, err + return nil, fmt.Errorf("failed to unpack validators: %w", err) + } + slices.SortFunc(res, common.Address.Cmp) + + // Update cache in case if existing state was used for validators retrieval. + if state == nil && blockNum != nil { + _ = c.validatorsCache.Add(*blockNum, res) } - var valSet []common.Address - err = c.governanceABI.UnpackIntoInterface(&valSet, method, result) - return valSet, err + return res, err } func (c *DBFT) shouldUpdateCommitteeAt(blockNum uint64) bool { diff --git a/core/state_processor.go b/core/state_processor.go index 9e32ab4e56..9a122db13f 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -25,6 +25,7 @@ import ( "github.com/ethereum/go-ethereum/consensus" "github.com/ethereum/go-ethereum/consensus/misc" "github.com/ethereum/go-ethereum/core/state" + "github.com/ethereum/go-ethereum/core/systemcontracts" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/crypto" @@ -79,6 +80,12 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg if beaconRoot := block.BeaconRoot(); beaconRoot != nil { ProcessBeaconBlockRoot(*beaconRoot, vmenv, statedb) } + if p.config.DBFT != nil { + err := ProcessOnPersist(vmenv, statedb) + if err != nil { + return nil, nil, 0, fmt.Errorf("could not apply OnPersist [%v]: %w", block.Hash().Hex(), err) + } + } // Iterate over and process the individual transactions for i, tx := range block.Transactions() { msg, err := TransactionToMessage(tx, signer, header.BaseFee) @@ -189,3 +196,28 @@ func ProcessBeaconBlockRoot(beaconRoot common.Hash, vmenv *vm.EVM, statedb *stat _, _, _ = vmenv.Call(vm.AccountRef(msg.From), *msg.To, msg.Data, 30_000_000, common.U2560) statedb.Finalise(true) } + +// ProcessOnPersist applies a system call to the governance contract. +func ProcessOnPersist(vmenv *vm.EVM, statedb *state.StateDB) error { + data, err := systemcontracts.GovernanceABI.Pack("onPersist") + if err != nil { + return fmt.Errorf("filed to pack onPersist call: %w", err) + } + msg := &Message{ + From: params.SystemAddress, + GasLimit: 30_000_000, + GasPrice: common.Big0, + GasFeeCap: common.Big0, + GasTipCap: common.Big0, + To: &systemcontracts.GovernanceProxyHash, + Data: data, + } + vmenv.Reset(NewEVMTxContext(msg), statedb) + statedb.AddAddressToAccessList(systemcontracts.GovernanceProxyHash) + _, _, err = vmenv.Call(vm.AccountRef(msg.From), *msg.To, msg.Data, 30_000_000, common.U2560) + if err != nil { + return fmt.Errorf("onPersist call failed: %w", err) + } + statedb.Finalise(true) + return nil +} diff --git a/core/systemcontracts/contracts.go b/core/systemcontracts/contracts.go index caf797baf8..2ea4c825f8 100644 --- a/core/systemcontracts/contracts.go +++ b/core/systemcontracts/contracts.go @@ -1,8 +1,29 @@ package systemcontracts +import ( + "fmt" + "strings" + + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" +) + +// governanceABI is an ABI of system governing contract. +const governanceABI = `[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"candidate","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"CandidateWithdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"candidate","type":"address"}],"name":"Exit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"validators","type":"address[]"}],"name":"Persist","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"candidate","type":"address"}],"name":"Register","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"voter","type":"address"},{"indexed":false,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Revoke","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"voter","type":"address"},{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Vote","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"voter","type":"address"},{"indexed":false,"internalType":"uint256","name":"reward","type":"uint256"}],"name":"VoterClaim","type":"event"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"candidateBalanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"candidateGasPerVote","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claimReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"consensusSize","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"currentConsensus","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentEpochStartHeight","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"epochDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"epochStartGasPerVote","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"exitCandidate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"exitHeightOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCandidates","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentConsensus","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"govReward","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minVoteAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"onPersist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"receivedVotes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shareRate","type":"uint256"}],"name":"registerCandidate","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"registerFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"revokeVote","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"scaleFactor","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"shareRateOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"candidateTo","type":"address"}],"name":"vote","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"voteHeight","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"votedAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"votedTo","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"voterGasPerVote","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdrawRegisterFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]` + // A set of genesis contracts. -const ( - // GovernanceContract is a governing contract hash that manages validators +var ( + // GovernanceProxyHash is a governing contract hash that manages validators // voting and rewards. - GovernanceContract = "0x0000000000000000000000000000000000001000" + GovernanceProxyHash = common.HexToAddress("0x1212000000000000000000000000000000000001") + // GovernanceABI is a compiled ABI of Governance contract. + GovernanceABI abi.ABI ) + +func init() { + var err error + GovernanceABI, err = abi.JSON(strings.NewReader(governanceABI)) + if err != nil { + panic(fmt.Errorf("failed to decode Governance contract ABI: %w", err)) + } +} diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index 3bc9bc51f0..7746be33b3 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -1138,6 +1138,14 @@ func DoCall(ctx context.Context, b Backend, args TransactionArgs, blockNrOrHash return doCall(ctx, b, args, state, header, overrides, blockOverrides, timeout, globalGasCap) } +// DoCallAtState executes the given transaction on the specified state with the given header. It's a +// handler for CallAtState and differs from the latter in that it returns the call result as is. +func DoCallAtState(ctx context.Context, b Backend, args TransactionArgs, state *state.StateDB, header *types.Header, overrides *StateOverride, blockOverrides *BlockOverrides, timeout time.Duration, globalGasCap uint64) (*core.ExecutionResult, error) { + defer func(start time.Time) { log.Debug("Executing EVM call finished", "runtime", time.Since(start)) }(time.Now()) + + return doCall(ctx, b, args, state, header, overrides, blockOverrides, timeout, globalGasCap) +} + // Call executes the given transaction on the state for the given block number. // // Additionally, the caller can specify a batch of contract for fields overriding. @@ -1160,6 +1168,22 @@ func (s *BlockChainAPI) Call(ctx context.Context, args TransactionArgs, blockNrO return result.Return(), result.Err } +// CallAtState executes the given transaction on the specified state with the given header. +// +// Note, this function performs changes in the given state and thus, it's a user's responsibility +// to back up the original state if needed. +func (s *BlockChainAPI) CallAtState(ctx context.Context, args TransactionArgs, state *state.StateDB, header *types.Header) (hexutil.Bytes, error) { + result, err := DoCallAtState(ctx, s.b, args, state, header, nil, nil, s.b.RPCEVMTimeout(), s.b.RPCGasCap()) + if err != nil { + return nil, err + } + // If the result contains a revert reason, try to unpack and return it. + if len(result.Revert()) > 0 { + return nil, newRevertError(result.Revert()) + } + return result.Return(), result.Err +} + // DoEstimateGas returns the lowest possible gas limit that allows the transaction to run // successfully at block `blockNrOrHash`. It returns error if the transaction would revert, or if // there are unexpected failures. The gas limit is capped by both `args.Gas` (if non-nil & diff --git a/miner/worker.go b/miner/worker.go index d405d50827..37a823d5c0 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -977,11 +977,22 @@ func (w *worker) prepareWork(genParams *generateParams) (*environment, error) { log.Error("Failed to create sealing context", "err", err) return nil, err } + var ( + context vm.BlockContext + vmenv *vm.EVM + ) if header.ParentBeaconRoot != nil { - context := core.NewEVMBlockContext(header, w.chain, nil) - vmenv := vm.NewEVM(context, vm.TxContext{}, env.state, w.chainConfig, vm.Config{}) + context = core.NewEVMBlockContext(header, w.chain, nil) + vmenv = vm.NewEVM(context, vm.TxContext{}, env.state, w.chainConfig, vm.Config{}) core.ProcessBeaconBlockRoot(*header.ParentBeaconRoot, vmenv, env.state) } + if w.chain.Config().DBFT != nil { + if vmenv == nil { + context = core.NewEVMBlockContext(header, w.chain, nil) + vmenv = vm.NewEVM(context, vm.TxContext{}, env.state, w.chainConfig, vm.Config{}) + } + core.ProcessOnPersist(vmenv, env.state) + } return env, nil } diff --git a/privnet/seven/genesis_privnet.json b/privnet/seven/genesis_privnet.json index 1fdf3c2a2b..b6d71ff763 100644 --- a/privnet/seven/genesis_privnet.json +++ b/privnet/seven/genesis_privnet.json @@ -26,36 +26,66 @@ "0x26f1794b81df2b832545b8b6bbca196b82e4feb1", "0x0b51369d02e47ee3f143391b837aa08c31aaa19b" ], - "coinbase": "0x1212100000000000000000000000000000000003" + "coinbase": "0x1212000000000000000000000000000000000003" } }, "difficulty": "1", "gasLimit": "30000000", "alloc": { - "74f4effb0b538baec703346b03b6d9292f53a4cd": { "balance": "100000000000000000000000" }, - "910ad1641b7125eff746accdca1f11148b22f472": { "balance": "100000000000000000000" }, - "fef5f250af14df73f983caab7b1f5002189c42e0": { "balance": "100000000000000000000" }, - "c51964013acbc6b271feecb0febd9e7a01202930": { "balance": "100000000000000000000" }, - "c5bbd9652546bc96be3dec97a38ee335f7873dfa": { "balance": "100000000000000000000" }, - "26f1794b81df2b832545b8b6bbca196b82e4feb1": { "balance": "100000000000000000000" }, - "0b51369d02e47ee3f143391b837aa08c31aaa19b": { "balance": "100000000000000000000" }, - "1212100000000000000000000000000000000004": { - "balance": "100000000000000000000000", - "code": "0x608060405234801561001057600080fd5b506004361061012c5760003560e01c8063a1fd836e116100ad578063cf30901211610071578063cf309012146102c3578063de35f5cb146102e7578063e976d431146102fa578063f83d08ba1461030b578063fec95b481461031357600080fd5b8063a1fd836e14610266578063a69df4b51461028c578063aab8ab0c14610294578063b2ca3ec4146102a7578063c34c7882146102ba57600080fd5b80637b259db4116100f45780637b259db4146101f35780638312f149146102125780638406c0791461022f5780638955fe8a1461024a5780638da5cb5b1461025357600080fd5b80630c340a2414610131578063131305e71461016157806335aa2e44146101a257806344c7e2f4146101b5578063504ad4ec146101de575b600080fd5b600554610144906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b61018a61016f3660046111c9565b6008602052600090815260409020546001600160401b031681565b6040516001600160401b039091168152602001610158565b6101446101b03660046111f2565b610327565b6101446101c33660046111c9565b6007602052600090815260409020546001600160a01b031681565b6101f16101ec366004611256565b610351565b005b60035461018a906801000000000000000090046001600160401b031681565b610221670de0b6b3a764000081565b604051908152602001610158565b61014473acc85ffb71f83b9bb264f6d64541926d375a6c1d81565b61022160015481565b600454610144906001600160a01b031681565b60035461027a90600160801b900460ff1681565b60405160ff9091168152602001610158565b6101f161068f565b6101f16102a23660046111c9565b610740565b600654610144906001600160a01b031681565b61022160025481565b6003546102d790600160901b900460ff1681565b6040519015158152602001610158565b60035461018a906001600160401b031681565b61022169021e19e0c9bab240000081565b6101f161094d565b60035461027a90600160881b900460ff1681565b6000818154811061033757600080fd5b6000918252602090912001546001600160a01b0316905081565b3373acc85ffb71f83b9bb264f6d64541926d375a6c1d146103a75760405162461bcd60e51b815260206004820152600b60248201526a2737ba103932b630bcb2b960a91b60448201526064015b60405180910390fd5b600354600160901b900460ff16156103d15760405162461bcd60e51b815260040161039e906112cf565b808061041f5760405162461bcd60e51b815260206004820152601f60248201527f4174206c656173742031206465706f7369742069732072657175697265642e00604482015260640161039e565b600354600160881b900460ff1681111561047b5760405162461bcd60e51b815260206004820152601b60248201527f546f6f206d616e79206465706f736974732070726f76696465642e0000000000604482015260640161039e565b600354610492906001600160401b03166001611311565b6001600160401b0316838360008181106104ae576104ae611338565b90506060020160400160208101906104c691906111c9565b6001600160401b0316146105375760405162461bcd60e51b815260206004820152603260248201527f4f6e6c7920746865206e657874206e6f6e636520697320616c6c6f776564206960448201527137103a3432903334b939ba10383937b7b31760711b606482015260840161039e565b60035461055090849084906001600160401b03166109da565b6105b15760405162461bcd60e51b815260206004820152602c60248201527f546865206e6f6e636573206f66207468652070726f6f6673206d75737420626560448201526b1039bab139b2b8bab2b73a1760a11b606482015260840161039e565b6105bc868686610a6d565b61061e5760405162461bcd60e51b815260206004820152602d60248201527f496e76616c6964206f7220696e73756666696369656e742076616c696461746f60448201526c391039b4b3b730ba3ab932b99760991b606482015260840161039e565b828261062b60018461134e565b81811061063a5761063a611338565b905060600201604001602081019061065291906111c9565b6003805467ffffffffffffffff19166001600160401b03929092169190911790556001805490879055610686818585610cff565b50505050505050565b6005546001600160a01b031633146106d85760405162461bcd60e51b815260206004820152600c60248201526b2737ba1033b7bb32b93737b960a11b604482015260640161039e565b600354600160901b900460ff166107315760405162461bcd60e51b815260206004820152601a60248201527f436f6e747261637420697320616c7265616479206c6f636b6564000000000000604482015260640161039e565b6003805460ff60901b19169055565b600354600160901b900460ff161561076a5760405162461bcd60e51b815260040161039e906112cf565b6001600160401b0380821660009081526007602090815260408083205460089092528220546001600160a01b039091169216908190036107e15760405162461bcd60e51b81526020600482015260126024820152714e6f20636c61696d61626c652066756e647360701b604482015260640161039e565b6001600160a01b03821661082c5760405162461bcd60e51b81526020600482015260126024820152714e6f20636c61696d61626c652066756e647360701b604482015260640161039e565b6001600160401b0383166000908152600860209081526040808320805467ffffffffffffffff191690556007909152812080546001600160a01b031916905561087482610fd7565b90506000836001600160a01b03168260405160006040518083038185875af1925050503d80600081146108c3576040519150601f19603f3d011682016040523d82523d6000602084013e6108c8565b606091505b505090508061090b5760405162461bcd60e51b815260206004820152600f60248201526e151c985b9cd9995c8819985a5b1959608a1b604482015260640161039e565b7fc050de00ef4ba397e08c78836db608d83db9c6335bf95019597119b9536f938985848660405161093e93929190611361565b60405180910390a15050505050565b6006546001600160a01b0316331461099b5760405162461bcd60e51b8152602060048201526011602482015270139bdd081cd958dd5c9a5d1e51dd585c99607a1b604482015260640161039e565b600354600160901b900460ff16156109c55760405162461bcd60e51b815260040161039e906112cf565b6003805460ff60901b1916600160901b179055565b600060015b60ff81168410610a60576109f660ff821684611311565b6001600160401b03168585610a0c60018561138d565b60ff16818110610a1e57610a1e611338565b9050606002016040016020810190610a3691906111c9565b6001600160401b031614610a4e576000915050610a66565b80610a58816113a6565b9150506109df565b50600190505b9392505050565b600354600090600160801b900460ff168214610acb5760405162461bcd60e51b815260206004820152601d60248201527f496e76616c6964206e756d626572206f66207369676e6174757265732e000000604482015260640161039e565b600084604051602001610ae091815260200190565b60408051601f198184030181529082905280516020918201207f19457468657265756d205369676e6564204d6573736167653a0a33320000000091830191909152603c820152605c0160408051808303601f190181528282528051602090910120600580845260c0840190925292506000919081602001602082028036833701905050905060005b6005811015610c3a5736868683818110610b8457610b84611338565b6060029190910191506001905084610b9f60208401846113c5565b604080516000815260208181018084529490945260ff9092168282015291840135606082015290830135608082015260a0016020604051602081039080840390855afa158015610bf3573d6000803e3d6000fd5b50505060206040510351838381518110610c0f57610c0f611338565b6001600160a01b03909216602092830291909101909101525080610c32816113e8565b915050610b68565b5060008080805b6005811015610cef578291505b6007821015610cd05760008281548110610c6a57610c6a611338565b60009182526020909120015485516001600160a01b0390911690869083908110610c9657610c96611338565b60200260200101516001600160a01b031603610cbe5783610cb6816113e8565b945050610cd0565b81610cc8816113e8565b925050610c4e565b610cdb826001611401565b925080610ce7816113e8565b915050610c41565b5050506005149695505050505050565b828160005b81811015610d845736858583818110610d1f57610d1f611338565b90506060020190506000610d61826040016020810190610d3f91906111c9565b610d4f60408501602086016111c9565b610d5c6020860186611414565b610ff7565b9050610d6d858261109c565b945050508080610d7c906113e8565b915050610d04565b506001548214610dce5760405162461bcd60e51b815260206004820152601560248201527424b73b30b634b2103232b837b9b4ba103937b7ba1760591b604482015260640161039e565b60005b81811015610fcf5736858583818110610dec57610dec611338565b60600291909101915060009050610e066020830183611414565b90506001600160a01b0381163b610f57576000610e31610e2c60408501602086016111c9565b610fd7565b90506000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114610e80576040519150601f19603f3d011682016040523d82523d6000602084013e610e85565b606091505b505090508015610eed577f2c20d394553ff35017f1f147d7e3a1ffc1caeaf1e422b5d9730fabe8c90042fe610ec060608601604087016111c9565b610ed060408701602088016111c9565b85604051610ee093929190611361565b60405180910390a1610f50565b610ef684611116565b7fb79dcd48431a0507fde36076107e606e63739e8a604f219cebe9aa0c1f17a115610f2760608601604087016111c9565b610f3760408701602088016111c9565b85604051610f4793929190611361565b60405180910390a15b5050610fba565b610f6082611116565b7fb79dcd48431a0507fde36076107e606e63739e8a604f219cebe9aa0c1f17a115610f9160608401604085016111c9565b610fa160408501602086016111c9565b83604051610fb193929190611361565b60405180910390a15b50508080610fc7906113e8565b915050610dd1565b505050505050565b6000610ff16001600160401b0383166402540be40061143d565b92915050565b6040516001600160c01b031960c085811b8216602084015284901b1660288201526bffffffffffffffffffffffff19606083901b16603082015260009060029060440160408051601f198184030181529082905261105491611454565b602060405180830381855afa158015611071573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906110949190611483565b949350505050565b6000600283836040516020016110bc929190918252602082015260400190565b60408051601f19818403018152908290526110d691611454565b602060405180830381855afa1580156110f3573d6000803e3d6000fd5b5050506040513d601f19601f82011682018060405250810190610a669190611483565b6111236020820182611414565b6007600061113760608501604086016111c9565b6001600160401b03168152602080820192909252604090810160002080546001600160a01b0319166001600160a01b0394909416939093179092556111809183019083016111c9565b6008600061119460608501604086016111c9565b6001600160401b0390811682526020820192909252604001600020805467ffffffffffffffff19169290911691909117905550565b6000602082840312156111db57600080fd5b81356001600160401b0381168114610a6657600080fd5b60006020828403121561120457600080fd5b5035919050565b60008083601f84011261121d57600080fd5b5081356001600160401b0381111561123457600080fd5b60208301915083602060608302850101111561124f57600080fd5b9250929050565b60008060008060006060868803121561126e57600080fd5b8535945060208601356001600160401b038082111561128c57600080fd5b61129889838a0161120b565b909650945060408801359150808211156112b157600080fd5b506112be8882890161120b565b969995985093965092949392505050565b60208082526012908201527110dbdb9d1c9858dd081a5cc81b1bd8dad95960721b604082015260600190565b634e487b7160e01b600052601160045260246000fd5b6001600160401b03818116838216019080821115611331576113316112fb565b5092915050565b634e487b7160e01b600052603260045260246000fd5b81810381811115610ff157610ff16112fb565b6001600160401b0393841681529190921660208201526001600160a01b03909116604082015260600190565b60ff8281168282160390811115610ff157610ff16112fb565b600060ff821660ff81036113bc576113bc6112fb565b60010192915050565b6000602082840312156113d757600080fd5b813560ff81168114610a6657600080fd5b6000600182016113fa576113fa6112fb565b5060010190565b80820180821115610ff157610ff16112fb565b60006020828403121561142657600080fd5b81356001600160a01b0381168114610a6657600080fd5b8082028115828204841417610ff157610ff16112fb565b6000825160005b81811015611475576020818601810151858301520161145b565b506000920191825250919050565b60006020828403121561149557600080fd5b505191905056fea2646970667358221220e02d47f2295ab4356fd494c7d31cea4076fca2f8f702a5ccedfac1b69565502464736f6c63430008120033", + "0x1212000000000000000000000000000000000000": { + "balance": "0", + "code": "0x608060405260043610610212575f3560e01c806370c647d5116101175780639f9d7f811161009f578063cb924df61161006e578063cb924df6146107f1578063ccd668e51461082d578063d8a05cec14610857578063e406fd2a14610881578063ec52fd5c1461089757610246565b80639f9d7f8114610725578063a70b9f0c1461074f578063bad69ad014610779578063c19eb73e146107b557610246565b806379885fd1116100e657806379885fd114610643578063829965cc1461067f57806389dc5c84146106a9578063902bdc26146106d35780639690293b1461070f57610246565b806370c647d51461058957806371785ab9146105c557806374a6b278146105ef578063776892611461061957610246565b806337409c6a1161019a5780634d21e426116101695780634d21e426146104a35780634dc47d34146104df5780635750af771461051b5780636bed4df5146105575780636dd7d8ea1461056d57610246565b806337409c6a146103ff5780633b4866c71461043b578063403b09931461045157806343c14b221461048d57610246565b80630b2a85ea116101e15780630b2a85ea1461030457806319e6e158146103205780631f26f2561461035c578063312ec75c14610386578063347b06d8146103c257610246565b8063038a35381461024a57806306a49fce14610274578063090248641461029e5780630ac1cc20146102da57610246565b36610246573460095f6102236108d3565b81526020019081526020015f205f82825461023e9190612e16565b925050819055005b5f80fd5b348015610255575f80fd5b5061025e6108e8565b60405161026b9190612e58565b60405180910390f35b34801561027f575f80fd5b506102886108ee565b6040516102959190612f58565b60405180910390f35b3480156102a9575f80fd5b506102c460048036038101906102bf9190612fa6565b6108ff565b6040516102d19190612e58565b60405180910390f35b3480156102e5575f80fd5b506102ee610914565b6040516102fb9190612e58565b60405180910390f35b61031e60048036038101906103199190612ffb565b61091a565b005b34801561032b575f80fd5b5061034660048036038101906103419190612ffb565b610ba8565b6040516103539190612e58565b60405180910390f35b348015610367575f80fd5b50610370610bbd565b60405161037d9190612e58565b60405180910390f35b348015610391575f80fd5b506103ac60048036038101906103a79190613026565b610bc3565b6040516103b99190612e58565b60405180910390f35b3480156103cd575f80fd5b506103e860048036038101906103e39190613026565b610bee565b6040516103f6929190613073565b60405180910390f35b34801561040a575f80fd5b5061042560048036038101906104209190613026565b610cb4565b6040516104329190612e58565b60405180910390f35b348015610446575f80fd5b5061044f610d0a565b005b34801561045c575f80fd5b5061047760048036038101906104729190613026565b61125a565b6040516104849190612e58565b60405180910390f35b348015610498575f80fd5b506104a161127a565b005b3480156104ae575f80fd5b506104c960048036038101906104c49190612fa6565b6115e0565b6040516104d69190612e58565b60405180910390f35b3480156104ea575f80fd5b5061050560048036038101906105009190612ffb565b6115f5565b6040516105129190612e58565b60405180910390f35b348015610526575f80fd5b50610541600480360381019061053c9190612ffb565b61160a565b60405161054e9190612e58565b60405180910390f35b348015610562575f80fd5b5061056b61161f565b005b61058760048036038101906105829190612fa6565b6118ff565b005b348015610594575f80fd5b506105af60048036038101906105aa9190612fa6565b611e46565b6040516105bc9190612e58565b60405180910390f35b3480156105d0575f80fd5b506105d9611e5b565b6040516105e69190612e58565b60405180910390f35b3480156105fa575f80fd5b50610603611ed3565b6040516106109190612e58565b60405180910390f35b348015610624575f80fd5b5061062d611ed8565b60405161063a9190612e58565b60405180910390f35b34801561064e575f80fd5b5061066960048036038101906106649190613026565b611ede565b604051610676919061309a565b60405180910390f35b34801561068a575f80fd5b50610693611f1b565b6040516106a09190612e58565b60405180910390f35b3480156106b4575f80fd5b506106bd611f21565b6040516106ca919061309a565b60405180910390f35b3480156106de575f80fd5b506106f960048036038101906106f49190612fa6565b611f39565b6040516107069190612e58565b60405180910390f35b34801561071a575f80fd5b50610723611f4e565b005b348015610730575f80fd5b5061073961208f565b6040516107469190612f58565b60405180910390f35b34801561075a575f80fd5b50610763612130565b6040516107709190612e58565b60405180910390f35b348015610784575f80fd5b5061079f600480360381019061079a9190612fa6565b612136565b6040516107ac9190612e58565b60405180910390f35b3480156107c0575f80fd5b506107db60048036038101906107d691906130b3565b61214b565b6040516107e8919061309a565b60405180910390f35b3480156107fc575f80fd5b5061081760048036038101906108129190613026565b612193565b6040516108249190612e58565b60405180910390f35b348015610838575f80fd5b506108416121b3565b60405161084e9190612e58565b60405180910390f35b348015610862575f80fd5b5061086b6108d3565b6040516108789190612e58565b60405180910390f35b34801561088c575f80fd5b506108956121bc565b005b3480156108a2575f80fd5b506108bd60048036038101906108b89190613026565b6122f6565b6040516108ca9190612e58565b60405180910390f35b5f60016005546108e391906130f1565b905090565b60015481565b60606108fa6007612316565b905090565b600e602052805f5260405f205f915090505481565b60025481565b600254341461095e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109559061317e565b60405180910390fd5b6103e881106109a2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610999906131e6565b60405180910390fd5b6109b633600761233590919063ffffffff16565b156109f6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109ed9061324e565b60405180910390fd5b610a0a33600761236290919063ffffffff16565b50600f5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f90555f610a5461238f565b905080600e5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f208190555081600d5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055503460105f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f208190555060018111610b2a575f610b2c565b805b60115f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055507feeda149c76076b34d4b9d8896c2f7efc0d33d1c7b53ea3c5db490d64613f603a33604051610b9c919061309a565b60405180910390a15050565b600a602052805f5260405f205f915090505481565b60065481565b6016602052815f5260405f208181548110610bdc575f80fd5b905f5260205f20015f91509150505481565b5f8060135f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8481526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1660145f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8581526020019081526020015f2054915091509250929050565b5f60125f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8381526020019081526020015f2054905092915050565b5f610d1361238f565b90505f805f60165f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20805480602002602001604051908101604052809291908181526020018280548015610d9d57602002820191905f5260205f20905b815481526020019060010190808311610d89575b505050505090505f8151905060165f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f610df19190612d20565b5f5b81811015611202575f838281518110610e0f57610e0e61326c565b5b60200260200101519050600187610e2691906130f1565b81101561117e5760145f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8281526020019081526020015f205486610e859190612e16565b955060145f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8281526020019081526020015f205f90555f60135f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8381526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505f600c5f8481526020019081526020015f20805480602002602001604051908101604052809291908181526020018280548015610fd457602002820191905f5260205f20905b815f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311610f8b575b505050505090505f805b5f54811015611046578373ffffffffffffffffffffffffffffffffffffffff168382815181106110115761101061326c565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff160361103957600191505b8080600101915050610fde565b508015611127575f5460125f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8681526020019081526020015f205460095f8781526020019081526020015f205460155f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8881526020019081526020015f20546111059190613299565b61110f9190613307565b6111199190613307565b886111249190612e16565b97505b60155f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8581526020019081526020015f205f90555050506111f4565b60018761118b91906130f1565b81106111f35760165f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2081908060018154018082558091505060019003905f5260205f20015f90919091909150555b5b508080600101915050610df3565b506112183384866112139190612e16565b6124ac565b7f703edbfbdca027dbf1185701b17f150b2c280a8f25b570a0a0bab84d72cf347433858560405161124b93929190613337565b60405180910390a15050505050565b6012602052815f5260405f20602052805f5260405f205f91509150505481565b5f611283611e5b565b90505f60135f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8381526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505f60145f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8481526020019081526020015f205490505f8111611386576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161137d9061317e565b60405180910390fd5b5f60125f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8581526020019081526020015f20549050818103611406576001600b5f8681526020019081526020015f205f8282546113fe91906130f1565b925050819055505b818161141291906130f1565b60125f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8681526020019081526020015f208190555081600a5f8681526020019081526020015f205f82825461148291906130f1565b9250508190555060135f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8581526020019081526020015f205f6101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905560145f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8581526020019081526020015f205f905560155f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8581526020019081526020015f205f905561159f33836124ac565b7f6ddfb4877cf7f45a590719822a3ae2d41e7a4dc9aeadca0532a85abae1c6ad7f3384846040516115d29392919061336c565b60405180910390a150505050565b6010602052805f5260405f205f915090505481565b6009602052805f5260405f205f915090505481565b600b602052805f5260405f205f915090505481565b5f61162861238f565b90506001811161166d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611664906133eb565b60405180910390fd5b5f8060115f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205490505b6001836116bd91906130f1565b811015611869575f600c5f8381526020019081526020015f2080548060200260200160405190810160405280929190818152602001828054801561175357602002820191905f5260205f20905b815f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001906001019080831161170a575b505050505090505f805b5f548110156117c5573373ffffffffffffffffffffffffffffffffffffffff168382815181106117905761178f61326c565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff16036117b857600191505b808060010191505061175d565b50801561185a576103e85f54600d5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20546103e861181c91906130f1565b60095f8781526020019081526020015f20546118389190613299565b6118429190613307565b61184c9190613307565b846118579190612e16565b93505b505080806001019150506116b0565b5060018261187791906130f1565b60115f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055506118c233826124ac565b7fe3ce84385ab3d4dac3d7a146f1f394969d88408c293159506eb6f885a1f6788633826040516118f3929190613073565b60405180910390a15050565b600154341015611944576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161193b9061317e565b60405180910390fd5b5f600e5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054116119c3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119ba90613453565b60405180910390fd5b5f6119cc61238f565b90505f60145f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8381526020019081526020015f205490505f8103611b15578260135f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8481526020019081526020015f205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060165f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2082908060018154018082558091505060019003905f5260205f20015f9091909190915055611bef565b8273ffffffffffffffffffffffffffffffffffffffff1660135f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8481526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611bee576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611be5906134bb565b60405180910390fd5b5b3481611bfb9190612e16565b60145f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8481526020019081526020015f20819055506103e8600d5f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205434611c979190613299565b611ca19190613307565b60155f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8481526020019081526020015f205f828254611cfb9190612e16565b925050819055505f60125f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8481526020019081526020015f205490505f8103611d82576001600b5f8581526020019081526020015f205f828254611d7a9190612e16565b925050819055505b3481611d8e9190612e16565b60125f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8581526020019081526020015f208190555034600a5f8581526020019081526020015f205f828254611dfe9190612e16565b925050819055507f66a9138482c99e9baf08860110ef332cc0c23b4a199a53593d8db0fc8f96fbfc338534604051611e389392919061336c565b60405180910390a150505050565b6011602052805f5260405f205f915090505481565b5f806005549050600454600654611e729190612e16565b43118015611e935750600354600a5f8381526020019081526020015f205410155b8015611eb157505f54600b5f8381526020019081526020015f205410155b15611ecb57600181611ec39190612e16565b915050611ed0565b809150505b90565b5f5481565b60035481565b6013602052815f5260405f20602052805f5260405f205f915091509054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60055481565b73121200000000000000000000000000000000000381565b600d602052805f5260405f205f915090505481565b5f600e5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205411611fcd576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611fc490613523565b60405180910390fd5b600e5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f905561201561238f565b600f5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055507f7c79e6e24ed041d1072d54523b53956f01b91b835f0490856370594d9d14470e33604051612085919061309a565b60405180910390a1565b6060600c5f61209c6108d3565b81526020019081526020015f2080548060200260200160405190810160405280929190818152602001828054801561212657602002820191905f5260205f20905b815f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190600101908083116120dd575b5050505050905090565b60045481565b600f602052805f5260405f205f915090505481565b600c602052815f5260405f208181548110612164575f80fd5b905f5260205f20015f915091509054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6015602052815f5260405f20602052805f5260405f205f91509150505481565b5f600554905090565b5f6121c561238f565b90506001600f5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20546122119190612e16565b8111612252576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016122499061358b565b60405180910390fd5b6122663360076125a790919063ffffffff16565b505f60105f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905060105f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f90556122f233826124ac565b5050565b6014602052815f5260405f20602052805f5260405f205f91509150505481565b60605f612324835f016125d4565b905060608190508092505050919050565b5f61235a835f018373ffffffffffffffffffffffffffffffffffffffff165f1b61262d565b905092915050565b5f612387835f018373ffffffffffffffffffffffffffffffffffffffff165f1b61264d565b905092915050565b5f8060055490506004546006546123a69190612e16565b431180156123c75750600354600a5f8381526020019081526020015f205410155b80156123e557505f54600b5f8381526020019081526020015f205410155b156124a55773121200000000000000000000000000000000000373ffffffffffffffffffffffffffffffffffffffff16633ccfd60b6040518163ffffffff1660e01b81526004015f604051808303815f87803b158015612443575f80fd5b505af1158015612455573d5f803e3d5ffd5b50505050612462816126b4565b600c5f8381526020019081526020015f209080519060200190612486929190612d3e565b506001816124949190612e16565b905080600581905550436006819055505b8091505090565b5f8273ffffffffffffffffffffffffffffffffffffffff16825f67ffffffffffffffff8111156124df576124de6135a9565b5b6040519080825280601f01601f1916602001820160405280156125115781602001600182028036833780820191505090505b5060405161251f9190613642565b5f6040518083038185875af1925050503d805f8114612559576040519150601f19603f3d011682016040523d82523d5f602084013e61255e565b606091505b50509050806125a2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612599906136c8565b60405180910390fd5b505050565b5f6125cc835f018373ffffffffffffffffffffffffffffffffffffffff165f1b612896565b905092915050565b6060815f0180548060200260200160405190810160405280929190818152602001828054801561262157602002820191905f5260205f20905b81548152602001906001019080831161260d575b50505050509050919050565b5f80836001015f8481526020019081526020015f20541415905092915050565b5f612658838361262d565b6126aa57825f0182908060018154018082558091505060019003905f5260205f20015f9091909190915055825f0180549050836001015f8481526020019081526020015f2081905550600190506126ae565b5f90505b92915050565b60605f6126bf6108ee565b90505f815190505f8167ffffffffffffffff8111156126e1576126e06135a9565b5b60405190808252806020026020018201604052801561270f5781602001602082028036833780820191505090505b5090505f5b828110156127af5760125f8583815181106127325761273161326c565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8781526020019081526020015f20548282815181106127965761279561326c565b5b6020026020010181815250508080600101915050612714565b506127bc83825f54612992565b5f805467ffffffffffffffff8111156127d8576127d76135a9565b5b6040519080825280602002602001820160405280156128065781602001602082028036833780820191505090505b5090505f5b5f54811015612889578481815181106128275761282661326c565b5b60200260200101518282815181106128425761284161326c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050808060010191505061280b565b5080945050505050919050565b5f80836001015f8481526020019081526020015f205490505f8114612987575f6001826128c391906130f1565b90505f6001865f01805490506128d991906130f1565b905080821461293f575f865f0182815481106128f8576128f761326c565b5b905f5260205f200154905080875f0184815481106129195761291861326c565b5b905f5260205f20018190555083876001015f8381526020019081526020015f2081905550505b855f01805480612952576129516136e6565b5b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f90556001935050505061298c565b5f9150505b92915050565b5f835190505f60016002846129a7919061371c565b6129b19190613784565b90505b5f81126129da576129c785858386612ae7565b80806129d2906137c4565b9150506129b4565b505f8290505b81811015612ae057835f815181106129fb576129fa61326c565b5b6020026020010151848281518110612a1657612a1561326c565b5b60200260200101511115612ad357838181518110612a3757612a3661326c565b5b6020026020010151845f81518110612a5257612a5161326c565b5b602002602001018181525050848181518110612a7157612a7061326c565b5b6020026020010151855f81518110612a8c57612a8b61326c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050612ad285855f86612ae7565b5b80806001019150506129e0565b5050505050565b5f6001836002612af79190613299565b612b019190612e16565b90505b81811015612d195781600182612b1a9190612e16565b108015612b66575083600182612b309190612e16565b81518110612b4157612b4061326c565b5b6020026020010151848281518110612b5c57612b5b61326c565b5b6020026020010151115b15612b7b57600181612b789190612e16565b90505b838381518110612b8e57612b8d61326c565b5b6020026020010151848281518110612ba957612ba861326c565b5b602002602001015111612d1957838381518110612bc957612bc861326c565b5b6020026020010151848281518110612be457612be361326c565b5b6020026020010151858381518110612bff57612bfe61326c565b5b60200260200101868681518110612c1957612c1861326c565b5b6020026020010182815250828152505050848381518110612c3d57612c3c61326c565b5b6020026020010151858281518110612c5857612c5761326c565b5b6020026020010151868381518110612c7357612c7261326c565b5b60200260200101878681518110612c8d57612c8c61326c565b5b602002602001018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152508273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681525050508092506001600282612d089190613299565b612d129190612e16565b9050612b04565b5050505050565b5080545f8255905f5260205f2090810190612d3b9190612dc5565b50565b828054828255905f5260205f20908101928215612db4579160200282015b82811115612db3578251825f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555091602001919060010190612d5c565b5b509050612dc19190612dc5565b5090565b5b80821115612ddc575f815f905550600101612dc6565b5090565b5f819050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f612e2082612de0565b9150612e2b83612de0565b9250828201905080821115612e4357612e42612de9565b5b92915050565b612e5281612de0565b82525050565b5f602082019050612e6b5f830184612e49565b92915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f612ec382612e9a565b9050919050565b612ed381612eb9565b82525050565b5f612ee48383612eca565b60208301905092915050565b5f602082019050919050565b5f612f0682612e71565b612f108185612e7b565b9350612f1b83612e8b565b805f5b83811015612f4b578151612f328882612ed9565b9750612f3d83612ef0565b925050600181019050612f1e565b5085935050505092915050565b5f6020820190508181035f830152612f708184612efc565b905092915050565b5f80fd5b612f8581612eb9565b8114612f8f575f80fd5b50565b5f81359050612fa081612f7c565b92915050565b5f60208284031215612fbb57612fba612f78565b5b5f612fc884828501612f92565b91505092915050565b612fda81612de0565b8114612fe4575f80fd5b50565b5f81359050612ff581612fd1565b92915050565b5f602082840312156130105761300f612f78565b5b5f61301d84828501612fe7565b91505092915050565b5f806040838503121561303c5761303b612f78565b5b5f61304985828601612f92565b925050602061305a85828601612fe7565b9150509250929050565b61306d81612eb9565b82525050565b5f6040820190506130865f830185613064565b6130936020830184612e49565b9392505050565b5f6020820190506130ad5f830184613064565b92915050565b5f80604083850312156130c9576130c8612f78565b5b5f6130d685828601612fe7565b92505060206130e785828601612fe7565b9150509250929050565b5f6130fb82612de0565b915061310683612de0565b925082820390508181111561311e5761311d612de9565b5b92915050565b5f82825260208201905092915050565b7f696e73756666696369656e7420616d6f756e74000000000000000000000000005f82015250565b5f613168601383613124565b915061317382613134565b602082019050919050565b5f6020820190508181035f8301526131958161315c565b9050919050565b7f696e76616c6964207261746500000000000000000000000000000000000000005f82015250565b5f6131d0600c83613124565b91506131db8261319c565b602082019050919050565b5f6020820190508181035f8301526131fd816131c4565b9050919050565b7f63616e64696461746520657869737473000000000000000000000000000000005f82015250565b5f613238601083613124565b915061324382613204565b602082019050919050565b5f6020820190508181035f8301526132658161322c565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f6132a382612de0565b91506132ae83612de0565b92508282026132bc81612de0565b915082820484148315176132d3576132d2612de9565b5b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f61331182612de0565b915061331c83612de0565b92508261332c5761332b6132da565b5b828204905092915050565b5f60608201905061334a5f830186613064565b6133576020830185612e49565b6133646040830184612e49565b949350505050565b5f60608201905061337f5f830186613064565b61338c6020830185613064565b6133996040830184612e49565b949350505050565b7f636c61696d206e6f7420737461727465640000000000000000000000000000005f82015250565b5f6133d5601183613124565b91506133e0826133a1565b602082019050919050565b5f6020820190508181035f830152613402816133c9565b9050919050565b7f63616e646964617465206e6f7420616c6c6f77656400000000000000000000005f82015250565b5f61343d601583613124565b915061344882613409565b602082019050919050565b5f6020820190508181035f83015261346a81613431565b9050919050565b7f6f6e6c79206f6e652063686f69636520697320616c6c6f7765640000000000005f82015250565b5f6134a5601a83613124565b91506134b082613471565b602082019050919050565b5f6020820190508181035f8301526134d281613499565b9050919050565b7f63616e646964617465206e6f74206578697374730000000000000000000000005f82015250565b5f61350d601483613124565b9150613518826134d9565b602082019050919050565b5f6020820190508181035f83015261353a81613501565b9050919050565b7f636c61696d206e6f7420616c6c6f7765640000000000000000000000000000005f82015250565b5f613575601183613124565b915061358082613541565b602082019050919050565b5f6020820190508181035f8301526135a281613569565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f81519050919050565b5f81905092915050565b5f5b838110156136075780820151818401526020810190506135ec565b5f8484015250505050565b5f61361c826135d6565b61362681856135e0565b93506136368185602086016135ea565b80840191505092915050565b5f61364d8284613612565b915081905092915050565b7f736166655472616e736665724554483a20455448207472616e736665722066615f8201527f696c656400000000000000000000000000000000000000000000000000000000602082015250565b5f6136b2602483613124565b91506136bd82613658565b604082019050919050565b5f6020820190508181035f8301526136df816136a6565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603160045260245ffd5b5f819050919050565b5f61372682613713565b915061373183613713565b925082613741576137406132da565b5b60015f0383147f80000000000000000000000000000000000000000000000000000000000000008314161561377957613778612de9565b5b828205905092915050565b5f61378e82613713565b915061379983613713565b925082820390508181125f8412168282135f8512151617156137be576137bd612de9565b5b92915050565b5f6137ce82613713565b91507f80000000000000000000000000000000000000000000000000000000000000008203613800576137ff612de9565b5b60018203905091905056fea2646970667358221220bc140edffe3d516441820d2e50897d8c7e71254ff08490f53e22023a3e0e990764736f6c63430008180033" + }, + "0x1212000000000000000000000000000000000001": { + "balance": "0", + "code": "0x60806040523661001357610011610017565b005b6100115b61001f6101a7565b6001600160a01b0316330361015f5760606001600160e01b0319600035166364d3180d60e11b810161005a576100536101da565b9150610157565b63587086bd60e11b6001600160e01b031982160161007a57610053610231565b63070d7c6960e41b6001600160e01b031982160161009a57610053610277565b621eb96f60e61b6001600160e01b03198216016100b9576100536102a8565b63a39f25e560e01b6001600160e01b03198216016100d9576100536102e8565b60405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b815160208301f35b6101676102fc565b565b606061018e83836040518060600160405280602781526020016108426027913961030c565b9392505050565b90565b6001600160a01b03163b151590565b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b60606101e4610384565b60006101f33660048184610695565b81019061020091906106db565b905061021d8160405180602001604052806000815250600061038f565b505060408051602081019091526000815290565b60606000806102433660048184610695565b810190610250919061070c565b915091506102608282600161038f565b604051806020016040528060008152509250505090565b6060610281610384565b60006102903660048184610695565b81019061029d91906106db565b905061021d816103bb565b60606102b2610384565b60006102bc6101a7565b604080516001600160a01b03831660208201529192500160405160208183030381529060405291505090565b60606102f2610384565b60006102bc610412565b610167610307610412565b610421565b6060600080856001600160a01b03168560405161032991906107f2565b600060405180830381855af49150503d8060008114610364576040519150601f19603f3d011682016040523d82523d6000602084013e610369565b606091505b509150915061037a86838387610445565b9695505050505050565b341561016757600080fd5b610398836104c6565b6000825111806103a55750805b156103b6576103b48383610169565b505b505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6103e46101a7565b604080516001600160a01b03928316815291841660208301520160405180910390a161040f81610506565b50565b600061041c6105af565b905090565b3660008037600080366000845af43d6000803e808015610440573d6000f35b3d6000fd5b606083156104b45782516000036104ad576001600160a01b0385163b6104ad5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161014e565b50816104be565b6104be83836105d7565b949350505050565b6104cf81610601565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6001600160a01b03811661056b5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b606482015260840161014e565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6101cb565b8151156105e75781518083602001fd5b8060405162461bcd60e51b815260040161014e919061080e565b6001600160a01b0381163b61066e5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b606482015260840161014e565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc61058e565b600080858511156106a557600080fd5b838611156106b257600080fd5b5050820193919092039150565b80356001600160a01b03811681146106d657600080fd5b919050565b6000602082840312156106ed57600080fd5b61018e826106bf565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561071f57600080fd5b610728836106bf565b9150602083013567ffffffffffffffff8082111561074557600080fd5b818501915085601f83011261075957600080fd5b81358181111561076b5761076b6106f6565b604051601f8201601f19908116603f01168101908382118183101715610793576107936106f6565b816040528281528860208487010111156107ac57600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b60005b838110156107e95781810151838201526020016107d1565b50506000910152565b600082516108048184602087016107ce565b9190910192915050565b602081526000825180602084015261082d8160408501602087016107ce565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a264697066735822122060cf01d0d0c15c838abecad7eebb680cda1dbe3d5984e7b64b6962b3134b4d8c64736f6c63430008120033", "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000005": "0x0f467b64b0f970e63994fe8a120410151cc094db", - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x07", - "0x0000000000000000000000000000000000000000000000000000000000000004": "0xbb03c5030cac72e290ae185a8b9b375c58f7a9a6", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e567": "0x97fb9c893c19da2672dbd790ac9fc406f138584b", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e569": "0x394831b50e496a4e85c97acdbd7943802d897c34", - "0x0000000000000000000000000000000000000000000000000000000000000003": "0x640500000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000006": "0xe7715472792d680ab4c5837e2131264a6153c89d", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563": "0xf82cf7e2b899a57d22653a6a742c0c60523d6a61", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e568": "0xb93ce875656d56935da316b27860b0fc7b60435a", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e565": "0x58e479a056df6d54600b4e02b8eb6390bcd8a550", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e566": "0x3a6eabc45ac029ccfaf49d54593a996f638e7cf7", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e564": "0xb42fbb03f30424aa903022269fcd62eabbdfcfae" + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x01", + "0x0000000000000000000000000000000000000000000000000000000000000001": "0x07", + "0x0000000000000000000000000000000000000000000000000000000000000002": "0x0de0b6b3a7640000", + "0x0000000000000000000000000000000000000000000000000000000000000003": "0x027b46536c66c8e3000000", + "0x0000000000000000000000000000000000000000000000000000000000000004": "0x3635c9adc5dea00000", + "0x0000000000000000000000000000000000000000000000000000000000000005": "0x01d880", + "0x0000000000000000000000000000000000000000000000000000000000000010": "0x07", + "0x0000000000000000000000000000000000000000000000000000000000000011": "0x07", + "0x31ecc21a745e3968a04e9570e4425bc18fa8019c68028196b546d1669c200c68": "0x74f4effb0b538baec703346b03b6d9292f53a4cd", + "0x31ecc21a745e3968a04e9570e4425bc18fa8019c68028196b546d1669c200c69": "0x910ad1641b7125eff746accdca1f11148b22f472", + "0x31ecc21a745e3968a04e9570e4425bc18fa8019c68028196b546d1669c200c6a": "0xfef5f250af14df73f983caab7b1f5002189c42e0", + "0x31ecc21a745e3968a04e9570e4425bc18fa8019c68028196b546d1669c200c6b": "0xc51964013acbc6b271feecb0febd9e7a01202930", + "0x31ecc21a745e3968a04e9570e4425bc18fa8019c68028196b546d1669c200c6c": "0xc5bbd9652546bc96be3dec97a38ee335f7873dfa", + "0x31ecc21a745e3968a04e9570e4425bc18fa8019c68028196b546d1669c200c6d": "0x26f1794b81df2b832545b8b6bbca196b82e4feb1", + "0x31ecc21a745e3968a04e9570e4425bc18fa8019c68028196b546d1669c200c6e": "0x0b51369d02e47ee3f143391b837aa08c31aaa19b", + "0x1b6847dc741a1b0cd08d278845f9d819d87b734759afb55fe2de5cb82a9ae672": "0x74f4effb0b538baec703346b03b6d9292f53a4cd", + "0x1b6847dc741a1b0cd08d278845f9d819d87b734759afb55fe2de5cb82a9ae673": "0x910ad1641b7125eff746accdca1f11148b22f472", + "0x1b6847dc741a1b0cd08d278845f9d819d87b734759afb55fe2de5cb82a9ae674": "0xfef5f250af14df73f983caab7b1f5002189c42e0", + "0x1b6847dc741a1b0cd08d278845f9d819d87b734759afb55fe2de5cb82a9ae675": "0xc51964013acbc6b271feecb0febd9e7a01202930", + "0x1b6847dc741a1b0cd08d278845f9d819d87b734759afb55fe2de5cb82a9ae676": "0xc5bbd9652546bc96be3dec97a38ee335f7873dfa", + "0x1b6847dc741a1b0cd08d278845f9d819d87b734759afb55fe2de5cb82a9ae677": "0x26f1794b81df2b832545b8b6bbca196b82e4feb1", + "0x1b6847dc741a1b0cd08d278845f9d819d87b734759afb55fe2de5cb82a9ae678": "0x0b51369d02e47ee3f143391b837aa08c31aaa19b", + "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x1212100000000000000000000000000000000001", + "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x1212000000000000000000000000000000000000" } + }, + "0x1212000000000000000000000000000000000002": { + "balance": "0", + "code": "0x60806040523661001357610011610017565b005b6100115b61001f6101a7565b6001600160a01b0316330361015f5760606001600160e01b0319600035166364d3180d60e11b810161005a576100536101da565b9150610157565b63587086bd60e11b6001600160e01b031982160161007a57610053610231565b63070d7c6960e41b6001600160e01b031982160161009a57610053610277565b621eb96f60e61b6001600160e01b03198216016100b9576100536102a8565b63a39f25e560e01b6001600160e01b03198216016100d9576100536102e8565b60405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b815160208301f35b6101676102fc565b565b606061018e83836040518060600160405280602781526020016108426027913961030c565b9392505050565b90565b6001600160a01b03163b151590565b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b60606101e4610384565b60006101f33660048184610695565b81019061020091906106db565b905061021d8160405180602001604052806000815250600061038f565b505060408051602081019091526000815290565b60606000806102433660048184610695565b810190610250919061070c565b915091506102608282600161038f565b604051806020016040528060008152509250505090565b6060610281610384565b60006102903660048184610695565b81019061029d91906106db565b905061021d816103bb565b60606102b2610384565b60006102bc6101a7565b604080516001600160a01b03831660208201529192500160405160208183030381529060405291505090565b60606102f2610384565b60006102bc610412565b610167610307610412565b610421565b6060600080856001600160a01b03168560405161032991906107f2565b600060405180830381855af49150503d8060008114610364576040519150601f19603f3d011682016040523d82523d6000602084013e610369565b606091505b509150915061037a86838387610445565b9695505050505050565b341561016757600080fd5b610398836104c6565b6000825111806103a55750805b156103b6576103b48383610169565b505b505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6103e46101a7565b604080516001600160a01b03928316815291841660208301520160405180910390a161040f81610506565b50565b600061041c6105af565b905090565b3660008037600080366000845af43d6000803e808015610440573d6000f35b3d6000fd5b606083156104b45782516000036104ad576001600160a01b0385163b6104ad5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161014e565b50816104be565b6104be83836105d7565b949350505050565b6104cf81610601565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6001600160a01b03811661056b5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b606482015260840161014e565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6101cb565b8151156105e75781518083602001fd5b8060405162461bcd60e51b815260040161014e919061080e565b6001600160a01b0381163b61066e5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b606482015260840161014e565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc61058e565b600080858511156106a557600080fd5b838611156106b257600080fd5b5050820193919092039150565b80356001600160a01b03811681146106d657600080fd5b919050565b6000602082840312156106ed57600080fd5b61018e826106bf565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561071f57600080fd5b610728836106bf565b9150602083013567ffffffffffffffff8082111561074557600080fd5b818501915085601f83011261075957600080fd5b81358181111561076b5761076b6106f6565b604051601f8201601f19908116603f01168101908382118183101715610793576107936106f6565b816040528281528860208487010111156107ac57600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b60005b838110156107e95781810151838201526020016107d1565b50506000910152565b600082516108048184602087016107ce565b9190910192915050565b602081526000825180602084015261082d8160408501602087016107ce565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a264697066735822122060cf01d0d0c15c838abecad7eebb680cda1dbe3d5984e7b64b6962b3134b4d8c64736f6c63430008120033", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000001": "0x989680", + "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x1212100000000000000000000000000000000002", + "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x1212000000000000000000000000000000000000" + } + }, + "0x1212000000000000000000000000000000000003": { + "balance": "0", + "code": "0x608060405260043610610036575f3560e01c80631633da6e146100415780633ccfd60b1461006b5780635aa6e67514610081575f80fd5b3661003d57005b5f80fd5b34801561004c575f80fd5b506100556100cd565b6040516100629190610327565b60405180910390f35b348015610076575f80fd5b5061007f610175565b005b34801561008c575f80fd5b506100a873121200000000000000000000000000000000000181565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610062565b606073121200000000000000000000000000000000000173ffffffffffffffffffffffffffffffffffffffff16639f9d7f816040518163ffffffff1660e01b81526004015f60405180830381865afa15801561012b573d5f803e3d5ffd5b505050506040513d5f823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261017091908101906103d5565b905090565b33731212000000000000000000000000000000000001146101f7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f4e6f7420676f7665726e616e636500000000000000000000000000000000000060448201526064015b60405180910390fd5b471561021b5761021b7312120000000000000000000000000000000000014761021d565b565b604080515f8082526020820190925273ffffffffffffffffffffffffffffffffffffffff841690839060405161025391906104b3565b5f6040518083038185875af1925050503d805f811461028d576040519150601f19603f3d011682016040523d82523d5f602084013e610292565b606091505b5050905080610322576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f736166655472616e736665724554483a20455448207472616e7366657220666160448201527f696c65640000000000000000000000000000000000000000000000000000000060648201526084016101ee565b505050565b602080825282518282018190525f9190848201906040850190845b8181101561037457835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101610342565b50909695505050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b805173ffffffffffffffffffffffffffffffffffffffff811681146103d0575f80fd5b919050565b5f60208083850312156103e6575f80fd5b825167ffffffffffffffff808211156103fd575f80fd5b818501915085601f830112610410575f80fd5b81518181111561042257610422610380565b8060051b6040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f8301168101818110858211171561046557610465610380565b604052918252848201925083810185019188831115610482575f80fd5b938501935b828510156104a757610498856103ad565b84529385019392850192610487565b98975050505050505050565b5f82515f5b818110156104d257602081860181015185830152016104b8565b505f92019182525091905056fea2646970667358221220bf0616af90ea4545d17e405fa3ba4df3062321a9a535fe45876c3962cc8f2f8c64736f6c63430008180033" + }, + "0x1212100000000000000000000000000000000001": { + "balance": "0", + "code": "0x6080604052600436106101de575f3560e01c8063786255f1116100fd5780639f9d7f8111610092578063d8ce95ab11610062578063d8ce95ab1461088c578063da0b3317146108b7578063db069ba5146108e2578063f4bbb82f1461090d575f80fd5b80639f9d7f811461083b578063a6580de81461084f578063a681dfec14610864578063b88a802f14610878575f80fd5b8063902bdc26116100cd578063902bdc26146107aa5780639690293b146107d557806398ca58df146107e95780639e40cdac14610814575f80fd5b8063786255f11461070d57806389dc5c84146107435780638e1900a81461076a5780638f1b321914610795575f80fd5b80634d21e426116101735780636900cad8116101435780636900cad81461067b5780636db504e71461069a5780636dd7d8ea146106db57806373c7fbe9146106ee575f80fd5b80634d21e4261461060c5780634ff0876a14610637578063611905331461064c578063683dd19114610660575f80fd5b80630ea6a041116101ae5780630ea6a041146105745780631f26f256146105b857806343c14b22146105cd5780634c569c25146105e1575f80fd5b806303f187ea1461050357806306a49fce1461052b5780630b2a85ea1461054c5780630d15fd771461055f575f80fd5b366104ff576101eb610922565b337312120000000000000000000000000000000000031461026d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f736964652063616c6c206e6f7420616c6c6f776564000000000000000000000060448201526064015b60405180910390fd5b5f60108054806020026020016040519081016040528092919081815260200182805480156102cf57602002820191905f5260205f20905b815473ffffffffffffffffffffffffffffffffffffffff1681526001909101906020018083116102a4575b505083519394505f925050505b818110156104f157600c5f8483815181106102f9576102f9612172565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20546103e8600154670de0b6b3a764000060085f88878151811061035f5761035f612172565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054346103ac91906121cc565b6103b691906121cc565b6103c09190612210565b6103ca9190612210565b6103d49190612210565b60125f8584815181106103e9576103e9612172565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546104389190612223565b925050819055506104e983828151811061045457610454612172565b60200260200101516103e860015460085f88878151811061047757610477612172565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20546103e86104c69190612236565b6104d090346121cc565b6104da9190612210565b6104e49190612210565b610963565b6001016102dc565b5050506104fd60015f55565b005b5f80fd5b34801561050e575f80fd5b5061051860045481565b6040519081526020015b60405180910390f35b348015610536575f80fd5b5061053f610a6d565b6040516105229190612249565b6104fd61055a3660046122a2565b610a7e565b34801561056a575f80fd5b50610518600b5481565b34801561057f575f80fd5b5061059361058e3660046122a2565b610d04565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610522565b3480156105c3575f80fd5b50610518600f5481565b3480156105d8575f80fd5b506104fd610d39565b3480156105ec575f80fd5b506105186105fb3660046122e1565b60126020525f908152604090205481565b348015610617575f80fd5b506105186106263660046122e1565b600a6020525f908152604090205481565b348015610642575f80fd5b5061051860055481565b348015610657575f80fd5b506104fd610f0e565b34801561066b575f80fd5b50610518670de0b6b3a764000081565b348015610686575f80fd5b506105936106953660046122a2565b611036565b3480156106a5575f80fd5b506105936106b43660046122e1565b600d6020525f908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b6104fd6106e93660046122e1565b611045565b3480156106f9575f80fd5b506105186107083660046122e1565b611384565b348015610718575f80fd5b506105186107273660046122fa565b601560209081525f928352604080842090915290825290205481565b34801561074e575f80fd5b5061059373121200000000000000000000000000000000000381565b348015610775575f80fd5b506105186107843660046122e1565b60136020525f908152604090205481565b3480156107a0575f80fd5b5061051860025481565b3480156107b5575f80fd5b506105186107c43660046122e1565b60086020525f908152604090205481565b3480156107e0575f80fd5b506104fd6113cb565b3480156107f4575f80fd5b506105186108033660046122e1565b60146020525f908152604090205481565b34801561081f575f80fd5b5061059373fffffffffffffffffffffffffffffffffffffffe81565b348015610846575f80fd5b5061053f61148f565b34801561085a575f80fd5b5061051860015481565b34801561086f575f80fd5b506104fd6114fc565b348015610883575f80fd5b506104fd61177e565b348015610897575f80fd5b506105186108a63660046122e1565b600c6020525f908152604090205481565b3480156108c2575f80fd5b506105186108d13660046122e1565b60096020525f908152604090205481565b3480156108ed575f80fd5b506105186108fc3660046122e1565b600e6020525f908152604090205481565b348015610918575f80fd5b5061051860035481565b60025f540361095d576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60025f55565b604080515f8082526020820190925273ffffffffffffffffffffffffffffffffffffffff8416908390604051610999919061234f565b5f6040518083038185875af1925050503d805f81146109d3576040519150601f19603f3d011682016040523d82523d5f602084013e6109d8565b606091505b5050905080610a68576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f736166655472616e736665724554483a20455448207472616e7366657220666160448201527f696c6564000000000000000000000000000000000000000000000000000000006064820152608401610264565b505050565b6060610a79600661183a565b905090565b323314610ae7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f6f6e6c7920616c6c6f7720454f410000000000000000000000000000000000006044820152606401610264565b600454341015610b53576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f696e73756666696369656e7420616d6f756e74000000000000000000000000006044820152606401610264565b6103e88110610bbe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f696e76616c6964207261746500000000000000000000000000000000000000006044820152606401610264565b610bc9600633611846565b15610c30576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f63616e64696461746520657869737473000000000000000000000000000000006044820152606401610264565b335f9081526009602052604090205415610ca6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f6c656674206e6f7420636c61696d6564000000000000000000000000000000006044820152606401610264565b610cb1600633611879565b50335f818152600860209081526040808320859055600a82529182902034905590519182527feeda149c76076b34d4b9d8896c2f7efc0d33d1c7b53ea3c5db490d64613f603a910160405180910390a150565b60108181548110610d13575f80fd5b5f9182526020909120015473ffffffffffffffffffffffffffffffffffffffff16905081565b610d41610922565b335f908152600d6020908152604080832054600e9092529091205473ffffffffffffffffffffffffffffffffffffffff909116908115801590610d8357505f81115b610de9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f7265766f6b65206e6f7420616c6c6f77656400000000000000000000000000006044820152606401610264565b5f610df4338461189a565b73ffffffffffffffffffffffffffffffffffffffff84165f908152600c6020526040812080549293508492909190610e2d908490612236565b9250508190555081600b5f828254610e459190612236565b9091555050335f818152600d6020908152604080832080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055600e8252808320839055601382528083208390556014825280832092909255815192835273ffffffffffffffffffffffffffffffffffffffff86169083015281018390527fb698e31a2abee5824d0d7bcfd2339aead7f9e9ae413fba50bf554ff3fa470b7b9060600160405180910390a1610f00336104e48385612223565b505050610f0c60015f55565b565b610f16610922565b335f9081526009602052604090205415801590610f585750600554610f3c9060026121cc565b335f90815260096020526040902054610f559190612223565b43115b610fbe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f7769746864726177206e6f7420616c6c6f7765640000000000000000000000006044820152606401610264565b335f818152600a60209081526040808320805490849055600983528184208490556008835281842093909355805193845290830182905290917f142e26dcca50281d2c46d90446bfc1c9bc260cef355ce917a52f1fec7c54b5bf910160405180910390a161102c3382610963565b50610f0c60015f55565b60118181548110610d13575f80fd5b61104d610922565b6002543410156110b9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f696e73756666696369656e7420616d6f756e74000000000000000000000000006044820152606401610264565b6110c4600682611846565b61112a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f63616e646964617465206e6f7420616c6c6f77656400000000000000000000006044820152606401610264565b335f908152600d602052604090205473ffffffffffffffffffffffffffffffffffffffff908116908216811480611175575073ffffffffffffffffffffffffffffffffffffffff8116155b6111db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f6f6e6c79206f6e652063686f69636520697320616c6c6f7765640000000000006044820152606401610264565b5f73ffffffffffffffffffffffffffffffffffffffff82161561120957611202338361189a565b9050611271565b335f818152600d6020908152604080832080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff89169081179091558352601282528083205493835260139091529020555b335f908152600e60205260408120805434929061128f908490612223565b909155505073ffffffffffffffffffffffffffffffffffffffff83165f908152600c6020526040812080543492906112c8908490612223565b9250508190555034600b5f8282546112e09190612223565b909155505073ffffffffffffffffffffffffffffffffffffffff821661131257335f9081526014602052604090204390555b6040805133815273ffffffffffffffffffffffffffffffffffffffff85166020820152348183015290517f66a9138482c99e9baf08860110ef332cc0c23b4a199a53593d8db0fc8f96fbfc9181900360600190a18015611376576113763382610963565b505061138160015f55565b50565b73ffffffffffffffffffffffffffffffffffffffff8082165f908152600d6020526040812054909116806113ba57505f92915050565b6113c48382611920565b9392505050565b6113d6600633611846565b61143c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f63616e646964617465206e6f74206578697374730000000000000000000000006044820152606401610264565b611447600633611a32565b50335f8181526009602090815260409182902043905590519182527f7c79e6e24ed041d1072d54523b53956f01b91b835f0490856370594d9d14470e910160405180910390a1565b606060108054806020026020016040519081016040528092919081815260200182805480156114f257602002820191905f5260205f20905b815473ffffffffffffffffffffffffffffffffffffffff1681526001909101906020018083116114c7575b5050505050905090565b3373fffffffffffffffffffffffffffffffffffffffe14611579576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f736964652063616c6c206e6f7420616c6c6f77656400000000000000000000006044820152606401610264565b73121200000000000000000000000000000000000373ffffffffffffffffffffffffffffffffffffffff16633ccfd60b6040518163ffffffff1660e01b81526004015f604051808303815f87803b1580156115d2575f80fd5b505af11580156115e4573d5f803e3d5ffd5b50505050600554600f546115f89190612223565b43101561160157565b5f61160c600661183a565b80519091505f5b818110156116f15760125f84838151811061163057611630612172565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205460155f85848151811061168757611687612172565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f600554600f546116d99190612210565b815260208101919091526040015f2055600101611613565b5043600f556001548110806117095750600354600b54105b15611724576011805461171e9160109161209a565b50611742565b61172c611a53565b8051611740916010916020909101906120e6565b505b7fe59e3b36b5c97b419925b60c92f5a4324c993934eb9cfe5232def67c1739337c60106040516117729190612365565b60405180910390a15050565b611786610922565b335f908152600d602052604090205473ffffffffffffffffffffffffffffffffffffffff1680611812576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f636c61696d206e6f7420616c6c6f7765640000000000000000000000000000006044820152606401610264565b5f61181d338361189a565b9050801561182f5761182f3382610963565b5050610f0c60015f55565b60605f6113c483611bf3565b73ffffffffffffffffffffffffffffffffffffffff81165f90815260018301602052604081205415155b90505b92915050565b5f6118708373ffffffffffffffffffffffffffffffffffffffff8416611c4c565b5f806118a68484611920565b73ffffffffffffffffffffffffffffffffffffffff8481165f90815260126020908152604080832054938916808452601383529281902093909355825191825281018390529192507fbeceb521ccd2816457290c3d1cb70cc1537f14307f2d9ac26a5093a38ea40948910160405180910390a19392505050565b73ffffffffffffffffffffffffffffffffffffffff8083165f90815260146020908152604080832054601383528184205494861684526012909252822054600f54929391928310611976575f9350505050611873565b73ffffffffffffffffffffffffffffffffffffffff85165f90815260156020526040812060055482906119aa600188612236565b6119b49190612210565b6119bf906001612223565b81526020019081526020015f20549050828111156119db578092505b670de0b6b3a76400006119ee8484612236565b73ffffffffffffffffffffffffffffffffffffffff89165f908152600e6020526040902054611a1d91906121cc565b611a279190612210565b979650505050505050565b5f6118708373ffffffffffffffffffffffffffffffffffffffff8416611c98565b60605f611a5e610a6d565b80519091505f8167ffffffffffffffff811115611a7d57611a7d612322565b604051908082528060200260200182016040528015611aa6578160200160208202803683370190505b5090505f5b82811015611b2f57600c5f858381518110611ac857611ac8612172565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054828281518110611b1c57611b1c612172565b6020908102919091010152600101611aab565b50611b3d8382600154611d82565b5f60015467ffffffffffffffff811115611b5957611b59612322565b604051908082528060200260200182016040528015611b82578160200160208202803683370190505b5090505f5b600154811015611bea57848181518110611ba357611ba3612172565b6020026020010151828281518110611bbd57611bbd612172565b73ffffffffffffffffffffffffffffffffffffffff90921660209283029190910190910152600101611b87565b50949350505050565b6060815f01805480602002602001604051908101604052809291908181526020018280548015611c4057602002820191905f5260205f20905b815481526020019060010190808311611c2c575b50505050509050919050565b5f818152600183016020526040812054611c9157508154600181810184555f848152602080822090930184905584548482528286019093526040902091909155611873565b505f611873565b5f8181526001830160205260408120548015611d72575f611cba600183612236565b85549091505f90611ccd90600190612236565b9050808214611d2c575f865f018281548110611ceb57611ceb612172565b905f5260205f200154905080875f018481548110611d0b57611d0b612172565b5f918252602080832090910192909255918252600188019052604090208390555b8554869080611d3d57611d3d6123b5565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f905560019350505050611873565b5f915050611873565b5092915050565b82515f6001611d926002856123e2565b611d9c9190612449565b90505b5f8112611dc457611db285858386611ec2565b80611dbc81612468565b915050611d9f565b50815b81811015611ebb57835f81518110611de157611de1612172565b6020026020010151848281518110611dfb57611dfb612172565b60200260200101511115611eb357838181518110611e1b57611e1b612172565b6020026020010151845f81518110611e3557611e35612172565b602002602001018181525050848181518110611e5357611e53612172565b6020026020010151855f81518110611e6d57611e6d612172565b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050611eb385855f86611ec2565b600101611dc7565b5050505050565b5f611ece8360026121cc565b611ed9906001612223565b90505b81811015611ebb5781611ef0826001612223565b108015611f38575083611f04826001612223565b81518110611f1457611f14612172565b6020026020010151848281518110611f2e57611f2e612172565b6020026020010151115b15611f4b57611f48600182612223565b90505b838381518110611f5d57611f5d612172565b6020026020010151848281518110611f7757611f77612172565b602002602001015111611ebb57838381518110611f9657611f96612172565b6020026020010151848281518110611fb057611fb0612172565b6020026020010151858381518110611fca57611fca612172565b60200260200101868681518110611fe357611fe3612172565b602002602001018281525082815250505084838151811061200657612006612172565b602002602001015185828151811061202057612020612172565b602002602001015186838151811061203a5761203a612172565b6020026020010187868151811061205357612053612172565b73ffffffffffffffffffffffffffffffffffffffff9384166020918202929092010152911690529150816120888160026121cc565b612093906001612223565b9050611edc565b828054828255905f5260205f209081019282156120d6575f5260205f209182015b828111156120d65782548255916001019190600101906120bb565b506120e292915061215e565b5090565b828054828255905f5260205f209081019282156120d6579160200282015b828111156120d657825182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909116178255602090920191600190910190612104565b5b808211156120e2575f815560010161215f565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b80820281158282048414176118735761187361219f565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f8261221e5761221e6121e3565b500490565b808201808211156118735761187361219f565b818103818111156118735761187361219f565b602080825282518282018190525f9190848201906040850190845b8181101561229657835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101612264565b50909695505050505050565b5f602082840312156122b2575f80fd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff811681146122dc575f80fd5b919050565b5f602082840312156122f1575f80fd5b611870826122b9565b5f806040838503121561230b575f80fd5b612314836122b9565b946020939093013593505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f82518060208501845e5f920191825250919050565b602080825282548282018190525f8481528281209092916040850190845b8181101561229657835473ffffffffffffffffffffffffffffffffffffffff1683526001938401939285019201612383565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603160045260245ffd5b5f826123f0576123f06121e3565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f8000000000000000000000000000000000000000000000000000000000000000831416156124445761244461219f565b500590565b8181035f831280158383131683831282161715611d7b57611d7b61219f565b5f7f800000000000000000000000000000000000000000000000000000000000000082036124985761249861219f565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff019056fea2646970667358221220073db2e70be5fb6643350cc3b6ab48ab5ac987410c4a17e5281353bfe3d23a4964736f6c63430008190033" + }, + "0x1212100000000000000000000000000000000002": { + "balance": "0", + "code": "0x608060405234801561001057600080fd5b506004361061007d5760003560e01c806390ac18661161005b57806390ac1866146100e6578063d96ed505146100f9578063e47d606014610110578063e4997dc51461013357600080fd5b80630ecb93c014610082578063701b70ac1461009757806389dc5c84146100bf575b600080fd5b610095610090366004610899565b610146565b005b6100aa6100a5366004610899565b6102e5565b60405190151581526020015b60405180910390f35b6100ce600361090960911b0181565b6040516001600160a01b0390911681526020016100b6565b6100956100f43660046108bd565b6103bc565b61010260015481565b6040519081526020016100b6565b6100aa61011e366004610899565b60026020526000908152604090205460ff1681565b610095610141366004610899565b6104de565b604080516001600160a01b03831660208201527f4912b57f7ea75243ecaff76a75bdedbc13a6f58c1c967b0427b8aee0a276309e91016040516020818303038152906040528051906020012061019b336102e5565b6101c05760405162461bcd60e51b81526004016101b7906108d6565b60405180910390fd5b6101ca8282610625565b6101d48282610683565b6101dd57505050565b6001600160a01b03831660009081526002602052604090205460ff16156102465760405162461bcd60e51b815260206004820181905260248201527f506f6c6963793a20426c61636b6c69737420616c72656164792065786973747360448201526064016101b7565b6001600160a01b038316600081815260026020908152604091829020805460ff1916600117905590519182527ff9dfc5050bb4c9b200f093a995458a80fb19943585b189fe5d317391abdc764591015b60405180910390a160408051838152602081018390527ff5aa3d6492eaf1a4d6787c5bd36e8ec61c245d4af2fd1fd387e387a50de9f8c5910160405180910390a16102e08261079e565b505050565b600080600361090960911b016001600160a01b0316631633da6e6040518163ffffffff1660e01b8152600401600060405180830381865afa15801561032e573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610356919081019061091f565b905060005b81518110156103b257818181518110610376576103766109e4565b60200260200101516001600160a01b0316846001600160a01b0316036103a0575060019392505050565b806103aa81610a10565b91505061035b565b5060009392505050565b7f0d48c1723f9a97946a942509ee525d5449a8f1d6460432fc2b267126c5cb1bce816040516020016103f091815260200190565b6040516020818303038152906040528051906020012061040f336102e5565b61042b5760405162461bcd60e51b81526004016101b7906108d6565b6104358282610625565b61043f8282610683565b61044857505050565b600083116104a95760405162461bcd60e51b815260206004820152602860248201527f506f6c6963793a207365744d696e476173507269636520696e76616c6964207060448201526730b930b6b2ba32b960c11b60648201526084016101b7565b60018390556040518381527f707bb10a9a561bf00f6acc0b0231a12146dc98352b4e8c8deb55e141ace3289090602001610296565b604080516001600160a01b03831660208201527f310cc9bfce6443143f03d0cdc4d66afa0b3c689539eb3e65cb1820b56d672465910160405160208183030381529060405280519060200120610533336102e5565b61054f5760405162461bcd60e51b81526004016101b7906108d6565b6105598282610625565b6105638282610683565b61056c57505050565b6001600160a01b03831660009081526002602052604090205460ff166105d45760405162461bcd60e51b815260206004820181905260248201527f506f6c6963793a20426c61636b6c69737420646f6573206e6f7420657869737460448201526064016101b7565b6001600160a01b038316600081815260026020908152604091829020805460ff1916905590519182527f2234edb6f393cd207251f6579b5852192c144c4c12b9cc32e80539ef12faed3f9101610296565b6000828152602081815260408083203380855290835292819020849055805192835290820184905281018290527f61699483e2a58589628399a22e34da872b583143ab99b3245ba6dacf4974d2e39060600160405180910390a15050565b600080600361090960911b016001600160a01b0316631633da6e6040518163ffffffff1660e01b8152600401600060405180830381865afa1580156106cc573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526106f4919081019061091f565b90506000805b82518110156107785784600080888152602001908152602001600020600085848151811061072a5761072a6109e4565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205403610766578161076281610a10565b9250505b8061077081610a10565b9150506106fa565b506003825160026107899190610a29565b6107939190610a40565b109150505b92915050565b6000600361090960911b016001600160a01b0316631633da6e6040518163ffffffff1660e01b8152600401600060405180830381865afa1580156107e6573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261080e919081019061091f565b905060005b81518110156102e0576000808481526020019081526020016000206000838381518110610842576108426109e4565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060009055808061087990610a10565b915050610813565b6001600160a01b038116811461089657600080fd5b50565b6000602082840312156108ab57600080fd5b81356108b681610881565b9392505050565b6000602082840312156108cf57600080fd5b5035919050565b6020808252600990820152682737ba1026b4b732b960b91b604082015260600190565b634e487b7160e01b600052604160045260246000fd5b805161091a81610881565b919050565b6000602080838503121561093257600080fd5b825167ffffffffffffffff8082111561094a57600080fd5b818501915085601f83011261095e57600080fd5b815181811115610970576109706108f9565b8060051b604051601f19603f83011681018181108582111715610995576109956108f9565b6040529182528482019250838101850191888311156109b357600080fd5b938501935b828510156109d8576109c98561090f565b845293850193928501926109b8565b98975050505050505050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600060018201610a2257610a226109fa565b5060010190565b8082028115828204841417610798576107986109fa565b600082610a5d57634e487b7160e01b600052601260045260246000fd5b50049056fea264697066735822122004d5477279b034c92f8cb848eaee962c9b62e3143e7901fe1f481a30e1ef748e64736f6c63430008120033" } } }