diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 159c47ca0191..bf5fbe4ab94b 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -155,6 +155,16 @@ var ( Usage: "Holesky network: pre-configured proof-of-stake test network", Category: flags.EthCategory, } + GnosisChainFlag = &cli.BoolFlag{ + Name: "gnosis", + Usage: "Gnosis chain network: pre-configured merged proof-of-authority test network", + Category: flags.EthCategory, + } + ChiadoFlag = &cli.BoolFlag{ + Name: "chiado", + Usage: "Chiado network: pre-configured merged proof-of-authority test network", + Category: flags.EthCategory, + } // Dev mode DeveloperFlag = &cli.BoolFlag{ Name: "dev", @@ -916,6 +926,8 @@ var ( GoerliFlag, SepoliaFlag, HoleskyFlag, + GnosisChainFlag, + ChiadoFlag, } // NetworkFlags is the flag group of all built-in supported networks. NetworkFlags = append([]cli.Flag{MainnetFlag}, TestnetFlags...) @@ -945,6 +957,12 @@ func MakeDataDir(ctx *cli.Context) string { if ctx.Bool(HoleskyFlag.Name) { return filepath.Join(path, "holesky") } + if ctx.Bool(GnosisChainFlag.Name) { + return filepath.Join(path, "gnosis") + } + if ctx.Bool(ChiadoFlag.Name) { + return filepath.Join(path, "chiado") + } return path } Fatalf("Cannot determine default data directory, please set manually (--datadir)") @@ -1007,6 +1025,10 @@ func setBootstrapNodes(ctx *cli.Context, cfg *p2p.Config) { urls = params.SepoliaBootnodes case ctx.Bool(GoerliFlag.Name): urls = params.GoerliBootnodes + case ctx.Bool(GnosisChainFlag.Name): + urls = params.GnosisBootnodes + case ctx.Bool(ChiadoFlag.Name): + urls = params.ChiadoBootnodes } } cfg.BootstrapNodes = mustParseBootnodes(urls) @@ -1434,6 +1456,10 @@ func SetDataDir(ctx *cli.Context, cfg *node.Config) { cfg.DataDir = filepath.Join(node.DefaultDataDir(), "sepolia") case ctx.Bool(HoleskyFlag.Name) && cfg.DataDir == node.DefaultDataDir(): cfg.DataDir = filepath.Join(node.DefaultDataDir(), "holesky") + case ctx.Bool(GnosisChainFlag.Name) && cfg.DataDir == node.DefaultDataDir(): + cfg.DataDir = filepath.Join(node.DefaultDataDir(), "gnosis") + case ctx.Bool(ChiadoFlag.Name) && cfg.DataDir == node.DefaultDataDir(): + cfg.DataDir = filepath.Join(node.DefaultDataDir(), "chiado") } } @@ -1585,7 +1611,7 @@ func CheckExclusive(ctx *cli.Context, args ...interface{}) { // SetEthConfig applies eth-related command line flags to the config. func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) { // Avoid conflicting network flags - CheckExclusive(ctx, MainnetFlag, DeveloperFlag, GoerliFlag, SepoliaFlag, HoleskyFlag) + CheckExclusive(ctx, MainnetFlag, DeveloperFlag, GoerliFlag, SepoliaFlag, HoleskyFlag, ChiadoFlag, GnosisChainFlag) CheckExclusive(ctx, DeveloperFlag, ExternalSignerFlag) // Can't use both ephemeral unlocked and external signer // Set configurations from CLI flags @@ -1754,6 +1780,18 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) { } cfg.Genesis = core.DefaultGoerliGenesisBlock() SetDNSDiscoveryDefaults(cfg, params.GoerliGenesisHash) + case ctx.Bool(GnosisChainFlag.Name): + if !ctx.IsSet(NetworkIdFlag.Name) { + cfg.NetworkId = 100 + } + cfg.Genesis = core.DefaultGnosisGenesisBlock() + SetDNSDiscoveryDefaults(cfg, params.GnosisGenesisHash) + case ctx.Bool(ChiadoFlag.Name): + if !ctx.IsSet(NetworkIdFlag.Name) { + cfg.NetworkId = 10200 + } + cfg.Genesis = core.DefaultChiadoGenesisBlock() + SetDNSDiscoveryDefaults(cfg, params.ChiadoGenesisHash) case ctx.Bool(DeveloperFlag.Name): if !ctx.IsSet(NetworkIdFlag.Name) { cfg.NetworkId = 1337 @@ -2063,6 +2101,10 @@ func MakeGenesis(ctx *cli.Context) *core.Genesis { genesis = core.DefaultSepoliaGenesisBlock() case ctx.Bool(GoerliFlag.Name): genesis = core.DefaultGoerliGenesisBlock() + case ctx.Bool(GnosisChainFlag.Name): + genesis = core.DefaultGnosisGenesisBlock() + case ctx.Bool(ChiadoFlag.Name): + genesis = core.DefaultChiadoGenesisBlock() case ctx.Bool(DeveloperFlag.Name): Fatalf("Developer chains are ephemeral") } diff --git a/consensus/aura/aura.go b/consensus/aura/aura.go new file mode 100644 index 000000000000..44f57dd86b12 --- /dev/null +++ b/consensus/aura/aura.go @@ -0,0 +1,1456 @@ +// Copyright 2017 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package aura + +import ( + "bytes" + "container/list" + "errors" + "fmt" + "math/big" + "sort" + "sync" + "sync/atomic" + "time" + + // "github.com/ethereum/erigon-lib/kv" + + "github.com/cockroachdb/pebble" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/consensus" + "github.com/ethereum/go-ethereum/consensus/clique" + "github.com/ethereum/go-ethereum/consensus/misc" + // "github.com/ethereum/go-ethereum/consensus/misc/eip1559" + "github.com/ethereum/go-ethereum/core/rawdb" + "github.com/ethereum/go-ethereum/core/state" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/ethdb" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/params" + "github.com/ethereum/go-ethereum/rlp" + "github.com/ethereum/go-ethereum/rpc" + "github.com/ethereum/go-ethereum/trie" + "github.com/holiman/uint256" + "golang.org/x/exp/constraints" + "golang.org/x/exp/slices" +) + +const DEBUG_LOG_FROM = 999_999_999 + +var ( + errOlderBlockTime = errors.New("timestamp older than parent") + + allowedFutureBlockTimeSeconds = int64(15) // Max seconds from current time allowed for blocks, before they're considered future blocks +) + +/* +Not implemented features from OS: + - two_thirds_majority_transition - because no chains in OE where this is != MaxUint64 - means 1/2 majority used everywhere + - emptyStepsTransition - same + +Repo with solidity sources: https://github.com/poanetwork/posdao-contracts +*/ + +type StepDurationInfo struct { + TransitionStep uint64 + TransitionTimestamp uint64 + StepDuration uint64 +} + +// EpochTransitionProof - Holds 2 proofs inside: ValidatorSetProof and FinalityProof +type EpochTransitionProof struct { + SignalNumber uint64 + SetProof []byte + FinalityProof []byte +} + +// ValidatorSetProof - validator set proof +type ValidatorSetProof struct { + Header *types.Header + Receipts types.Receipts +} + +// FirstValidatorSetProof state-dependent proofs for the safe contract: +// only "first" proofs are such. +type FirstValidatorSetProof struct { // TODO: whaaat? here is no state! + ContractAddress common.Address + Header *types.Header +} + +type EpochTransition struct { + /// Block hash at which the transition occurred. + BlockHash common.Hash + /// Block number at which the transition occurred. + BlockNumber uint64 + /// "transition/epoch" proof from the engine combined with a finality proof. + ProofRlp []byte +} + +type Step struct { + calibrate bool // whether calibration is enabled. + inner atomic.Uint64 + // Planned durations of steps. + durations []StepDurationInfo +} + +func (s *Step) doCalibrate() { + if s.calibrate { + if !s.optCalibrate() { + ctr := s.inner.Load() + panic(fmt.Errorf("step counter under- or overflow: %d", ctr)) + } + } +} + +// optCalibrate Calibrates the AuRa step number according to the current time. +func (s *Step) optCalibrate() bool { + now := time.Now().Unix() + var info StepDurationInfo + i := 0 + for _, d := range s.durations { + if d.TransitionTimestamp >= uint64(now) { + break + } + info = d + i++ + } + if i == 0 { + panic("durations cannot be empty") + } + + if uint64(now) < info.TransitionTimestamp { + return false + } + + newStep := (uint64(now)-info.TransitionTimestamp)/info.StepDuration + info.TransitionStep + s.inner.Store(newStep) + return true +} + +type PermissionedStep struct { + inner *Step + canPropose atomic.Bool +} + +type ReceivedStepHashes map[uint64]map[common.Address]common.Hash //BTreeMap<(u64, Address), H256> + +// nolint +func (r ReceivedStepHashes) get(step uint64, author common.Address) (common.Hash, bool) { + res, ok := r[step] + if !ok { + return common.Hash{}, false + } + result, ok := res[author] + return result, ok +} + +// nolint +func (r ReceivedStepHashes) insert(step uint64, author common.Address, blockHash common.Hash) { + res, ok := r[step] + if !ok { + res = map[common.Address]common.Hash{} + r[step] = res + } + res[author] = blockHash +} + +// nolint +func (r ReceivedStepHashes) dropAncient(step uint64) { + for i := range r { + if i < step { + delete(r, i) + } + } +} + +// nolint +type EpochManager struct { + epochTransitionHash common.Hash // H256, + epochTransitionNumber uint64 // BlockNumber + finalityChecker *RollingFinality + force bool +} + +func NewEpochManager() *EpochManager { + return &EpochManager{ + finalityChecker: NewRollingFinality([]common.Address{}), + force: true, + } +} + +func (e *EpochManager) noteNewEpoch() { e.force = true } + +// zoomValidators - Zooms to the epoch after the header with the given hash. Returns true if succeeded, false otherwise. +// It's analog of zoom_to_after function in OE, but doesn't require external locking +// nolint +func (e *EpochManager) zoomToAfter(chain consensus.ChainHeaderReader, er *NonTransactionalEpochReader, validators ValidatorSet, hash common.Hash, call Syscall) (*RollingFinality, uint64, bool) { + var lastWasParent bool + if e.finalityChecker.lastPushed != nil { + lastWasParent = *e.finalityChecker.lastPushed == hash + } + + // early exit for current target == chain head, but only if the epochs are + // the same. + if lastWasParent && !e.force { + return e.finalityChecker, e.epochTransitionNumber, true + } + e.force = false + + // epoch_transition_for can be an expensive call, but in the absence of + // forks it will only need to be called for the block directly after + // epoch transition, in which case it will be O(1) and require a single + // DB lookup. + lastTransition, ok := epochTransitionFor(chain, er, hash) + if !ok { + if lastTransition.BlockNumber > DEBUG_LOG_FROM { + fmt.Printf("zoom1: %d\n", lastTransition.BlockNumber) + } + return e.finalityChecker, e.epochTransitionNumber, false + } + + // extract other epoch set if it's not the same as the last. + if lastTransition.BlockHash != e.epochTransitionHash { + proof := &EpochTransitionProof{} + if err := rlp.DecodeBytes(lastTransition.ProofRlp, proof); err != nil { + panic(err) + } + first := proof.SignalNumber == 0 + if lastTransition.BlockNumber > DEBUG_LOG_FROM { + fmt.Printf("zoom2: %d,%d\n", lastTransition.BlockNumber, len(proof.SetProof)) + } + + // use signal number so multi-set first calculation is correct. + list, _, err := validators.epochSet(first, proof.SignalNumber, proof.SetProof, call) + if err != nil { + panic(fmt.Errorf("proof produced by this engine is invalid: %w", err)) + } + epochSet := list.validators + log.Trace("[aura] Updating finality checker with new validator set extracted from epoch", "num", lastTransition.BlockNumber) + e.finalityChecker = NewRollingFinality(epochSet) + if proof.SignalNumber >= DEBUG_LOG_FROM { + fmt.Printf("new rolling finality: %d\n", proof.SignalNumber) + for i := 0; i < len(epochSet); i++ { + fmt.Printf("\t%x\n", epochSet[i]) + } + } + } + + e.epochTransitionHash = lastTransition.BlockHash + e.epochTransitionNumber = lastTransition.BlockNumber + return e.finalityChecker, e.epochTransitionNumber, true +} + +// / Get the transition to the epoch the given parent hash is part of +// / or transitions to. +// / This will give the epoch that any children of this parent belong to. +// / +// / The block corresponding the the parent hash must be stored already. +// nolint +func epochTransitionFor(chain consensus.ChainHeaderReader, e *NonTransactionalEpochReader, parentHash common.Hash) (transition EpochTransition, ok bool) { + //TODO: probably this version of func doesn't support non-canonical epoch transitions + h := chain.GetHeaderByHash(parentHash) + if h == nil { + return transition, false + } + num, hash, transitionProof, err := e.FindBeforeOrEqualNumber(h.Number.Uint64()) + if err != nil { + panic(err) + } + if transitionProof == nil { + panic("genesis epoch transition must already be set") + } + return EpochTransition{BlockNumber: num, BlockHash: hash, ProofRlp: transitionProof}, true +} + +type Syscall func(common.Address, []byte) ([]byte, error) + +// AuRa +// nolint +type AuRa struct { + e *NonTransactionalEpochReader + exitCh chan struct{} + lock sync.RWMutex // Protects the signer fields + + step PermissionedStep + // History of step hashes recently received from peers. + receivedStepHashes ReceivedStepHashes + + cfg AuthorityRoundParams + EmptyStepsSet *EmptyStepSet + EpochManager *EpochManager // Mutex, + + certifier *common.Address // certifies service transactions + certifierLock sync.RWMutex + + Syscall Syscall +} + +func SortedKeys[K constraints.Ordered, V any](m map[K]V) []K { + keys := make([]K, len(m)) + i := 0 + for k := range m { + keys[i] = k + i++ + } + slices.Sort(keys) + return keys +} + +func NewAuRa(spec *params.AuRaConfig, db ethdb.KeyValueStore) (*AuRa, error) { + auraParams, err := FromJson(spec) + if err != nil { + return nil, err + } + + if _, ok := auraParams.StepDurations[0]; !ok { + return nil, fmt.Errorf("authority Round step 0 duration is undefined") + } + for _, v := range auraParams.StepDurations { + if v == 0 { + return nil, fmt.Errorf("authority Round step duration cannot be 0") + } + } + //shouldTimeout := auraParams.StartStep == nil + initialStep := uint64(0) + if auraParams.StartStep != nil { + initialStep = *auraParams.StartStep + } + durations := make([]StepDurationInfo, 0, 1+len(auraParams.StepDurations)) + durInfo := StepDurationInfo{ + TransitionStep: 0, + TransitionTimestamp: 0, + StepDuration: auraParams.StepDurations[0], + } + durations = append(durations, durInfo) + times := SortedKeys(auraParams.StepDurations) + for i := 1; i < len(auraParams.StepDurations); i++ { // skip first + time := times[i] + dur := auraParams.StepDurations[time] + step, t, ok := nextStepTimeDuration(durInfo, time) + if !ok { + return nil, fmt.Errorf("timestamp overflow") + } + durInfo.TransitionStep = step + durInfo.TransitionTimestamp = t + durInfo.StepDuration = dur + durations = append(durations, durInfo) + } + step := &Step{ + calibrate: auraParams.StartStep == nil, + durations: durations, + } + step.inner.Store(initialStep) + step.doCalibrate() + + /* + let engine = Arc::new(AuthorityRound { + epoch_manager: Mutex::new(EpochManager::blank()), + received_step_hashes: RwLock::new(Default::default()), + gas_limit_override_cache: Mutex::new(LruCache::new(GAS_LIMIT_OVERRIDE_CACHE_CAPACITY)), + }) + // Do not initialize timeouts for tests. + if should_timeout { + let handler = TransitionHandler { + step: engine.step.clone(), + client: engine.client.clone(), + }; + engine + .transition_service + .register_handler(Arc::new(handler))?; + } + */ + + exitCh := make(chan struct{}) + + c := &AuRa{ + e: newEpochReader(db), + exitCh: exitCh, + step: PermissionedStep{inner: step}, + cfg: auraParams, + receivedStepHashes: ReceivedStepHashes{}, + EpochManager: NewEpochManager(), + } + c.step.canPropose.Store(true) + + return c, nil +} + +type epochReader interface { + GetEpoch(blockHash common.Hash, blockN uint64) (transitionProof []byte, err error) + GetPendingEpoch(blockHash common.Hash, blockN uint64) (transitionProof []byte, err error) + FindBeforeOrEqualNumber(number uint64) (blockNum uint64, blockHash common.Hash, transitionProof []byte, err error) +} +type epochWriter interface { + epochReader + PutEpoch(blockHash common.Hash, blockN uint64, transitionProof []byte) (err error) + PutPendingEpoch(blockHash common.Hash, blockN uint64, transitionProof []byte) (err error) +} + +type NonTransactionalEpochReader struct { + db ethdb.KeyValueStore +} + +func newEpochReader(db ethdb.KeyValueStore) *NonTransactionalEpochReader { + return &NonTransactionalEpochReader{db: db} +} + +func (cr *NonTransactionalEpochReader) GetEpoch(hash common.Hash, number uint64) (v []byte, err error) { + return rawdb.ReadEpoch(cr.db, number, hash) +} +func (cr *NonTransactionalEpochReader) PutEpoch(hash common.Hash, number uint64, proof []byte) error { + return rawdb.WriteEpoch(cr.db, number, hash, proof) +} +func (cr *NonTransactionalEpochReader) GetPendingEpoch(hash common.Hash, number uint64) (v []byte, err error) { + return rawdb.ReadPendingEpoch(cr.db, number, hash) +} +func (cr *NonTransactionalEpochReader) PutPendingEpoch(hash common.Hash, number uint64, proof []byte) error { + return rawdb.WritePendingEpoch(cr.db, number, hash, proof) +} +func (cr *NonTransactionalEpochReader) FindBeforeOrEqualNumber(number uint64) (blockNum uint64, blockHash common.Hash, transitionProof []byte, err error) { + return rawdb.FindEpochBeforeOrEqualNumber(cr.db, number) +} + +// A helper accumulator function mapping a step duration and a step duration transition timestamp +// to the corresponding step number and the correct starting second of the step. +func nextStepTimeDuration(info StepDurationInfo, time uint64) (uint64, uint64, bool) { + stepDiff := time + info.StepDuration + if stepDiff < 1 { + return 0, 0, false + } + stepDiff -= 1 + if stepDiff < info.TransitionTimestamp { + return 0, 0, false + } + stepDiff -= info.TransitionTimestamp + if info.StepDuration == 0 { + return 0, 0, false + } + stepDiff /= info.StepDuration + timeDiff := stepDiff * info.StepDuration + return info.TransitionStep + stepDiff, info.TransitionTimestamp + timeDiff, true +} + +// Type returns underlying consensus engine +// func (c *AuRa) Type() chain.ConsensusName { +// return chain.AuRaConsensus +// } + +// Author implements consensus.Engine, returning the Ethereum address recovered +// from the signature in the header's extra-data section. +// This is thread-safe (only access the Coinbase of the header) +func (c *AuRa) Author(header *types.Header) (common.Address, error) { + /* + let message = keccak(empty_step_rlp(self.step, &self.parent_hash)); + let public = publickey::recover(&self.signature.into(), &message)?; + Ok(publickey::public_to_address(&public)) + */ + return header.Coinbase, nil +} + +// VerifyHeader checks whether a header conforms to the consensus rules. +func (c *AuRa) VerifyHeader(chain consensus.ChainHeaderReader, header *types.Header) error { + // Ensure that the header's extra-data section is of a reasonable size + if uint64(len(header.Extra)) > params.MaximumExtraDataSize { + return fmt.Errorf("extra-data too long: %d > %d", len(header.Extra), params.MaximumExtraDataSize) + } + // Verify the header's timestamp + unixNow := time.Now().Unix() + if header.Time > uint64(unixNow+allowedFutureBlockTimeSeconds) { + return consensus.ErrFutureBlock + } + // Verify that the gas limit is <= 2^63-1 + if header.GasLimit > params.MaxGasLimit { + return fmt.Errorf("invalid gasLimit: have %v, max %v", header.GasLimit, params.MaxGasLimit) + } + // Verify that the gasUsed is <= gasLimit + if header.GasUsed > header.GasLimit { + return fmt.Errorf("invalid gasUsed: have %d, gasLimit %d", header.GasUsed, header.GasLimit) + } + // Verify the block's gas usage and (if applicable) verify the base fee. + + // Verify that the block number is parent's +1 + + // Verify the non-existence of withdrawalsHash. + if header.WithdrawalsHash != nil { + return fmt.Errorf("invalid withdrawalsHash: have %x, expected nil", header.WithdrawalsHash) + } + + // Verify the non-existence of cancun-specific header fields + switch { + case header.ExcessBlobGas != nil: + return fmt.Errorf("invalid excessBlobGas: have %d, expected nil", header.ExcessBlobGas) + case header.BlobGasUsed != nil: + return fmt.Errorf("invalid blobGasUsed: have %d, expected nil", header.BlobGasUsed) + case header.ParentBeaconRoot != nil: + return fmt.Errorf("invalid parentBeaconRoot, have %#x, expected nil", header.ParentBeaconRoot) + } + + // If all checks passed, validate any special fields for hard forks + if err := misc.VerifyDAOHeaderExtraData(chain.Config(), header); err != nil { + return err + } + return nil + +} + +func (c *AuRa) VerifyHeaders(chain consensus.ChainHeaderReader, headers []*types.Header) (chan<- struct{}, <-chan error) { + abort := make(chan struct{}) + results := make(chan error, len(headers)) + + go func() { + for _, header := range headers { + err := c.VerifyHeader(chain, header) + + select { + case <-abort: + return + case results <- err: + } + } + }() + return abort, results +} + +// nolint +func (c *AuRa) hasReceivedStepHashes(step uint64, author common.Address, newHash common.Hash) bool { + /* + self + .received_step_hashes + .read() + .get(&received_step_key) + .map_or(false, |h| *h != new_hash) + */ + return false +} + +// nolint +func (c *AuRa) insertReceivedStepHashes(step uint64, author common.Address, newHash common.Hash) { + /* + self.received_step_hashes + .write() + .insert(received_step_key, new_hash); + */ +} + +// VerifyUncles implements consensus.Engine, always returning an error for any +// uncles as this consensus mechanism doesn't permit uncles. +func (c *AuRa) VerifyUncles(chain consensus.ChainReader, header *types.Block) error { + return nil + //if len(uncles) > 0 { + // return errors.New("uncles not allowed") + //} + //return nil +} + +// VerifySeal implements consensus.Engine, checking whether the signature contained +// in the header satisfies the consensus protocol requirements. +// func (c *AuRa) VerifySeal(chain consensus.ChainHeaderReader, header *types.Header) error { +// return nil +//snap, err := c.Snapshot(chain, header.Number.Uint64(), header.Hash(), nil) +//if err != nil { +// return err +//} +//return c.verifySeal(chain, header, snap) +// } + +// Prepare implements consensus.Engine, preparing all the consensus fields of the +// header for running the transactions on top. +func (c *AuRa) Prepare(chain consensus.ChainHeaderReader, header *types.Header, statedb *state.StateDB) error { + // return nil + /// If the block isn't a checkpoint, cast a random vote (good enough for now) + //header.Coinbase = common.Address{} + //header.Nonce = types.BlockNonce{} + // + //number := header.Number.Uint64() + /// Assemble the voting snapshot to check which votes make sense + //snap, err := c.Snapshot(chain, number-1, header.ParentHash, nil) + //if err != nil { + // return err + //} + //if number%c.config.Epoch != 0 { + // c.lock.RLock() + // + // // Gather all the proposals that make sense voting on + // addresses := make([]common.Address, 0, len(c.proposals)) + // for address, authorize := range c.proposals { + // if snap.validVote(address, authorize) { + // addresses = append(addresses, address) + // } + // } + // // If there's pending proposals, cast a vote on them + // if len(addresses) > 0 { + // header.Coinbase = addresses[rand.Intn(len(addresses))] + // if c.proposals[header.Coinbase] { + // copy(header.Nonce[:], NonceAuthVote) + // } else { + // copy(header.Nonce[:], nonceDropVote) + // } + // } + // c.lock.RUnlock() + //} + /// Set the correct difficulty + //header.Difficulty = calcDifficulty(snap, c.signer) + // + /// Ensure the extra data has all its components + //if len(header.Extra) < ExtraVanity { + // header.Extra = append(header.Extra, bytes.Repeat([]byte{0x00}, ExtraVanity-len(header.Extra))...) + //} + //header.Extra = header.Extra[:ExtraVanity] + // + //if number%c.config.Epoch == 0 { + // for _, signer := range snap.GetSigners() { + // header.Extra = append(header.Extra, signer[:]...) + // } + //} + //header.Extra = append(header.Extra, make([]byte, ExtraSeal)...) + // + /// Mix digest is reserved for now, set to empty + //header.MixDigest = common.Hash{} + // + /// Ensure the timestamp has the correct delay + //parent := chain.GetHeader(header.ParentHash, number-1) + //if parent == nil { + // return consensus.ErrUnknownAncestor + //} + //header.Time = parent.Time + c.config.Period + // + //now := uint64(time.Now().Unix()) + //if header.Time < now { + // header.Time = now + //} + // + //return nil + // } + + c.verifyGasLimitOverride(chain.Config(), chain, header, statedb, c.Syscall) + + // func (c *AuRa) Initialize(config *params.ChainConfig, chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []types.Transaction, uncles []*types.Header, syscall consensus.SystemCall) { + blockNum := header.Number.Uint64() + for address, rewrittenCode := range c.cfg.RewriteBytecode[blockNum] { + statedb.SetCode(address, rewrittenCode) + } + + c.certifierLock.Lock() + if c.cfg.Registrar != nil && c.certifier == nil && chain.Config().IsLondon(header.Number) { + c.certifier = getCertifier(*c.cfg.Registrar, c.Syscall) + } + c.certifierLock.Unlock() + + if blockNum == 1 { + proof, err := c.GenesisEpochData(header) + if err != nil { + panic(err) + } + err = c.e.PutEpoch(header.ParentHash, 0, proof) //TODO: block 0 hardcoded - need fix it inside validators + if err != nil { + panic(err) + } + } + + //if err := c.verifyFamily(chain, e, header, call, syscall); err != nil { //TODO: OE has it as a separate engine call? why? + // panic(err) + //} + + // check_and_lock_block -> check_epoch_end_signal + + epoch, err := c.e.GetEpoch(header.ParentHash, blockNum-1) + if err != nil { + return err + } + isEpochBegin := epoch != nil + if !isEpochBegin { + return nil + } + return c.cfg.Validators.onEpochBegin(isEpochBegin, header, c.Syscall) + // check_and_lock_block -> check_epoch_end_signal END (before enact) + +} + +func (c *AuRa) ApplyRewards(header *types.Header, state *state.StateDB) error { + rewards, err := c.CalculateRewards(nil, header, nil) + if err != nil { + return err + } + for _, r := range rewards { + state.AddBalance(r.Beneficiary, &r.Amount) + } + return nil +} + +// word `signal epoch` == word `pending epoch` +func (c *AuRa) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, withdrawals []*types.Withdrawal, receipts []*types.Receipt) { + if err := c.ApplyRewards(header, state); err != nil { + panic(err) + } + + // check_and_lock_block -> check_epoch_end_signal (after enact) + if header.Number.Uint64() >= DEBUG_LOG_FROM { + fmt.Printf("finalize1: %d,%d\n", header.Number.Uint64(), len(receipts)) + } + pendingTransitionProof, err := c.cfg.Validators.signalEpochEnd(header.Number.Uint64() == 0, header, receipts) + if err != nil { + panic(err) + } + if pendingTransitionProof != nil { + if header.Number.Uint64() >= DEBUG_LOG_FROM { + fmt.Printf("insert_pending_transition: %d,receipts=%d, lenProof=%d\n", header.Number.Uint64(), len(receipts), len(pendingTransitionProof)) + } + if err = c.e.PutPendingEpoch(header.Hash(), header.Number.Uint64(), pendingTransitionProof); err != nil { + panic(err) + } + } + // check_and_lock_block -> check_epoch_end_signal END + + finalized := buildFinality(c.EpochManager, chain, c.e, c.cfg.Validators, header, c.Syscall) + c.EpochManager.finalityChecker.print(header.Number.Uint64()) + epochEndProof, err := isEpochEnd(chain, c.e, finalized, header) + if err != nil { + panic(err) + } + if epochEndProof != nil { + c.EpochManager.noteNewEpoch() + log.Info("[aura] epoch transition", "block_num", header.Number.Uint64()) + if err := c.e.PutEpoch(header.Hash(), header.Number.Uint64(), epochEndProof); err != nil { + panic(err) + } + } +} + +func buildFinality(e *EpochManager, chain consensus.ChainHeaderReader, er *NonTransactionalEpochReader, validators ValidatorSet, header *types.Header, syscall Syscall) []unAssembledHeader { + // commit_block -> aura.build_finality + _, _, ok := e.zoomToAfter(chain, er, validators, header.ParentHash, syscall) + if !ok { + return []unAssembledHeader{} + } + if e.finalityChecker.lastPushed == nil || *e.finalityChecker.lastPushed != header.ParentHash { + if err := e.finalityChecker.buildAncestrySubChain(func(hash common.Hash) ([]common.Address, common.Hash, common.Hash, uint64, bool) { + h := chain.GetHeaderByHash(hash) + if h == nil { + return nil, common.Hash{}, common.Hash{}, 0, false + } + return []common.Address{h.Coinbase}, h.Hash(), h.ParentHash, h.Number.Uint64(), true + }, header.ParentHash, e.epochTransitionHash); err != nil { + //log.Warn("[aura] buildAncestrySubChain", "err", err) + return []unAssembledHeader{} + } + } + + res, err := e.finalityChecker.push(header.Hash(), header.Number.Uint64(), []common.Address{header.Coinbase}) + if err != nil { + //log.Warn("[aura] finalityChecker.push", "err", err) + return []unAssembledHeader{} + } + return res +} + +func isEpochEnd(chain consensus.ChainHeaderReader, e *NonTransactionalEpochReader, finalized []unAssembledHeader, header *types.Header) ([]byte, error) { + // commit_block -> aura.is_epoch_end + for i := range finalized { + pendingTransitionProof, err := e.GetPendingEpoch(finalized[i].hash, finalized[i].number) + // GNOSIS: pebble returns an error when a non-existent value + // isn't found, which is what happens at genesis. + if err != nil && !errors.Is(err, pebble.ErrNotFound) { + return nil, err + } + if pendingTransitionProof == nil { + continue + } + if header.Number.Uint64() >= DEBUG_LOG_FROM { + fmt.Printf("pending transition: %d,%x,len=%d\n", finalized[i].number, finalized[i].hash, len(pendingTransitionProof)) + } + + finalityProof := allHeadersUntil(chain, header, finalized[i].hash) + var finalizedHeader *types.Header + if finalized[i].hash == header.Hash() { + finalizedHeader = header + } else { + finalizedHeader = chain.GetHeader(finalized[i].hash, finalized[i].number) + } + signalNumber := finalizedHeader.Number + finalityProof = append(finalityProof, finalizedHeader) + for i, j := 0, len(finalityProof)-1; i < j; i, j = i+1, j-1 { // reverse + finalityProof[i], finalityProof[j] = finalityProof[j], finalityProof[i] + } + finalityProofRLP, err := rlp.EncodeToBytes(finalityProof) + if err != nil { + return nil, err + } + /* + // We turn off can_propose here because upon validator set change there can + // be two valid proposers for a single step: one from the old set and + // one from the new. + // + // This way, upon encountering an epoch change, the proposer from the + // new set will be forced to wait until the next step to avoid sealing a + // block that breaks the invariant that the parent's step < the block's step. + self.step.can_propose.store(false, AtomicOrdering::SeqCst); + */ + return rlp.EncodeToBytes(EpochTransitionProof{SignalNumber: signalNumber.Uint64(), SetProof: pendingTransitionProof, FinalityProof: finalityProofRLP}) + } + return nil, nil +} + +// allHeadersUntil walk the chain backwards from current head until finalized_hash +// to construct transition proof. author == ec_recover(sig) known +// since the blocks are in the DB. +func allHeadersUntil(chain consensus.ChainHeaderReader, from *types.Header, to common.Hash) (out []*types.Header) { + var header = from + for { + header = chain.GetHeader(header.ParentHash, header.Number.Uint64()-1) + if header == nil { + panic("not found header") + } + if header.Number.Uint64() == 0 { + break + } + if to == header.Hash() { + break + } + out = append(out, header) + } + return out +} + +//func (c *AuRa) check_epoch_end(cc *params.ChainConfig, header *types.Header, state *state.StateDB, txs []types.Transaction, uncles []*types.Header, syscall consensus.SystemCall) { +//} + +// FinalizeAndAssemble implements consensus.Engine +func (c *AuRa) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt, withdrawals []*types.Withdrawal) (*types.Block, error) { + c.Finalize(chain, header, state, txs, uncles, withdrawals, receipts) + + // Assemble and return the final block for sealing + return types.NewBlockWithWithdrawals(header, txs, uncles, receipts, withdrawals, trie.NewStackTrie(nil)), nil +} + +// Authorize injects a private key into the consensus engine to mint new blocks +// with. +func (c *AuRa) Authorize(signer common.Address, signFn clique.SignerFn) { + c.lock.Lock() + defer c.lock.Unlock() + + //c.signer = signer + //c.signFn = signFn +} + +func (c *AuRa) GenesisEpochData(header *types.Header) ([]byte, error) { + setProof, err := c.cfg.Validators.genesisEpochData(header, c.Syscall) + if err != nil { + return nil, err + } + res, err := rlp.EncodeToBytes(EpochTransitionProof{SignalNumber: 0, SetProof: setProof, FinalityProof: []byte{}}) + if err != nil { + panic(err) + } + //fmt.Printf("reere: %x\n", res) + //f91a84f9020da00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0fad4af258fd11939fae0c6c6eec9d340b1caac0b0196fd9a1bc3f489c5bf00b3a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200008083663be080808080b8410000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f91871b914c26060604052600436106100fc576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806303aca79214610101578063108552691461016457806340a141ff1461019d57806340c9cdeb146101d65780634110a489146101ff57806345199e0a1461025757806349285b58146102c15780634d238c8e14610316578063752862111461034f578063900eb5a8146103645780639a573786146103c7578063a26a47d21461041c578063ae4b1b5b14610449578063b3f05b971461049e578063b7ab4db5146104cb578063d3e848f114610535578063fa81b2001461058a578063facd743b146105df575b600080fd5b341561010c57600080fd5b6101226004808035906020019091905050610630565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561016f57600080fd5b61019b600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190505061066f565b005b34156101a857600080fd5b6101d4600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610807565b005b34156101e157600080fd5b6101e9610bb7565b6040518082815260200191505060405180910390f35b341561020a57600080fd5b610236600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610bbd565b60405180831515151581526020018281526020019250505060405180910390f35b341561026257600080fd5b61026a610bee565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156102ad578082015181840152602081019050610292565b505050509050019250505060405180910390f35b34156102cc57600080fd5b6102d4610c82565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561032157600080fd5b61034d600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610d32565b005b341561035a57600080fd5b610362610fcc565b005b341561036f57600080fd5b61038560048080359060200190919050506110fc565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156103d257600080fd5b6103da61113b565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561042757600080fd5b61042f6111eb565b604051808215151515815260200191505060405180910390f35b341561045457600080fd5b61045c6111fe565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156104a957600080fd5b6104b1611224565b604051808215151515815260200191505060405180910390f35b34156104d657600080fd5b6104de611237565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b83811015610521578082015181840152602081019050610506565b505050509050019250505060405180910390f35b341561054057600080fd5b6105486112cb565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561059557600080fd5b61059d6112f1565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156105ea57600080fd5b610616600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050611317565b604051808215151515815260200191505060405180910390f35b60078181548110151561063f57fe5b90600052602060002090016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600460029054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415156106cb57600080fd5b600460019054906101000a900460ff161515156106e757600080fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415151561072357600080fd5b80600a60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506001600460016101000a81548160ff0219169083151502179055507f600bcf04a13e752d1e3670a5a9f1c21177ca2a93c6f5391d4f1298d098097c22600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a150565b600080600061081461113b565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561084d57600080fd5b83600960008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900460ff1615156108a957600080fd5b600960008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101549350600160078054905003925060078381548110151561090857fe5b906000526020600020900160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1691508160078581548110151561094657fe5b906000526020600020900160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555083600960008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101819055506007838154811015156109e557fe5b906000526020600020900160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556000600780549050111515610a2757600080fd5b6007805480919060019003610a3c9190611370565b506000600960008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101819055506000600960008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160006101000a81548160ff0219169083151502179055506000600460006101000a81548160ff0219169083151502179055506001430340600019167f55252fa6eee4741b4e24a74a70e9c11fd2c2281df8d6ea13126ff845f7825c89600760405180806020018281038252838181548152602001915080548015610ba257602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311610b58575b50509250505060405180910390a25050505050565b60085481565b60096020528060005260406000206000915090508060000160009054906101000a900460ff16908060010154905082565b610bf661139c565b6007805480602002602001604051908101604052809291908181526020018280548015610c7857602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311610c2e575b5050505050905090565b6000600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166349285b586000604051602001526040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b1515610d1257600080fd5b6102c65a03f11515610d2357600080fd5b50505060405180519050905090565b610d3a61113b565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610d7357600080fd5b80600960008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900460ff16151515610dd057600080fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614151515610e0c57600080fd5b6040805190810160405280600115158152602001600780549050815250600960008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548160ff0219169083151502179055506020820151816001015590505060078054806001018281610ea991906113b0565b9160005260206000209001600084909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550506000600460006101000a81548160ff0219169083151502179055506001430340600019167f55252fa6eee4741b4e24a74a70e9c11fd2c2281df8d6ea13126ff845f7825c89600760405180806020018281038252838181548152602001915080548015610fba57602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311610f70575b50509250505060405180910390a25050565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480156110365750600460009054906101000a900460ff16155b151561104157600080fd5b6001600460006101000a81548160ff0219169083151502179055506007600690805461106e9291906113dc565b506006805490506008819055507f8564cd629b15f47dc310d45bcbfc9bcf5420b0d51bf0659a16c67f91d27632536110a4611237565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156110e75780820151818401526020810190506110cc565b505050509050019250505060405180910390a1565b60068181548110151561110b57fe5b90600052602060002090016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16639a5737866000604051602001526040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b15156111cb57600080fd5b6102c65a03f115156111dc57600080fd5b50505060405180519050905090565b600460019054906101000a900460ff1681565b600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600460009054906101000a900460ff1681565b61123f61139c565b60068054806020026020016040519081016040528092919081815260200182805480156112c157602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311611277575b5050505050905090565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600460029054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000600960008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900460ff169050919050565b81548183558181151161139757818360005260206000209182019101611396919061142e565b5b505050565b602060405190810160405280600081525090565b8154818355818115116113d7578183600052602060002091820191016113d6919061142e565b5b505050565b82805482825590600052602060002090810192821561141d5760005260206000209182015b8281111561141c578254825591600101919060010190611401565b5b50905061142a9190611453565b5090565b61145091905b8082111561144c576000816000905550600101611434565b5090565b90565b61149391905b8082111561148f57600081816101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905550600101611459565b5090565b905600a165627a7a7230582036ea35935c8246b68074adece2eab70c40e69a0193c08a6277ce06e5b25188510029b8f3f8f1a08023c0d95fc2364e0bf7593f5ff32e1db8ef9f4b41c0bd474eae62d1af896e99808080a0b47b4f0b3e73b5edc8f9a9da1cbcfed562eb06bf54619b6aefeadebf5b3604c280a0da6ec08940a924cb08c947dd56cdb40076b29a6f0ea4dba4e2d02d9a9a72431b80a030cc4138c9e74b6cf79d624b4b5612c0fd888e91f55316cfee7d1694e1a90c0b80a0c5d54b915b56a888eee4e6eeb3141e778f9b674d1d322962eed900f02c29990aa017256b36ef47f907c6b1378a2636942ce894c17075e56fc054d4283f6846659e808080a03340bbaeafcda3a8672eb83099231dbbfab8dae02a1e8ec2f7180538fac207e080b86bf869a033aa5d69545785694b808840be50c182dad2ec3636dfccbe6572fb69828742c0b846f8440101a0663ce0d171e545a26aa67e4ca66f72ba96bb48287dbcc03beea282867f80d44ba01f0e7726926cb43c03a0abf48197dba78522ec8ba1b158e2aa30da7d2a2c6f9eb838f7a03868bdfa8727775661e4ccf117824a175a33f8703d728c04488fbfffcafda9f99594e8ddc5c7a2d2f0d7a9798459c0104fdf5e987acaa3e2a02052222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f01b853f851808080a07bb75cabebdcbd1dbb4331054636d0c6d7a2b08483b9e04df057395a7434c9e080808080808080a0e61e567237b49c44d8f906ceea49027260b4010c10a547b38d8b131b9d3b6f848080808080b8d3f8d1a0dc277c93a9f9dcee99aac9b8ba3cfa4c51821998522469c37715644e8fbac0bfa0ab8cdb808c8303bb61fb48e276217be9770fa83ecf3f90f2234d558885f5abf1808080a0fe137c3a474fbde41d89a59dd76da4c55bf696b86d3af64a55632f76cf30786780808080a06301b39b2ea8a44df8b0356120db64b788e71f52e1d7a6309d0d2e5b86fee7cb80a0da5d8b08dea0c5a4799c0f44d8a24d7cdf209f9b7a5588c1ecafb5361f6b9f07a01b7779e149cadf24d4ffb77ca7e11314b8db7097e4d70b2a173493153ca2e5a0808080b853f851808080a0a87d9bb950836582673aa0eecc0ff64aac607870637a2dd2012b8b1b31981f698080a08da6d5c36a404670c553a2c9052df7cd604f04e3863c4c7b9e0027bfd54206d680808080808080808080b86bf869a02080c7b7ae81a58eb98d9c78de4a1fd7fd9535fc953ed2be602daaa41767312ab846f8448080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 + //f91a8c80b91a87f91a84f9020da00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0fad4af258fd11939fae0c6c6eec9d340b1caac0b0196fd9a1bc3f489c5bf00b3a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200008083663be080808080b8410000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f91871b914c26060604052600436106100fc576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806303aca79214610101578063108552691461016457806340a141ff1461019d57806340c9cdeb146101d65780634110a489146101ff57806345199e0a1461025757806349285b58146102c15780634d238c8e14610316578063752862111461034f578063900eb5a8146103645780639a573786146103c7578063a26a47d21461041c578063ae4b1b5b14610449578063b3f05b971461049e578063b7ab4db5146104cb578063d3e848f114610535578063fa81b2001461058a578063facd743b146105df575b600080fd5b341561010c57600080fd5b6101226004808035906020019091905050610630565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561016f57600080fd5b61019b600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190505061066f565b005b34156101a857600080fd5b6101d4600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610807565b005b34156101e157600080fd5b6101e9610bb7565b6040518082815260200191505060405180910390f35b341561020a57600080fd5b610236600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610bbd565b60405180831515151581526020018281526020019250505060405180910390f35b341561026257600080fd5b61026a610bee565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156102ad578082015181840152602081019050610292565b505050509050019250505060405180910390f35b34156102cc57600080fd5b6102d4610c82565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561032157600080fd5b61034d600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610d32565b005b341561035a57600080fd5b610362610fcc565b005b341561036f57600080fd5b61038560048080359060200190919050506110fc565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156103d257600080fd5b6103da61113b565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561042757600080fd5b61042f6111eb565b604051808215151515815260200191505060405180910390f35b341561045457600080fd5b61045c6111fe565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156104a957600080fd5b6104b1611224565b604051808215151515815260200191505060405180910390f35b34156104d657600080fd5b6104de611237565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b83811015610521578082015181840152602081019050610506565b505050509050019250505060405180910390f35b341561054057600080fd5b6105486112cb565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561059557600080fd5b61059d6112f1565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156105ea57600080fd5b610616600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050611317565b604051808215151515815260200191505060405180910390f35b60078181548110151561063f57fe5b90600052602060002090016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600460029054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415156106cb57600080fd5b600460019054906101000a900460ff161515156106e757600080fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415151561072357600080fd5b80600a60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506001600460016101000a81548160ff0219169083151502179055507f600bcf04a13e752d1e3670a5a9f1c21177ca2a93c6f5391d4f1298d098097c22600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a150565b600080600061081461113b565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561084d57600080fd5b83600960008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900460ff1615156108a957600080fd5b600960008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101549350600160078054905003925060078381548110151561090857fe5b906000526020600020900160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1691508160078581548110151561094657fe5b906000526020600020900160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555083600960008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101819055506007838154811015156109e557fe5b906000526020600020900160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556000600780549050111515610a2757600080fd5b6007805480919060019003610a3c9190611370565b506000600960008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101819055506000600960008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160006101000a81548160ff0219169083151502179055506000600460006101000a81548160ff0219169083151502179055506001430340600019167f55252fa6eee4741b4e24a74a70e9c11fd2c2281df8d6ea13126ff845f7825c89600760405180806020018281038252838181548152602001915080548015610ba257602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311610b58575b50509250505060405180910390a25050505050565b60085481565b60096020528060005260406000206000915090508060000160009054906101000a900460ff16908060010154905082565b610bf661139c565b6007805480602002602001604051908101604052809291908181526020018280548015610c7857602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311610c2e575b5050505050905090565b6000600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166349285b586000604051602001526040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b1515610d1257600080fd5b6102c65a03f11515610d2357600080fd5b50505060405180519050905090565b610d3a61113b565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610d7357600080fd5b80600960008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900460ff16151515610dd057600080fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614151515610e0c57600080fd5b6040805190810160405280600115158152602001600780549050815250600960008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548160ff0219169083151502179055506020820151816001015590505060078054806001018281610ea991906113b0565b9160005260206000209001600084909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550506000600460006101000a81548160ff0219169083151502179055506001430340600019167f55252fa6eee4741b4e24a74a70e9c11fd2c2281df8d6ea13126ff845f7825c89600760405180806020018281038252838181548152602001915080548015610fba57602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311610f70575b50509250505060405180910390a25050565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480156110365750600460009054906101000a900460ff16155b151561104157600080fd5b6001600460006101000a81548160ff0219169083151502179055506007600690805461106e9291906113dc565b506006805490506008819055507f8564cd629b15f47dc310d45bcbfc9bcf5420b0d51bf0659a16c67f91d27632536110a4611237565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156110e75780820151818401526020810190506110cc565b505050509050019250505060405180910390a1565b60068181548110151561110b57fe5b90600052602060002090016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16639a5737866000604051602001526040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b15156111cb57600080fd5b6102c65a03f115156111dc57600080fd5b50505060405180519050905090565b600460019054906101000a900460ff1681565b600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600460009054906101000a900460ff1681565b61123f61139c565b60068054806020026020016040519081016040528092919081815260200182805480156112c157602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311611277575b5050505050905090565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600460029054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000600960008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900460ff169050919050565b81548183558181151161139757818360005260206000209182019101611396919061142e565b5b505050565b602060405190810160405280600081525090565b8154818355818115116113d7578183600052602060002091820191016113d6919061142e565b5b505050565b82805482825590600052602060002090810192821561141d5760005260206000209182015b8281111561141c578254825591600101919060010190611401565b5b50905061142a9190611453565b5090565b61145091905b8082111561144c576000816000905550600101611434565b5090565b90565b61149391905b8082111561148f57600081816101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905550600101611459565b5090565b905600a165627a7a7230582036ea35935c8246b68074adece2eab70c40e69a0193c08a6277ce06e5b25188510029b8f3f8f1a08023c0d95fc2364e0bf7593f5ff32e1db8ef9f4b41c0bd474eae62d1af896e99808080a0b47b4f0b3e73b5edc8f9a9da1cbcfed562eb06bf54619b6aefeadebf5b3604c280a0da6ec08940a924cb08c947dd56cdb40076b29a6f0ea4dba4e2d02d9a9a72431b80a030cc4138c9e74b6cf79d624b4b5612c0fd888e91f55316cfee7d1694e1a90c0b80a0c5d54b915b56a888eee4e6eeb3141e778f9b674d1d322962eed900f02c29990aa017256b36ef47f907c6b1378a2636942ce894c17075e56fc054d4283f6846659e808080a03340bbaeafcda3a8672eb83099231dbbfab8dae02a1e8ec2f7180538fac207e080b86bf869a033aa5d69545785694b808840be50c182dad2ec3636dfccbe6572fb69828742c0b846f8440101a0663ce0d171e545a26aa67e4ca66f72ba96bb48287dbcc03beea282867f80d44ba01f0e7726926cb43c03a0abf48197dba78522ec8ba1b158e2aa30da7d2a2c6f9eb838f7a03868bdfa8727775661e4ccf117824a175a33f8703d728c04488fbfffcafda9f99594e8ddc5c7a2d2f0d7a9798459c0104fdf5e987acaa3e2a02052222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f01b853f851808080a07bb75cabebdcbd1dbb4331054636d0c6d7a2b08483b9e04df057395a7434c9e080808080808080a0e61e567237b49c44d8f906ceea49027260b4010c10a547b38d8b131b9d3b6f848080808080b8d3f8d1a0dc277c93a9f9dcee99aac9b8ba3cfa4c51821998522469c37715644e8fbac0bfa0ab8cdb808c8303bb61fb48e276217be9770fa83ecf3f90f2234d558885f5abf1808080a0fe137c3a474fbde41d89a59dd76da4c55bf696b86d3af64a55632f76cf30786780808080a06301b39b2ea8a44df8b0356120db64b788e71f52e1d7a6309d0d2e5b86fee7cb80a0da5d8b08dea0c5a4799c0f44d8a24d7cdf209f9b7a5588c1ecafb5361f6b9f07a01b7779e149cadf24d4ffb77ca7e11314b8db7097e4d70b2a173493153ca2e5a0808080b853f851808080a0a87d9bb950836582673aa0eecc0ff64aac607870637a2dd2012b8b1b31981f698080a08da6d5c36a404670c553a2c9052df7cd604f04e3863c4c7b9e0027bfd54206d680808080808080808080b86bf869a02080c7b7ae81a58eb98d9c78de4a1fd7fd9535fc953ed2be602daaa41767312ab846f8448080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47080 + return res, nil +} + +func (c *AuRa) Seal(chain consensus.ChainHeaderReader, block *types.Block, results chan<- *types.Block, stop <-chan struct{}) error { + return nil + //header := block.Header() + // + /// Sealing the genesis block is not supported + //number := header.Number.Uint64() + //if number == 0 { + // return errUnknownBlock + //} + /// For 0-period chains, refuse to seal empty blocks (no reward but would spin sealing) + //if c.config.Period == 0 && len(block.Transactions()) == 0 { + // log.Info("Sealing paused, waiting for transactions") + // return nil + //} + /// Don't hold the signer fields for the entire sealing procedure + //c.lock.RLock() + //signer, signFn := c.signer, c.signFn + //c.lock.RUnlock() + // + /// Bail out if we're unauthorized to sign a block + //snap, err := c.Snapshot(chain, number-1, header.ParentHash, nil) + //if err != nil { + // return err + //} + //if _, authorized := snap.Signers[signer]; !authorized { + // return ErrUnauthorizedSigner + //} + /// If we're amongst the recent signers, wait for the next block + //for seen, recent := range snap.Recents { + // if recent == signer { + // // Signer is among RecentsRLP, only wait if the current block doesn't shift it out + // if limit := uint64(len(snap.Signers)/2 + 1); number < limit || seen > number-limit { + // log.Info("Signed recently, must wait for others") + // return nil + // } + // } + //} + /// Sweet, the protocol permits us to sign the block, wait for our time + //delay := time.Unix(int64(header.Time), 0).Sub(time.Now()) // nolint: gosimple + //if header.Difficulty.Cmp(diffNoTurn) == 0 { + // // It's not our turn explicitly to sign, delay it a bit + // wiggle := time.Duration(len(snap.Signers)/2+1) * wiggleTime + // delay += time.Duration(rand.Int63n(int64(wiggle))) + // + // log.Trace("Out-of-turn signing requested", "wiggle", common.PrettyDuration(wiggle)) + //} + /// Sign all the things! + //sighash, err := signFn(signer, accounts.MimetypeClique, CliqueRLP(header)) + //if err != nil { + // return err + //} + //copy(header.Extra[len(header.Extra)-ExtraSeal:], sighash) + /// Wait until sealing is terminated or delay timeout. + //log.Trace("Waiting for slot to sign and propagate", "delay", common.PrettyDuration(delay)) + //go func() { + // select { + // case <-stop: + // return + // case <-time.After(delay): + // } + // + // select { + // case results <- block.WithSeal(header): + // default: + // log.Warn("Sealing result is not read by miner", "sealhash", SealHash(header)) + // } + //}() + // + //return nil +} + +func (c *AuRa) CalcDifficulty(chain consensus.ChainHeaderReader, time uint64, parent *types.Header) *big.Int { + currentStep := c.step.inner.inner.Load() + currentEmptyStepsLen := 0 + return calculateScore(parent.Step, currentStep, uint64(currentEmptyStepsLen)).ToBig() + + /* TODO: do I need gasLimit override logic here ? + if let Some(gas_limit) = self.gas_limit_override(header) { + trace!(target: "engine", "Setting gas limit to {} for block {}.", gas_limit, header.number()); + let parent_gas_limit = *parent.gas_limit(); + header.set_gas_limit(gas_limit); + if parent_gas_limit != gas_limit { + info!(target: "engine", "Block gas limit was changed from {} to {}.", parent_gas_limit, gas_limit); + } + } + */ +} + +// calculateScore - analog of PoW difficulty: +// +// sqrt(U256::max_value()) + parent_step - current_step + current_empty_steps +func calculateScore(parentStep, currentStep, currentEmptySteps uint64) *uint256.Int { + maxU128 := uint256.NewInt(0).SetAllOne() + maxU128 = maxU128.Rsh(maxU128, 128) + res := maxU128.Add(maxU128, uint256.NewInt(parentStep)) + res = res.Sub(res, uint256.NewInt(currentStep)) + res = res.Add(res, uint256.NewInt(currentEmptySteps)) + return res +} + +func (c *AuRa) SealHash(header *types.Header) common.Hash { + return clique.SealHash(header) +} + +// See https://openethereum.github.io/Permissioning.html#gas-price +// This is thread-safe: it only accesses the `certifier` which is used behind a RWLock +func (c *AuRa) IsServiceTransaction(sender common.Address) bool { + c.certifierLock.RLock() + defer c.certifierLock.RUnlock() + if c.certifier == nil { + return false + } + packed, err := certifierAbi().Pack("certified", sender) + if err != nil { + panic(err) + } + out, err := c.Syscall(*c.certifier, packed) + if err != nil { + panic(err) + } + res, err := certifierAbi().Unpack("certified", out) + if err != nil { + log.Warn("error while detecting service tx on AuRa", "err", err) + return false + } + if len(res) == 0 { + return false + } + if certified, ok := res[0].(bool); ok { + return certified + } + return false +} + +func SafeClose(ch chan struct{}) { + if ch == nil { + return + } + select { + case <-ch: + // Channel was already closed + default: + close(ch) + } +} + +// Close implements consensus.Engine. It's a noop for clique as there are no background threads. +func (c *AuRa) Close() error { + SafeClose(c.exitCh) + return nil +} + +// APIs implements consensus.Engine, returning the user facing RPC API to allow +// controlling the signer voting. +func (c *AuRa) APIs(chain consensus.ChainHeaderReader) []rpc.API { + return []rpc.API{ + //{ + //Namespace: "clique", + //Version: "1.0", + //Service: &API{chain: chain, clique: c}, + //Public: false, + //} + } +} + +// nolint +func (c *AuRa) emptySteps(fromStep, toStep uint64, parentHash common.Hash) []EmptyStep { + from := EmptyStep{step: fromStep + 1, parentHash: parentHash} + to := EmptyStep{step: toStep} + res := []EmptyStep{} + if to.LessOrEqual(&from) { + return res + } + + c.EmptyStepsSet.Sort() + c.EmptyStepsSet.ForEach(func(i int, step *EmptyStep) { + if step.Less(&from) || (&to).Less(step) { + return + } + if step.parentHash != parentHash { + return + } + res = append(res, *step) + }) + return res +} + +func (c *AuRa) CalculateRewards(_ *params.ChainConfig, header *types.Header, _ []*types.Header) ([]consensus.Reward, error) { + var rewardContractAddress BlockRewardContract + var foundContract bool + for _, c := range c.cfg.BlockRewardContractTransitions { + if c.blockNum > header.Number.Uint64() { + break + } + foundContract = true + rewardContractAddress = c + } + if foundContract { + beneficiaries := []common.Address{header.Coinbase} + rewardKind := []consensus.RewardKind{consensus.RewardAuthor} + var amounts []*big.Int + beneficiaries, amounts = callBlockRewardAbi(rewardContractAddress.address, c.Syscall, beneficiaries, rewardKind) + rewards := make([]consensus.Reward, len(amounts)) + for i, amount := range amounts { + rewards[i].Beneficiary = beneficiaries[i] + rewards[i].Kind = consensus.RewardExternal + rewards[i].Amount = *amount + } + return rewards, nil + } + + // block_reward.iter.rev().find(|&(block, _)| *block <= number) + var reward BlockReward + var found bool + for i := range c.cfg.BlockReward { + if c.cfg.BlockReward[i].blockNum > header.Number.Uint64() { + break + } + found = true + reward = c.cfg.BlockReward[i] + } + if !found { + return nil, errors.New("Current block's reward is not found; this indicates a chain config error") + } + + r := consensus.Reward{Beneficiary: header.Coinbase, Kind: consensus.RewardAuthor, Amount: *reward.amount} + return []consensus.Reward{r}, nil +} + +// See https://github.com/gnosischain/specs/blob/master/execution/withdrawals.md +func (c *AuRa) ExecuteSystemWithdrawals(withdrawals []*types.Withdrawal) error { + if c.cfg.WithdrawalContractAddress == nil { + return nil + } + + maxFailedWithdrawalsToProcess := big.NewInt(4) + amounts := make([]uint64, 0, len(withdrawals)) + addresses := make([]common.Address, 0, len(withdrawals)) + for _, w := range withdrawals { + amounts = append(amounts, w.Amount) + addresses = append(addresses, w.Address) + } + + packed, err := withdrawalAbi().Pack("executeSystemWithdrawals", maxFailedWithdrawalsToProcess, amounts, addresses) + if err != nil { + return err + } + + _, err = c.Syscall(*c.cfg.WithdrawalContractAddress, packed) + if err != nil { + log.Warn("ExecuteSystemWithdrawals", "err", err) + } + return err +} + +// An empty step message that is included in a seal, the only difference is that it doesn't include +// the `parent_hash` in order to save space. The included signature is of the original empty step +// message, which can be reconstructed by using the parent hash of the block in which this sealed +// empty message is included. +// nolint +type SealedEmptyStep struct { + signature []byte // H520 + step uint64 +} + +/* +// extracts the empty steps from the header seal. should only be called when there are 3 fields in the seal +// (i.e. header.number() >= self.empty_steps_transition). +func headerEmptySteps(header *types.Header) ([]EmptyStep, error) { + s := headerEmptyStepsRaw(header) + sealedSteps := []SealedEmptyStep{} + err := rlp.DecodeBytes(s, &sealedSteps) + if err != nil { + return nil, err + } + steps := make([]EmptyStep, len(sealedSteps)) + for i := range sealedSteps { + steps[i] = newEmptyStepFromSealed(sealedSteps[i], header.ParentHash) + } + return steps, nil +} + +func newEmptyStepFromSealed(step SealedEmptyStep, parentHash common.Hash) EmptyStep { + return EmptyStep{ + signature: step.signature, + step: step.step, + parentHash: parentHash, + } +} + +// extracts the raw empty steps vec from the header seal. should only be called when there are 3 fields in the seal +// (i.e. header.number() >= self.empty_steps_transition) +func headerEmptyStepsRaw(header *types.Header) []byte { + if len(header.Seal) < 3 { + panic("was checked with verify_block_basic; has 3 fields; qed") + } + return header.Seal[2] +} +*/ + +// A message broadcast by authorities when it's their turn to seal a block but there are no +// transactions. Other authorities accumulate these messages and later include them in the seal as +// proof. +// +// An empty step message is created _instead of_ a block if there are no pending transactions. +// It cannot itself be a parent, and `parent_hash` always points to the most recent block. E.g.: +// - Validator A creates block `bA`. +// - Validator B has no pending transactions, so it signs an empty step message `mB` +// instead whose hash points to block `bA`. +// - Validator C also has no pending transactions, so it also signs an empty step message `mC` +// instead whose hash points to block `bA`. +// - Validator D creates block `bD`. The parent is block `bA`, and the header includes `mB` and `mC`. +type EmptyStep struct { + // The signature of the other two fields, by the message's author. + signature []byte // H520 + // This message's step number. + step uint64 + // The hash of the most recent block. + parentHash common.Hash // H256 +} + +func (s *EmptyStep) Less(other *EmptyStep) bool { + if s.step < other.step { + return true + } + if bytes.Compare(s.parentHash[:], other.parentHash[:]) < 0 { + return true + } + if bytes.Compare(s.signature, other.signature) < 0 { + return true + } + return false +} +func (s *EmptyStep) LessOrEqual(other *EmptyStep) bool { + if s.step <= other.step { + return true + } + if bytes.Compare(s.parentHash[:], other.parentHash[:]) <= 0 { + return true + } + if bytes.Compare(s.signature, other.signature) <= 0 { + return true + } + return false +} + +// Returns `true` if the message has a valid signature by the expected proposer in the message's step. +func (s *EmptyStep) verify(validators ValidatorSet) (bool, error) { //nolint + //sRlp, err := EmptyStepRlp(s.step, s.parentHash) + //if err != nil { + // return false, err + //} + //message := crypto.Keccak256(sRlp) + + /* + let correct_proposer = step_proposer(validators, &self.parent_hash, self.step); + + publickey::verify_address(&correct_proposer, &self.signature.into(), &message) + .map_err(|e| e.into()) + */ + return true, nil +} + +// nolint +func (s *EmptyStep) author() (common.Address, error) { + sRlp, err := EmptyStepRlp(s.step, s.parentHash) + if err != nil { + return common.Address{}, err + } + message := crypto.Keccak256(sRlp) + public, err := crypto.SigToPub(message, s.signature) + // public, err := secp256k1.RecoverPubkey(message, s.signature) + if err != nil { + return common.Address{}, err + } + return crypto.PubkeyToAddress(*public), nil +} + +type EmptyStepSet struct { + lock sync.Mutex + list []*EmptyStep +} + +func (s *EmptyStepSet) Less(i, j int) bool { return s.list[i].Less(s.list[j]) } +func (s *EmptyStepSet) Swap(i, j int) { s.list[i], s.list[j] = s.list[j], s.list[i] } +func (s *EmptyStepSet) Len() int { return len(s.list) } + +func (s *EmptyStepSet) Sort() { + s.lock.Lock() + defer s.lock.Unlock() + sort.Stable(s) +} + +func (s *EmptyStepSet) ForEach(f func(int, *EmptyStep)) { + s.lock.Lock() + defer s.lock.Unlock() + for i, el := range s.list { + f(i, el) + } +} + +func EmptyStepFullRlp(signature []byte, emptyStepRlp []byte) ([]byte, error) { + type A struct { + s []byte + r []byte + } + + return rlp.EncodeToBytes(A{s: signature, r: emptyStepRlp}) +} + +func EmptyStepRlp(step uint64, parentHash common.Hash) ([]byte, error) { + type A struct { + s uint64 + h common.Hash + } + return rlp.EncodeToBytes(A{s: step, h: parentHash}) +} + +// nolint +type unAssembledHeader struct { + hash common.Hash + number uint64 + signers []common.Address +} +type unAssembledHeaders struct { + l *list.List +} + +func (u unAssembledHeaders) PushBack(header *unAssembledHeader) { u.l.PushBack(header) } +func (u unAssembledHeaders) PushFront(header *unAssembledHeader) { u.l.PushFront(header) } +func (u unAssembledHeaders) Pop() *unAssembledHeader { + e := u.l.Front() + if e == nil { + return nil + } + u.l.Remove(e) + return e.Value.(*unAssembledHeader) +} +func (u unAssembledHeaders) Front() *unAssembledHeader { + e := u.l.Front() + if e == nil { + return nil + } + return e.Value.(*unAssembledHeader) +} + +// RollingFinality checker for authority round consensus. +// Stores a chain of unfinalized hashes that can be pushed onto. +// nolint +type RollingFinality struct { + headers unAssembledHeaders //nolint + signers *SimpleList + signCount map[common.Address]uint + lastPushed *common.Hash // Option, +} + +// NewRollingFinality creates a blank finality checker under the given validator set. +func NewRollingFinality(signers []common.Address) *RollingFinality { + return &RollingFinality{ + signers: NewSimpleList(signers), + headers: unAssembledHeaders{l: list.New()}, + signCount: map[common.Address]uint{}, + } +} + +// Clears the finality status, but keeps the validator set. +func (f *RollingFinality) print(num uint64) { + if num > DEBUG_LOG_FROM { + h := f.headers + i := 0 + for e := h.l.Front(); e != nil; e = e.Next() { + i++ + a := e.Value.(*unAssembledHeader) + fmt.Printf("\t%d,%x\n", a.number, a.signers[0]) + } + if i == 0 { + fmt.Printf("\tempty\n") + } + } +} + +func (f *RollingFinality) clear() { + f.headers = unAssembledHeaders{l: list.New()} + f.signCount = map[common.Address]uint{} + f.lastPushed = nil +} + +// Push a hash onto the rolling finality checker (implying `subchain_head` == head.parent) +// +// Fails if `signer` isn't a member of the active validator set. +// Returns a list of all newly finalized headers. +func (f *RollingFinality) push(head common.Hash, num uint64, signers []common.Address) (newlyFinalized []unAssembledHeader, err error) { + for i := range signers { + if !f.hasSigner(signers[i]) { + return nil, fmt.Errorf("unknown validator") + } + } + + f.addSigners(signers) + f.headers.PushBack(&unAssembledHeader{hash: head, number: num, signers: signers}) + + for f.isFinalized() { + e := f.headers.Pop() + if e == nil { + panic("headers length always greater than sign count length") + } + f.removeSigners(e.signers) + newlyFinalized = append(newlyFinalized, *e) + } + f.lastPushed = &head + return newlyFinalized, nil +} + +// isFinalized returns whether the first entry in `self.headers` is finalized. +func (f *RollingFinality) isFinalized() bool { + e := f.headers.Front() + if e == nil { + return false + } + return len(f.signCount)*2 > len(f.signers.validators) +} +func (f *RollingFinality) hasSigner(signer common.Address) bool { + for j := range f.signers.validators { + if f.signers.validators[j] == signer { + return true + + } + } + return false +} +func (f *RollingFinality) addSigners(signers []common.Address) bool { + for i := range signers { + count, ok := f.signCount[signers[i]] + if ok { + f.signCount[signers[i]] = count + 1 + } else { + f.signCount[signers[i]] = 1 + } + } + return false +} +func (f *RollingFinality) removeSigners(signers []common.Address) { + for i := range signers { + count, ok := f.signCount[signers[i]] + if !ok { + panic("all hashes in `header` should have entries in `sign_count` for their signers") + //continue + } + if count <= 1 { + delete(f.signCount, signers[i]) + } else { + f.signCount[signers[i]] = count - 1 + } + } +} +func (f *RollingFinality) buildAncestrySubChain(get func(hash common.Hash) ([]common.Address, common.Hash, common.Hash, uint64, bool), parentHash, epochTransitionHash common.Hash) error { // starts from chainHeadParentHash + f.clear() + + for { + signers, blockHash, newParentHash, blockNum, ok := get(parentHash) + if !ok { + return nil + } + if blockHash == epochTransitionHash { + return nil + } + for i := range signers { + if !f.hasSigner(signers[i]) { + return fmt.Errorf("unknown validator: blockNum=%d", blockNum) + } + } + if f.lastPushed == nil { + copyHash := parentHash + f.lastPushed = ©Hash + } + f.addSigners(signers) + f.headers.PushFront(&unAssembledHeader{hash: blockHash, number: blockNum, signers: signers}) + // break when we've got our first finalized block. + if f.isFinalized() { + e := f.headers.Pop() + if e == nil { + panic("we just pushed a block") + } + f.removeSigners(e.signers) + //log.Info("[aura] finality encountered already finalized block", "hash", e.hash.String(), "number", e.number) + break + } + + parentHash = newParentHash + } + return nil +} diff --git a/consensus/aura/aura_test.go b/consensus/aura/aura_test.go new file mode 100644 index 000000000000..4b92c5e0261f --- /dev/null +++ b/consensus/aura/aura_test.go @@ -0,0 +1,56 @@ +package aura_test + +// import ( +// "testing" + +// "github.com/stretchr/testify/require" + +// "github.com/ethereum/go-ethereum-lib/kv/memdb" +// libcommon "github.com/ethereum/go-ethereum/common" + +// "github.com/ethereum/go-ethereum/consensus/aura" +// "github.com/ethereum/go-ethereum/core" +// "github.com/ethereum/go-ethereum/core/types" +// "github.com/ethereum/go-ethereum/trie" +// ) + +// Check that the first block of Gnosis Chain, which doesn't have any transactions, +// does not change the state root. +// func TestEmptyBlock(t *testing.T) { +// require := require.New(t) +// genesis := core.DefaultGnosisGenesisBlock() +// genesisBlock := genesis.ToBlock() + +// genesis.Config.TerminalTotalDifficultyPassed = false + +// chainConfig := genesis.Config +// auraDB := memdb.NewTestDB(t) +// engine, err := aura.NewAuRa(chainConfig.Aura, auraDB) +// require.NoError(err) +// m := stages.MockWithGenesisEngine(t, genesis, engine, false) + +// time := uint64(1539016985) +// header := core.MakeEmptyHeader(genesisBlock.Header(), chainConfig, time, nil) +// header.UncleHash = types.EmptyUncleHash +// header.TxHash = trie.EmptyRoot +// header.ReceiptHash = trie.EmptyRoot +// header.Coinbase = libcommon.HexToAddress("0xcace5b3c29211740e595850e80478416ee77ca21") +// header.Difficulty = engine.CalcDifficulty(nil, time, +// 0, +// genesisBlock.Difficulty(), +// genesisBlock.NumberU64(), +// genesisBlock.Hash(), +// genesisBlock.UncleHash(), +// genesisBlock.Header().AuRaStep, +// ) + +// block := types.NewBlockWithHeader(header) + +// headers, blocks, receipts := make([]*types.Header, 1), make(types.Blocks, 1), make([]types.Receipts, 1) +// headers[0] = header +// blocks[0] = block + +// chain := &core.ChainPack{Headers: headers, Blocks: blocks, Receipts: receipts, TopBlock: block} +// err = m.InsertChain(chain) +// require.NoError(err) +// } diff --git a/consensus/aura/auraabi/abi.go b/consensus/aura/auraabi/abi.go new file mode 100644 index 000000000000..8622847f4872 --- /dev/null +++ b/consensus/aura/auraabi/abi.go @@ -0,0 +1,4 @@ +package auraabi + +//go:generate abigen -abi ./../contracts/block_reward.json -pkg auraabi -type block_reward -out ./gen_block_reward.go +//go:generate abigen -abi ./../contracts/validator_set.json -pkg auraabi -type validator_set -out ./gen_validator_set.go diff --git a/consensus/aura/auraabi/gen_block_reward.go b/consensus/aura/auraabi/gen_block_reward.go new file mode 100644 index 000000000000..500267fe8d51 --- /dev/null +++ b/consensus/aura/auraabi/gen_block_reward.go @@ -0,0 +1,202 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package auraabi + +import ( + "errors" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" +) + +// Reference imports to suppress errors if they are not otherwise used. +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +// BlockRewardMetaData contains all meta data concerning the BlockReward contract. +var BlockRewardMetaData = &bind.MetaData{ + ABI: "[{\"constant\":false,\"inputs\":[{\"name\":\"benefactors\",\"type\":\"address[]\"},{\"name\":\"kind\",\"type\":\"uint16[]\"}],\"name\":\"reward\",\"outputs\":[{\"name\":\"\",\"type\":\"address[]\"},{\"name\":\"\",\"type\":\"uint256[]\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", +} + +// BlockRewardABI is the input ABI used to generate the binding from. +// Deprecated: Use BlockRewardMetaData.ABI instead. +var BlockRewardABI = BlockRewardMetaData.ABI + +// BlockReward is an auto generated Go binding around an Ethereum contract. +type BlockReward struct { + BlockRewardCaller // Read-only binding to the contract + BlockRewardTransactor // Write-only binding to the contract + BlockRewardFilterer // Log filterer for contract events +} + +// BlockRewardCaller is an auto generated read-only Go binding around an Ethereum contract. +type BlockRewardCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// BlockRewardTransactor is an auto generated write-only Go binding around an Ethereum contract. +type BlockRewardTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// BlockRewardFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type BlockRewardFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// BlockRewardSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type BlockRewardSession struct { + Contract *BlockReward // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// BlockRewardCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type BlockRewardCallerSession struct { + Contract *BlockRewardCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// BlockRewardTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type BlockRewardTransactorSession struct { + Contract *BlockRewardTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// BlockRewardRaw is an auto generated low-level Go binding around an Ethereum contract. +type BlockRewardRaw struct { + Contract *BlockReward // Generic contract binding to access the raw methods on +} + +// BlockRewardCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type BlockRewardCallerRaw struct { + Contract *BlockRewardCaller // Generic read-only contract binding to access the raw methods on +} + +// BlockRewardTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type BlockRewardTransactorRaw struct { + Contract *BlockRewardTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewBlockReward creates a new instance of BlockReward, bound to a specific deployed contract. +func NewBlockReward(address common.Address, backend bind.ContractBackend) (*BlockReward, error) { + contract, err := bindBlockReward(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &BlockReward{BlockRewardCaller: BlockRewardCaller{contract: contract}, BlockRewardTransactor: BlockRewardTransactor{contract: contract}, BlockRewardFilterer: BlockRewardFilterer{contract: contract}}, nil +} + +// NewBlockRewardCaller creates a new read-only instance of BlockReward, bound to a specific deployed contract. +func NewBlockRewardCaller(address common.Address, caller bind.ContractCaller) (*BlockRewardCaller, error) { + contract, err := bindBlockReward(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &BlockRewardCaller{contract: contract}, nil +} + +// NewBlockRewardTransactor creates a new write-only instance of BlockReward, bound to a specific deployed contract. +func NewBlockRewardTransactor(address common.Address, transactor bind.ContractTransactor) (*BlockRewardTransactor, error) { + contract, err := bindBlockReward(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &BlockRewardTransactor{contract: contract}, nil +} + +// NewBlockRewardFilterer creates a new log filterer instance of BlockReward, bound to a specific deployed contract. +func NewBlockRewardFilterer(address common.Address, filterer bind.ContractFilterer) (*BlockRewardFilterer, error) { + contract, err := bindBlockReward(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &BlockRewardFilterer{contract: contract}, nil +} + +// bindBlockReward binds a generic wrapper to an already deployed contract. +func bindBlockReward(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := BlockRewardMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_BlockReward *BlockRewardRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _BlockReward.Contract.BlockRewardCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_BlockReward *BlockRewardRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _BlockReward.Contract.BlockRewardTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_BlockReward *BlockRewardRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _BlockReward.Contract.BlockRewardTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_BlockReward *BlockRewardCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _BlockReward.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_BlockReward *BlockRewardTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _BlockReward.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_BlockReward *BlockRewardTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _BlockReward.Contract.contract.Transact(opts, method, params...) +} + +// Reward is a paid mutator transaction binding the contract method 0xf91c2898. +// +// Solidity: function reward(address[] benefactors, uint16[] kind) returns(address[], uint256[]) +func (_BlockReward *BlockRewardTransactor) Reward(opts *bind.TransactOpts, benefactors []common.Address, kind []uint16) (*types.Transaction, error) { + return _BlockReward.contract.Transact(opts, "reward", benefactors, kind) +} + +// Reward is a paid mutator transaction binding the contract method 0xf91c2898. +// +// Solidity: function reward(address[] benefactors, uint16[] kind) returns(address[], uint256[]) +func (_BlockReward *BlockRewardSession) Reward(benefactors []common.Address, kind []uint16) (*types.Transaction, error) { + return _BlockReward.Contract.Reward(&_BlockReward.TransactOpts, benefactors, kind) +} + +// Reward is a paid mutator transaction binding the contract method 0xf91c2898. +// +// Solidity: function reward(address[] benefactors, uint16[] kind) returns(address[], uint256[]) +func (_BlockReward *BlockRewardTransactorSession) Reward(benefactors []common.Address, kind []uint16) (*types.Transaction, error) { + return _BlockReward.Contract.Reward(&_BlockReward.TransactOpts, benefactors, kind) +} diff --git a/consensus/aura/auraabi/gen_validator_set.go b/consensus/aura/auraabi/gen_validator_set.go new file mode 100644 index 000000000000..a1d51d68a839 --- /dev/null +++ b/consensus/aura/auraabi/gen_validator_set.go @@ -0,0 +1,461 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package auraabi + +import ( + "errors" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" +) + +// Reference imports to suppress errors if they are not otherwise used. +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +// ValidatorSetMetaData contains all meta data concerning the ValidatorSet contract. +var ValidatorSetMetaData = &bind.MetaData{ + ABI: "[{\"constant\":false,\"inputs\":[],\"name\":\"finalizeChange\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getValidators\",\"outputs\":[{\"name\":\"validators\",\"type\":\"address[]\"}],\"payable\":false,\"type\":\"function\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"_parent_hash\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"_new_set\",\"type\":\"address[]\"}],\"name\":\"InitiateChange\",\"type\":\"event\"},{\"constant\":true,\"inputs\":[],\"name\":\"emitInitiateChangeCallable\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"emitInitiateChange\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_reportingValidator\",\"type\":\"address\"},{\"name\":\"_maliciousValidator\",\"type\":\"address\"},{\"name\":\"_blockNumber\",\"type\":\"uint256\"}],\"name\":\"shouldValidatorReport\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"}]", +} + +// ValidatorSetABI is the input ABI used to generate the binding from. +// Deprecated: Use ValidatorSetMetaData.ABI instead. +var ValidatorSetABI = ValidatorSetMetaData.ABI + +// ValidatorSet is an auto generated Go binding around an Ethereum contract. +type ValidatorSet struct { + ValidatorSetCaller // Read-only binding to the contract + ValidatorSetTransactor // Write-only binding to the contract + ValidatorSetFilterer // Log filterer for contract events +} + +// ValidatorSetCaller is an auto generated read-only Go binding around an Ethereum contract. +type ValidatorSetCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ValidatorSetTransactor is an auto generated write-only Go binding around an Ethereum contract. +type ValidatorSetTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ValidatorSetFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type ValidatorSetFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ValidatorSetSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type ValidatorSetSession struct { + Contract *ValidatorSet // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// ValidatorSetCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type ValidatorSetCallerSession struct { + Contract *ValidatorSetCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// ValidatorSetTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type ValidatorSetTransactorSession struct { + Contract *ValidatorSetTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// ValidatorSetRaw is an auto generated low-level Go binding around an Ethereum contract. +type ValidatorSetRaw struct { + Contract *ValidatorSet // Generic contract binding to access the raw methods on +} + +// ValidatorSetCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type ValidatorSetCallerRaw struct { + Contract *ValidatorSetCaller // Generic read-only contract binding to access the raw methods on +} + +// ValidatorSetTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type ValidatorSetTransactorRaw struct { + Contract *ValidatorSetTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewValidatorSet creates a new instance of ValidatorSet, bound to a specific deployed contract. +func NewValidatorSet(address common.Address, backend bind.ContractBackend) (*ValidatorSet, error) { + contract, err := bindValidatorSet(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &ValidatorSet{ValidatorSetCaller: ValidatorSetCaller{contract: contract}, ValidatorSetTransactor: ValidatorSetTransactor{contract: contract}, ValidatorSetFilterer: ValidatorSetFilterer{contract: contract}}, nil +} + +// NewValidatorSetCaller creates a new read-only instance of ValidatorSet, bound to a specific deployed contract. +func NewValidatorSetCaller(address common.Address, caller bind.ContractCaller) (*ValidatorSetCaller, error) { + contract, err := bindValidatorSet(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &ValidatorSetCaller{contract: contract}, nil +} + +// NewValidatorSetTransactor creates a new write-only instance of ValidatorSet, bound to a specific deployed contract. +func NewValidatorSetTransactor(address common.Address, transactor bind.ContractTransactor) (*ValidatorSetTransactor, error) { + contract, err := bindValidatorSet(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &ValidatorSetTransactor{contract: contract}, nil +} + +// NewValidatorSetFilterer creates a new log filterer instance of ValidatorSet, bound to a specific deployed contract. +func NewValidatorSetFilterer(address common.Address, filterer bind.ContractFilterer) (*ValidatorSetFilterer, error) { + contract, err := bindValidatorSet(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &ValidatorSetFilterer{contract: contract}, nil +} + +// bindValidatorSet binds a generic wrapper to an already deployed contract. +func bindValidatorSet(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := ValidatorSetMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_ValidatorSet *ValidatorSetRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _ValidatorSet.Contract.ValidatorSetCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_ValidatorSet *ValidatorSetRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _ValidatorSet.Contract.ValidatorSetTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_ValidatorSet *ValidatorSetRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _ValidatorSet.Contract.ValidatorSetTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_ValidatorSet *ValidatorSetCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _ValidatorSet.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_ValidatorSet *ValidatorSetTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _ValidatorSet.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_ValidatorSet *ValidatorSetTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _ValidatorSet.Contract.contract.Transact(opts, method, params...) +} + +// EmitInitiateChangeCallable is a free data retrieval call binding the contract method 0x3d3b5458. +// +// Solidity: function emitInitiateChangeCallable() view returns(bool) +func (_ValidatorSet *ValidatorSetCaller) EmitInitiateChangeCallable(opts *bind.CallOpts) (bool, error) { + var out []interface{} + err := _ValidatorSet.contract.Call(opts, &out, "emitInitiateChangeCallable") + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// EmitInitiateChangeCallable is a free data retrieval call binding the contract method 0x3d3b5458. +// +// Solidity: function emitInitiateChangeCallable() view returns(bool) +func (_ValidatorSet *ValidatorSetSession) EmitInitiateChangeCallable() (bool, error) { + return _ValidatorSet.Contract.EmitInitiateChangeCallable(&_ValidatorSet.CallOpts) +} + +// EmitInitiateChangeCallable is a free data retrieval call binding the contract method 0x3d3b5458. +// +// Solidity: function emitInitiateChangeCallable() view returns(bool) +func (_ValidatorSet *ValidatorSetCallerSession) EmitInitiateChangeCallable() (bool, error) { + return _ValidatorSet.Contract.EmitInitiateChangeCallable(&_ValidatorSet.CallOpts) +} + +// GetValidators is a free data retrieval call binding the contract method 0xb7ab4db5. +// +// Solidity: function getValidators() returns(address[] validators) +func (_ValidatorSet *ValidatorSetCaller) GetValidators(opts *bind.CallOpts) ([]common.Address, error) { + var out []interface{} + err := _ValidatorSet.contract.Call(opts, &out, "getValidators") + + if err != nil { + return *new([]common.Address), err + } + + out0 := *abi.ConvertType(out[0], new([]common.Address)).(*[]common.Address) + + return out0, err + +} + +// GetValidators is a free data retrieval call binding the contract method 0xb7ab4db5. +// +// Solidity: function getValidators() returns(address[] validators) +func (_ValidatorSet *ValidatorSetSession) GetValidators() ([]common.Address, error) { + return _ValidatorSet.Contract.GetValidators(&_ValidatorSet.CallOpts) +} + +// GetValidators is a free data retrieval call binding the contract method 0xb7ab4db5. +// +// Solidity: function getValidators() returns(address[] validators) +func (_ValidatorSet *ValidatorSetCallerSession) GetValidators() ([]common.Address, error) { + return _ValidatorSet.Contract.GetValidators(&_ValidatorSet.CallOpts) +} + +// ShouldValidatorReport is a free data retrieval call binding the contract method 0xcbd2d528. +// +// Solidity: function shouldValidatorReport(address _reportingValidator, address _maliciousValidator, uint256 _blockNumber) view returns(bool) +func (_ValidatorSet *ValidatorSetCaller) ShouldValidatorReport(opts *bind.CallOpts, _reportingValidator common.Address, _maliciousValidator common.Address, _blockNumber *big.Int) (bool, error) { + var out []interface{} + err := _ValidatorSet.contract.Call(opts, &out, "shouldValidatorReport", _reportingValidator, _maliciousValidator, _blockNumber) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// ShouldValidatorReport is a free data retrieval call binding the contract method 0xcbd2d528. +// +// Solidity: function shouldValidatorReport(address _reportingValidator, address _maliciousValidator, uint256 _blockNumber) view returns(bool) +func (_ValidatorSet *ValidatorSetSession) ShouldValidatorReport(_reportingValidator common.Address, _maliciousValidator common.Address, _blockNumber *big.Int) (bool, error) { + return _ValidatorSet.Contract.ShouldValidatorReport(&_ValidatorSet.CallOpts, _reportingValidator, _maliciousValidator, _blockNumber) +} + +// ShouldValidatorReport is a free data retrieval call binding the contract method 0xcbd2d528. +// +// Solidity: function shouldValidatorReport(address _reportingValidator, address _maliciousValidator, uint256 _blockNumber) view returns(bool) +func (_ValidatorSet *ValidatorSetCallerSession) ShouldValidatorReport(_reportingValidator common.Address, _maliciousValidator common.Address, _blockNumber *big.Int) (bool, error) { + return _ValidatorSet.Contract.ShouldValidatorReport(&_ValidatorSet.CallOpts, _reportingValidator, _maliciousValidator, _blockNumber) +} + +// EmitInitiateChange is a paid mutator transaction binding the contract method 0x93b4e25e. +// +// Solidity: function emitInitiateChange() returns() +func (_ValidatorSet *ValidatorSetTransactor) EmitInitiateChange(opts *bind.TransactOpts) (*types.Transaction, error) { + return _ValidatorSet.contract.Transact(opts, "emitInitiateChange") +} + +// EmitInitiateChange is a paid mutator transaction binding the contract method 0x93b4e25e. +// +// Solidity: function emitInitiateChange() returns() +func (_ValidatorSet *ValidatorSetSession) EmitInitiateChange() (*types.Transaction, error) { + return _ValidatorSet.Contract.EmitInitiateChange(&_ValidatorSet.TransactOpts) +} + +// EmitInitiateChange is a paid mutator transaction binding the contract method 0x93b4e25e. +// +// Solidity: function emitInitiateChange() returns() +func (_ValidatorSet *ValidatorSetTransactorSession) EmitInitiateChange() (*types.Transaction, error) { + return _ValidatorSet.Contract.EmitInitiateChange(&_ValidatorSet.TransactOpts) +} + +// FinalizeChange is a paid mutator transaction binding the contract method 0x75286211. +// +// Solidity: function finalizeChange() returns() +func (_ValidatorSet *ValidatorSetTransactor) FinalizeChange(opts *bind.TransactOpts) (*types.Transaction, error) { + return _ValidatorSet.contract.Transact(opts, "finalizeChange") +} + +// FinalizeChange is a paid mutator transaction binding the contract method 0x75286211. +// +// Solidity: function finalizeChange() returns() +func (_ValidatorSet *ValidatorSetSession) FinalizeChange() (*types.Transaction, error) { + return _ValidatorSet.Contract.FinalizeChange(&_ValidatorSet.TransactOpts) +} + +// FinalizeChange is a paid mutator transaction binding the contract method 0x75286211. +// +// Solidity: function finalizeChange() returns() +func (_ValidatorSet *ValidatorSetTransactorSession) FinalizeChange() (*types.Transaction, error) { + return _ValidatorSet.Contract.FinalizeChange(&_ValidatorSet.TransactOpts) +} + +// ValidatorSetInitiateChangeIterator is returned from FilterInitiateChange and is used to iterate over the raw logs and unpacked data for InitiateChange events raised by the ValidatorSet contract. +type ValidatorSetInitiateChangeIterator struct { + Event *ValidatorSetInitiateChange // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *ValidatorSetInitiateChangeIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(ValidatorSetInitiateChange) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(ValidatorSetInitiateChange) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *ValidatorSetInitiateChangeIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *ValidatorSetInitiateChangeIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// ValidatorSetInitiateChange represents a InitiateChange event raised by the ValidatorSet contract. +type ValidatorSetInitiateChange struct { + ParentHash [32]byte + NewSet []common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterInitiateChange is a free log retrieval operation binding the contract event 0x55252fa6eee4741b4e24a74a70e9c11fd2c2281df8d6ea13126ff845f7825c89. +// +// Solidity: event InitiateChange(bytes32 indexed _parent_hash, address[] _new_set) +func (_ValidatorSet *ValidatorSetFilterer) FilterInitiateChange(opts *bind.FilterOpts, _parent_hash [][32]byte) (*ValidatorSetInitiateChangeIterator, error) { + + var _parent_hashRule []interface{} + for _, _parent_hashItem := range _parent_hash { + _parent_hashRule = append(_parent_hashRule, _parent_hashItem) + } + + logs, sub, err := _ValidatorSet.contract.FilterLogs(opts, "InitiateChange", _parent_hashRule) + if err != nil { + return nil, err + } + return &ValidatorSetInitiateChangeIterator{contract: _ValidatorSet.contract, event: "InitiateChange", logs: logs, sub: sub}, nil +} + +// WatchInitiateChange is a free log subscription operation binding the contract event 0x55252fa6eee4741b4e24a74a70e9c11fd2c2281df8d6ea13126ff845f7825c89. +// +// Solidity: event InitiateChange(bytes32 indexed _parent_hash, address[] _new_set) +func (_ValidatorSet *ValidatorSetFilterer) WatchInitiateChange(opts *bind.WatchOpts, sink chan<- *ValidatorSetInitiateChange, _parent_hash [][32]byte) (event.Subscription, error) { + + var _parent_hashRule []interface{} + for _, _parent_hashItem := range _parent_hash { + _parent_hashRule = append(_parent_hashRule, _parent_hashItem) + } + + logs, sub, err := _ValidatorSet.contract.WatchLogs(opts, "InitiateChange", _parent_hashRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(ValidatorSetInitiateChange) + if err := _ValidatorSet.contract.UnpackLog(event, "InitiateChange", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseInitiateChange is a log parse operation binding the contract event 0x55252fa6eee4741b4e24a74a70e9c11fd2c2281df8d6ea13126ff845f7825c89. +// +// Solidity: event InitiateChange(bytes32 indexed _parent_hash, address[] _new_set) +func (_ValidatorSet *ValidatorSetFilterer) ParseInitiateChange(log types.Log) (*ValidatorSetInitiateChange, error) { + event := new(ValidatorSetInitiateChange) + if err := _ValidatorSet.contract.UnpackLog(event, "InitiateChange", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} diff --git a/consensus/aura/aurainterfaces/interface.go b/consensus/aura/aurainterfaces/interface.go new file mode 100644 index 000000000000..cbcdc45c3c0d --- /dev/null +++ b/consensus/aura/aurainterfaces/interface.go @@ -0,0 +1,44 @@ +package aurainterfaces + +import ( + "math/big" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/consensus" +) + +// see openethereum/crates/ethcore/res/contracts/block_reward.json +type BlockRewardABI interface { + Reward(benefactors []common.Address, kind []consensus.RewardKind) ([]common.Address, []*big.Int, error) +} + +type abiDecoder func([]byte, interface{}) error + +// see openethereum/crates/ethcore/res/contracts/validator_set.json +type ValidatorSetABI interface { + GetValidators() ([]byte, abiDecoder) + ShouldValidatorReport(ourAddr, maliciousValidatorAddress common.Address, blockNum uint64) ([]byte, abiDecoder) +} + +type SealKind [][]byte + +// Proposal seal; should be broadcasted, but not inserted into blockchain. +type SealProposal SealKind + +// Regular block seal; should be part of the blockchain. +type SealRegular SealKind + +// Engine does not generate seal for this block right now. +type None SealKind + +// / The type of sealing the engine is currently able to perform. +type SealingState uint8 + +const ( + /// The engine is ready to seal a block. + SealingStateReady SealingState = 0 + /// The engine can't seal at the moment, and no block should be prepared and queued. + SealingStateNotReady SealingState = 1 + /// The engine does not seal internally. + SealingStateExternal SealingState = 2 +) diff --git a/consensus/aura/config.go b/consensus/aura/config.go new file mode 100644 index 000000000000..0aa1ccbcbbdb --- /dev/null +++ b/consensus/aura/config.go @@ -0,0 +1,196 @@ +// Copyright 2017 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +// Package aura implements the proof-of-authority consensus engine. +package aura + +import ( + "errors" + "math/big" + "sort" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/params" +) + +func newValidatorSetFromJson(j *params.ValidatorSetJson, posdaoTransition *uint64) ValidatorSet { + if j.List != nil { + return &SimpleList{validators: j.List} + } + if j.SafeContract != nil { + return NewValidatorSafeContract(*j.SafeContract, posdaoTransition, nil) + } + if j.Contract != nil { + return &ValidatorContract{ + contractAddress: *j.Contract, + validators: NewValidatorSafeContract(*j.Contract, posdaoTransition, nil), + posdaoTransition: posdaoTransition, + } + } + if j.Multi != nil { + l := map[uint64]ValidatorSet{} + for block, set := range j.Multi { + l[block] = newValidatorSetFromJson(set, posdaoTransition) + } + return NewMulti(l) + } + + return nil +} + +type Code struct { + Code []byte + CodeHash common.Hash +} + +type BlockRewardContract struct { + blockNum uint64 + address common.Address // On-chain address. +} + +type BlockRewardContractList []BlockRewardContract + +func (r BlockRewardContractList) Less(i, j int) bool { return r[i].blockNum < r[j].blockNum } +func (r BlockRewardContractList) Len() int { return len(r) } +func (r BlockRewardContractList) Swap(i, j int) { r[i], r[j] = r[j], r[i] } + +type BlockReward struct { + blockNum uint64 + amount *big.Int +} + +type BlockRewardList []BlockReward + +func (r BlockRewardList) Less(i, j int) bool { return r[i].blockNum < r[j].blockNum } +func (r BlockRewardList) Len() int { return len(r) } +func (r BlockRewardList) Swap(i, j int) { r[i], r[j] = r[j], r[i] } + +func NewBlockRewardContract(address common.Address) *BlockRewardContract { + return &BlockRewardContract{address: address} +} + +type AuthorityRoundParams struct { + // A map defining intervals of blocks with the given times (in seconds) to wait before next + // block or authority switching. The keys in the map are steps of starting blocks of those + // periods. The entry at `0` should be defined. + // + // Wait times (durations) are additionally required to be less than 65535 since larger values + // lead to slow block issuance. + StepDurations map[uint64]uint64 + // Starting step, + StartStep *uint64 + // Valid validators. + Validators ValidatorSet + // Chain score validation transition block. + ValidateScoreTransition uint64 + // Monotonic step validation transition block. + ValidateStepTransition uint64 + // Immediate transitions. + ImmediateTransitions bool + // Block reward in base units. + BlockReward BlockRewardList + // Block reward contract addresses with their associated starting block numbers. + BlockRewardContractTransitions BlockRewardContractList + // Number of accepted uncles transition block. + MaximumUncleCountTransition uint64 + // Number of accepted uncles. + MaximumUncleCount uint + // Transition block to strict empty steps validation. + StrictEmptyStepsTransition uint64 + // If set, enables random number contract integration. It maps the transition block to the contract address. + RandomnessContractAddress map[uint64]common.Address + // The addresses of contracts that determine the block gas limit with their associated block + // numbers. + BlockGasLimitContractTransitions map[uint64]common.Address + // If set, this is the block number at which the consensus engine switches from AuRa to AuRa + // with POSDAO modifications. + PosdaoTransition *uint64 + // Stores human-readable keys associated with addresses, like DNS information. + // This contract is primarily required to store the address of the Certifier contract. + Registrar *common.Address + + // See https://github.com/gnosischain/specs/blob/master/execution/withdrawals.md + WithdrawalContractAddress *common.Address + + RewriteBytecode map[uint64]map[common.Address][]byte +} + +func FromJson(jsonParams *params.AuRaConfig) (AuthorityRoundParams, error) { + params := AuthorityRoundParams{ + Validators: newValidatorSetFromJson(jsonParams.Validators, jsonParams.PosdaoTransition), + StartStep: jsonParams.StartStep, + RandomnessContractAddress: jsonParams.RandomnessContractAddress, + BlockGasLimitContractTransitions: jsonParams.BlockGasLimitContractTransitions, + PosdaoTransition: jsonParams.PosdaoTransition, + Registrar: jsonParams.Registrar, + WithdrawalContractAddress: jsonParams.WithdrawalContractAddress, + } + params.StepDurations = map[uint64]uint64{} + if jsonParams.StepDuration != nil { + params.StepDurations[0] = *jsonParams.StepDuration + } + + for blockNum, address := range jsonParams.BlockRewardContractTransitions { + params.BlockRewardContractTransitions = append(params.BlockRewardContractTransitions, BlockRewardContract{blockNum: uint64(blockNum), address: address}) + } + sort.Sort(params.BlockRewardContractTransitions) + if jsonParams.BlockRewardContractAddress != nil { + transitionBlockNum := uint64(0) + if jsonParams.BlockRewardContractTransition != nil { + transitionBlockNum = *jsonParams.BlockRewardContractTransition + } + if len(params.BlockRewardContractTransitions) > 0 && transitionBlockNum >= params.BlockRewardContractTransitions[0].blockNum { + return params, errors.New("blockRewardContractTransition should be less than any of the keys in BlockRewardContractTransitions") + } + contract := BlockRewardContract{blockNum: transitionBlockNum, address: *jsonParams.BlockRewardContractAddress} + params.BlockRewardContractTransitions = append(BlockRewardContractList{contract}, params.BlockRewardContractTransitions...) + } + + if jsonParams.ValidateScoreTransition != nil { + params.ValidateScoreTransition = *jsonParams.ValidateScoreTransition + } + if jsonParams.ValidateStepTransition != nil { + params.ValidateStepTransition = *jsonParams.ValidateStepTransition + } + if jsonParams.ImmediateTransitions != nil { + params.ImmediateTransitions = *jsonParams.ImmediateTransitions + } + if jsonParams.MaximumUncleCount != nil { + params.MaximumUncleCount = *jsonParams.MaximumUncleCount + } + if jsonParams.MaximumUncleCountTransition != nil { + params.MaximumUncleCountTransition = *jsonParams.MaximumUncleCountTransition + } + + if jsonParams.BlockReward == nil { + params.BlockReward = append(params.BlockReward, BlockReward{blockNum: 0, amount: big.NewInt(0)}) + } else { + if jsonParams.BlockReward != nil { + params.BlockReward = append(params.BlockReward, BlockReward{blockNum: 0, amount: big.NewInt(int64(*jsonParams.BlockReward))}) + } + } + sort.Sort(params.BlockReward) + + params.RewriteBytecode = make(map[uint64]map[common.Address][]byte, len(jsonParams.RewriteBytecode)) + for block, overrides := range jsonParams.RewriteBytecode { + params.RewriteBytecode[block] = make(map[common.Address][]byte, len(overrides)) + for address, code := range overrides { + params.RewriteBytecode[block][address] = []byte(code) + } + } + + return params, nil +} diff --git a/consensus/aura/config_test.go b/consensus/aura/config_test.go new file mode 100644 index 000000000000..c611d5cf5291 --- /dev/null +++ b/consensus/aura/config_test.go @@ -0,0 +1,35 @@ +package aura + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/params" +) + +func TestGnosisBlockRewardContractTransitions(t *testing.T) { + spec := params.GnosisChainConfig.Aura + + param, err := FromJson(spec) + require.NoError(t, err) + + require.Equal(t, 2, len(param.BlockRewardContractTransitions)) + assert.Equal(t, uint64(1310), param.BlockRewardContractTransitions[0].blockNum) + assert.Equal(t, common.HexToAddress("0x867305d19606aadba405ce534e303d0e225f9556"), param.BlockRewardContractTransitions[0].address) + assert.Equal(t, uint64(9186425), param.BlockRewardContractTransitions[1].blockNum) + assert.Equal(t, common.HexToAddress("0x481c034c6d9441db23ea48de68bcae812c5d39ba"), param.BlockRewardContractTransitions[1].address) +} + +func TestInvalidBlockRewardContractTransition(t *testing.T) { + spec := *(params.GnosisChainConfig.Aura) + + // blockRewardContractTransition should be smaller than any block number in blockRewardContractTransitions + invalidTransition := uint64(10_000_000) + spec.BlockRewardContractTransition = &invalidTransition + + _, err := FromJson(&spec) + assert.Error(t, err) +} diff --git a/consensus/aura/contract_abi.go b/consensus/aura/contract_abi.go new file mode 100644 index 000000000000..37890d7dffbf --- /dev/null +++ b/consensus/aura/contract_abi.go @@ -0,0 +1,132 @@ +package aura + +import ( + "bytes" + "math/big" + + "github.com/holiman/uint256" + + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/consensus" + "github.com/ethereum/go-ethereum/consensus/aura/contracts" + "github.com/ethereum/go-ethereum/crypto" +) + +func callBlockRewardAbi(contractAddr common.Address, syscall Syscall, beneficiaries []common.Address, rewardKind []consensus.RewardKind) ([]common.Address, []*big.Int) { + castedKind := make([]uint16, len(rewardKind)) + for i := range rewardKind { + castedKind[i] = uint16(rewardKind[i]) + } + packed, err := blockRewardAbi().Pack("reward", beneficiaries, castedKind) + if err != nil { + panic(err) + } + out, err := syscall(contractAddr, packed) + if err != nil { + panic(err) + } + if len(out) == 0 { + return nil, nil + } + res, err := blockRewardAbi().Unpack("reward", out) + if err != nil { + panic(err) + } + beneficiariesRes := res[0].([]common.Address) + rewardsBig := res[1].([]*big.Int) + // rewardsU256 := make([]*big.Int, len(rewardsBig)) + // for i := 0; i < len(rewardsBig); i++ { + // var overflow bool + // rewards[i], overflow = uint256.FromBig(rewardsBig[i]) + // if overflow { + // panic("Overflow in callBlockRewardAbi") + // } + // } + return beneficiariesRes, rewardsBig +} + +func callBlockGasLimitAbi(contractAddr common.Address, syscall Syscall) *uint256.Int { + packed, err := blockGasLimitAbi().Pack("blockGasLimit") + if err != nil { + panic(err) + } + out, err := syscall(contractAddr, packed) + if err != nil { + panic(err) + } + if len(out) == 0 { + return uint256.NewInt(0) + } + res, err := blockGasLimitAbi().Unpack("blockGasLimit", out) + if err != nil { + panic(err) + } + + val, overflow := uint256.FromBig(res[0].(*big.Int)) + if overflow { + panic("Overflow casting bigInt value to uint256") + } + return val +} + +func blockGasLimitAbi() abi.ABI { + a, err := abi.JSON(bytes.NewReader(contracts.BlockGasLimit)) + if err != nil { + panic(err) + } + return a +} + +func blockRewardAbi() abi.ABI { + a, err := abi.JSON(bytes.NewReader(contracts.BlockReward)) + if err != nil { + panic(err) + } + return a +} + +func certifierAbi() abi.ABI { + a, err := abi.JSON(bytes.NewReader(contracts.Certifier)) + if err != nil { + panic(err) + } + return a +} + +func registrarAbi() abi.ABI { + a, err := abi.JSON(bytes.NewReader(contracts.Registrar)) + if err != nil { + panic(err) + } + return a +} + +func withdrawalAbi() abi.ABI { + a, err := abi.JSON(bytes.NewReader(contracts.Withdrawal)) + if err != nil { + panic(err) + } + return a +} + +func getCertifier(registrar common.Address, syscall Syscall) *common.Address { + hashedKey := crypto.Keccak256Hash([]byte("service_transaction_checker")) + packed, err := registrarAbi().Pack("getAddress", hashedKey, "A") + if err != nil { + panic(err) + } + out, err := syscall(registrar, packed) + if err != nil { + panic(err) + } + if len(out) == 0 { + return nil + } + res, err := registrarAbi().Unpack("getAddress", out) + if err != nil { + panic(err) + } + certifier := res[0].(common.Address) + return &certifier +} diff --git a/consensus/aura/contracts/authority_round_random.json b/consensus/aura/contracts/authority_round_random.json new file mode 100644 index 000000000000..90766c93ef21 --- /dev/null +++ b/consensus/aura/contracts/authority_round_random.json @@ -0,0 +1,149 @@ +[ + { + "constant": false, + "inputs": [ + { + "name": "_secretHash", + "type": "bytes32" + }, + { + "name": "_cipher", + "type": "bytes" + } + ], + "name": "commitHash", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_number", + "type": "uint256" + } + ], + "name": "revealNumber", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "currentCollectRound", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_collectRound", + "type": "uint256" + }, + { + "name": "_miningAddress", + "type": "address" + } + ], + "name": "getCommitAndCipher", + "outputs": [ + { + "name": "", + "type": "bytes32" + }, + { + "name": "", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_collectRound", + "type": "uint256" + }, + { + "name": "_validator", + "type": "address" + } + ], + "name": "isCommitted", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isCommitPhase", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isRevealPhase", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_collectRound", + "type": "uint256" + }, + { + "name": "_validator", + "type": "address" + } + ], + "name": "sentReveal", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } +] \ No newline at end of file diff --git a/consensus/aura/contracts/block_gas_limit.json b/consensus/aura/contracts/block_gas_limit.json new file mode 100644 index 000000000000..8ca9cf96946c --- /dev/null +++ b/consensus/aura/contracts/block_gas_limit.json @@ -0,0 +1,16 @@ +[ + { + "constant": true, + "inputs": [], + "name": "blockGasLimit", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } +] \ No newline at end of file diff --git a/consensus/aura/contracts/block_reward.json b/consensus/aura/contracts/block_reward.json new file mode 100644 index 000000000000..9209967f3ace --- /dev/null +++ b/consensus/aura/contracts/block_reward.json @@ -0,0 +1,29 @@ +[ + { + "constant": false, + "inputs": [ + { + "name": "benefactors", + "type": "address[]" + }, + { + "name": "kind", + "type": "uint16[]" + } + ], + "name": "reward", + "outputs": [ + { + "name": "", + "type": "address[]" + }, + { + "name": "", + "type": "uint256[]" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/consensus/aura/contracts/certifier.json b/consensus/aura/contracts/certifier.json new file mode 100644 index 000000000000..5025acb92fea --- /dev/null +++ b/consensus/aura/contracts/certifier.json @@ -0,0 +1,164 @@ +[ + { + "constant": false, + "inputs": [ + { + "name": "_new", + "type": "address" + } + ], + "name": "setOwner", + "outputs": [], + "payable": false, + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_who", + "type": "address" + } + ], + "name": "certify", + "outputs": [], + "payable": false, + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_who", + "type": "address" + }, + { + "name": "_field", + "type": "string" + } + ], + "name": "getAddress", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_who", + "type": "address" + } + ], + "name": "revoke", + "outputs": [], + "payable": false, + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "owner", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "delegate", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_who", + "type": "address" + }, + { + "name": "_field", + "type": "string" + } + ], + "name": "getUint", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_new", + "type": "address" + } + ], + "name": "setDelegate", + "outputs": [], + "payable": false, + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_who", + "type": "address" + } + ], + "name": "certified", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_who", + "type": "address" + }, + { + "name": "_field", + "type": "string" + } + ], + "name": "get", + "outputs": [ + { + "name": "", + "type": "bytes32" + } + ], + "payable": false, + "type": "function" + } +] diff --git a/consensus/aura/contracts/embed.go b/consensus/aura/contracts/embed.go new file mode 100644 index 000000000000..0a87b2d0b811 --- /dev/null +++ b/consensus/aura/contracts/embed.go @@ -0,0 +1,20 @@ +package contracts + +import ( + _ "embed" +) + +//go:embed block_reward.json +var BlockReward []byte + +//go:embed certifier.json +var Certifier []byte + +//go:embed registrar.json +var Registrar []byte + +//go:embed withdrawal.json +var Withdrawal []byte + +//go:embed block_gas_limit.json +var BlockGasLimit []byte diff --git a/consensus/aura/contracts/registrar.json b/consensus/aura/contracts/registrar.json new file mode 100644 index 000000000000..2f4aab1fdbfa --- /dev/null +++ b/consensus/aura/contracts/registrar.json @@ -0,0 +1,21 @@ +[ + {"constant":false,"inputs":[{"name":"_new","type":"address"}],"name":"setOwner","outputs":[],"type":"function"}, + {"constant":false,"inputs":[{"name":"_name","type":"string"}],"name":"confirmReverse","outputs":[{"name":"success","type":"bool"}],"type":"function"}, + {"constant":false,"inputs":[{"name":"_name","type":"bytes32"}],"name":"reserve","outputs":[{"name":"success","type":"bool"}],"type":"function"}, + {"constant":false,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_key","type":"string"},{"name":"_value","type":"bytes32"}],"name":"set","outputs":[{"name":"success","type":"bool"}],"type":"function"}, + {"constant":false,"inputs":[{"name":"_name","type":"bytes32"}],"name":"drop","outputs":[{"name":"success","type":"bool"}],"type":"function"}, + {"constant":true,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_key","type":"string"}],"name":"getAddress","outputs":[{"name":"","type":"address"}],"type":"function"}, + {"constant":false,"inputs":[{"name":"_amount","type":"uint256"}],"name":"setFee","outputs":[],"type":"function"}, + {"constant":false,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_to","type":"address"}],"name":"transfer","outputs":[{"name":"success","type":"bool"}],"type":"function"}, + {"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"type":"function"}, + {"constant":true,"inputs":[{"name":"_name","type":"bytes32"}],"name":"reserved","outputs":[{"name":"reserved","type":"bool"}],"type":"function"}, + {"constant":false,"inputs":[],"name":"drain","outputs":[],"type":"function"}, + {"constant":false,"inputs":[{"name":"_name","type":"string"},{"name":"_who","type":"address"}],"name":"proposeReverse","outputs":[{"name":"success","type":"bool"}],"type":"function"}, + {"constant":true,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_key","type":"string"}],"name":"getUint","outputs":[{"name":"","type":"uint256"}],"type":"function"}, + {"constant":true,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_key","type":"string"}],"name":"get","outputs":[{"name":"","type":"bytes32"}],"type":"function"}, + {"constant":true,"inputs":[],"name":"fee","outputs":[{"name":"","type":"uint256"}],"type":"function"}, + {"constant":true,"inputs":[{"name":"","type":"address"}],"name":"reverse","outputs":[{"name":"","type":"string"}],"type":"function"}, + {"constant":false,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_key","type":"string"},{"name":"_value","type":"uint256"}],"name":"setUint","outputs":[{"name":"success","type":"bool"}],"type":"function"}, + {"constant":false,"inputs":[],"name":"removeReverse","outputs":[],"type":"function"}, + {"constant":false,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_key","type":"string"},{"name":"_value","type":"address"}],"name":"setAddress","outputs":[{"name":"success","type":"bool"}],"type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"name":"amount","type":"uint256"}],"name":"Drained","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"amount","type":"uint256"}],"name":"FeeChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"bytes32"},{"indexed":true,"name":"owner","type":"address"}],"name":"Reserved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"bytes32"},{"indexed":true,"name":"oldOwner","type":"address"},{"indexed":true,"name":"newOwner","type":"address"}],"name":"Transferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"bytes32"},{"indexed":true,"name":"owner","type":"address"}],"name":"Dropped","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"bytes32"},{"indexed":true,"name":"owner","type":"address"},{"indexed":true,"name":"key","type":"string"}],"name":"DataChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"string"},{"indexed":true,"name":"reverse","type":"address"}],"name":"ReverseProposed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"string"},{"indexed":true,"name":"reverse","type":"address"}],"name":"ReverseConfirmed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"string"},{"indexed":true,"name":"reverse","type":"address"}],"name":"ReverseRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"old","type":"address"},{"indexed":true,"name":"current","type":"address"}],"name":"NewOwner","type":"event"} +] \ No newline at end of file diff --git a/consensus/aura/contracts/test_authority_round_random.json b/consensus/aura/contracts/test_authority_round_random.json new file mode 100644 index 000000000000..beab82ab4864 --- /dev/null +++ b/consensus/aura/contracts/test_authority_round_random.json @@ -0,0 +1,265 @@ +[ + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "address" + } + ], + "name": "ciphers", + "outputs": [ + { + "name": "", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_collectRound", + "type": "uint256" + }, + { + "name": "_miningAddress", + "type": "address" + } + ], + "name": "getCipher", + "outputs": [ + { + "name": "", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_secretHash", + "type": "bytes32" + }, + { + "name": "_cipher", + "type": "bytes" + } + ], + "name": "commitHash", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getValue", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "address" + } + ], + "name": "hashes", + "outputs": [ + { + "name": "", + "type": "bytes32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "value", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "address" + } + ], + "name": "secrets", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_collectRound", + "type": "uint256" + }, + { + "name": "_miningAddress", + "type": "address" + } + ], + "name": "sentReveal", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isCommitPhase", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_number", + "type": "uint256" + } + ], + "name": "revealNumber", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getRound", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_collectRound", + "type": "uint256" + }, + { + "name": "_miningAddress", + "type": "address" + } + ], + "name": "isCommitted", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isRevealPhase", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_collectRound", + "type": "uint256" + }, + { + "name": "_miningAddress", + "type": "address" + } + ], + "name": "getCommit", + "outputs": [ + { + "name": "", + "type": "bytes32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } +] \ No newline at end of file diff --git a/consensus/aura/contracts/test_authority_round_random.sol b/consensus/aura/contracts/test_authority_round_random.sol new file mode 100644 index 000000000000..66c971786358 --- /dev/null +++ b/consensus/aura/contracts/test_authority_round_random.sol @@ -0,0 +1,101 @@ +pragma solidity 0.5.10; + +/// @dev Randomness test contract based on https://github.com/poanetwork/posdao-contracts. +/// Generates and stores random numbers in a RANDAO manner and accumulates a random seed. +contract Random { + mapping(uint256 => mapping(address => bytes32)) public hashes; + mapping(uint256 => mapping(address => bytes)) public ciphers; + mapping(uint256 => mapping(address => uint256)) public secrets; + uint256 public value; + + /// @dev Called by the validator's node to store a hash and a cipher of the validator's secret on each collection + /// round. The validator's node must use its mining address to call this function. + /// This function can only be called once per collection round (during the `commits phase`). + /// @param _secretHash The Keccak-256 hash of the validator's secret. + /// @param _cipher The cipher of the validator's secret. Can be used by the node to decrypt and reveal. + function commitHash(bytes32 _secretHash, bytes calldata _cipher) external { + require(block.coinbase == msg.sender); + require(_isCommitPhase(block.number - 1)); + uint256 round = _collectRound(block.number - 1); + require(!isCommitted(round, msg.sender)); + hashes[round][msg.sender] = _secretHash; + ciphers[round][msg.sender] = _cipher; + } + + /// @dev Called by the validator's node to XOR its secret with the current random seed. + /// The validator's node must use its mining address to call this function. + /// This function can only be called once per collection round (during the `reveals phase`). + /// @param _number The validator's secret. + function revealNumber(uint256 _number) external { + require(block.coinbase == msg.sender); + require(_isRevealPhase(block.number - 1)); + uint256 round = _collectRound(block.number - 1); + require(!sentReveal(round, msg.sender)); + require(hashes[round][msg.sender] == keccak256(abi.encodePacked(_number))); + secrets[round][msg.sender] = _number; + value ^= _number; + } + + /// @dev Returns the Keccak-256 hash and cipher of the validator's secret for the specified collection round + /// and the specified validator stored by the validator through the `commitHash` function. + /// @param _collectRound The serial number of the collection round for which hash and cipher should be retrieved. + /// @param _miningAddress The mining address of validator. + function getCommitAndCipher( + uint256 _collectRound, + address _miningAddress + ) public view returns(bytes32, bytes memory) { + return (hashes[_collectRound][_miningAddress], ciphers[_collectRound][_miningAddress]); + } + + /// @dev Returns a boolean flag indicating whether the specified validator has committed their secret's hash for the + /// specified collection round. + /// @param _collectRound The serial number of the collection round for which the checkup should be done. + /// @param _miningAddress The mining address of the validator. + function isCommitted(uint256 _collectRound, address _miningAddress) public view returns(bool) { + return hashes[_collectRound][_miningAddress] != bytes32(0); + } + + /// @dev Returns a boolean flag indicating whether the current phase of the current collection round + /// is a `commits phase`. Used by the validator's node to determine if it should commit the hash of + /// the secret during the current collection round. + function isCommitPhase() public view returns(bool) { + return _isCommitPhase(block.number); + } + + /// @dev Returns a boolean flag indicating whether the current phase of the current collection round + /// is a `reveals phase`. Used by the validator's node to determine if it should reveal the secret during + /// the current collection round. + function isRevealPhase() public view returns(bool) { + return _isRevealPhase(block.number); + } + + /// @dev Returns a boolean flag of whether the specified validator has revealed their secret for the + /// specified collection round. + /// @param _collectRound The serial number of the collection round for which the checkup should be done. + /// @param _miningAddress The mining address of the validator. + function sentReveal(uint256 _collectRound, address _miningAddress) public view returns(bool) { + return secrets[_collectRound][_miningAddress] != uint256(0); + } + + /// @dev Returns the current collect round number. + function currentCollectRound() public view returns(uint256) { + return _collectRound(block.number); + } + + /// @dev Returns the current random value. + function getValue() public view returns(uint256) { + return value; + } + + function _collectRound(uint256 blockNumber) private pure returns(uint256) { + return blockNumber / 6; + } + + function _isCommitPhase(uint256 blockNumber) private pure returns(bool) { + return blockNumber % 6 < 3; + } + + function _isRevealPhase(uint256 blockNumber) private pure returns(bool) { + return blockNumber % 6 >= 3; + } +} diff --git a/consensus/aura/contracts/test_validator_set.json b/consensus/aura/contracts/test_validator_set.json new file mode 100644 index 000000000000..7ed6a000fe5d --- /dev/null +++ b/consensus/aura/contracts/test_validator_set.json @@ -0,0 +1,8 @@ +[ + {"constant":false,"inputs":[{"name":"_validators","type":"address[]"}],"name":"setValidators","outputs":[],"payable":false,"type":"function"}, + {"constant":false,"inputs":[{"name":"","type":"address"},{"name":"","type":"bytes"}],"name":"reportMalicious","outputs":[],"payable":false,"type":"function"}, + {"constant":false,"inputs":[],"name":"finalizeChange","outputs":[],"payable":false,"type":"function"}, + {"constant":true,"inputs":[],"name":"getValidators","outputs":[{"name":"_validators","type":"address[]"}],"payable":false,"type":"function"}, + {"constant":false,"inputs":[{"name":"","type":"address"}],"name":"reportBenign","outputs":[],"payable":false,"type":"function"}, + {"anonymous":false,"inputs":[{"indexed":true,"name":"_parent_hash","type":"bytes32"},{"indexed":false,"name":"_new_set","type":"address[]"}],"name":"InitiateChange","type":"event"} +] diff --git a/consensus/aura/contracts/tx_acl.json b/consensus/aura/contracts/tx_acl.json new file mode 100644 index 000000000000..e110797d96fb --- /dev/null +++ b/consensus/aura/contracts/tx_acl.json @@ -0,0 +1 @@ +[ { "constant": true, "inputs": [], "name": "contractNameHash", "outputs": [ { "name": "", "type": "bytes32" } ], "payable": false, "stateMutability": "view", "type": "function" }, { "constant": true, "inputs": [], "name": "contractName", "outputs": [ { "name": "", "type": "string" } ], "payable": false, "stateMutability": "view", "type": "function" }, { "constant": true, "inputs": [], "name": "contractVersion", "outputs": [ { "name": "", "type": "uint256" } ], "payable": false, "stateMutability": "view", "type": "function" }, { "constant": true, "inputs": [ { "name": "sender", "type": "address" }, { "name": "to", "type": "address" }, { "name": "value", "type": "uint256" } ], "name": "allowedTxTypes", "outputs": [ { "name": "", "type": "uint32" }, { "name": "", "type": "bool" } ], "payable": false, "stateMutability": "view", "type": "function" } ] diff --git a/consensus/aura/contracts/tx_acl_deprecated.json b/consensus/aura/contracts/tx_acl_deprecated.json new file mode 100644 index 000000000000..cc924cafb81d --- /dev/null +++ b/consensus/aura/contracts/tx_acl_deprecated.json @@ -0,0 +1 @@ +[{"constant":true,"inputs":[{"name":"sender","type":"address"}],"name":"allowedTxTypes","outputs":[{"name":"","type":"uint32"}],"payable":false,"stateMutability":"nonpayable","type":"function"}] diff --git a/consensus/aura/contracts/tx_acl_gas_price.json b/consensus/aura/contracts/tx_acl_gas_price.json new file mode 100644 index 000000000000..37b08e9f0dbc --- /dev/null +++ b/consensus/aura/contracts/tx_acl_gas_price.json @@ -0,0 +1,83 @@ +[ + { + "constant": true, + "inputs": [], + "name": "contractNameHash", + "outputs": [ + { + "name": "", + "type": "bytes32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "contractName", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "contractVersion", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "sender", + "type": "address" + }, + { + "name": "to", + "type": "address" + }, + { + "name": "value", + "type": "uint256" + }, + { + "name": "gasPrice", + "type": "uint256" + }, + { + "name": "data", + "type": "bytes" + } + ], + "name": "allowedTxTypes", + "outputs": [ + { + "name": "", + "type": "uint32" + }, + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } +] \ No newline at end of file diff --git a/consensus/aura/contracts/validator_report.json b/consensus/aura/contracts/validator_report.json new file mode 100644 index 000000000000..e0c011432696 --- /dev/null +++ b/consensus/aura/contracts/validator_report.json @@ -0,0 +1,5 @@ +[ + {"constant":false,"inputs":[{"name":"validator","type":"address"},{"name":"blockNumber","type":"uint256"},{"name":"proof","type":"bytes"}],"name":"reportMalicious","outputs":[],"payable":false,"type":"function"}, + {"constant":false,"inputs":[{"name":"validator","type":"address"},{"name":"blockNumber","type":"uint256"}],"name":"reportBenign","outputs":[],"payable":false,"type":"function"}, + {"constant": true, "inputs": [ { "name": "validator", "type": "address" }, { "name": "blockNum", "type": "uint256" } ], "name": "maliceReportedForBlock", "outputs": [ { "name": "", "type": "address[]" } ], "payable": false, "stateMutability": "view", "type": "function" } +] diff --git a/consensus/aura/contracts/validator_set.json b/consensus/aura/contracts/validator_set.json new file mode 100644 index 000000000000..660e8b614bbe --- /dev/null +++ b/consensus/aura/contracts/validator_set.json @@ -0,0 +1,55 @@ +[ + {"constant":false,"inputs":[],"name":"finalizeChange","outputs":[],"payable":false,"type":"function"}, + {"constant":true,"inputs":[],"name":"getValidators","outputs":[{"name":"validators","type":"address[]"}],"payable":false,"type":"function"}, + {"anonymous":false,"inputs":[{"indexed":true,"name":"_parent_hash","type":"bytes32"},{"indexed":false,"name":"_new_set","type":"address[]"}],"name":"InitiateChange","type":"event"}, + { + "constant": true, + "inputs": [], + "name": "emitInitiateChangeCallable", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "emitInitiateChange", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_reportingValidator", + "type": "address" + }, + { + "name": "_maliciousValidator", + "type": "address" + }, + { + "name": "_blockNumber", + "type": "uint256" + } + ], + "name": "shouldValidatorReport", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ] \ No newline at end of file diff --git a/consensus/aura/contracts/withdrawal.json b/consensus/aura/contracts/withdrawal.json new file mode 100644 index 000000000000..1f706b8d4e5a --- /dev/null +++ b/consensus/aura/contracts/withdrawal.json @@ -0,0 +1,23 @@ +[ + { + "constant": false, + "inputs": [ + { + "name": "maxNumberOfFailedWithdrawalsToProcess", + "type": "uint256" + }, + { + "name": "amounts", + "type": "uint64[]" + }, + { + "name": "addresses", + "type": "address[]" + } + ], + "name": "executeSystemWithdrawals", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/consensus/aura/finality_test.go b/consensus/aura/finality_test.go new file mode 100644 index 000000000000..e132f658ff46 --- /dev/null +++ b/consensus/aura/finality_test.go @@ -0,0 +1,72 @@ +package aura + +import ( + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/assert" +) + +func TestRollingFinality(t *testing.T) { + t.Run("RejectsUnknownSigners", func(t *testing.T) { + f := NewRollingFinality([]common.Address{{1}, {2}, {3}}) + _, err := f.push(common.Hash{}, 0, []common.Address{{0}, {4}}) + assert.Error(t, err) + _, err = f.push(common.Hash{}, 0, []common.Address{{0}, {1}, {4}}) + assert.Error(t, err) + }) + t.Run("FinalizeMultiple", func(t *testing.T) { + signers := []common.Address{{0}, {1}, {2}, {3}, {4}, {5}} + f := NewRollingFinality(signers) + // 3 / 6 signers is < 51% so no finality. + for i := 0; i < 6; i++ { + l, err := f.push(common.Hash{byte(i)}, uint64(i%3), []common.Address{signers[i%3]}) + assert.NoError(t, err) + assert.Equal(t, 0, len(l)) + } + // after pushing a block signed by a fourth validator, the first four + // blocks of the unverified chain become verified. + l, err := f.push(common.Hash{byte(6)}, 6, []common.Address{signers[4]}) + assert.NoError(t, err) + for i := uint64(0); i < 4; i++ { + assert.Equal(t, common.Hash{byte(i)}, l[i].hash) + } + assert.Equal(t, 4, len(l)) + }) + t.Run("FromAncestry", func(t *testing.T) { + signers := []common.Address{{0}, {1}, {2}, {3}, {4}, {5}} + f := NewRollingFinality(signers) + i := 12 + get := func(hash common.Hash) ([]common.Address, common.Hash, common.Hash, uint64, bool) { + i-- + if i == -1 { + return nil, common.Hash{}, common.Hash{}, 0, false + } + return []common.Address{signers[i%6]}, common.Hash{byte(i)}, common.Hash{byte(i - 1)}, uint64(i), true + } + err := f.buildAncestrySubChain(get, common.Hash{11}, common.Hash{99}) + assert.NoError(t, err) + assert.Equal(t, 3, f.headers.l.Len()) + assert.Equal(t, common.Hash{11}, *f.lastPushed) + }) + t.Run("FromAncestryMultipleSigners", func(t *testing.T) { + signers := []common.Address{{0}, {1}, {2}, {3}, {4}, {5}} + f := NewRollingFinality(signers) + i := 12 + get := func(hash common.Hash) ([]common.Address, common.Hash, common.Hash, uint64, bool) { + i-- + if i == -1 { + return nil, common.Hash{}, common.Hash{}, 0, false + } + return []common.Address{signers[i%6], signers[(i+1)%6], signers[(i+2)%6]}, common.Hash{byte(i)}, common.Hash{byte(i - 1)}, uint64(i), true + } + err := f.buildAncestrySubChain(get, common.Hash{11}, common.Hash{99}) + assert.NoError(t, err) + + // only the last hash has < 51% of authorities' signatures + assert.Equal(t, 1, f.headers.l.Len()) + assert.Equal(t, common.Hash{11}, f.headers.Front().hash) + assert.Equal(t, common.Hash{11}, *f.lastPushed) + }) + +} diff --git a/consensus/aura/gaslimit_override.go b/consensus/aura/gaslimit_override.go new file mode 100644 index 000000000000..c8f13604f6c1 --- /dev/null +++ b/consensus/aura/gaslimit_override.go @@ -0,0 +1,71 @@ +package aura + +import ( + lru "github.com/hashicorp/golang-lru/v2" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/consensus" + "github.com/ethereum/go-ethereum/core/state" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/params" + "github.com/holiman/uint256" +) + +type GasLimitOverride struct { + cache *lru.Cache[common.Hash, *uint256.Int] +} + +func NewGasLimitOverride() *GasLimitOverride { + // The number of recent block hashes for which the gas limit override is memoized. + const GasLimitOverrideCacheCapacity = 10 + + cache, err := lru.New[common.Hash, *uint256.Int](GasLimitOverrideCacheCapacity) + if err != nil { + panic("error creating prefetching cache for blocks") + } + return &GasLimitOverride{cache: cache} +} + +func (pb *GasLimitOverride) Pop(hash common.Hash) *uint256.Int { + if val, ok := pb.cache.Get(hash); ok && val != nil { + pb.cache.Remove(hash) + return val + } + return nil +} + +func (pb *GasLimitOverride) Add(hash common.Hash, b *uint256.Int) { + if b == nil { + return + } + pb.cache.ContainsOrAdd(hash, b) +} + +func (c *AuRa) HasGasLimitContract() bool { + return len(c.cfg.BlockGasLimitContractTransitions) != 0 +} + +func (c *AuRa) GetBlockGasLimitFromContract(_ *params.ChainConfig) uint64 { + // var blockLimitContract + addr, ok := c.cfg.BlockGasLimitContractTransitions[0] + if !ok { + return 0 + } + gasLimit := callBlockGasLimitAbi(addr, c.Syscall) + return gasLimit.Uint64() +} + +func (c *AuRa) verifyGasLimitOverride(config *params.ChainConfig, chain consensus.ChainHeaderReader, header *types.Header, statedb *state.StateDB, syscallCustom Syscall) { + // TODO(gballet): take care of that when we reach the merge + //IsPoSHeader check is necessary as merge.go calls Initialize on AuRa indiscriminately + // gasLimitOverride := c.HasGasLimitContract() && !misc.IsPoSHeader(header) + // if gasLimitOverride { + blockGasLimit := c.GetBlockGasLimitFromContract(config) + + if blockGasLimit > 0 { + if header.GasLimit != blockGasLimit { + panic("Block gas limit doesn't match BlockGasLimitContract with AuRa") + } + } + // } +} diff --git a/consensus/aura/validators.go b/consensus/aura/validators.go new file mode 100644 index 000000000000..67cb0c013558 --- /dev/null +++ b/consensus/aura/validators.go @@ -0,0 +1,931 @@ +package aura + +import ( + "container/list" + "fmt" + "sort" + "strings" + "sync" + "sync/atomic" + + lru "github.com/hashicorp/golang-lru/v2" + + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/consensus/aura/auraabi" + "github.com/ethereum/go-ethereum/consensus/aura/aurainterfaces" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/rlp" +) + +// nolint +type CallResults struct { + data []byte + proof [][]byte + execError string +} + +// Type alias for a function we can make calls through synchronously. +// Returns the call result and state proof for each call. +type Call func(common.Address, []byte) (CallResults, error) + +// A system-calling closure. Enacts calls on a block's state from the system address. +type SystemCall func(common.Address, []byte) (CallResults, error) + +type client interface { + CallAtBlockHash(common.Hash, common.Address, []byte) (CallResults, error) + CallAtLatestBlock(common.Address, []byte) (CallResults, error) + SystemCallAtBlockHash(blockHash common.Hash, contract common.Address, data []byte) (CallResults, error) +} + +type ValidatorSet interface { + + // Get the default "Call" helper, for use in general operation. + // TODO [keorn]: this is a hack intended to migrate off of + // a strict dependency on state always being available. + defaultCaller(blockHash common.Hash) (Call, error) + + // Called for each new block this node is creating. If this block is + // the first block of an epoch, this is called *after* `on_epoch_begin()`, + // but with the same parameters. + // + // Returns a list of contract calls to be pushed onto the new block. + //func generateEngineTransactions(_firstInEpoch bool, _header *types.Header, _call SystemCall) -> Result, EthcoreError> + + // Signalling that a new epoch has begun. + // + // All calls here will be from the `SYSTEM_ADDRESS`: 2^160 - 2 + // and will have an effect on the block's state. + // The caller provided here may not generate proofs. + // + // `first` is true if this is the first block in the set. + onEpochBegin(firstInEpoch bool, header *types.Header, caller Syscall) error + + // Called on the close of every block. + onCloseBlock(_header *types.Header, _address common.Address) error + + // Draws a validator nonce modulo number of validators. + // getWithCaller(parentHash common.Hash, nonce uint, caller consensus.Call) (common.Address, error) + // Returns the current number of validators. + // countWithCaller(parentHash common.Hash, caller consensus.Call) (uint64, error) + + // Recover the validator set from the given proof, the block number, and + // whether this header is first in its set. + // + // May fail if the given header doesn't kick off an epoch or + // the proof is invalid. + // + // Returns the set, along with a flag indicating whether finality of a specific + // hash should be proven. + epochSet(firstInEpoch bool, num uint64, setProof []byte, call Syscall) (SimpleList, common.Hash, error) + + // Extract genesis epoch data from the genesis state and header. + genesisEpochData(header *types.Header, call Syscall) ([]byte, error) + + /* + // Returns the current number of validators. + fn count(&self, parent: &H256) -> usize { + let default = self.default_caller(BlockId::Hash(*parent)); + self.count_with_caller(parent, &*default) + } + + // Signalling that a new epoch has begun. + // + // All calls here will be from the `SYSTEM_ADDRESS`: 2^160 - 2 + // and will have an effect on the block's state. + // The caller provided here may not generate proofs. + // + // `first` is true if this is the first block in the set. + fn on_epoch_begin( + &self, + _first: bool, + _header: &Header, + _call: &mut SystemCall, + ) -> Result<(), ::error::Error> { + Ok(()) + } + + // Extract genesis epoch data from the genesis state and header. + fn genesis_epoch_data(&self, _header: &Header, _call: &Call) -> Result, String> { + Ok(Vec::new()) + } + */ + // Whether this block is the last one in its epoch. + // + // Indicates that the validator set changed at the given block in a manner + // that doesn't require finality. + // + // `first` is true if this is the first block in the set. + signalEpochEnd(firstInEpoch bool, header *types.Header, receipts types.Receipts) ([]byte, error) + /* + // Whether the given block signals the end of an epoch, but change won't take effect + // until finality. + // + // Engine should set `first` only if the header is genesis. Multiplexing validator + // sets can set `first` to internal changes. + fn signals_epoch_end( + &self, + first: bool, + header: &Header, + aux: AuxiliaryData, + ) -> ::engines::EpochChange; + + // Recover the validator set from the given proof, the block number, and + // whether this header is first in its set. + // + // May fail if the given header doesn't kick off an epoch or + // the proof is invalid. + // + // Returns the set, along with a flag indicating whether finality of a specific + // hash should be proven. + fn epoch_set( + &self, + first: bool, + machine: &EthereumMachine, + number: BlockNumber, + proof: &[u8], + ) -> Result<(SimpleList, Option), ::error::Error>; + + // Checks if a given address is a validator, with the given function + // for executing synchronous calls to contracts. + fn contains_with_caller( + &self, + parent_block_hash: &H256, + address: &Address, + caller: &Call, + ) -> bool; + + // Draws an validator nonce modulo number of validators. + fn get_with_caller(&self, parent_block_hash: &H256, nonce: usize, caller: &Call) -> Address; + + + // Notifies about malicious behaviour. + fn report_malicious( + &self, + _validator: &Address, + _set_block: BlockNumber, + _block: BlockNumber, + _proof: Bytes, + ) { + } + // Notifies about benign misbehaviour. + fn report_benign(&self, _validator: &Address, _set_block: BlockNumber, _block: BlockNumber) {} + */ +} + +// func get(s ValidatorSet, h common.Hash, nonce uint, call consensus.Call) (common.Address, error) { +// //d, err := s.defaultCaller(h) +// //if err != nil { +// // return common.Address{}, err +// //} +// return s.getWithCaller(h, nonce, call) +// } +// func count(s ValidatorSet, h common.Hash, call consensus.Call) (uint64, error) { +// //d, err := s.defaultCaller(h) +// //if err != nil { +// // return 0, err +// //} +// return s.countWithCaller(h, call) +// } + +// nolint +type MultiItem struct { + num uint64 + hash common.Hash + set ValidatorSet +} + +type Multi struct { + sorted []MultiItem + parent func(common.Hash) *types.Header +} + +func (s *Multi) Less(i, j int) bool { return s.sorted[i].num < s.sorted[j].num } +func (s *Multi) Len() int { return len(s.sorted) } +func (s *Multi) Swap(i, j int) { s.sorted[i], s.sorted[j] = s.sorted[j], s.sorted[i] } + +func NewMulti(m map[uint64]ValidatorSet) *Multi { + if _, ok := m[0]; !ok { + panic("ValidatorSet has to be specified from block 0") + } + list := make([]MultiItem, len(m)) + i := 0 + for n, v := range m { + list[i] = MultiItem{num: n, set: v} + i++ + } + multi := &Multi{sorted: list} + sort.Sort(multi) + return multi +} + +func (s *Multi) defaultCaller(blockHash common.Hash) (Call, error) { + set, ok := s.correctSet(blockHash) + if !ok { + return nil, fmt.Errorf("no validator set for given blockHash: %x", blockHash) + } + return set.defaultCaller(blockHash) +} + +// func (s *Multi) getWithCaller(parentHash common.Hash, nonce uint, caller consensus.Call) (common.Address, error) { +// panic("not implemented") +// } +// func (s *Multi) countWithCaller(parentHash common.Hash, caller consensus.Call) (uint64, error) { +// set, ok := s.correctSet(parentHash) +// if !ok { +// return math.MaxUint64, nil +// } +// return set.countWithCaller(parentHash, caller) +// } + +func (s *Multi) correctSet(blockHash common.Hash) (ValidatorSet, bool) { + parent := s.parent(blockHash) + if parent == nil { + return nil, false + } + _, set := s.correctSetByNumber(parent.Number.Uint64()) + return set, set != nil +} + +func (s *Multi) correctSetByNumber(parentNumber uint64) (uint64, ValidatorSet) { + // get correct set by block number, along with block number at which + // this set was activated. + for i := len(s.sorted) - 1; i >= 0; i-- { + if s.sorted[i].num <= parentNumber+1 { + return s.sorted[i].num, s.sorted[i].set + } + } + panic("constructor validation ensures that there is at least one validator set for block 0; block 0 is less than any uint; qed") +} + +func (s *Multi) get(num uint64) (firstInEpoch bool, set ValidatorSet) { + block, set := s.correctSetByNumber(num) + firstInEpoch = block == num + return firstInEpoch, set +} + +func (s *Multi) onCloseBlock(header *types.Header, address common.Address) error { + _, set := s.get(header.Number.Uint64()) + return set.onCloseBlock(header, address) +} + +// TODO: do we need add `proof` argument? +// nolint +func (s *Multi) epochSet(firstInEpoch bool, num uint64, proof []byte, call Syscall) (SimpleList, common.Hash, error) { + setBlock, set := s.correctSetByNumber(num) + firstInEpoch = setBlock == num + return set.epochSet(firstInEpoch, num, proof, call) +} +func (s *Multi) genesisEpochData(header *types.Header, call Syscall) ([]byte, error) { + _, set := s.correctSetByNumber(0) + return set.genesisEpochData(header, call) +} + +func (s *Multi) onEpochBegin(_ bool, header *types.Header, caller Syscall) error { + setTransition, set := s.correctSetByNumber(header.Number.Uint64()) + return set.onEpochBegin(setTransition == header.Number.Uint64(), header, caller) +} +func (s *Multi) signalEpochEnd(_ bool, header *types.Header, r types.Receipts) ([]byte, error) { + num := header.Number.Uint64() + setBlock, set := s.correctSetByNumber(num) + first := setBlock == num + return set.signalEpochEnd(first, header, r) +} + +type SimpleList struct { + validators []common.Address +} + +func (s *SimpleList) epochSet(firstInEpoch bool, num uint64, proof []byte, call Syscall) (SimpleList, common.Hash, error) { + return *s, common.Hash{}, nil +} +func (s *SimpleList) onEpochBegin(firstInEpoch bool, header *types.Header, caller Syscall) error { + return nil +} +func (s *SimpleList) onCloseBlock(_header *types.Header, _address common.Address) error { + return nil +} +func (s *SimpleList) defaultCaller(blockHash common.Hash) (Call, error) { + return nil, nil //simple list doesn't require calls +} + +// func (s *SimpleList) getWithCaller(parentHash common.Hash, nonce uint, caller consensus.Call) (common.Address, error) { +// if len(s.validators) == 0 { +// return common.Address{}, fmt.Errorf("cannot operate with an empty validator set") +// } +// return s.validators[nonce%uint(len(s.validators))], nil +// } +// +// func (s *SimpleList) countWithCaller(parentHash common.Hash, caller consensus.Call) (uint64, error) { +// return uint64(len(s.validators)), nil +// } +func (s *SimpleList) genesisEpochData(header *types.Header, call Syscall) ([]byte, error) { + return []byte{}, nil +} + +func (s *SimpleList) signalEpochEnd(_ bool, header *types.Header, r types.Receipts) ([]byte, error) { + return nil, nil +} + +// Draws an validator nonce modulo number of validators. + +func NewSimpleList(validators []common.Address) *SimpleList { + return &SimpleList{validators: validators} +} + +// nolint +type ReportQueueItem struct { + addr common.Address + blockNum uint64 + data []byte +} + +// nolint +type ReportQueue struct { + mu sync.RWMutex + list *list.List +} + +// nolint +func (q *ReportQueue) push(addr common.Address, blockNum uint64, data []byte) { + q.mu.Lock() + defer q.mu.Unlock() + q.list.PushBack(&ReportQueueItem{addr: addr, blockNum: blockNum, data: data}) +} + +// Filters reports of validators that have already been reported or are banned. +// nolint +func (q *ReportQueue) filter(abi aurainterfaces.ValidatorSetABI, client client, ourAddr, contractAddr common.Address) error { + q.mu.Lock() + defer q.mu.Unlock() + for e := q.list.Front(); e != nil; e = e.Next() { + el := e.Value.(*ReportQueueItem) + // Check if the validator should be reported. + maliciousValidatorAddress := el.addr + data, decoder := abi.ShouldValidatorReport(ourAddr, maliciousValidatorAddress, el.blockNum) + res, err := client.CallAtLatestBlock(contractAddr, data) + if err != nil { + return err + } + if res.execError != "" { + log.Warn("Failed to query report status, dropping pending report.", "reason", res.execError) + continue + } + var shouldReport bool + err = decoder(res.data, &res) + if err != nil { + return err + } + if !shouldReport { + q.list.Remove(e) + } + } + return nil +} + +// Removes reports from the queue if it contains more than `MAX_QUEUED_REPORTS` entries. +// nolint +func (q *ReportQueue) truncate() { + // The maximum number of reports to keep queued. + const MaxQueuedReports = 10 + + q.mu.RLock() + defer q.mu.RUnlock() + // Removes reports from the queue if it contains more than `MAX_QUEUED_REPORTS` entries. + if q.list.Len() > MaxQueuedReports { + log.Warn("Removing reports from report cache, even though it has not been finalized", "amount", q.list.Len()-MaxQueuedReports) + } + i := 0 + for e := q.list.Front(); e != nil; e = e.Next() { + if i > MaxQueuedReports { + q.list.Remove(e) + } + i++ + } +} + +// The validator contract should have the following interface: +// nolint +type ValidatorSafeContract struct { + contractAddress common.Address + validators *lru.Cache[common.Hash, *SimpleList] // RwLock>, + reportQueue ReportQueue //Mutex, + // The block number where we resent the queued reports last time. + resentReportsInBlock atomic.Uint64 + // If set, this is the block number at which the consensus engine switches from AuRa to AuRa + // with POSDAO modifications. + posdaoTransition *uint64 + + abi abi.ABI + client client +} + +func NewValidatorSafeContract(contractAddress common.Address, posdaoTransition *uint64, client client) *ValidatorSafeContract { + const MemoizeCapacity = 500 + c, err := lru.New[common.Hash, *SimpleList](MemoizeCapacity) + if err != nil { + panic("error creating ValidatorSafeContract cache") + } + + parsed, err := abi.JSON(strings.NewReader(auraabi.ValidatorSetABI)) + if err != nil { + panic(err) + } + return &ValidatorSafeContract{contractAddress: contractAddress, posdaoTransition: posdaoTransition, validators: c, abi: parsed} +} + +// Called for each new block this node is creating. If this block is +// the first block of an epoch, this is called *after* `on_epoch_begin()`, +// but with the same parameters. +// +// Returns a list of contract calls to be pushed onto the new block. +// func generateEngineTransactions(_firstInEpoch bool, _header *types.Header, _call SystemCall) -> Result, EthcoreError> +func (s *ValidatorSafeContract) epochSet(firstInEpoch bool, num uint64, setProof []byte, call Syscall) (SimpleList, common.Hash, error) { + if firstInEpoch { + var proof FirstValidatorSetProof + if err := rlp.DecodeBytes(setProof, &proof); err != nil { + return SimpleList{}, common.Hash{}, fmt.Errorf("[ValidatorSafeContract.epochSet] %w", err) + } + + if num == 0 { + return *NewSimpleList([]common.Address{proof.Header.Coinbase}), proof.Header.ParentHash, nil + } + l, ok := s.getListSyscall(call) + if !ok { + panic(1) + } + + //addresses, err := checkFirstValidatorSetProof(s.contractAddress, oldHeader, state_items) + //if err != nil { + // panic(err) + // return SimpleList{}, common.Hash{}, fmt.Errorf("insufitient proof: block=%d,%x: %w", oldHeader.Number.Uint64(), oldHeader.Hash(), err) + //} + + //fmt.Printf("aaaa: %x,%x\n", common.HexToAddress("0xe8ddc5c7a2d2f0d7a9798459c0104fdf5e987aca"), params.SokolGenesisHash) + //fmt.Printf("bbbbb: %x,%x\n", proof.ContractAddress, proof.Header.Hash()) + return *l, proof.Header.ParentHash, nil + } + var proof ValidatorSetProof + if err := rlp.DecodeBytes(setProof, &proof); err != nil { + return SimpleList{}, common.Hash{}, fmt.Errorf("[ValidatorSafeContract.epochSet] %w", err) + } + + if num > DEBUG_LOG_FROM { + fmt.Printf("epoch_set1: %d,%d,%d\n", proof.Header.Number.Uint64(), len(setProof), len(proof.Receipts)) + } + ll, ok := s.extractFromEvent(proof.Header, proof.Receipts) + if !ok { + panic(1) + } + + // ensure receipts match header. + // TODO: optimize? these were just decoded. + /* + let found_root = ::triehash::ordered_trie_root(receipts.iter().map(|r| r.encode())); + if found_root != *old_header.receipts_root() { + return Err(::error::BlockError::InvalidReceiptsRoot(Mismatch { + expected: *old_header.receipts_root(), + found: found_root, + }) + .into()); + } + + let bloom = self.expected_bloom(&old_header); + + match self.extract_from_event(bloom, &old_header, &receipts) { + Some(list) => Ok((list, Some(old_header.hash()))), + None => Err(::engines::EngineError::InsufficientProof( + "No log event in proof.".into(), + ) + .into()), + } + */ + return *ll, common.Hash{}, nil + /* + setProof, err := decodeValidatorSetProof(proof.SetProof) + if err != nil { + return SimpleList{}, common.Hash{}, err + } + _ = setProof + */ + +} + +// check a first proof: fetch the validator set at the given block. +// nolint +func checkFirstValidatorSetProof(contract_address common.Address, oldHeader *types.Header, dbItems [][]byte) ([]common.Address, error) { + /* + fn check_first_proof( + machine: &EthereumMachine, + contract_address: Address, + old_header: Header, + state_items: &[DBValue], + ) -> Result, String> { + use types::transaction::{Action, Transaction, TypedTransaction}; + + // TODO: match client contract_call_tx more cleanly without duplication. + const PROVIDED_GAS: u64 = 50_000_000; + + let env_info = ::vm::EnvInfo { + number: old_header.number(), + author: *old_header.author(), + difficulty: *old_header.difficulty(), + gas_limit: PROVIDED_GAS.into(), + timestamp: old_header.timestamp(), + last_hashes: { + // this will break if we don't inclue all 256 last hashes. + let mut last_hashes: Vec<_> = (0..256).map(|_| H256::default()).collect(); + last_hashes[255] = *old_header.parent_hash(); + Arc::new(last_hashes) + }, + gas_used: 0.into(), + }; + + // check state proof using given machine. + let number = old_header.number(); + let (data, decoder) = validator_set::functions::get_validators::call(); + + let from = Address::default(); + let tx = TypedTransaction::Legacy(Transaction { + nonce: machine.account_start_nonce(number), + action: Action::Call(contract_address), + gas: PROVIDED_GAS.into(), + gas_price: U256::default(), + value: U256::default(), + data, + }) + .fake_sign(from); + + let res = ::state::check_proof( + state_items, + *old_header.state_root(), + &tx, + machine, + &env_info, + ); + + match res { + ::state::ProvedExecution::BadProof => Err("Bad proof".into()), + ::state::ProvedExecution::Failed(e) => Err(format!("Failed call: {}", e)), + ::state::ProvedExecution::Complete(e) => { + decoder.decode(&e.output).map_err(|e| e.to_string()) + } + } + } + */ + return nil, nil +} + +// inter-contract proofs are a header and receipts. +// checking will involve ensuring that the receipts match the header and +// extracting the validator set from the receipts. +// nolint +func (s *ValidatorSafeContract) defaultCaller(blockHash common.Hash) (Call, error) { + return func(addr common.Address, data []byte) (CallResults, error) { + return s.client.CallAtBlockHash(blockHash, addr, data) + }, nil +} + +// func (s *ValidatorSafeContract) getWithCaller(blockHash common.Hash, nonce uint, caller consensus.Call) (common.Address, error) { +// set, ok := s.validators.Get(blockHash) +// if ok { +// return get(set, blockHash, nonce, caller) +// } + +// list, ok := s.getList(caller) +// if !ok { +// return common.Address{}, nil +// } +// s.validators.Add(blockHash, list) +// return get(list, blockHash, nonce, caller) +// } +// func (s *ValidatorSafeContract) countWithCaller(parentHash common.Hash, caller consensus.Call) (uint64, error) { +// set, ok := s.validators.Get(parentHash) +// if ok { +// return count(set, parentHash, caller) +// } +// list, ok := s.getList(caller) +// if !ok { +// return math.MaxUint64, nil +// } +// s.validators.Add(parentHash, list) +// return count(list, parentHash, caller) +// } + +// func (s *ValidatorSafeContract) getList(caller consensus.Call) (*SimpleList, bool) { +// packed, err := s.abi.Pack("getValidators") +// if err != nil { +// panic(err) +// } +// out, err := caller(s.contractAddress, packed) +// if err != nil { +// panic(err) +// } +// res, err := s.abi.Unpack("getValidators", out) +// if err != nil { +// panic(err) +// } +// out0 := *abi.ConvertType(res[0], new([]common.Address)).(*[]common.Address) +// return NewSimpleList(out0), true +// } + +func (s *ValidatorSafeContract) getListSyscall(caller Syscall) (*SimpleList, bool) { + packed, err := s.abi.Pack("getValidators") + if err != nil { + panic(err) + } + out, err := caller(s.contractAddress, packed) + if err != nil { + panic(err) + } + res, err := s.abi.Unpack("getValidators", out) + if err != nil { + panic(err) + } + out0 := *abi.ConvertType(res[0], new([]common.Address)).(*[]common.Address) + return NewSimpleList(out0), true +} + +func (s *ValidatorSafeContract) genesisEpochData(header *types.Header, call Syscall) ([]byte, error) { + return proveInitial(s, s.contractAddress, header, call) +} + +func (s *ValidatorSafeContract) onEpochBegin(firstInEpoch bool, header *types.Header, caller Syscall) error { + data := common.FromHex("75286211") // s.abi.Pack("finalizeChange") + _, err := caller(s.contractAddress, data) + if err != nil { + return err + } + + /* + let data = validator_set::functions::finalize_change::encode_input(); + caller(self.contract_address, data) + .map(|_| ()) + .map_err(::engines::EngineError::FailedSystemCall) + .map_err(Into::into) + */ + return nil +} + +func (s *ValidatorSafeContract) signalEpochEnd(firstInEpoch bool, header *types.Header, r types.Receipts) ([]byte, error) { + // transition to the first block of a contract requires finality but has no log event. + if firstInEpoch { + /* + let state_proof = Arc::new(FirstValidatorSetProof { + contract_address: self.contract_address, + header: header.clone(), + }); + return ::engines::EpochChange::Yes(::engines::Proof::WithState(state_proof as Arc<_>)); + */ + return rlp.EncodeToBytes(FirstValidatorSetProof{Header: header, ContractAddress: s.contractAddress}) + } + + // otherwise, we're checking for logs. + //let bloom = self.expected_bloom(header); + //let header_bloom = header.log_bloom(); + //if &bloom & header_bloom != bloom { + // return ::engines::EpochChange::No; + //} + + _, ok := s.extractFromEvent(header, r) + if !ok { + return nil, nil + } + proof, err := rlp.EncodeToBytes(ValidatorSetProof{Header: header, Receipts: r}) + if err != nil { + return nil, err + } + if header.Number.Uint64() >= DEBUG_LOG_FROM { + fmt.Printf("signalEpochEnd: %d,%d, proofLen=%d\n", header.Number.Uint64(), len(r), len(proof)) + } + return proof, nil +} + +func (s *ValidatorSafeContract) extractFromEvent(header *types.Header, receipts types.Receipts) (*SimpleList, bool) { + if len(receipts) == 0 { + if header.Number.Uint64() >= DEBUG_LOG_FROM { + fmt.Printf("extractFromEvent1: %d\n", header.Number.Uint64()) + } + return nil, false + } + if header.Number.Uint64() >= DEBUG_LOG_FROM { + fmt.Printf("extractFromEvent111: %d,%d\n", header.Number.Uint64(), len(receipts)) + } + + // iterate in reverse because only the _last_ change in a given + // block actually has any effect. + // the contract should only increment the nonce once. + for j := len(receipts) - 1; j >= 0; j-- { + logs := receipts[j].Logs + /* + TODO: skipped next bloom check (is it required?) + expectedBloom := expected_bloom(&self, header: &Header) -> Bloom { + let topics = vec![*EVENT_NAME_HASH, *header.parent_hash()]; + + debug!(target: "engine", "Expected topics for header {}: {:?}", + header.hash(), topics); + + LogEntry { + address: self.contract_address, + topics: topics, + data: Vec::new(), // irrelevant for bloom. + } + .bloom() + } + if !r.log_bloom.contains_bloom(&bloom){ + continue + } + */ + for i := 0; i < len(logs); i++ { + l := logs[i] + if header.Number.Uint64() >= DEBUG_LOG_FROM { + fmt.Printf("extractFromEvent3: %d\n", header.Number.Uint64()) + } + if len(l.Topics) != 2 { + continue + } + found := l.Address == s.contractAddress && l.Topics[0] == EVENT_NAME_HASH && l.Topics[1] == header.ParentHash + if !found { + if header.Number.Uint64() >= DEBUG_LOG_FROM { + fmt.Printf("extractFromEvent4: %d\n", header.Number.Uint64()) + } + continue + } + + contract := bind.NewBoundContract(l.Address, s.abi, nil, nil, nil) + event := new(auraabi.ValidatorSetInitiateChange) + if err := contract.UnpackLog(event, "InitiateChange", *l); err != nil { + panic(err) + } + if header.Number.Uint64() >= DEBUG_LOG_FROM { + fmt.Printf("extractFromEvent5: %d\n", header.Number.Uint64()) + } + + // only one last log is taken into account + return NewSimpleList(event.NewSet), true + } + } + /* + let check_log = |log: &LogEntry| { + log.address == self.contract_address + && log.topics.len() == 2 + && log.topics[0] == *EVENT_NAME_HASH + && log.topics[1] == *header.parent_hash() + }; + + //// iterate in reverse because only the _last_ change in a given + //// block actually has any effect. + //// the contract should only increment the nonce once. + let mut decoded_events = receipts + .iter() + .rev() + .filter(|r| r.log_bloom.contains_bloom(&bloom)) + .flat_map(|r| r.logs.iter()) + .filter(move |l| check_log(l)) + .filter_map(|log| { + validator_set::events::initiate_change::parse_log( + (log.topics.clone(), log.data.clone()).into(), + ) + .ok() + }); + + // only last log is taken into account + decoded_events.next().map(|matched_event| { + let l = SimpleList::new(matched_event.new_set); + println!("matched_event: {:?}", l); + l + }) + */ + return nil, false +} + +const EVENT_NAME = "InitiateChange(bytes32,address[])" + +var EVENT_NAME_HASH = crypto.Keccak256Hash([]byte(EVENT_NAME)) + +func (s *ValidatorSafeContract) onCloseBlock(header *types.Header, ourAddress common.Address) error { + // Skip the rest of the function unless there has been a transition to POSDAO AuRa. + if s.posdaoTransition != nil && header.Number.Uint64() < *s.posdaoTransition { + log.Trace("Skipping resending of queued malicious behavior reports") + return nil + } + /* + err := s.reportQueue.filter(s.abi, s.client, ourAddress, s.contractAddress) + if err != nil { + return err + } + s.reportQueue.truncate() + */ + + /* + let mut resent_reports_in_block = self.resent_reports_in_block.lock(); + + // Skip at least one block after sending malicious reports last time. + if header.number() > *resent_reports_in_block + REPORTS_SKIP_BLOCKS { + *resent_reports_in_block = header.number(); + let mut nonce = client.latest_nonce(our_address); + for (address, block, data) in report_queue.iter() { + debug!(target: "engine", "Retrying to report validator {} for misbehavior on block {} with nonce {}.", + address, block, nonce); + while match self.transact(data.clone(), nonce) { + Ok(()) => false, + Err(EthcoreError( + EthcoreErrorKind::Transaction(transaction::Error::Old), + _, + )) => true, + Err(err) => { + warn!(target: "engine", "Cannot report validator {} for misbehavior on block {}: {}", + address, block, err); + false + } + } { + warn!(target: "engine", "Nonce {} already used. Incrementing.", nonce); + nonce += U256::from(1); + } + nonce += U256::from(1); + } + } + + Ok(()) + + */ + return nil +} + +// ValidatorContract a validator contract with reporting. +type ValidatorContract struct { + contractAddress common.Address + validators *ValidatorSafeContract + posdaoTransition *uint64 +} + +func (s *ValidatorContract) epochSet(firstInEpoch bool, num uint64, proof []byte, call Syscall) (SimpleList, common.Hash, error) { + return s.validators.epochSet(firstInEpoch, num, proof, call) +} +func (s *ValidatorContract) defaultCaller(blockHash common.Hash) (Call, error) { + return s.validators.defaultCaller(blockHash) +} + +// func (s *ValidatorContract) getWithCaller(parentHash common.Hash, nonce uint, caller consensus.Call) (common.Address, error) { +// return s.validators.getWithCaller(parentHash, nonce, caller) +// } +// +// func (s *ValidatorContract) countWithCaller(parentHash common.Hash, caller consensus.Call) (uint64, error) { +// return s.validators.countWithCaller(parentHash, caller) +// } +func (s *ValidatorContract) onEpochBegin(firstInEpoch bool, header *types.Header, caller Syscall) error { + return s.validators.onEpochBegin(firstInEpoch, header, caller) +} +func (s *ValidatorContract) onCloseBlock(header *types.Header, address common.Address) error { + return s.validators.onCloseBlock(header, address) +} +func (s *ValidatorContract) genesisEpochData(header *types.Header, call Syscall) ([]byte, error) { + return s.validators.genesisEpochData(header, call) +} +func (s *ValidatorContract) signalEpochEnd(firstInEpoch bool, header *types.Header, r types.Receipts) ([]byte, error) { + return s.validators.signalEpochEnd(firstInEpoch, header, r) +} + +func proveInitial(s *ValidatorSafeContract, contractAddr common.Address, header *types.Header, caller Syscall) ([]byte, error) { + return rlp.EncodeToBytes(FirstValidatorSetProof{Header: header, ContractAddress: s.contractAddress}) + //list, err := s.getList(caller) + //fmt.Printf("aaa: %x,%t\n", list, err) + + //return common.FromHex("0xf91a84f9020da00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0fad4af258fd11939fae0c6c6eec9d340b1caac0b0196fd9a1bc3f489c5bf00b3a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200008083663be080808080b8410000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f91871b914c26060604052600436106100fc576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806303aca79214610101578063108552691461016457806340a141ff1461019d57806340c9cdeb146101d65780634110a489146101ff57806345199e0a1461025757806349285b58146102c15780634d238c8e14610316578063752862111461034f578063900eb5a8146103645780639a573786146103c7578063a26a47d21461041c578063ae4b1b5b14610449578063b3f05b971461049e578063b7ab4db5146104cb578063d3e848f114610535578063fa81b2001461058a578063facd743b146105df575b600080fd5b341561010c57600080fd5b6101226004808035906020019091905050610630565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561016f57600080fd5b61019b600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190505061066f565b005b34156101a857600080fd5b6101d4600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610807565b005b34156101e157600080fd5b6101e9610bb7565b6040518082815260200191505060405180910390f35b341561020a57600080fd5b610236600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610bbd565b60405180831515151581526020018281526020019250505060405180910390f35b341561026257600080fd5b61026a610bee565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156102ad578082015181840152602081019050610292565b505050509050019250505060405180910390f35b34156102cc57600080fd5b6102d4610c82565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561032157600080fd5b61034d600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610d32565b005b341561035a57600080fd5b610362610fcc565b005b341561036f57600080fd5b61038560048080359060200190919050506110fc565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156103d257600080fd5b6103da61113b565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561042757600080fd5b61042f6111eb565b604051808215151515815260200191505060405180910390f35b341561045457600080fd5b61045c6111fe565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156104a957600080fd5b6104b1611224565b604051808215151515815260200191505060405180910390f35b34156104d657600080fd5b6104de611237565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b83811015610521578082015181840152602081019050610506565b505050509050019250505060405180910390f35b341561054057600080fd5b6105486112cb565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561059557600080fd5b61059d6112f1565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156105ea57600080fd5b610616600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050611317565b604051808215151515815260200191505060405180910390f35b60078181548110151561063f57fe5b90600052602060002090016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600460029054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415156106cb57600080fd5b600460019054906101000a900460ff161515156106e757600080fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415151561072357600080fd5b80600a60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506001600460016101000a81548160ff0219169083151502179055507f600bcf04a13e752d1e3670a5a9f1c21177ca2a93c6f5391d4f1298d098097c22600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a150565b600080600061081461113b565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561084d57600080fd5b83600960008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900460ff1615156108a957600080fd5b600960008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101549350600160078054905003925060078381548110151561090857fe5b906000526020600020900160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1691508160078581548110151561094657fe5b906000526020600020900160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555083600960008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101819055506007838154811015156109e557fe5b906000526020600020900160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556000600780549050111515610a2757600080fd5b6007805480919060019003610a3c9190611370565b506000600960008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101819055506000600960008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160006101000a81548160ff0219169083151502179055506000600460006101000a81548160ff0219169083151502179055506001430340600019167f55252fa6eee4741b4e24a74a70e9c11fd2c2281df8d6ea13126ff845f7825c89600760405180806020018281038252838181548152602001915080548015610ba257602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311610b58575b50509250505060405180910390a25050505050565b60085481565b60096020528060005260406000206000915090508060000160009054906101000a900460ff16908060010154905082565b610bf661139c565b6007805480602002602001604051908101604052809291908181526020018280548015610c7857602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311610c2e575b5050505050905090565b6000600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166349285b586000604051602001526040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b1515610d1257600080fd5b6102c65a03f11515610d2357600080fd5b50505060405180519050905090565b610d3a61113b565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610d7357600080fd5b80600960008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900460ff16151515610dd057600080fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614151515610e0c57600080fd5b6040805190810160405280600115158152602001600780549050815250600960008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548160ff0219169083151502179055506020820151816001015590505060078054806001018281610ea991906113b0565b9160005260206000209001600084909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550506000600460006101000a81548160ff0219169083151502179055506001430340600019167f55252fa6eee4741b4e24a74a70e9c11fd2c2281df8d6ea13126ff845f7825c89600760405180806020018281038252838181548152602001915080548015610fba57602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311610f70575b50509250505060405180910390a25050565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480156110365750600460009054906101000a900460ff16155b151561104157600080fd5b6001600460006101000a81548160ff0219169083151502179055506007600690805461106e9291906113dc565b506006805490506008819055507f8564cd629b15f47dc310d45bcbfc9bcf5420b0d51bf0659a16c67f91d27632536110a4611237565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156110e75780820151818401526020810190506110cc565b505050509050019250505060405180910390a1565b60068181548110151561110b57fe5b90600052602060002090016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16639a5737866000604051602001526040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b15156111cb57600080fd5b6102c65a03f115156111dc57600080fd5b50505060405180519050905090565b600460019054906101000a900460ff1681565b600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600460009054906101000a900460ff1681565b61123f61139c565b60068054806020026020016040519081016040528092919081815260200182805480156112c157602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311611277575b5050505050905090565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600460029054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000600960008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900460ff169050919050565b81548183558181151161139757818360005260206000209182019101611396919061142e565b5b505050565b602060405190810160405280600081525090565b8154818355818115116113d7578183600052602060002091820191016113d6919061142e565b5b505050565b82805482825590600052602060002090810192821561141d5760005260206000209182015b8281111561141c578254825591600101919060010190611401565b5b50905061142a9190611453565b5090565b61145091905b8082111561144c576000816000905550600101611434565b5090565b90565b61149391905b8082111561148f57600081816101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905550600101611459565b5090565b905600a165627a7a7230582036ea35935c8246b68074adece2eab70c40e69a0193c08a6277ce06e5b25188510029b8f3f8f1a08023c0d95fc2364e0bf7593f5ff32e1db8ef9f4b41c0bd474eae62d1af896e99808080a0b47b4f0b3e73b5edc8f9a9da1cbcfed562eb06bf54619b6aefeadebf5b3604c280a0da6ec08940a924cb08c947dd56cdb40076b29a6f0ea4dba4e2d02d9a9a72431b80a030cc4138c9e74b6cf79d624b4b5612c0fd888e91f55316cfee7d1694e1a90c0b80a0c5d54b915b56a888eee4e6eeb3141e778f9b674d1d322962eed900f02c29990aa017256b36ef47f907c6b1378a2636942ce894c17075e56fc054d4283f6846659e808080a03340bbaeafcda3a8672eb83099231dbbfab8dae02a1e8ec2f7180538fac207e080b86bf869a033aa5d69545785694b808840be50c182dad2ec3636dfccbe6572fb69828742c0b846f8440101a0663ce0d171e545a26aa67e4ca66f72ba96bb48287dbcc03beea282867f80d44ba01f0e7726926cb43c03a0abf48197dba78522ec8ba1b158e2aa30da7d2a2c6f9eb838f7a03868bdfa8727775661e4ccf117824a175a33f8703d728c04488fbfffcafda9f99594e8ddc5c7a2d2f0d7a9798459c0104fdf5e987acaa3e2a02052222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f01b853f851808080a07bb75cabebdcbd1dbb4331054636d0c6d7a2b08483b9e04df057395a7434c9e080808080808080a0e61e567237b49c44d8f906ceea49027260b4010c10a547b38d8b131b9d3b6f848080808080b8d3f8d1a0dc277c93a9f9dcee99aac9b8ba3cfa4c51821998522469c37715644e8fbac0bfa0ab8cdb808c8303bb61fb48e276217be9770fa83ecf3f90f2234d558885f5abf1808080a0fe137c3a474fbde41d89a59dd76da4c55bf696b86d3af64a55632f76cf30786780808080a06301b39b2ea8a44df8b0356120db64b788e71f52e1d7a6309d0d2e5b86fee7cb80a0da5d8b08dea0c5a4799c0f44d8a24d7cdf209f9b7a5588c1ecafb5361f6b9f07a01b7779e149cadf24d4ffb77ca7e11314b8db7097e4d70b2a173493153ca2e5a0808080b853f851808080a0a87d9bb950836582673aa0eecc0ff64aac607870637a2dd2012b8b1b31981f698080a08da6d5c36a404670c553a2c9052df7cd604f04e3863c4c7b9e0027bfd54206d680808080808080808080b86bf869a02080c7b7ae81a58eb98d9c78de4a1fd7fd9535fc953ed2be602daaa41767312ab846f8448080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"), nil + //return common.FromHex("0xf91a84f9020da00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0fad4af258fd11939fae0c6c6eec9d340b1caac0b0196fd9a1bc3f489c5bf00b3a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200008083663be080808080b8410000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f91871b8d3f8d1a0dc277c93a9f9dcee99aac9b8ba3cfa4c51821998522469c37715644e8fbac0bfa0ab8cdb808c8303bb61fb48e276217be9770fa83ecf3f90f2234d558885f5abf1808080a0fe137c3a474fbde41d89a59dd76da4c55bf696b86d3af64a55632f76cf30786780808080a06301b39b2ea8a44df8b0356120db64b788e71f52e1d7a6309d0d2e5b86fee7cb80a0da5d8b08dea0c5a4799c0f44d8a24d7cdf209f9b7a5588c1ecafb5361f6b9f07a01b7779e149cadf24d4ffb77ca7e11314b8db7097e4d70b2a173493153ca2e5a0808080b8f3f8f1a08023c0d95fc2364e0bf7593f5ff32e1db8ef9f4b41c0bd474eae62d1af896e99808080a0b47b4f0b3e73b5edc8f9a9da1cbcfed562eb06bf54619b6aefeadebf5b3604c280a0da6ec08940a924cb08c947dd56cdb40076b29a6f0ea4dba4e2d02d9a9a72431b80a030cc4138c9e74b6cf79d624b4b5612c0fd888e91f55316cfee7d1694e1a90c0b80a0c5d54b915b56a888eee4e6eeb3141e778f9b674d1d322962eed900f02c29990aa017256b36ef47f907c6b1378a2636942ce894c17075e56fc054d4283f6846659e808080a03340bbaeafcda3a8672eb83099231dbbfab8dae02a1e8ec2f7180538fac207e080b838f7a03868bdfa8727775661e4ccf117824a175a33f8703d728c04488fbfffcafda9f99594e8ddc5c7a2d2f0d7a9798459c0104fdf5e987acaa3e2a02052222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f01b853f851808080a0a87d9bb950836582673aa0eecc0ff64aac607870637a2dd2012b8b1b31981f698080a08da6d5c36a404670c553a2c9052df7cd604f04e3863c4c7b9e0027bfd54206d680808080808080808080b86bf869a033aa5d69545785694b808840be50c182dad2ec3636dfccbe6572fb69828742c0b846f8440101a0663ce0d171e545a26aa67e4ca66f72ba96bb48287dbcc03beea282867f80d44ba01f0e7726926cb43c03a0abf48197dba78522ec8ba1b158e2aa30da7d2a2c6f9eb86bf869a02080c7b7ae81a58eb98d9c78de4a1fd7fd9535fc953ed2be602daaa41767312ab846f8448080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470b853f851808080a07bb75cabebdcbd1dbb4331054636d0c6d7a2b08483b9e04df057395a7434c9e080808080808080a0e61e567237b49c44d8f906ceea49027260b4010c10a547b38d8b131b9d3b6f848080808080b914c26060604052600436106100fc576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806303aca79214610101578063108552691461016457806340a141ff1461019d57806340c9cdeb146101d65780634110a489146101ff57806345199e0a1461025757806349285b58146102c15780634d238c8e14610316578063752862111461034f578063900eb5a8146103645780639a573786146103c7578063a26a47d21461041c578063ae4b1b5b14610449578063b3f05b971461049e578063b7ab4db5146104cb578063d3e848f114610535578063fa81b2001461058a578063facd743b146105df575b600080fd5b341561010c57600080fd5b6101226004808035906020019091905050610630565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561016f57600080fd5b61019b600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190505061066f565b005b34156101a857600080fd5b6101d4600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610807565b005b34156101e157600080fd5b6101e9610bb7565b6040518082815260200191505060405180910390f35b341561020a57600080fd5b610236600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610bbd565b60405180831515151581526020018281526020019250505060405180910390f35b341561026257600080fd5b61026a610bee565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156102ad578082015181840152602081019050610292565b505050509050019250505060405180910390f35b34156102cc57600080fd5b6102d4610c82565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561032157600080fd5b61034d600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610d32565b005b341561035a57600080fd5b610362610fcc565b005b341561036f57600080fd5b61038560048080359060200190919050506110fc565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156103d257600080fd5b6103da61113b565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561042757600080fd5b61042f6111eb565b604051808215151515815260200191505060405180910390f35b341561045457600080fd5b61045c6111fe565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156104a957600080fd5b6104b1611224565b604051808215151515815260200191505060405180910390f35b34156104d657600080fd5b6104de611237565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b83811015610521578082015181840152602081019050610506565b505050509050019250505060405180910390f35b341561054057600080fd5b6105486112cb565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561059557600080fd5b61059d6112f1565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156105ea57600080fd5b610616600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050611317565b604051808215151515815260200191505060405180910390f35b60078181548110151561063f57fe5b90600052602060002090016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600460029054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415156106cb57600080fd5b600460019054906101000a900460ff161515156106e757600080fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415151561072357600080fd5b80600a60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506001600460016101000a81548160ff0219169083151502179055507f600bcf04a13e752d1e3670a5a9f1c21177ca2a93c6f5391d4f1298d098097c22600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a150565b600080600061081461113b565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561084d57600080fd5b83600960008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900460ff1615156108a957600080fd5b600960008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101549350600160078054905003925060078381548110151561090857fe5b906000526020600020900160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1691508160078581548110151561094657fe5b906000526020600020900160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555083600960008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101819055506007838154811015156109e557fe5b906000526020600020900160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556000600780549050111515610a2757600080fd5b6007805480919060019003610a3c9190611370565b506000600960008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101819055506000600960008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160006101000a81548160ff0219169083151502179055506000600460006101000a81548160ff0219169083151502179055506001430340600019167f55252fa6eee4741b4e24a74a70e9c11fd2c2281df8d6ea13126ff845f7825c89600760405180806020018281038252838181548152602001915080548015610ba257602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311610b58575b50509250505060405180910390a25050505050565b60085481565b60096020528060005260406000206000915090508060000160009054906101000a900460ff16908060010154905082565b610bf661139c565b6007805480602002602001604051908101604052809291908181526020018280548015610c7857602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311610c2e575b5050505050905090565b6000600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166349285b586000604051602001526040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b1515610d1257600080fd5b6102c65a03f11515610d2357600080fd5b50505060405180519050905090565b610d3a61113b565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610d7357600080fd5b80600960008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900460ff16151515610dd057600080fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614151515610e0c57600080fd5b6040805190810160405280600115158152602001600780549050815250600960008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548160ff0219169083151502179055506020820151816001015590505060078054806001018281610ea991906113b0565b9160005260206000209001600084909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550506000600460006101000a81548160ff0219169083151502179055506001430340600019167f55252fa6eee4741b4e24a74a70e9c11fd2c2281df8d6ea13126ff845f7825c89600760405180806020018281038252838181548152602001915080548015610fba57602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311610f70575b50509250505060405180910390a25050565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480156110365750600460009054906101000a900460ff16155b151561104157600080fd5b6001600460006101000a81548160ff0219169083151502179055506007600690805461106e9291906113dc565b506006805490506008819055507f8564cd629b15f47dc310d45bcbfc9bcf5420b0d51bf0659a16c67f91d27632536110a4611237565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156110e75780820151818401526020810190506110cc565b505050509050019250505060405180910390a1565b60068181548110151561110b57fe5b90600052602060002090016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16639a5737866000604051602001526040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b15156111cb57600080fd5b6102c65a03f115156111dc57600080fd5b50505060405180519050905090565b600460019054906101000a900460ff1681565b600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600460009054906101000a900460ff1681565b61123f61139c565b60068054806020026020016040519081016040528092919081815260200182805480156112c157602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311611277575b5050505050905090565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600460029054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000600960008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900460ff169050919050565b81548183558181151161139757818360005260206000209182019101611396919061142e565b5b505050565b602060405190810160405280600081525090565b8154818355818115116113d7578183600052602060002091820191016113d6919061142e565b5b505050565b82805482825590600052602060002090810192821561141d5760005260206000209182015b8281111561141c578254825591600101919060010190611401565b5b50905061142a9190611453565b5090565b61145091905b8082111561144c576000816000905550600101611434565b5090565b90565b61149391905b8082111561148f57600081816101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905550600101611459565b5090565b905600a165627a7a7230582036ea35935c8246b68074adece2eab70c40e69a0193c08a6277ce06e5b25188510029"), nil + /* + + // given a provider and caller, generate proof. this will just be a state proof + // of `getValidators`. + fn prove_initial( + contract_address: Address, + header: &Header, + caller: &Call, + ) -> Result, String> { + use std::cell::RefCell; + + let epoch_proof = RefCell::new(None); + let validators = { + let (data, decoder) = validator_set::functions::get_validators::call(); + let (value, proof) = caller(contract_address, data)?; + *epoch_proof.borrow_mut() = Some(encode_first_proof(header, &proof)); + decoder.decode(&value).map_err(|e| e.to_string())? + }; + + let proof = epoch_proof + .into_inner() + .expect("epoch_proof always set after call; qed"); + + trace!(target: "engine", "obtained proof for initial set: {} validators, {} bytes", + validators.len(), proof.len()); + + info!(target: "engine", "Signal for switch to contract-based validator set."); + info!(target: "engine", "Initial contract validators: {:?}", validators); + + Ok(proof) + } + */ +} diff --git a/consensus/beacon/consensus.go b/consensus/beacon/consensus.go index e856f4e6cead..46fb194dc9b8 100644 --- a/consensus/beacon/consensus.go +++ b/consensus/beacon/consensus.go @@ -23,6 +23,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/consensus" + "github.com/ethereum/go-ethereum/consensus/aura" "github.com/ethereum/go-ethereum/consensus/misc/eip1559" "github.com/ethereum/go-ethereum/consensus/misc/eip4844" "github.com/ethereum/go-ethereum/core/state" @@ -333,31 +334,38 @@ func (beacon *Beacon) verifyHeaders(chain consensus.ChainHeaderReader, headers [ // Prepare implements consensus.Engine, initializing the difficulty field of a // header to conform to the beacon protocol. The changes are done inline. -func (beacon *Beacon) Prepare(chain consensus.ChainHeaderReader, header *types.Header) error { +func (beacon *Beacon) Prepare(chain consensus.ChainHeaderReader, header *types.Header, statedb *state.StateDB) error { // Transition isn't triggered yet, use the legacy rules for preparation. reached, err := IsTTDReached(chain, header.ParentHash, header.Number.Uint64()-1) if err != nil { return err } if !reached { - return beacon.ethone.Prepare(chain, header) + return beacon.ethone.Prepare(chain, header, statedb) } header.Difficulty = beaconDifficulty return nil } // Finalize implements consensus.Engine and processes withdrawals on top. -func (beacon *Beacon) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, withdrawals []*types.Withdrawal) { +func (beacon *Beacon) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, withdrawals []*types.Withdrawal, receipts []*types.Receipt) { if !beacon.IsPoSHeader(header) { - beacon.ethone.Finalize(chain, header, state, txs, uncles, nil) - return + beacon.ethone.Finalize(chain, header, state, txs, uncles, nil, receipts) + } else if a, ok := beacon.ethone.(*aura.AuRa); ok { + // GNOSIS: if the network has merged and this was an ex-AuRa + // network, still call the reward contract. + if err := a.ApplyRewards(header, state); err != nil { + panic(fmt.Sprintf("error applying reward %v", err)) + } } + // Withdrawals processing. - for _, w := range withdrawals { - // Convert amount from gwei to wei. - amount := new(big.Int).SetUint64(w.Amount) - amount = amount.Mul(amount, big.NewInt(params.GWei)) - state.AddBalance(w.Address, amount) + if withdrawals != nil { + if auraEngine, ok := beacon.ethone.(*aura.AuRa); ok { + if err := auraEngine.ExecuteSystemWithdrawals(withdrawals); err != nil { + panic(err) + } + } } // No block reward which is issued by consensus layer instead. } @@ -380,7 +388,7 @@ func (beacon *Beacon) FinalizeAndAssemble(chain consensus.ChainHeaderReader, hea } } // Finalize and assemble the block. - beacon.Finalize(chain, header, state, txs, uncles, withdrawals) + beacon.Finalize(chain, header, state, txs, uncles, withdrawals, receipts) // Assign the final state root to header. header.Root = state.IntermediateRoot(true) @@ -435,10 +443,11 @@ func (beacon *Beacon) Close() error { // This function is not suitable for a part of APIs like Prepare or CalcDifficulty // because the header difficulty is not set yet. func (beacon *Beacon) IsPoSHeader(header *types.Header) bool { - if header.Difficulty == nil { - panic("IsPoSHeader called with invalid difficulty") - } - return header.Difficulty.Cmp(beaconDifficulty) == 0 + // return header.Difficulty.Cmp(beaconDifficulty) == 0 + // return header.Number.Cmp(big.NewInt()) + // non-uint64 block numbers are 2,92271023×10¹² years in + // the future, but better be ready. + return !header.Number.IsInt64() || header.Number.Uint64() >= params.GnosisForkBlock } // InnerEngine returns the embedded eth1 consensus engine. @@ -470,3 +479,13 @@ func IsTTDReached(chain consensus.ChainHeaderReader, parentHash common.Hash, par } return td.Cmp(chain.Config().TerminalTotalDifficulty) >= 0, nil } + +func (beacon *Beacon) SetAuraSyscall(sc aura.Syscall) { + if a, ok := beacon.ethone.(*aura.AuRa); ok { + a.Syscall = sc + } +} + +func (beacon *Beacon) AuraPrepare(chain consensus.ChainHeaderReader, header *types.Header, statedb *state.StateDB) { + beacon.ethone.Prepare(chain, header, statedb) +} diff --git a/consensus/clique/clique.go b/consensus/clique/clique.go index c693189ea5ef..6590424e6924 100644 --- a/consensus/clique/clique.go +++ b/consensus/clique/clique.go @@ -512,7 +512,7 @@ func (c *Clique) verifySeal(snap *Snapshot, header *types.Header, parents []*typ // Prepare implements consensus.Engine, preparing all the consensus fields of the // header for running the transactions on top. -func (c *Clique) Prepare(chain consensus.ChainHeaderReader, header *types.Header) error { +func (c *Clique) Prepare(chain consensus.ChainHeaderReader, header *types.Header, _ *state.StateDB) error { // If the block isn't a checkpoint, cast a random vote (good enough for now) header.Coinbase = common.Address{} header.Nonce = types.BlockNonce{} @@ -580,7 +580,7 @@ func (c *Clique) Prepare(chain consensus.ChainHeaderReader, header *types.Header // Finalize implements consensus.Engine. There is no post-transaction // consensus rules in clique, do nothing here. -func (c *Clique) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, withdrawals []*types.Withdrawal) { +func (c *Clique) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, withdrawals []*types.Withdrawal, _ []*types.Receipt) { // No block rewards in PoA, so the state remains as is } @@ -591,7 +591,7 @@ func (c *Clique) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header * return nil, errors.New("clique does not support withdrawals") } // Finalize block - c.Finalize(chain, header, state, txs, uncles, nil) + c.Finalize(chain, header, state, txs, uncles, nil, receipts) // Assign the final state root to header. header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number)) diff --git a/consensus/consensus.go b/consensus/consensus.go index 3a2c2d222916..391fdab4fdf2 100644 --- a/consensus/consensus.go +++ b/consensus/consensus.go @@ -81,7 +81,7 @@ type Engine interface { // Prepare initializes the consensus fields of a block header according to the // rules of a particular engine. The changes are executed inline. - Prepare(chain ChainHeaderReader, header *types.Header) error + Prepare(chain ChainHeaderReader, header *types.Header, state *state.StateDB) error // Finalize runs any post-transaction state modifications (e.g. block rewards // or process withdrawals) but does not assemble the block. @@ -89,7 +89,7 @@ type Engine interface { // Note: The state database might be updated to reflect any consensus rules // that happen at finalization (e.g. block rewards). Finalize(chain ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, - uncles []*types.Header, withdrawals []*types.Withdrawal) + uncles []*types.Header, withdrawals []*types.Withdrawal, receipts []*types.Receipt) // FinalizeAndAssemble runs any post-transaction state modifications (e.g. block // rewards or process withdrawals) and assembles the final block. @@ -127,3 +127,25 @@ type PoW interface { // Hashrate returns the current mining hashrate of a PoW consensus engine. Hashrate() float64 } + +// RewardKind - The kind of block reward. +// Depending on the consensus engine the allocated block reward might have +// different semantics which could lead e.g. to different reward values. +type RewardKind uint16 + +const ( + // RewardAuthor - attributed to the block author. + RewardAuthor RewardKind = 0 + // RewardEmptyStep - attributed to the author(s) of empty step(s) included in the block (AuthorityRound engine). + RewardEmptyStep RewardKind = 1 + // RewardExternal - attributed by an external protocol (e.g. block reward contract). + RewardExternal RewardKind = 2 + // RewardUncle - attributed to the block uncle(s) with given difference. + RewardUncle RewardKind = 3 +) + +type Reward struct { + Beneficiary common.Address + Kind RewardKind + Amount big.Int +} diff --git a/consensus/ethash/consensus.go b/consensus/ethash/consensus.go index 130dfdf213bf..d32e170805f1 100644 --- a/consensus/ethash/consensus.go +++ b/consensus/ethash/consensus.go @@ -490,7 +490,7 @@ var DynamicDifficultyCalculator = makeDifficultyCalculator // Prepare implements consensus.Engine, initializing the difficulty field of a // header to conform to the ethash protocol. The changes are done inline. -func (ethash *Ethash) Prepare(chain consensus.ChainHeaderReader, header *types.Header) error { +func (ethash *Ethash) Prepare(chain consensus.ChainHeaderReader, header *types.Header, _ *state.StateDB) error { parent := chain.GetHeader(header.ParentHash, header.Number.Uint64()-1) if parent == nil { return consensus.ErrUnknownAncestor @@ -500,7 +500,7 @@ func (ethash *Ethash) Prepare(chain consensus.ChainHeaderReader, header *types.H } // Finalize implements consensus.Engine, accumulating the block and uncle rewards. -func (ethash *Ethash) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, withdrawals []*types.Withdrawal) { +func (ethash *Ethash) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, withdrawals []*types.Withdrawal, _ []*types.Receipt) { // Accumulate any block and uncle rewards accumulateRewards(chain.Config(), state, header, uncles) } @@ -512,7 +512,7 @@ func (ethash *Ethash) FinalizeAndAssemble(chain consensus.ChainHeaderReader, hea return nil, errors.New("ethash does not support withdrawals") } // Finalize block - ethash.Finalize(chain, header, state, txs, uncles, nil) + ethash.Finalize(chain, header, state, txs, uncles, nil, receipts) // Assign the final state root to header. header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number)) diff --git a/core/allocs/chiado.json b/core/allocs/chiado.json new file mode 100644 index 000000000000..a332c3a8b6d4 --- /dev/null +++ b/core/allocs/chiado.json @@ -0,0 +1,88 @@ +{ + "0x0000000000000000000000000000000000000001": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000002": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000003": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000004": { + "balance": "0x1" + }, + "0xB03a86b3126157C039b55E21D378587CcFc04d45": { + "balance": "0xc9f2c9cd04674edea40000000" + }, + "0xcC4e00A72d871D6c328BcFE9025AD93d0a26dF51": { + "balance": "0xc9f2c9cd04674edea40000000" + }, + "0x1000000000000000000000000000000000000001": { + "balance": "0x0", + "constructor": "0x60806040526040516108053803806108058339818101604052604081101561002657600080fd5b50805160209182015160408051600081529384018082527f656970313936372e70726f78792e696d706c656d656e746174696f6e00000000905251603c81850301902091929091839190600019016000805160206107aa8339815191521461008a57fe5b61009c826001600160e01b036101bd16565b805115610154576000826001600160a01b0316826040518082805190602001908083835b602083106100df5780518252601f1990920191602091820191016100c0565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855af49150503d806000811461013f576040519150601f19603f3d011682016040523d82523d6000602084013e610144565b606091505b505090508061015257600080fd5b505b5050604080517f656970313936372e70726f78792e61646d696e000000000000000000000000008152905190819003601301902060008051602061078a833981519152600019909101146101a457fe5b6101b6816001600160e01b0361023716565b505061024f565b6101d08161024960201b6104801760201c565b610225576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603b8152602001806107ca603b913960400191505060405180910390fd5b6000805160206107aa83398151915255565b60008051602061078a83398151915255565b3b151590565b61052c8061025e6000396000f3fe60806040526004361061004a5760003560e01c80633659cfe6146100545780634f1ef286146100875780635c60da1b146101075780638f28397014610138578063f851a4401461016b575b610052610180565b005b34801561006057600080fd5b506100526004803603602081101561007757600080fd5b50356001600160a01b031661019a565b6100526004803603604081101561009d57600080fd5b6001600160a01b0382351691908101906040810160208201356401000000008111156100c857600080fd5b8201836020820111156100da57600080fd5b803590602001918460018302840111640100000000831117156100fc57600080fd5b5090925090506101cb565b34801561011357600080fd5b5061011c61026f565b604080516001600160a01b039092168252519081900360200190f35b34801561014457600080fd5b506100526004803603602081101561015b57600080fd5b50356001600160a01b031661027e565b34801561017757600080fd5b5061011c61033c565b610188610198565b610198610193610346565b61036b565b565b6101a261038f565b6001600160a01b0316336001600160a01b0316146101bf57600080fd5b6101c8816103b4565b50565b6101d361038f565b6001600160a01b0316336001600160a01b0316146101f057600080fd5b6101f9836103b4565b6000836001600160a01b031683836040518083838082843760405192019450600093509091505080830381855af49150503d8060008114610256576040519150601f19603f3d011682016040523d82523d6000602084013e61025b565b606091505b505090508061026957600080fd5b50505050565b6000610279610346565b905090565b61028661038f565b6001600160a01b0316336001600160a01b0316146102a357600080fd5b6001600160a01b0381166102e85760405162461bcd60e51b81526004018080602001828103825260368152602001806104876036913960400191505060405180910390fd5b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f61031161038f565b604080516001600160a01b03928316815291841660208301528051918290030190a16101c8816103f4565b600061027961038f565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b3660008037600080366000845af43d6000803e80801561038a573d6000f35b3d6000fd5b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b6103bd81610418565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610355565b61042181610480565b61045c5760405162461bcd60e51b815260040180806020018281038252603b8152602001806104bd603b913960400191505060405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc55565b3b15159056fe43616e6e6f74206368616e6765207468652061646d696e206f6620612070726f787920746f20746865207a65726f206164647265737343616e6e6f742073657420612070726f787920696d706c656d656e746174696f6e20746f2061206e6f6e2d636f6e74726163742061646472657373a265627a7a72305820a9aab4b95b654a79b32f5aa284796894f8329aaa083932695296085b196c27bd64736f6c634300050a0032b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc43616e6e6f742073657420612070726f787920696d706c656d656e746174696f6e20746f2061206e6f6e2d636f6e747261637420616464726573730000000000000000000000001000000000000000000000000000000000000000000000000000000000000000b03a86b3126157c039b55e21d378587ccfc04d45" + }, + "0x1000000000000000000000000000000000000000": { + "balance": "0x0", + "constructor": "0x608060405234801561001057600080fd5b506141f5806100206000396000f3fe608060405234801561001057600080fd5b50600436106103b85760003560e01c806383465b82116101f4578063b41832e41161011a578063cd24327e116100ad578063ee99205c1161007c578063ee99205c14610e29578063eebc7a3914610e31578063facd743b14610e39578063fe54477e14610e5f576103b8565b8063cd24327e14610d79578063d207778214610de7578063e284789514610def578063e717de3a14610e0c576103b8565b8063c9e9694d116100e9578063c9e9694d14610cf8578063cbd2d52814610d1e578063cccf3a0214610d54578063ccf69e9b14610d71576103b8565b8063b41832e414610c3f578063b7ab4db514610c65578063b927ef4314610c6d578063c476dd4014610c75576103b8565b8063a48b042a11610192578063a881c5fd11610161578063a881c5fd14610be3578063a92252ae14610c09578063b172b22214610c2f578063b2c65a1014610c37576103b8565b8063a48b042a14610b50578063a4e01eaa14610b6d578063a657e57914610b8a578063a670eb5614610b92576103b8565b806393b4e25e116101ce57806393b4e25e14610ae857806394f3a24114610af05780639b4a14bf14610b0d578063a26301f914610b2a576103b8565b806383465b8214610a6b5780639184d0ad14610a9157806392d276b414610abf576103b8565b8063392e53cd116102e45780636729c2dc11610277578063714897df11610246578063714897df14610a2d57806374bdb37214610a355780637528621114610a3d57806381db0a4914610a45576103b8565b80636729c2dc1461090f5780636b5ecfd3146109175780636e85d53d1461093d578063704189ca14610a25576103b8565b806356b54bae116102b357806356b54bae1461081b5780635836d08a14610823578063595bddf9146108495780635ccee1de14610907576103b8565b8063392e53cd146107c85780633d34d9ef146107d05780633d3b5458146107f65780634d04481e146107fe576103b8565b80631776dee31161035c5780632bbb7b721161032b5780632bbb7b721461061c5780632f248e3014610642578063374dc77d1461065f578063378bf28b14610736576103b8565b80631776dee31461057c5780631a7fa237146105985780631d0cd4c6146105d05780631ee4d0bc146105f6576103b8565b80630636bdac116103985780630636bdac1461049157806309bee538146104ff5780630bf480c01461055757806316cf66ab1461055f576103b8565b80624a8803146103bd5780625351751461042457806305461c8514610466575b600080fd5b6103c5610e67565b604051808060200183151515158152602001828103825284818151815260200191508051906020019060200280838360005b8381101561040f5781810151838201526020016103f7565b50505050905001935050505060405180910390f35b61044a6004803603602081101561043a57600080fd5b50356001600160a01b0316610f21565b604080516001600160a01b039092168252519081900360200190f35b61048f6004803603606081101561047c57600080fd5b5080359060208101359060400135610f3c565b005b61048f600480360360208110156104a757600080fd5b810190602081018135600160201b8111156104c157600080fd5b8201836020820111156104d357600080fd5b803590602001918460208302840111600160201b831117156104f457600080fd5b50909250905061100d565b610507611073565b60408051602080825283518183015283519192839290830191858101910280838360005b8381101561054357818101518382015260200161052b565b505050509050019250505060405180910390f35b6105076110cc565b61044a6004803603602081101561057557600080fd5b5035611125565b610584611140565b604080519115158252519081900360200190f35b6105be600480360360208110156105ae57600080fd5b50356001600160a01b0316611147565b60408051918252519081900360200190f35b6105be600480360360208110156105e657600080fd5b50356001600160a01b0316611173565b61044a6004803603602081101561060c57600080fd5b50356001600160a01b031661119b565b6105be6004803603602081101561063257600080fd5b50356001600160a01b03166111b6565b61048f6004803603602081101561065857600080fd5b50356111c8565b6105be6004803603608081101561067557600080fd5b6001600160a01b038235811692602081013590911691810190606081016040820135600160201b8111156106a857600080fd5b8201836020820111156106ba57600080fd5b803590602001918460018302840111600160201b831117156106db57600080fd5b919390929091602081019035600160201b8111156106f857600080fd5b82018360208201111561070a57600080fd5b803590602001918460018302840111600160201b8311171561072b57600080fd5b50909250905061134a565b6107536004803603602081101561074c57600080fd5b50356113f1565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561078d578181015183820152602001610775565b50505050905090810190601f1680156107ba5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61058461148c565b61048f600480360360208110156107e657600080fd5b50356001600160a01b031661149d565b61058461194d565b6105846004803603602081101561081457600080fd5b503561196a565b61044a61199a565b6105be6004803603602081101561083957600080fd5b50356001600160a01b03166119a9565b61048f6004803603604081101561085f57600080fd5b810190602081018135600160201b81111561087957600080fd5b82018360208201111561088b57600080fd5b803590602001918460018302840111600160201b831117156108ac57600080fd5b919390929091602081019035600160201b8111156108c957600080fd5b8201836020820111156108db57600080fd5b803590602001918460018302840111600160201b831117156108fc57600080fd5b5090925090506119d1565b61048f611a82565b610507611f99565b6105846004803603602081101561092d57600080fd5b50356001600160a01b0316611fef565b61048f600480360360e081101561095357600080fd5b6001600160a01b03823581169260208101358216926040820135831692606083013516919081019060a081016080820135600160201b81111561099557600080fd5b8201836020820111156109a757600080fd5b803590602001918460208302840111600160201b831117156109c857600080fd5b919390929091602081019035600160201b8111156109e557600080fd5b8201836020820111156109f757600080fd5b803590602001918460208302840111600160201b83111715610a1857600080fd5b9193509150351515612004565b6105be61224e565b6105be61227e565b6105be612283565b61048f612289565b61048f60048036036020811015610a5b57600080fd5b50356001600160a01b0316612382565b6105be60048036036020811015610a8157600080fd5b50356001600160a01b03166125a5565b61058460048036036040811015610aa757600080fd5b506001600160a01b03813516906020013515156125b7565b610ac761270a565b604080519283526001600160a01b0390911660208301528051918290030190f35b61048f61271c565b61048f60048036036020811015610b0657600080fd5b5035612805565b61058460048036036020811015610b2357600080fd5b5035612833565b6105be60048036036020811015610b4057600080fd5b50356001600160a01b0316612848565b61058460048036036020811015610b6657600080fd5b503561285a565b61058460048036036020811015610b8357600080fd5b503561290e565b6105be61292d565b610bc860048036036060811015610ba857600080fd5b506001600160a01b03813581169160208101359091169060400135612933565b60408051921515835290151560208301528051918290030190f35b61058460048036036020811015610bf957600080fd5b50356001600160a01b0316612b1f565b61058460048036036020811015610c1f57600080fd5b50356001600160a01b0316612b32565b61044a612b4f565b61048f612b5e565b6105be60048036036020811015610c5557600080fd5b50356001600160a01b0316612d39565b610507612d61565b6105be612e11565b61048f60048036036060811015610c8b57600080fd5b6001600160a01b0382351691602081013591810190606081016040820135600160201b811115610cba57600080fd5b820183602082011115610ccc57600080fd5b803590602001918460018302840111600160201b83111715610ced57600080fd5b509092509050612e17565b6105be60048036036020811015610d0e57600080fd5b50356001600160a01b0316613022565b61058460048036036060811015610d3457600080fd5b506001600160a01b0381358116916020810135909116906040013561304a565b61075360048036036020811015610d6a57600080fd5b5035613104565b61044a61316c565b61048f60048036036020811015610d8f57600080fd5b810190602081018135600160201b811115610da957600080fd5b820183602082011115610dbb57600080fd5b803590602001918460208302840111600160201b83111715610ddc57600080fd5b50909250905061317b565b6105be6131ce565b61044a60048036036020811015610e0557600080fd5b50356131d4565b61058460048036036020811015610e2257600080fd5b50356131ef565b61044a613204565b610507613213565b61058460048036036020811015610e4f57600080fd5b50356001600160a01b03166132be565b6105076132e9565b600454604080518281526020808402820101909152606091600091908015610e99578160200160208202803883390190505b50915060005b8251811015610f1557601e600060036001018381548110610ebc57fe5b9060005260206000200154815260200190815260200160002060009054906101000a90046001600160a01b0316838281518110610ef557fe5b6001600160a01b0390921660209283029190910190910152600101610e9f565b505060035460ff169091565b6010602052600090815260409020546001600160a01b031681565b6025546001600160a01b03163314610f5357600080fd5b60008381526027602052604090205460ff1615610f6f57611008565b6000838152601e60205260409020546001600160a01b0316610f9057600080fd5b81610f9a57600080fd5b600083815260096020526040902054821115610fc25760008381526009602052604090208290555b600083815260086020908152604080832080546001019055600b9091529020819055610fed8361333f565b15610ffc57610ffc600061343e565b61100461347a565b6019555b505050565b6011546001600160a01b0316331461102457600080fd5b61106f828280806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250691d5b9c995d99585b195960b21b925061347e915050565b5050565b606060268054806020026020016040519081016040528092919081815260200182805480156110c157602002820191906000526020600020905b8154815260200190600101908083116110ad575b505050505090505b90565b606060036001018054806020026020016040519081016040528092919081815260200182805480156110c157602002820191906000526020600020908154815260200190600101908083116110ad575050505050905090565b601f602052600090815260409020546001600160a01b031681565b6004541590565b6001600160a01b0381166000908152601c60209081526040808320548352600a9091529020545b919050565b6001600160a01b03166000908152601c60209081526040808320548352600890915290205490565b6014602052600090815260409020546001600160a01b031681565b601c6020526000908152604090205481565b6111d061148c565b6111d957600080fd5b60008181526027602052604090205460ff166111f457600080fd5b6000818152601f60205260409020546001600160a01b031633811480611232575061121d613486565b6001600160a01b0316336001600160a01b0316145b61123b57600080fd5b601554604080516302f248e360e41b81526004810185905290516001600160a01b0390921691632f248e309160248082019260009290919082900301818387803b15801561128857600080fd5b505af115801561129c573d6000803e3d6000fd5b506000925050505b6026548110156113245782602682815481106112bc57fe5b9060005260206000200154141561131c576026805460001981019081106112df57fe5b9060005260206000200154602682815481106112f757fe5b60009182526020909120015560268054906113169060001983016140a6565b50611324565b6001016112a4565b506000828152602760205260409020805460ff1916905561134361347a565b6019555050565b6015546000906001600160a01b0316331461136457600080fd5b600061137088886134ab565b90506113e68187878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8b0181900481028201810190925289815292508991508890819084018382808284376000920191909152506137de92505050565b979650505050505050565b60246020908152600091825260409182902080548351601f6002600019610100600186161502019093169290920491820184900484028101840190945280845290918301828280156114845780601f1061145957610100808354040283529160200191611484565b820191906000526020600020905b81548152906001019060200180831161146757829003601f168201915b505050505081565b600c546001600160a01b0316151590565b6114a561148c565b6114ae57600080fd5b33600081815260106020908152604080832054601d909252909120546001600160a01b039182169184166114e157600080fd5b6001600160a01b0382166114f457600080fd5b836001600160a01b0316826001600160a01b0316141561151357600080fd5b8061151d57600080fd5b6021541561152a57600080fd5b601554604080516322e8c68760e21b81526001600160a01b03878116600483015291519190921691638ba31a1c916024808301926020929190829003018186803b15801561157757600080fd5b505afa15801561158b573d6000803e3d6000fd5b505050506040513d60208110156115a157600080fd5b5051156115ad57600080fd5b6001600160a01b0384166000908152601a6020526040902054156115d057600080fd5b6001600160a01b0384166000908152601b602052604090205460ff16156115f657600080fd5b6000818152600e602052604090205460ff16156118ee57611615611140565b61161e57600080fd5b60055460ff161561162e57600080fd5b6117426116bc6002601160009054906101000a90046001600160a01b03166001600160a01b0316631c77c58c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561168457600080fd5b505afa158015611698573d6000803e3d6000fd5b505050506040513d60208110156116ae57600080fd5b50519063ffffffff61394416565b601560009054906101000a90046001600160a01b03166001600160a01b0316638c2243ae6040518163ffffffff1660e01b815260040160206040518083038186803b15801561170a57600080fd5b505afa15801561171e573d6000803e3d6000fd5b505050506040513d602081101561173457600080fd5b50519063ffffffff61396b16565b61174a61347a565b1061175457600080fd5b606061175e613213565b905060005b81518110156117d357836001600160a01b031682828151811061178257fe5b60200260200101516001600160a01b031614156117cb57858282815181106117a657fe5b60200260200101906001600160a01b031690816001600160a01b0316815250506117d3565b600101611763565b50600180546117e4916004916140ca565b506021829055602280546001600160a01b0319166001600160a01b038781169190911790915560115460408051630b40282360e01b81526004810186905290519190921691630b40282391602480830192600092919082900301818387803b15801561184f57600080fd5b505af1158015611863573d6000803e3d6000fd5b50505050600161187161347a565b03407f55252fa6eee4741b4e24a74a70e9c11fd2c2281df8d6ea13126ff845f7825c89826040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156118d55781810151838201526020016118bd565b505050509050019250505060405180910390a250611906565b6118fa82858386613980565b61190261347a565b6019555b836001600160a01b0316826001600160a01b0316827fad4c947995a3daa512a7371d31325a21227249f8dc1c52c1a4c6fe8475a3ebb160405160405180910390a450505050565b6000611957611140565b8015611965575060055460ff165b905090565b6000818152600960205260408120548061198857600091505061116e565b8061199161347a565b11159392505050565b600c546001600160a01b031681565b6001600160a01b03166000908152601c60209081526040808320548352600990915290205490565b6119d961148c565b6119e257600080fd5b336000908152601d6020526040902054806119fc57600080fd5b611a708186868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8a0181900481028201810190925288815292508891508790819084018382808284376000920191909152506137de92505050565b611a7861347a565b6019555050505050565b600c546001600160a01b03163314611a9957600080fd5b6015546040805163a5d54f6560e01b815290516060926001600160a01b03169163a5d54f65916004808301926000929190829003018186803b158015611ade57600080fd5b505afa158015611af2573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526020811015611b1b57600080fd5b810190808051600160201b811115611b3257600080fd5b82016020810184811115611b4557600080fd5b81518560208202830111600160201b82111715611b6157600080fd5b505060265490945060009350601310159150611b809050576000611b87565b6026546013035b9050808251118015611b9857508015155b15611e345760115460408051634191031360e11b815290516000926001600160a01b0316916383220626916004808301926020929190829003018186803b158015611be257600080fd5b505afa158015611bf6573d6000803e3d6000fd5b505050506040513d6020811015611c0c57600080fd5b50516015546040805163957950a760e01b815290519293506060926000926001600160a01b03169163957950a79160048083019286929190829003018186803b158015611c5857600080fd5b505afa158015611c6c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040908152811015611c9557600080fd5b810190808051600160201b811115611cac57600080fd5b82016020810184811115611cbf57600080fd5b81518560208202830111600160201b82111715611cdb57600080fd5b50506020909101518151919550935015801592509050611cfb5750600081115b15611e2c57606084604051908082528060200260200182016040528015611d2c578160200160208202803883390190505b50865190915060005b8251811015611e1f57604080516020808201989098528151808203890181529082019091528051960195909520946000611d70868689613a09565b9050888181518110611d7e57fe5b6020026020010151848381518110611d9257fe5b602002602001018181525050858181518110611daa57fe5b602002602001015185039450828060019003935050888381518110611dcb57fe5b6020026020010151898281518110611ddf57fe5b602002602001018181525050858381518110611df757fe5b6020026020010151868281518110611e0b57fe5b602090810291909101015250600101611d35565b50611e2982613a56565b50505b505050611e3d565b611e3d82613a56565b611e47600161343e565b815115611eb757601560009054906101000a90046001600160a01b03166001600160a01b0316631555371c6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015611e9e57600080fd5b505af1158015611eb2573d6000803e3d6000fd5b505050505b601560009054906101000a90046001600160a01b03166001600160a01b031663ee435f556040518163ffffffff1660e01b8152600401600060405180830381600087803b158015611f0757600080fd5b505af1158015611f1b573d6000803e3d6000fd5b50506015546001600160a01b031691506320d96e469050611f3a61347a565b6001016040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b158015611f7357600080fd5b505af1158015611f87573d6000803e3d6000fd5b5050600060185550611343905061347a565b606060018054806020026020016040519081016040528092919081815260200182805480156110c157602002820191906000526020600020908154815260200190600101908083116110ad575050505050905090565b601b6020526000908152604090205460ff1681565b61200c61347a565b1580612030575061201b613486565b6001600160a01b0316336001600160a01b0316145b61203957600080fd5b61204161148c565b1561204b57600080fd5b6001600160a01b03891661205e57600080fd5b6001600160a01b03871661207157600080fd5b6001600160a01b03861661208457600080fd5b8361208e57600080fd5b83821461209a57600080fd5b60138411156120a857600080fd5b600c80546001600160a01b03808c166001600160a01b031992831617909255602580548b8416908316179055601180548a841690831617905560158054928916929091169190911790556120fa61347a565b60195560005b8481101561224257600086868381811061211657fe5b905060200201356001600160a01b03169050600085858481811061213657fe5b905060200201356001600160a01b03169050600061215483836134ab565b60008054600181810183557f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563909101839055805480820182557fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf601839055828252600e60209081526040808420805460ff1916841790556017909152909120805490910190559050831580156121e75750845b15612237576026805460018181019092557f744a2cf8fd7008e3d53b67916e73460df9fa5214e3ef23dd4259ca09493a3594018290556000828152602760205260409020805460ff191690911790555b505050600101612100565b50505050505050505050565b602654600090612260575060006110c9565b602660008154811061226e57fe5b9060005260206000200154905090565b601381565b60195481565b6002600160a01b03331461229c57600080fd5b60035460ff1615612331576122af613c82565b6122b96001613d3b565b600c60009054906101000a90046001600160a01b03166001600160a01b031663c5dd76286040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561230957600080fd5b505af115801561231d573d6000803e3d6000fd5b5050505061232961347a565b601855612354565b60045415612348576123436000613d3b565b612354565b61235061347a565b6018555b61235c613eaf565b6003805460ff19168155600061237360048261411a565b505061237d61347a565b601955565b61238a61148c565b61239357600080fd5b336000818152601d60205260409020546001600160a01b0383166123b657600080fd5b826001600160a01b0316826001600160a01b031614156123d557600080fd5b806123df57600080fd5b602154156123ec57600080fd5b601554604080516322e8c68760e21b81526001600160a01b03868116600483015291519190921691638ba31a1c916024808301926020929190829003018186803b15801561243957600080fd5b505afa15801561244d573d6000803e3d6000fd5b505050506040513d602081101561246357600080fd5b50511561246f57600080fd5b6001600160a01b0383166000908152601a60205260409020541561249257600080fd5b6001600160a01b0383166000908152601b602052604090205460ff16156124b857600080fd5b6000818152601e60209081526040808320546001600160a01b03868116808652601d85528386208690558882168087528487208890559086526010855283862080546001600160a01b03199081169091558187528487208054821693909416928317909355868652601f855283862080548416821790558186526014855283862080549093168117909255908452601b909252909120805460ff1916600117905561256161347a565b6019556040516001600160a01b03808616919085169084907f5c44164828293bba0353472e907f7ee26a8659f916e6311fe826a7c70510e35290600090a450505050565b601a6020526000908152604090205481565b60008082156125df57506001600160a01b0383166000908152601c60205260409020546125fa565b506001600160a01b0383166000908152601a60205260409020545b6000818152600e602052604081205460ff16801561261e575061261c8261196a565b155b9050601560009054906101000a90046001600160a01b03166001600160a01b031663794c0c686040518163ffffffff1660e01b815260040160206040518083038186803b15801561266e57600080fd5b505afa158015612682573d6000803e3d6000fd5b505050506040513d602081101561269857600080fd5b505115806126a65750601854155b156126b45791506127049050565b60136018546126c161347a565b0311612700576000828152600f602052604081205460ff1680156126eb57506126e98361196a565b155b905081806126f65750805b9350505050612704565b9150505b92915050565b6021546022546001600160a01b031682565b61272461148c565b61272d57600080fd5b61273561194d565b61273e57600080fd5b6000612748613f0e565b6001549091501561280257600161275d61347a565b03407f55252fa6eee4741b4e24a74a70e9c11fd2c2281df8d6ea13126ff845f7825c89612788613213565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156127c45781810151838201526020016127ac565b505050509050019250505060405180910390a2600180546127e7916004916140ca565b506003805460ff19168215151790556127fe61347a565b6019555b50565b61280d613486565b6001600160a01b0316336001600160a01b03161461282a57600080fd5b61280281613f26565b600e6020526000908152604090205460ff1681565b601d6020526000908152604090205481565b6000818152600e602052604081205460ff16156128795750600161116e565b6004546000905b808210156128be57600480548390811061289657fe5b90600052602060002001548414156128b35760019250505061116e565b600190910190612880565b50506001546000905b8082101561290457600182815481106128dc57fe5b90600052602060002001548414156128f95760019250505061116e565b6001909101906128c7565b5060009392505050565b6000818152600a602052604081205461292561347a565b111592915050565b60205481565b6000806129418560016125b7565b61295057506000905080612b17565b61295b8460006125b7565b61296a57506000905080612b17565b6001600160a01b038086166000908152601c60209081526040808320549388168352601a90915281205490546001811115612a825760155460408051630f29818d60e31b815290516000926001600160a01b03169163794c0c68916004808301926020929190829003018186803b1580156129e457600080fd5b505afa1580156129f8573d6000803e3d6000fd5b505050506040513d6020811015612a0e57600080fd5b5051600085815260126020908152604080832084845282528083205460139092528220549293509190828210612a535760018503838303600a0281612a4f57fe5b0490505b8460320283118015612a6457508083115b15612a7d57600060019850985050505050505050612b17565b505050505b6000612a8c61347a565b905080871115612aa6576000809550955050505050612b17565b60648082118015612ab8575080820388105b15612ace57600080965096505050505050612b17565b60008481526007602090815260408083208b8452825280832088845290915290205460ff1615612b0957600080965096505050505050612b17565b600160009650965050505050505b935093915050565b6000612b2a82611147565b61292561347a565b600080612b3e836119a9565b90508061198857600091505061116e565b6025546001600160a01b031681565b612b66613486565b6001600160a01b0316336001600160a01b031614612b8357600080fd5b60265415612b9057600080fd5b601654736a3154a1f55a8faf96dfde75d25eff0c06eb678414612bb257600080fd5b6016805460268054600181810183557f744a2cf8fd7008e3d53b67916e73460df9fa5214e3ef23dd4259ca09493a35949182019390935581548084019092557359be7069745a9820a75aa66357a50a5d7f66ced591018190558254600090815260276020526040808220805460ff1990811686179091559282527f4bf96c2adb0c7a309689f5f3e58c1a880f1b61efb59c1459be862d2666e5acdb8054909316909317909155601554925482516394f3a24160e01b8152600481019190915291516001600160a01b03909316926394f3a24192602480820193929182900301818387803b158015612ca257600080fd5b505af1158015612cb6573d6000803e3d6000fd5b5050601554604080516394f3a24160e01b81527359be7069745a9820a75aa66357a50a5d7f66ced5600482015290516001600160a01b0390921693506394f3a241925060248082019260009290919082900301818387803b158015612d1a57600080fd5b505af1158015612d2e573d6000803e3d6000fd5b505060006016555050565b6001600160a01b03166000908152601c60209081526040808320548352601790915290205490565b606080600080549050604051908082528060200260200182016040528015612d93578160200160208202803883390190505b50905060005b8151811015612e0b57601e6000808381548110612db257fe5b9060005260206000200154815260200190815260200160002060009054906101000a90046001600160a01b0316828281518110612deb57fe5b6001600160a01b0390921660209283029190910190910152600101612d99565b50905090565b60185481565b612e1f61148c565b612e2857600080fd5b336000818152601c60209081526040808320546001600160a01b0389168452601a90925290912054612e5b8360016125b7565b15612e6957612e6982613fff565b600080612e77858a8a612933565b9150915081612ef3578015612ee957604080516001808252818301909252606091602080830190803883390190505090508581600081518110612eb657fe5b60200260200101906001600160a01b031690816001600160a01b031681525050612ee781637370616d60e01b61347e565b505b505050505061301c565b60008381526006602090815260408083208b84528252808320805460018181018355828652848620909101899055878552600784528285208d86528452828520898652845293829020805460ff191690941790935580516001600160a01b03808a1682528d16928101929092528051869288928d927fc98c577e9aca0ce08e747dd843b95214821e69106d6916218997e8a8f357f3189281900390910190a46000548154612fa890600263ffffffff61394416565b111561224257604080516001808252818301909252606091602080830190803883390190505090508a81600081518110612fde57fe5b60200260200101906001600160a01b031690816001600160a01b03168152505061301481686d616c6963696f757360b81b61347e565b505050505050505b50505050565b6001600160a01b03166000908152601c60209081526040808320548352600b90915290205490565b60008061305561347a565b90508060010183111561306c5760009150506130fd565b60648111801561307e57508260648203115b1561308d5760009150506130fd565b6001600160a01b0384166000908152601a60205260409020546130af8161196a565b156130bf576000925050506130fd565b6001600160a01b0386166000908152601c6020908152604080832054938352600782528083208784528252808320938352929052205460ff16159150505b9392505050565b60236020908152600091825260409182902080548351601f6002600019610100600186161502019093169290920491820184900484028101840190945280845290918301828280156114845780601f1061145957610100808354040283529160200191611484565b6011546001600160a01b031681565b613183613486565b6001600160a01b0316336001600160a01b0316146131a057600080fd5b60005b81811015611008576131c68383838181106131ba57fe5b90506020020135613f26565b6001016131a3565b600d5481565b601e602052600090815260409020546001600160a01b031681565b60276020526000908152604090205460ff1681565b6015546001600160a01b031681565b606080600180549050604051908082528060200260200182016040528015613245578160200160208202803883390190505b50905060005b8151811015612e0b57601e60006001838154811061326557fe5b9060005260206000200154815260200190815260200160002060009054906101000a90046001600160a01b031682828151811061329e57fe5b6001600160a01b039092166020928302919091019091015260010161324b565b6001600160a01b03166000908152601c60209081526040808320548352600e90915290205460ff1690565b606060008054806020026020016040519081016040528092919081815260200182805480156110c157602002820191906000526020600020908154815260200190600101908083116110ad575050505050905090565b60155460408051630a38dcbd60e41b81526004810184905290516000926001600160a01b03169163a38dcbd0916024808301928692919082900301818387803b15801561338b57600080fd5b505af115801561339f573d6000803e3d6000fd5b505060018054925082141590506133ba57600091505061116e565b60005b818110156129045783600182815481106133d357fe5b90600052602060002001541415613436576001808303815481106133f357fe5b90600052602060002001546001828154811061340b57fe5b600091825260209091200155600180549061342a9060001983016140a6565b5060019250505061116e565b6001016133bd565b6005805460ff19166001179055808015613459575060015415155b1561346e576005805461ff0019166101001790555b50600d80546001019055565b4390565b61134361347a565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b602154600090156134bb57600080fd5b6001600160a01b0383166134ce57600080fd5b6001600160a01b0382166134e157600080fd5b816001600160a01b0316836001600160a01b0316141561350057600080fd5b6001600160a01b03828116600090815260106020526040902054161561352557600080fd5b6001600160a01b03838116600090815260106020526040902054161561354a57600080fd5b6001600160a01b03828116600090815260146020526040902054161561356f57600080fd5b6001600160a01b03838116600090815260146020526040902054161561359457600080fd5b601554604080516322e8c68760e21b81526001600160a01b03868116600483015291519190921691638ba31a1c916024808301926020929190829003018186803b1580156135e157600080fd5b505afa1580156135f5573d6000803e3d6000fd5b505050506040513d602081101561360b57600080fd5b50511561361757600080fd5b601554604080516322e8c68760e21b81526001600160a01b03858116600483015291519190921691638ba31a1c916024808301926020929190829003018186803b15801561366457600080fd5b505afa158015613678573d6000803e3d6000fd5b505050506040513d602081101561368e57600080fd5b50511561369a57600080fd5b6001600160a01b0383166000908152601a6020526040902054156136bd57600080fd5b6001600160a01b0382166000908152601a6020526040902054156136e057600080fd5b6001600160a01b0383166000908152601b602052604090205460ff161561370657600080fd5b6001600160a01b0382166000908152601b602052604090205460ff161561372c57600080fd5b506020805460019081018083556001600160a01b039485166000818152601c8552604080822084905595909616808752601d8552858720839055828752601e855285872080546001600160a01b03199081168417909155818852601086528688208054821684179055838852601f865286882080548216831790559187526014855285872080549092168117909155601a84528486208290558552601b90925291909220805460ff1916909117905590565b610100825111156137ee57600080fd5b610400815111156137fe57600080fd5b6000838152602360209081526040909120835161381d92850190614138565b506000838152602460209081526040909120825161383d92840190614138565b50827f79a6be597f1291d06b4ccea662f373201edec72cbcc5df2ccfcd74ce9ff4b2e98383604051808060200180602001838103835285818151815260200191508051906020019080838360005b838110156138a357818101518382015260200161388b565b50505050905090810190601f1680156138d05780820380516001836020036101000a031916815260200191505b50838103825284518152845160209182019186019080838360005b838110156139035781810151838201526020016138eb565b50505050905090810190601f1680156139305780820380516001836020036101000a031916815260200191505b5094505050505060405180910390a2505050565b60008261395357506000612704565b8282028284828161396057fe5b04146130fd57600080fd5b60008282111561397a57600080fd5b50900390565b6001600160a01b039384166000818152601c60209081526040808320839055958716808352868320869055858352601e825286832080546001600160a01b0319908116831790915594909716808352601082528683208054861689179055928252601481528582208054851690559581528481208054909316909117909155601a909352912055565b600080838381613a1557fe5b0690506000805b828211613a4857868181518110613a2f57fe5b6020026020010151820191508080600101915050613a1c565b600019019695505050505050565b8051613c1e5760005b600154811015613c1857600060018281548110613a7857fe5b6000918252602080832090910154808352602790915260409091205490915060ff1615613aa55750613c10565b601554604080516317775f1960e31b81526004810184905290516001600160a01b039092169163bbbaf8c891602480820192602092909190829003018186803b158015613af157600080fd5b505afa158015613b05573d6000803e3d6000fd5b505050506040513d6020811015613b1b57600080fd5b50518015613ba55750601554604080516371f87fb360e11b8152600481018490526000602482015290516001600160a01b039092169163e3f0ff6691604480820192602092909190829003018186803b158015613b7757600080fd5b505afa158015613b8b573d6000803e3d6000fd5b505050506040513d6020811015613ba157600080fd5b5051155b15613bb05750613c10565b600180541415613bc05750613c18565b600180546000198101908110613bd257fe5b906000526020600020015460018381548110613bea57fe5b6000918252602090912001556001805490613c099060001983016140a6565b5050600019015b600101613a5f565b50612802565b60268054613c2e916001916140ca565b5060005b815181108015613c4457506001546013115b1561106f576001828281518110613c5757fe5b6020908102919091018101518254600181810185556000948552929093209092019190915501613c32565b60025460005b81811015613cd6576000600f600060028481548110613ca357fe5b60009182526020808320919091015483528201929092526040019020805460ff1916911515919091179055600101613c88565b505060008054905b81811015613d2b576001600f6000808481548110613cf857fe5b60009182526020808320919091015483528201929092526040019020805460ff1916911515919091179055600101613cde565b60008054611008916002916140ca565b6060600080805480602002602001604051908101604052809291908181526020018280548015613d8a57602002820191906000526020600020905b815481526020019060010190808311613d76575b50505050509150600090505b8151811015613de2576000600e6000848481518110613db157fe5b6020908102919091018101518252810191909152604001600020805460ff1916911515919091179055600101613d96565b60048054613df2916000916140ca565b506000805480602002602001604051908101604052809291908181526020018280548015613e3f57602002820191906000526020600020905b815481526020019060010190808311613e2b575b50505050509150600090505b8151811015611008576000828281518110613e6257fe5b6020908102919091018101516000818152600e9092526040909120805460ff1916600117905590508315613ea6576000818152601760205260409020805460010190555b50600101613e4b565b6021548015613ef6576000818152601e6020908152604080832054602254601f9093529220546001600160a01b03928316929182169116613ef283838684613980565b5050505b506000602155602280546001600160a01b0319169055565b6005805461ffff198116909155610100900460ff1690565b60008181526027602052604090205460ff1615613f4257600080fd5b602654601311613f5157600080fd5b6026805460018181019092557f744a2cf8fd7008e3d53b67916e73460df9fa5214e3ef23dd4259ca09493a359401829055600082815260276020526040808220805460ff191690931790925560155482516394f3a24160e01b81526004810185905292516001600160a01b03909116926394f3a24192602480830193919282900301818387803b158015613fe457600080fd5b505af1158015613ff8573d6000803e3d6000fd5b5050505050565b60155460408051630f29818d60e31b815290516000926001600160a01b03169163794c0c68916004808301926020929190829003018186803b15801561404457600080fd5b505afa158015614058573d6000803e3d6000fd5b505050506040513d602081101561406e57600080fd5b505160009283526012602090815260408085209285529181528184208054600190810190915560139091529220805490920190915550565b815481835581811115611008576000838152602090206110089181019083016141a6565b82805482825590600052602060002090810192821561410a5760005260206000209182015b8281111561410a5782548255916001019190600101906140ef565b506141169291506141a6565b5090565b508054600082559060005260206000209081019061280291906141a6565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061417957805160ff191683800117855561410a565b8280016001018555821561410a579182015b8281111561410a57825182559160200191906001019061418b565b6110c991905b8082111561411657600081556001016141ac56fea265627a7a7230582055f1a6432160796b00712c102535aff37d15150aeb81412e0c35d8522cd3bc3164736f6c634300050a0032" + }, + "0x1100000000000000000000000000000000000001": { + "balance": "0x0", + "constructor": "0x60806040526040516108053803806108058339818101604052604081101561002657600080fd5b50805160209182015160408051600081529384018082527f656970313936372e70726f78792e696d706c656d656e746174696f6e00000000905251603c81850301902091929091839190600019016000805160206107aa8339815191521461008a57fe5b61009c826001600160e01b036101bd16565b805115610154576000826001600160a01b0316826040518082805190602001908083835b602083106100df5780518252601f1990920191602091820191016100c0565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855af49150503d806000811461013f576040519150601f19603f3d011682016040523d82523d6000602084013e610144565b606091505b505090508061015257600080fd5b505b5050604080517f656970313936372e70726f78792e61646d696e000000000000000000000000008152905190819003601301902060008051602061078a833981519152600019909101146101a457fe5b6101b6816001600160e01b0361023716565b505061024f565b6101d08161024960201b6104801760201c565b610225576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603b8152602001806107ca603b913960400191505060405180910390fd5b6000805160206107aa83398151915255565b60008051602061078a83398151915255565b3b151590565b61052c8061025e6000396000f3fe60806040526004361061004a5760003560e01c80633659cfe6146100545780634f1ef286146100875780635c60da1b146101075780638f28397014610138578063f851a4401461016b575b610052610180565b005b34801561006057600080fd5b506100526004803603602081101561007757600080fd5b50356001600160a01b031661019a565b6100526004803603604081101561009d57600080fd5b6001600160a01b0382351691908101906040810160208201356401000000008111156100c857600080fd5b8201836020820111156100da57600080fd5b803590602001918460018302840111640100000000831117156100fc57600080fd5b5090925090506101cb565b34801561011357600080fd5b5061011c61026f565b604080516001600160a01b039092168252519081900360200190f35b34801561014457600080fd5b506100526004803603602081101561015b57600080fd5b50356001600160a01b031661027e565b34801561017757600080fd5b5061011c61033c565b610188610198565b610198610193610346565b61036b565b565b6101a261038f565b6001600160a01b0316336001600160a01b0316146101bf57600080fd5b6101c8816103b4565b50565b6101d361038f565b6001600160a01b0316336001600160a01b0316146101f057600080fd5b6101f9836103b4565b6000836001600160a01b031683836040518083838082843760405192019450600093509091505080830381855af49150503d8060008114610256576040519150601f19603f3d011682016040523d82523d6000602084013e61025b565b606091505b505090508061026957600080fd5b50505050565b6000610279610346565b905090565b61028661038f565b6001600160a01b0316336001600160a01b0316146102a357600080fd5b6001600160a01b0381166102e85760405162461bcd60e51b81526004018080602001828103825260368152602001806104876036913960400191505060405180910390fd5b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f61031161038f565b604080516001600160a01b03928316815291841660208301528051918290030190a16101c8816103f4565b600061027961038f565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b3660008037600080366000845af43d6000803e80801561038a573d6000f35b3d6000fd5b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b6103bd81610418565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610355565b61042181610480565b61045c5760405162461bcd60e51b815260040180806020018281038252603b8152602001806104bd603b913960400191505060405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc55565b3b15159056fe43616e6e6f74206368616e6765207468652061646d696e206f6620612070726f787920746f20746865207a65726f206164647265737343616e6e6f742073657420612070726f787920696d706c656d656e746174696f6e20746f2061206e6f6e2d636f6e74726163742061646472657373a265627a7a72305820a9aab4b95b654a79b32f5aa284796894f8329aaa083932695296085b196c27bd64736f6c634300050a0032b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc43616e6e6f742073657420612070726f787920696d706c656d656e746174696f6e20746f2061206e6f6e2d636f6e747261637420616464726573730000000000000000000000001100000000000000000000000000000000000000000000000000000000000000b03a86b3126157c039b55e21d378587ccfc04d45" + }, + "0x1100000000000000000000000000000000000000": { + "balance": "0x0", + "constructor": "0x608060405234801561001057600080fd5b5061579480620000216000396000f3fe6080604052600436106103c35760003560e01c80638c2243ae116101f2578063cd22c7521161010d578063e3f0ff66116100a0578063f07860961161006f578063f078609614611033578063f3fef3a314611048578063f494250114611081578063fb367a9b14611096576103c3565b8063e3f0ff6614610efd578063e4a9e42e14610f36578063edd7db7514611009578063ee435f551461101e576103c3565b8063d609ea93116100dc578063d609ea9314610ea9578063da7a9b6a14610ebe578063df6f55f514610ed3578063dfc8bf4e14610ee8576103c3565b8063cd22c75214610dfe578063cfef144114610e28578063d290c21d14610e5b578063d2f2a13614610e70576103c3565b8063a4c0ed3611610185578063b61ed63a11610154578063b61ed63a14610cc4578063bbbaf8c814610cfd578063bcdb0d3814610d27578063cc4a666714610d51576103c3565b8063a4c0ed3614610bde578063a5d54f6514610c6e578063adc9772e14610c83578063b172b22214610caf576103c3565b806397997ebb116101c157806397997ebb14610b4b5780639fb0e72e14610b60578063a1fc275314610b8a578063a38dcbd014610bb4576103c3565b80638c2243ae14610a6157806394f3a24114610a76578063950a651314610aa0578063957950a714610adb576103c3565b80633ea15d62116102e2578063673a2a1f116102755780637069e746116102445780637069e746146109ef57806374bdb37214610a04578063794c0c6814610a195780638ba31a1c14610a2e576103c3565b8063673a2a1f146109365780636bda15771461094b5780636d01b4fe146109865780636e69cd8b146109c5576103c3565b80635292fccf116102b15780635292fccf14610891578063561c4c81146108c4578063570941d2146108ee5780635fef764314610921576103c3565b80633ea15d621461074b5780633fb1a1e4146108045780634070a2d01461083d57806348aaa4a214610867576103c3565b806327d89b3a1161035a5780632ebfaf4e116103295780632ebfaf4e146106445780632f248e30146106d3578063381883b0146106fd578063392e53cd14610736576103c3565b806327d89b3a146105865780632a8f6ecd146105bf5780632bafde8d146105e95780632d21d21714610613576103c3565b80631555371c116103965780631555371c146104b1578063186dc46f146104c657806320d96e4614610519578063251441a914610543576103c3565b806302a53ba1146103c85780630555c5e214610413578063073b62fe1461043f578063093411da14610478575b600080fd5b3480156103d457600080fd5b50610401600480360360408110156103eb57600080fd5b50803590602001356001600160a01b0316611173565b60408051918252519081900360200190f35b34801561041f57600080fd5b5061043d6004803603602081101561043657600080fd5b5035611190565b005b34801561044b57600080fd5b506104016004803603604081101561046257600080fd5b50803590602001356001600160a01b0316611325565b34801561048457600080fd5b506104016004803603604081101561049b57600080fd5b50803590602001356001600160a01b0316611359565b3480156104bd57600080fd5b5061043d611376565b3480156104d257600080fd5b50610505600480360360608110156104e957600080fd5b508035906001600160a01b036020820135169060400135611418565b604080519115158252519081900360200190f35b34801561052557600080fd5b5061043d6004803603602081101561053c57600080fd5b503561143e565b34801561054f57600080fd5b5061043d6004803603606081101561056657600080fd5b506001600160a01b0381358116916020810135909116906040013561145a565b34801561059257600080fd5b50610401600480360360408110156105a957600080fd5b50803590602001356001600160a01b03166115f2565b3480156105cb57600080fd5b50610401600480360360208110156105e257600080fd5b503561160f565b3480156105f557600080fd5b5061043d6004803603602081101561060c57600080fd5b5035611621565b34801561061f57600080fd5b5061062861165c565b604080516001600160a01b039092168252519081900360200190f35b34801561065057600080fd5b506106836004803603606081101561066757600080fd5b506001600160a01b03813516906020810135906040013561166b565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156106bf5781810151838201526020016106a7565b505050509050019250505060405180910390f35b3480156106df57600080fd5b5061043d600480360360208110156106f657600080fd5b5035611780565b34801561070957600080fd5b506104016004803603604081101561072057600080fd5b50803590602001356001600160a01b03166117e3565b34801561074257600080fd5b50610505611800565b34801561075757600080fd5b5061043d6004803603604081101561076e57600080fd5b810190602081018135600160201b81111561078857600080fd5b82018360208201111561079a57600080fd5b803590602001918460208302840111600160201b831117156107bb57600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550505090356001600160a01b031691506118129050565b34801561081057600080fd5b506104016004803603604081101561082757600080fd5b50803590602001356001600160a01b0316611e87565b34801561084957600080fd5b506104016004803603602081101561086057600080fd5b5035611ea4565b34801561087357600080fd5b5061043d6004803603602081101561088a57600080fd5b5035611eb6565b34801561089d57600080fd5b5061043d600480360360208110156108b457600080fd5b50356001600160a01b0316611ef1565b3480156108d057600080fd5b50610683600480360360208110156108e757600080fd5b5035612045565b3480156108fa57600080fd5b5061043d6004803603602081101561091157600080fd5b50356001600160a01b03166120b1565b34801561092d57600080fd5b5061040161213d565b34801561094257600080fd5b50610683612143565b34801561095757600080fd5b506104016004803603604081101561096e57600080fd5b506001600160a01b038135811691602001351661219b565b34801561099257600080fd5b50610401600480360360608110156109a957600080fd5b508035906001600160a01b03602082013516906040013561235a565b3480156109d157600080fd5b50610401600480360360208110156109e857600080fd5b503561237d565b3480156109fb57600080fd5b5061040161238f565b348015610a1057600080fd5b50610401612395565b348015610a2557600080fd5b5061040161239b565b348015610a3a57600080fd5b5061040160048036036020811015610a5157600080fd5b50356001600160a01b03166123a1565b348015610a6d57600080fd5b506104016123bc565b348015610a8257600080fd5b5061043d60048036036020811015610a9957600080fd5b50356123e1565b348015610aac57600080fd5b5061040160048036036040811015610ac357600080fd5b506001600160a01b0381358116916020013516612420565b348015610ae757600080fd5b50610af06125d1565b6040518080602001838152602001828103825284818151815260200191508051906020019060200280838360005b83811015610b36578181015183820152602001610b1e565b50505050905001935050505060405180910390f35b348015610b5757600080fd5b50610401612634565b348015610b6c57600080fd5b5061040160048036036020811015610b8357600080fd5b503561263a565b348015610b9657600080fd5b5061068360048036036020811015610bad57600080fd5b503561264c565b348015610bc057600080fd5b5061043d60048036036020811015610bd757600080fd5b50356126b6565b348015610bea57600080fd5b5061050560048036036060811015610c0157600080fd5b6001600160a01b0382351691602081013591810190606081016040820135600160201b811115610c3057600080fd5b820183602082011115610c4257600080fd5b803590602001918460018302840111600160201b83111715610c6357600080fd5b5090925090506126d6565b348015610c7a57600080fd5b5061068361283c565b61043d60048036036040811015610c9957600080fd5b506001600160a01b038135169060200135612892565b348015610cbb57600080fd5b5061062861289c565b348015610cd057600080fd5b5061043d60048036036040811015610ce757600080fd5b506001600160a01b0381351690602001356128ab565b348015610d0957600080fd5b5061050560048036036020811015610d2057600080fd5b5035612cd7565b348015610d3357600080fd5b5061040160048036036020811015610d4a57600080fd5b5035612d12565b348015610d5d57600080fd5b5061043d6004803603610100811015610d7557600080fd5b6001600160a01b038235811692602081013590911691810190606081016040820135600160201b811115610da857600080fd5b820183602082011115610dba57600080fd5b803590602001918460208302840111600160201b83111715610ddb57600080fd5b919350915080359060208101359060408101359060608101359060800135612d24565b348015610e0a57600080fd5b5061040160048036036020811015610e2157600080fd5b5035612f0f565b348015610e3457600080fd5b5061043d60048036036020811015610e4b57600080fd5b50356001600160a01b0316612f21565b348015610e6757600080fd5b50610683613128565b348015610e7c57600080fd5b5061040160048036036040811015610e9357600080fd5b50803590602001356001600160a01b031661317e565b348015610eb557600080fd5b5061040161319b565b348015610eca57600080fd5b506104016131a1565b348015610edf57600080fd5b506106836131a7565b348015610ef457600080fd5b506106286131fd565b348015610f0957600080fd5b5061040160048036036040811015610f2057600080fd5b50803590602001356001600160a01b031661320c565b61040160048036036080811015610f4c57600080fd5b8135916001600160a01b0360208201351691810190606081016040820135600160201b811115610f7b57600080fd5b820183602082011115610f8d57600080fd5b803590602001918460018302840111600160201b83111715610fae57600080fd5b919390929091602081019035600160201b811115610fcb57600080fd5b820183602082011115610fdd57600080fd5b803590602001918460018302840111600160201b83111715610ffe57600080fd5b509092509050613229565b34801561101557600080fd5b5061043d6132a3565b34801561102a57600080fd5b5061043d613452565b34801561103f57600080fd5b50610401613474565b34801561105457600080fd5b5061043d6004803603604081101561106b57600080fd5b506001600160a01b03813516906020013561347a565b34801561108d57600080fd5b50610505613568565b3480156110a257600080fd5b5061115a600480360360608110156110b957600080fd5b810190602081018135600160201b8111156110d357600080fd5b8201836020820111156110e557600080fd5b803590602001918460208302840111600160201b8311171561110657600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550506001600160a01b0383358116945060209093013590921691506135aa9050565b6040805192835260208301919091528051918290030190f35b602a60209081526000928352604080842090915290825290205481565b611198613c33565b6001600160a01b0316336001600160a01b0316146111b557600080fd5b60006111bf613c58565b90506035546000146111d057600080fd5b6037548110806111e05750603754155b6111e957600080fd5b816111f2613c5c565b146111fc57600080fd5b600054828161120757fe5b061561121257600080fd5b6000805461122790849063ffffffff613cd816565b603780549084905590915060005b60005481101561131c57600080828154811061124d57fe5b6000918252602080832090910154603954604080516316cf66ab60e01b81526004810184905290519295506001600160a01b03909116926316cf66ab92602480840193829003018186803b1580156112a457600080fd5b505afa1580156112b8573d6000803e3d6000fd5b505050506040513d60208110156112ce57600080fd5b50516000838152603160209081526040808320838052909152902054909150156112f757600080fd5b611302818287613cfa565b506000908152600b60205260409020839055600101611235565b50603755505050565b6000828152600a602090815260408083206001600160a01b0385168452825280832060355484529091529020545b92915050565b602b60209081526000928352604080842090915290825290205481565b6039546001600160a01b0316331461138d57600080fd5b606060038054806020026020016040519081016040528092919081815260200182805480156113db57602002820191906000526020600020905b8154815260200190600101908083116113c7575b50939450600093505050505b81518110156114145761140c8282815181106113ff57fe5b60200260200101516141dc565b6001016113e7565b5050565b603060209081526000938452604080852082529284528284209052825290205460ff1681565b6039546001600160a01b0316331461145557600080fd5b603755565b816001600160a01b0316836001600160a01b0316141561147957600080fd5b6039546040805163a26301f960e01b81526001600160a01b0386811660048301529151600093929092169163a26301f991602480820192602092909190829003018186803b1580156114ca57600080fd5b505afa1580156114de573d6000803e3d6000fd5b505050506040513d60208110156114f457600080fd5b50516039546040805163a26301f960e01b81526001600160a01b0387811660048301529151939450600093919092169163a26301f9916024808301926020929190829003018186803b15801561154957600080fd5b505afa15801561155d573d6000803e3d6000fd5b505050506040513d602081101561157357600080fd5b50519050336115838682866142c8565b61158e858286613cfa565b603554604080516001600160a01b03898116825260208201889052818301879052606082018690529151828516928916917f982f87186288986ca297b6c86b6d4547934327c6e005ce210da6b0cdc06a370d919081900360800190a4505050505050565b603260209081526000928352604080842090915290825290205481565b60386020526000908152604090205481565b611629613c33565b6001600160a01b0316336001600160a01b03161461164657600080fd5b61164e611800565b61165757600080fd5b602555565b6053546001600160a01b031681565b6001600160a01b0383166000908152600860205260409020606090826116df578054604080516020808402820181019092528281529183918301828280156116d257602002820191906000526020600020905b8154815260200190600101908083116116be575b5050505050915050611779565b80546000906116f4908663ffffffff61453a16565b90508084116117035783611705565b805b60405190808252806020026020018201604052801561172e578160200160208202803883390190505b50925060005b835181101561177557828187018154811061174b57fe5b906000526020600020015484828151811061176257fe5b6020908102919091010152600101611734565b5050505b9392505050565b6039546001600160a01b0316331461179757600080fd5b806117a157600080fd5b6000818152603160209081526040808320838052909152902054156117d7576117c98161454f565b6117d28161460b565b6117e0565b6117e0816146c4565b50565b603360209081526000928352604080842090915290825290205481565b6039546001600160a01b031615155b90565b3a61181c57600080fd5b611824611800565b61182d57600080fd5b6039546040805163a26301f960e01b81526001600160a01b03848116600483015291513393600093169163a26301f9916024808301926020929190829003018186803b15801561187c57600080fd5b505afa158015611890573d6000803e3d6000fd5b505050506040513d60208110156118a657600080fd5b505190506001600160a01b0383166118bd57600080fd5b6001600160a01b0382166118d057600080fd5b806118da57600080fd5b6000836001600160a01b0316836001600160a01b031614156118fd5760006118ff565b825b9050600080846001600160a01b0316866001600160a01b0316146119715760008481526032602090815260408083206001600160a01b038916845290915290205491508161194c57600080fd5b5060008381526033602090815260408083206001600160a01b03881684529091529020545b60395460408051632b5aa5d760e11b815290516000926001600160a01b0316916356b54bae916004808301926020929190829003018186803b1580156119b657600080fd5b505afa1580156119ca573d6000803e3d6000fd5b505050506040513d60208110156119e057600080fd5b505190506119ec615708565b50604080518082019091526000808252602082018190528951611ad957826001600160a01b031663e7f6cfe2886040518263ffffffff1660e01b81526004018082815260200191505060006040518083038186803b158015611a4d57600080fd5b505afa158015611a61573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526020811015611a8a57600080fd5b810190808051600160201b811115611aa157600080fd5b82016020810184811115611ab457600080fd5b81518560208202830111600160201b82111715611ad057600080fd5b50909d50505050505b60005b8a51811015611df25760008b8281518110611af357fe5b602002602001015190508160001480611b2157508b6001830381518110611b1657fe5b602002602001015181115b611b2a57600080fd5b6035548110611b3857600080fd5b60008981526030602090815260408083206001600160a01b038c168452825280832084845290915290205460ff1615611b715750611dea565b611b79615708565b8a6001600160a01b03168c6001600160a01b031614611c655787821015611ba1575050611dea565b818711158015611bb057508615155b15611bbc575050611df2565b611bc98289868d8f61474d565b9350816001019750856001600160a01b031663877ffdea85848d6040518463ffffffff1660e01b8152600401808481526020018381526020018281526020019350505050604080518083038186803b158015611c2457600080fd5b505afa158015611c38573d6000803e3d6000fd5b505050506040513d6040811015611c4e57600080fd5b508051602091820151918301919091528152611cec565b60408051631289b17960e01b815260048101849052602481018c905281516001600160a01b03891692631289b1799260448082019391829003018186803b158015611caf57600080fd5b505afa158015611cc3573d6000803e3d6000fd5b505050506040513d6040811015611cd957600080fd5b5080516020918201519183019190915281525b80518551611cff9163ffffffff6147bf16565b855260208082015190860151611d1a9163ffffffff6147bf16565b8560200181815250506001603060008c815260200190815260200160002060008b6001600160a01b03166001600160a01b03168152602001908152602001600020600084815260200190815260200160002060006101000a81548160ff021916908315150217905550818b6001600160a01b03168d6001600160a01b03167f6d8e1b032c4629c85b1e460dedd0e2d7c5eb72880982d3e495f0f892b7f64406846000015185602001518f60405180848152602001838152602001828152602001935050505060405180910390a450505b600101611adc565b50826001600160a01b03166370cafd65836000015184602001518b6040518463ffffffff1660e01b815260040180848152602001838152602001826001600160a01b03166001600160a01b031681526020019350505050600060405180830381600087803b158015611e6357600080fd5b505af1158015611e77573d6000803e3d6000fd5b5050505050505050505050505050565b603160209081526000928352604080842090915290825290205481565b60286020526000908152604090205481565b611ebe613c33565b6001600160a01b0316336001600160a01b031614611edb57600080fd5b611ee3611800565b611eec57600080fd5b602455565b611ef9613c33565b6001600160a01b0316336001600160a01b031614611f1657600080fd5b6001600160a01b038116611f2957600080fd5b6039546040805163a26301f960e01b815273eb43574e8f4fddf11fbaf65a8632ca92262a1266600482018190529151919269043c33c193756480000092849283926001600160a01b03169163a26301f991602480820192602092909190829003018186803b158015611f9a57600080fd5b505afa158015611fae573d6000803e3d6000fd5b505050506040513d6020811015611fc457600080fd5b505114611fd057600080fd5b6000838152600b6020526040812055611fea8180846142c8565b611ff484836147d1565b603554604080518481526020810186905281516001600160a01b0385169283927f5c5eecdba4673a19126d31c4ea006153eec8120d460905a4643cacd174da8722929081900390910190a450505050565b6000818152600660209081526040918290208054835181840281018401909452808452606093928301828280156120a557602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311612087575b50505050509050919050565b6120b9613c33565b6001600160a01b0316336001600160a01b0316146120d657600080fd5b6120de611800565b6120e757600080fd5b6001600160a01b0381166120fa57600080fd5b6053546001600160a01b03161561211057600080fd5b605380546001600160a01b0319166001600160a01b038316179055612133613c5c565b156117e057600080fd5b60245481565b6060600080548060200260200160405190810160405280929190818152602001828054801561219157602002820191906000526020600020905b81548152602001906001019080831161217d575b5050505050905090565b6039546040805163a26301f960e01b81526001600160a01b03858116600483015291516000938493169163a26301f9916024808301926020929190829003018186803b1580156121ea57600080fd5b505afa1580156121fe573d6000803e3d6000fd5b505050506040513d602081101561221457600080fd5b5051905060006001600160a01b038481169086161415612235576000612237565b835b90506001600160a01b038581169085161415612253838261488c565b6122635760009350505050611353565b60008381526031602090815260408083206001600160a01b0386168452909152902054816122ae576000848152600b60205260409020546122ab90829063ffffffff61453a16565b90505b60395460408051635245821560e11b81526004810187905290516001600160a01b039092169163a48b042a91602480820192602092909190829003018186803b1580156122fa57600080fd5b505afa15801561230e573d6000803e3d6000fd5b505050506040513d602081101561232457600080fd5b505161233557935061135392505050565b60006123418585611325565b90508082111561234f578091505b509695505050505050565b602660209081526000938452604080852082529284528284209052825290205481565b602c6020526000908152604090205481565b60375481565b603a5481565b60355481565b6001600160a01b031660009081526008602052604090205490565b60375460009080156123cf5760016123d2565b60005b60ff1660365482010391505090565b6039546001600160a01b031633146123f857600080fd5b6004546002541461240857600080fd5b6000818152600b60205260408120556117e0816148c2565b6039546040805163a26301f960e01b81526001600160a01b03858116600483015291516000938493169163a26301f9916024808301926020929190829003018186803b15801561246f57600080fd5b505afa158015612483573d6000803e3d6000fd5b505050506040513d602081101561249957600080fd5b505190506001600160a01b0384811690841614156000816124bb5760006124bd565b845b90506124c9838361488c565b6124d95760009350505050611353565b60395460408051635245821560e11b81526004810186905290516001600160a01b039092169163a48b042a91602480820192602092909190829003018186803b15801561252557600080fd5b505afa158015612539573d6000803e3d6000fd5b505050506040513d602081101561254f57600080fd5b50516125615760009350505050611353565b60008381526031602090815260408083206001600160a01b0385168452909152902054826125ac576000848152600b60205260409020546125a990829063ffffffff61453a16565b90505b6125c66125b98584611325565b829063ffffffff61453a16565b979650505050505050565b6060600060046005548180548060200260200160405190810160405280929190818152602001828054801561262557602002820191906000526020600020905b815481526020019060010190808311612611575b50505050509150915091509091565b60345481565b602e6020526000908152604090205481565b6000818152600760209081526040918290208054835181840281018401909452808452606093928301828280156120a5576020028201919060005260206000209081546001600160a01b031681526001909101906020018083116120875750505050509050919050565b6039546001600160a01b031633146126cd57600080fd5b6117e0816141dc565b60006126e0611800565b6126e957600080fd5b6053546001600160a01b0316331461270057600080fd5b601482101561270e57600080fd5b600080606085858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050506020820151606081901c955060581c60ff1615801594509192506128239050576000806060602084015160ff8160501c16935050826040519080825280601f01601f1916602001820160405280156127a7576020820181803883390190505b50905082609a60208301378351609a84013560f01c92508190838501601801146127d057600080fd5b826040519080825280601f01601f1916602001820160405280156127fb576020820181803883390190505b5091508284609c016020840137816128188c8e8a60018686614a0e565b50505050505061282e565b61282e838989613cfa565b506001979650505050505050565b60606002805480602002602001604051908101604052809291908181526020018280548015612191576020028201919060005260206000209081548152602001906001019080831161217d575050505050905090565b6114148282614be1565b603b546001600160a01b031681565b3a6128b557600080fd5b6128bd611800565b6128c657600080fd5b6039546040805163a26301f960e01b81526001600160a01b0385811660048301529151600093929092169163a26301f991602480820192602092909190829003018186803b15801561291757600080fd5b505afa15801561292b573d6000803e3d6000fd5b505050506040513d602081101561294157600080fd5b505190506001600160a01b03831661295857600080fd5b8161296257600080fd5b8061296c57600080fd5b3360006001600160a01b038516821415612987576000612989565b815b90506129a0836001600160a01b038316151561488c565b6129a957600080fd5b60008381526027602090815260408083206001600160a01b0385168085529083528184205487855260288452828520546031855283862092865291845282852054888652603890945291842054919390929190881315612a8f5787612a0e8a88612420565b811115612a1a57600080fd5b612a2a858263ffffffff6147bf16565b9450612a3c848263ffffffff6147bf16565b9350612a4e838263ffffffff61453a16565b9250612a60828263ffffffff61453a16565b60355460008a81526029602090815260408083206001600160a01b038c1684529091529020559150612ade9050565b6000889003612aa4858263ffffffff61453a16565b9450612ab6848263ffffffff61453a16565b9350612ac8838263ffffffff6147bf16565b9250612ada828263ffffffff6147bf16565b9150505b60008781526027602090815260408083206001600160a01b03808a168086529184528285208990558b855260288452828520889055603184528285209185529083528184208690558a84526038909252909120829055868116908a161415612c24576000878152600b6020526040902054821015612b5b57600080fd5b811580612b6a57506024548210155b612b7357600080fd5b6039546040805163738bef1d60e11b8152600481018a905290516000926001600160a01b03169163e717de3a916024808301926020929190829003018186803b158015612bbf57600080fd5b505afa158015612bd3573d6000803e3d6000fd5b505050506040513d6020811015612be957600080fd5b50511590506000891315612c145782612c0f5780612c0657600080fd5b612c0f886146c4565b612c1e565b612c1e8882614c7f565b50612c6d565b811580612c3357506025548210155b612c3c57600080fd5b6000881315612c595781612c5457612c548787614cfb565b612c63565b612c638787614e4a565b612c6d8787614f07565b612c768761460b565b603554866001600160a01b03168a6001600160a01b03167f89b66c7c015442886e0ce3c9c8137443ebbe1b1766f6b3a942dde6c3bb82517d8b8b604051808381526020018281526020019250505060405180910390a4505050505050505050565b6000818152602d602052604081205481548110801561177957508260008281548110612cff57fe5b9060005260206000200154149392505050565b602f6020526000908152604090205481565b6001600160a01b038916612d3757600080fd5b85612d4157600080fd5b84612d4b57600080fd5b83612d5557600080fd5b82612d5f57600080fd5b808311612d6b57600080fd5b80612d7557600080fd5b612d7d613c58565b1580612da15750612d8c613c33565b6001600160a01b0316336001600160a01b0316145b612daa57600080fd5b612db2611800565b15612dbc57600080fd5b603980546001600160a01b03808c166001600160a01b031992831617909255603b8054928b169290911691909117905560005b86811015612edf57878782818110612e0357fe5b9050602002013560001415612e1757600080fd5b612e34888883818110612e2657fe5b905060200201356000614c7f565b6039546001600160a01b031663e717de3a898984818110612e5157fe5b905060200201356040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015612e8c57600080fd5b505afa158015612ea0573d6000803e3d6000fd5b505050506040513d6020811015612eb657600080fd5b5051612ed757612ed7888883818110612ecb57fe5b905060200201356146c4565b600101612def565b5060258590556024849055603683905560378290556034819055612f01613c58565b603a55505050505050505050565b602d6020526000908152604090205481565b6039546040805163a26301f960e01b81526001600160a01b0384811660048301529151600093929092169163a26301f991602480820192602092909190829003018186803b158015612f7257600080fd5b505afa158015612f86573d6000803e3d6000fd5b505050506040513d6020811015612f9c57600080fd5b5051905080612faa57600080fd5b3360006001600160a01b038416821415612fc5576000612fc7565b815b60008481526029602090815260408083206001600160a01b038516845290915290205460355491925010612ffa57600080fd5b61300f836001600160a01b0383161515614fea565b1561301957600080fd5b60008381526027602090815260408083206001600160a01b03851684529091529020548061304657600080fd5b60008481526027602090815260408083206001600160a01b038616845282528083208390558683526028909152902054613086908263ffffffff61453a16565b600085815260286020908152604080832093909355603181528282206001600160a01b0386168352905220546130c1576130c18486856151a5565b6130cb83826147d1565b603554836001600160a01b0316866001600160a01b03167f3b1f0416a322c81d02b7eb108c29b8c9cf15503da84e83c389c529625b10389e8488604051808381526020018281526020019250505060405180910390a45050505050565b60606003805480602002602001604051908101604052809291908181526020018280548015612191576020028201919060005260206000209081548152602001906001019080831161217d575050505050905090565b602960209081526000928352604080842090915290825290205481565b60365481565b60255481565b60606001805480602002602001604051908101604052809291908181526020018280548015612191576020028201919060005260206000209081548152602001906001019080831161217d575050505050905090565b6039546001600160a01b031681565b602760209081526000928352604080842090915290825290205481565b60006125c6873388600089898080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8d018190048102820181019092528b815292508b91508a9081908401838280828437600092019190915250614a0e92505050565b3a6132ad57600080fd5b6132b5611800565b6132be57600080fd5b6039546040805163a26301f960e01b815233600482015290516000926001600160a01b03169163a26301f9916024808301926020929190829003018186803b15801561330957600080fd5b505afa15801561331d573d6000803e3d6000fd5b505050506040513d602081101561333357600080fd5b505190508061334157600080fd5b600060355411806133c7575060395460408051639b4a14bf60e01b81526004810184905290516001600160a01b0390921691639b4a14bf91602480820192602092909190829003018186803b15801561339957600080fd5b505afa1580156133ad573d6000803e3d6000fd5b505050506040513d60208110156133c357600080fd5b5051155b6133d057600080fd5b6039546040805163738bef1d60e11b81526004810184905290516001600160a01b039092169163e717de3a91602480820192602092909190829003018186803b15801561341c57600080fd5b505afa158015613430573d6000803e3d6000fd5b505050506040513d602081101561344657600080fd5b5051156126cd57600080fd5b6039546001600160a01b0316331461346957600080fd5b603580546001019055565b610bb881565b6039546040805163a26301f960e01b81526001600160a01b03858116600483015291513393600093169163a26301f9916024808301926020929190829003018186803b1580156134c957600080fd5b505afa1580156134dd573d6000803e3d6000fd5b505050506040513d60208110156134f357600080fd5b505190506135028483856142c8565b61350c82846147d1565b603554826001600160a01b0316856001600160a01b03167f5c5eecdba4673a19126d31c4ea006153eec8120d460905a4643cacd174da87228685604051808381526020018281526020019250505060405180910390a450505050565b600080613573613c58565b905060375481101561358957600091505061180f565b6034546036546037549190039061359e576001015b60375490910310905090565b6039546040805163a26301f960e01b81526001600160a01b03858116600483015291516000938493849391169163a26301f991602480820192602092909190829003018186803b1580156135fd57600080fd5b505afa158015613611573d6000803e3d6000fd5b505050506040513d602081101561362757600080fd5b505190506001600160a01b03851661363e57600080fd5b6001600160a01b03841661365157600080fd5b8061365b57600080fd5b6000856001600160a01b0316856001600160a01b0316141561367e576000613680565b845b604080516002808252606080830184529394509091602083019080388339019050509050856001600160a01b0316876001600160a01b0316146137595760008381526032602090815260408083206001600160a01b038a1684529091528120548251909183916136ec57fe5b6020026020010181815250508060008151811061370557fe5b60200260200101516000141561371a57600080fd5b60008381526033602090815260408083206001600160a01b038a16845290915290205481518290600190811061374c57fe5b6020026020010181815250505b60395460408051632b5aa5d760e11b815290516000926001600160a01b0316916356b54bae916004808301926020929190829003018186803b15801561379e57600080fd5b505afa1580156137b2573d6000803e3d6000fd5b505050506040513d60208110156137c857600080fd5b505190506137d4615708565b50604080518082019091526000808252602082018190528a516138c157826001600160a01b031663e7f6cfe2876040518263ffffffff1660e01b81526004018082815260200191505060006040518083038186803b15801561383557600080fd5b505afa158015613849573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561387257600080fd5b810190808051600160201b81111561388957600080fd5b8201602081018481111561389c57600080fd5b81518560208202830111600160201b821117156138b857600080fd5b50909e50505050505b60005b8b51811015613c195780158061390257508b60018203815181106138e457fe5b60200260200101518c82815181106138f857fe5b6020026020010151115b61390b57600080fd5b6035548c828151811061391a57fe5b60200260200101511061392c57600080fd5b60008781526030602090815260408083206001600160a01b038a16845290915281208d519091908e908490811061395f57fe5b60209081029190910181015182528101919091526040016000205460ff161561398757613c11565b61398f615708565b8a6001600160a01b03168c6001600160a01b031614613b4157856000815181106139b557fe5b60200260200101518d83815181106139c957fe5b602002602001015110156139dd5750613c11565b8c82815181106139e957fe5b6020026020010151866001815181106139fe57fe5b602002602001015111158015613a29575085600181518110613a1c57fe5b6020026020010151600014155b15613a345750613c19565b613a688d8381518110613a4357fe5b602002602001015187600081518110613a5857fe5b6020026020010151858b8f61474d565b92508c8281518110613a7657fe5b602002602001015160010186600081518110613a8e57fe5b602002602001018181525050846001600160a01b031663877ffdea848f8581518110613ab657fe5b60200260200101518b6040518463ffffffff1660e01b8152600401808481526020018381526020018281526020019350505050604080518083038186803b158015613b0057600080fd5b505afa158015613b14573d6000803e3d6000fd5b505050506040513d6040811015613b2a57600080fd5b508051602091820151918301919091528152613bdc565b846001600160a01b0316631289b1798e8481518110613b5c57fe5b60200260200101518a6040518363ffffffff1660e01b81526004018083815260200182815260200192505050604080518083038186803b158015613b9f57600080fd5b505afa158015613bb3573d6000803e3d6000fd5b505050506040513d6040811015613bc957600080fd5b5080516020918201519183019190915281525b80518451613bef9163ffffffff6147bf16565b845260208082015190850151613c0a9163ffffffff6147bf16565b6020850152505b6001016138c4565b50508051602090910151909a909950975050505050505050565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b4390565b605354604080516370a0823160e01b815230600482015290516000926001600160a01b0316916370a08231916024808301926020929190829003018186803b158015613ca757600080fd5b505afa158015613cbb573d6000803e3d6000fd5b505050506040513d6020811015613cd157600080fd5b5051905090565b6000808211613ce657600080fd5b6000828481613cf157fe5b04949350505050565b3a613d0457600080fd5b613d0c611800565b613d1557600080fd5b6039546040805163a26301f960e01b81526001600160a01b0386811660048301529151600093929092169163a26301f991602480820192602092909190829003018186803b158015613d6657600080fd5b505afa158015613d7a573d6000803e3d6000fd5b505050506040513d6020811015613d9057600080fd5b505190506001600160a01b038416613da757600080fd5b80613db157600080fd5b81613dbb57600080fd5b60395460408051632682240f60e11b81526004810184905290516001600160a01b0390921691634d04481e91602480820192602092909190829003018186803b158015613e0757600080fd5b505afa158015613e1b573d6000803e3d6000fd5b505050506040513d6020811015613e3157600080fd5b505115613e3d57600080fd5b613e45613568565b613e4e57600080fd5b6000846001600160a01b0316846001600160a01b03161415613e71576000613e73565b835b60008381526031602090815260408083206001600160a01b038516845290915281205491925090613eaa908563ffffffff6147bf16565b9050856001600160a01b0316856001600160a01b03161415613eda57602454811015613ed557600080fd5b613f0c565b602554811015613ee957600080fd5b6000838152603160209081526040808320838052909152902054613f0c57600080fd5b60008381526031602090815260408083206001600160a01b03861684529091529020819055613f4b84613f3f8585611325565b9063ffffffff6147bf16565b6000848152600a602090815260408083206001600160a01b038716845282528083206035548452825280832093909355858252603890522054613f94908563ffffffff6147bf16565b6000848152603860205260409020556001600160a01b038581169087161415614040576039546040805163738bef1d60e11b815260048101869052905161403b9286926001600160a01b039091169163e717de3a91602480820192602092909190829003018186803b15801561400957600080fd5b505afa15801561401d573d6000803e3d6000fd5b505050506040513d602081101561403357600080fd5b505115614c7f565b614175565b61404a8386614e4a565b6140548386614f07565b6001600160a01b038516600090815260086020908152604080832080546009845282852088865290935290832054909282821015806140a957508684838154811061409b57fe5b906000526020600020015414155b905080156140e8576001600160a01b03891660009081526009602090815260408083208a84528252822085905585546001810187558683529120018790555b8261417057603954604080516341a32dc160e11b81526001600160a01b038c81166004830152915191909216916383465b82916024808301926020929190829003018186803b15801561413a57600080fd5b505afa15801561414e573d6000803e3d6000fd5b505050506040513d602081101561416457600080fd5b50511561417057600080fd5b505050505b61417e8361460b565b603554856001600160a01b0316876001600160a01b03167f1111552b4d689ce73a2a7356e066e28215e6d61a2294e89ac9e02a933ebb0d508787604051808381526020018281526020019250505060405180910390a4505050505050565b6000818152602d60205260408120549054811080156142115750816000828154811061420457fe5b9060005260206000200154145b1561428257600080548190600019810190811061422a57fe5b90600052602060002001549050806000838154811061424557fe5b6000918252602080832090910192909255828152602d9091526040808220849055848252812081905580549061427f906000198301615722565b50505b61428b826152f5565b1561429e5761429982615320565b6142a7565b6142a7826153c6565b6142b0826148c2565b6142b982615449565b6142c1613c58565b603a555050565b3a6142d257600080fd5b6142da611800565b6142e357600080fd5b6039546040805163a26301f960e01b81526001600160a01b0386811660048301529151600093929092169163a26301f991602480820192602092909190829003018186803b15801561433457600080fd5b505afa158015614348573d6000803e3d6000fd5b505050506040513d602081101561435e57600080fd5b505190506001600160a01b03841661437557600080fd5b8161437f57600080fd5b8061438957600080fd5b614393848461219b565b82111561439f57600080fd5b6000846001600160a01b0316846001600160a01b031614156143c25760006143c4565b835b60008381526031602090815260408083206001600160a01b0385168452909152812054919250906143fb908563ffffffff61453a16565b90506000856001600160a01b0316876001600160a01b0316141561443d576000848152600b602052604090205482101561443457600080fd5b50602454614442565b506025545b81158061444f5750808210155b61445857600080fd5b60008481526031602090815260408083206001600160a01b038716845290915281208390556144878585611325565b90508581101561449857600061449c565b8581035b6000868152600a602090815260408083206001600160a01b0389168452825280832060355484528252808320939093558782526038905220546144e5908763ffffffff61453a16565b60008681526038602052604090205582614504576145048589896151a5565b876001600160a01b0316876001600160a01b031614614527576145278588614f07565b6145308561460b565b5050505050505050565b60008282111561454957600080fd5b50900390565b6000818152602e602052604090205460025480821015806145875750826002838154811061457957fe5b906000526020600020015414155b156145fd576000838152602e602052604081208290556002805460018181019092557f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace0185905560048054918201815582527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b01555b61460683615449565b505050565b614613613c58565b603a55600080614622836154ef565b91509150816146325750506117e0565b60006004828154811061464157fe5b90600052602060002001549050600060386000868152602001908152602001600020549050806004848154811061467457fe5b6000918252602090912001558181106146a45760055461469c9083830363ffffffff6147bf16565b6005556146bd565b6005546146b99082840363ffffffff61453a16565b6005555b5050505050565b6000818152602f602052604090205460035480821015806146fc575082600383815481106146ee57fe5b906000526020600020015414155b15614744576000838152602f602052604081208290556003805460018101825591527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b018390555b614606836148c2565b60005b5060008281526026602090815260408083206001600160a01b03851684528252808320888452909152902054801561479b5760001981146147915780614794565b60005b90506147b6565b848614156147aa5750826147b6565b60001990950194614750565b95945050505050565b60008282018381101561177957600080fd5b3a6147db57600080fd5b6147e3611800565b6147ec57600080fd5b6053546001600160a01b031661480157600080fd5b6053546040805163a9059cbb60e01b81526001600160a01b038581166004830152602482018590529151919092169163a9059cbb9160448083019260209291908290030181600087803b15801561485757600080fd5b505af115801561486b573d6000803e3d6000fd5b505050506040513d602081101561488157600080fd5b50516142b957600080fd5b60006148988383614fea565b156148a557506000611353565b6148ad613568565b6148b957506000611353565b50600192915050565b600454600254146148d2576117e0565b6000818152602e602052604090205460025481108015614908575081600282815481106148fb57fe5b9060005260206000200154145b15611414576004818154811061491a57fe5b906000526020600020015460055410614955576004818154811061493a57fe5b6000918252602090912001546005805491909103905561495b565b60006005555b600280546000198101916000918390811061497257fe5b90600052602060002001549050806002848154811061498d57fe5b9060005260206000200181905550600482815481106149a857fe5b9060005260206000200154600484815481106149c057fe5b6000918252602080832090910192909255828152602e909152604080822085905585825281205560028054906149fa906000198301615722565b5060048054906146bd906000198301615722565b60395460405163374dc77d60e01b81526001600160a01b03868116600483019081528882166024840152608060448401908152865160848501528651600095869594169363374dc77d938b938d938b938b939291606482019160a4019060208701908083838f5b83811015614a8d578181015183820152602001614a75565b50505050905090810190601f168015614aba5780820380516001836020036101000a031916815260200191505b50838103825284518152845160209182019186019080838360005b83811015614aed578181015183820152602001614ad5565b50505050905090810190601f168015614b1a5780820380516001836020036101000a031916815260200191505b509650505050505050602060405180830381600087803b158015614b3d57600080fd5b505af1158015614b51573d6000803e3d6000fd5b505050506040513d6020811015614b6757600080fd5b505190508415614b8157614b7c87888a613cfa565b614b8b565b614b8b8789614be1565b856001600160a01b0316876001600160a01b03167f7342ad45e4a4592daa7f7e40b50c1c2ce42aa21da0242065e849a8509de7ba7e836040518082815260200191505060405180910390a3979650505050505050565b33614bed838284613cfa565b3415614bf857600080fd5b6053546001600160a01b0316614c0d57600080fd5b605354604080516356e4bb9760e11b81526001600160a01b038481166004830152602482018690529151919092169163adc9772e91604480830192600092919082900301818387803b158015614c6257600080fd5b505af1158015614c76573d6000803e3d6000fd5b50505050505050565b614c8882612cd7565b614ce35760008054838252602d602052604082208190556001810182559080527f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56301829055614cd561553f565b6000541115614ce357600080fd5b614cec82615320565b8015611414576114148261454f565b6000828152600660209081526040808320602a83528184206001600160a01b038616855290925290912054815481108015614d5e5750826001600160a01b0316828281548110614d4757fe5b6000918252602090912001546001600160a01b0316145b15614e0357815460009083906000198101908110614d7857fe5b9060005260206000200160009054906101000a90046001600160a01b0316905080838381548110614da557fe5b600091825260208083209190910180546001600160a01b0319166001600160a01b03948516179055878252602a8152604080832085851684529091528082208590559186168152908120558254614e00846000198301615722565b50505b60008481526027602090815260408083206001600160a01b038716845290915290205415614e3a57614e358484615545565b614e44565b614e4484846155fb565b50505050565b6000828152600660209081526040808320602a83528184206001600160a01b03861685529092529091205481548082101580614eaf5750836001600160a01b0316838381548110614e9757fe5b6000918252602090912001546001600160a01b031614155b15614efd576000858152602a602090815260408083206001600160a01b0388168085529083529083208490558554600181018755868452919092200180546001600160a01b03191690911790555b6146bd85856155fb565b60355460008381526031602090815260408083206001600160a01b038616845290915290205460019091019080614f4057600019614f42565b805b60008581526026602090815260408083206001600160a01b038816808552908352818420878552835281842094909455878352603282528083209383529290522054614fae5760008481526032602090815260408083206001600160a01b038716845290915290208290555b8015614fbb576000614fbd565b815b60009485526033602090815260408087206001600160a01b03909616875294905292909320919091555050565b6000811561507c57603954604080516352700f5560e11b81526004810186905290516001600160a01b039092169163a4e01eaa91602480820192602092909190829003018186803b15801561503e57600080fd5b505afa158015615052573d6000803e3d6000fd5b505050506040513d602081101561506857600080fd5b50511561507757506001611353565b61519c565b60395460408051632682240f60e11b81526004810186905290516001600160a01b0390921691634d04481e91602480820192602092909190829003018186803b1580156150c857600080fd5b505afa1580156150dc573d6000803e3d6000fd5b505050506040513d60208110156150f257600080fd5b50511561510157506001611353565b603b546001600160a01b03161580159061518f5750603b546040805163cd2ecdf360e01b81526004810186905290516001600160a01b039092169163cd2ecdf391602480820192602092909190829003018186803b15801561516257600080fd5b505afa158015615176573d6000803e3d6000fd5b505050506040513d602081101561518c57600080fd5b50515b1561519c57506001611353565b50600092915050565b816001600160a01b0316816001600160a01b031614156152d4576039546040805163738bef1d60e11b81526004810186905290516001600160a01b039092169163e717de3a91602480820192602092909190829003018186803b15801561520b57600080fd5b505afa15801561521f573d6000803e3d6000fd5b505050506040513d602081101561523557600080fd5b50516152cf5760395460408051639b4a14bf60e01b81526004810186905290516001600160a01b0390921691639b4a14bf91602480820192602092909190829003018186803b15801561528757600080fd5b505afa15801561529b573d6000803e3d6000fd5b505050506040513d60208110156152b157600080fd5b5051156152c6576152c1836146c4565b6152cf565b6152cf836141dc565b614606565b6152de8382614cfb565b6152e7836152f5565b156146065761460683615320565b6000818152603860205260408120541580156113535750506000908152602860205260409020541590565b6000818152602c6020526040902054600154811080156153565750816001828154811061534957fe5b9060005260206000200154145b15611414576001805460009190600019810190811061537157fe5b90600052602060002001549050806001838154811061538c57fe5b6000918252602080832090910192909255828152602c90915260408082208490558482528120556001805490614e44906000198301615722565b6000818152602c602052604090205460015480821015806153fe575082600183815481106153f057fe5b906000526020600020015414155b15614606576000838152602c6020526040812082905560018054808201825591527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf601839055505050565b6000818152602f60205260409020546003548110801561547f5750816003828154811061547257fe5b9060005260206000200154145b15611414576003805460009190600019810190811061549a57fe5b9060005260206000200154905080600383815481106154b557fe5b6000918252602080832090910192909255828152602f90915260408082208490558482528120556003805490614e44906000198301615722565b6000818152602e6020526040812054600254811080156155255750826002828154811061551857fe5b9060005260206000200154145b15615533576001915061553a565b5060009050805b915091565b610bb890565b6000828152600760209081526040808320602b83528184206001600160a01b038616855290925290912054815480821015806155aa5750836001600160a01b031683838154811061559257fe5b6000918252602090912001546001600160a01b031614155b156146bd576000948552602b602090815260408087206001600160a01b039690961680885295825286209190915582546001810184559285529093200180546001600160a01b031916909117905550565b6000828152600760209081526040808320602b83528184206001600160a01b03861685529092529091205481548110801561565e5750826001600160a01b031682828154811061564757fe5b6000918252602090912001546001600160a01b0316145b15614e445781546000908390600019810190811061567857fe5b9060005260206000200160009054906101000a90046001600160a01b03169050808383815481106156a557fe5b600091825260208083209190910180546001600160a01b0319166001600160a01b03948516179055878252602b8152604080832085851684529091528082208590559186168152908120558254615700846000198301615722565b505050505050565b604051806040016040528060008152602001600081525090565b8154818355818111156146065760008381526020902061460691810190830161180f91905b8082111561575b5760008155600101615747565b509056fea265627a7a72305820996d14df4eb718bdfaf51d30633ce9f875a01d08087e1f0c649175bcda695ad364736f6c634300050a0032" + }, + "0x2000000000000000000000000000000000000001": { + "balance": "0x0", + "constructor": "0x60806040526040516108053803806108058339818101604052604081101561002657600080fd5b50805160209182015160408051600081529384018082527f656970313936372e70726f78792e696d706c656d656e746174696f6e00000000905251603c81850301902091929091839190600019016000805160206107aa8339815191521461008a57fe5b61009c826001600160e01b036101bd16565b805115610154576000826001600160a01b0316826040518082805190602001908083835b602083106100df5780518252601f1990920191602091820191016100c0565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855af49150503d806000811461013f576040519150601f19603f3d011682016040523d82523d6000602084013e610144565b606091505b505090508061015257600080fd5b505b5050604080517f656970313936372e70726f78792e61646d696e000000000000000000000000008152905190819003601301902060008051602061078a833981519152600019909101146101a457fe5b6101b6816001600160e01b0361023716565b505061024f565b6101d08161024960201b6104801760201c565b610225576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603b8152602001806107ca603b913960400191505060405180910390fd5b6000805160206107aa83398151915255565b60008051602061078a83398151915255565b3b151590565b61052c8061025e6000396000f3fe60806040526004361061004a5760003560e01c80633659cfe6146100545780634f1ef286146100875780635c60da1b146101075780638f28397014610138578063f851a4401461016b575b610052610180565b005b34801561006057600080fd5b506100526004803603602081101561007757600080fd5b50356001600160a01b031661019a565b6100526004803603604081101561009d57600080fd5b6001600160a01b0382351691908101906040810160208201356401000000008111156100c857600080fd5b8201836020820111156100da57600080fd5b803590602001918460018302840111640100000000831117156100fc57600080fd5b5090925090506101cb565b34801561011357600080fd5b5061011c61026f565b604080516001600160a01b039092168252519081900360200190f35b34801561014457600080fd5b506100526004803603602081101561015b57600080fd5b50356001600160a01b031661027e565b34801561017757600080fd5b5061011c61033c565b610188610198565b610198610193610346565b61036b565b565b6101a261038f565b6001600160a01b0316336001600160a01b0316146101bf57600080fd5b6101c8816103b4565b50565b6101d361038f565b6001600160a01b0316336001600160a01b0316146101f057600080fd5b6101f9836103b4565b6000836001600160a01b031683836040518083838082843760405192019450600093509091505080830381855af49150503d8060008114610256576040519150601f19603f3d011682016040523d82523d6000602084013e61025b565b606091505b505090508061026957600080fd5b50505050565b6000610279610346565b905090565b61028661038f565b6001600160a01b0316336001600160a01b0316146102a357600080fd5b6001600160a01b0381166102e85760405162461bcd60e51b81526004018080602001828103825260368152602001806104876036913960400191505060405180910390fd5b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f61031161038f565b604080516001600160a01b03928316815291841660208301528051918290030190a16101c8816103f4565b600061027961038f565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b3660008037600080366000845af43d6000803e80801561038a573d6000f35b3d6000fd5b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b6103bd81610418565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610355565b61042181610480565b61045c5760405162461bcd60e51b815260040180806020018281038252603b8152602001806104bd603b913960400191505060405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc55565b3b15159056fe43616e6e6f74206368616e6765207468652061646d696e206f6620612070726f787920746f20746865207a65726f206164647265737343616e6e6f742073657420612070726f787920696d706c656d656e746174696f6e20746f2061206e6f6e2d636f6e74726163742061646472657373a265627a7a72305820a9aab4b95b654a79b32f5aa284796894f8329aaa083932695296085b196c27bd64736f6c634300050a0032b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc43616e6e6f742073657420612070726f787920696d706c656d656e746174696f6e20746f2061206e6f6e2d636f6e747261637420616464726573730000000000000000000000002000000000000000000000000000000000000000000000000000000000000000b03a86b3126157c039b55e21d378587ccfc04d45" + }, + "0x2000000000000000000000000000000000000000": { + "balance": "0x0", + "constructor": "0x608060405234801561001057600080fd5b50614620806100206000396000f3fe6080604052600436106102935760003560e01c80636834fc901161015a578063adc481a7116100c1578063dfc8bf4e1161007a578063dfc8bf4e14610d5c578063e706ba2714610d71578063e7f6cfe214610da1578063f8fdc6b914610dcb578063f91c289814610dfb578063faaf3aff14610f5f57610293565b8063adc481a714610c8f578063b25a00fd14610ca4578063b4a523e814610cb9578063c5dd762814610cec578063cc7cab9514610d01578063cdf7a09014610d3257610293565b80638c439867116101135780638c43986714610ad65780639a0a9fdc14610b51578063a4c0ed3614610b66578063a9add57d14610c2c578063aa9fa27414610c41578063ac8a094214610c7a57610293565b80636834fc901461096557806368c49f3d146109e057806370cafd65146109f5578063727b071d14610a345780638737929a14610a64578063877ffdea14610aa057610293565b80633bf47e96116101fe5780634b6368cf116101b75780634b6368cf1461086a5780634de6c0361461087f57806353251389146108ba578063553a5c85146108e45780635fba554e146108f9578063621784781461093b57610293565b80633bf47e96146106c45780633d84b8c1146106ee578063419ce2641461072157806343544960146107365780634476d66a14610805578063485cc9551461082f57610293565b8063212329f311610250578063212329f31461042d578063222fafb2146105375780632ee57f8d14610561578063307bff261461059357806330f6eb1614610662578063392e53cd1461069b57610293565b80630ac2daa014610298578063118d2191146102da5780631289b1791461030f578063128b265f14610358578063171d54dd146103825780631f1a01b7146103fd575b600080fd5b3480156102a457600080fd5b506102c8600480360360408110156102bb57600080fd5b5080359060200135610f74565b60408051918252519081900360200190f35b3480156102e657600080fd5b5061030d600480360360208110156102fd57600080fd5b50356001600160a01b0316610f91565b005b34801561031b57600080fd5b5061033f6004803603604081101561033257600080fd5b5080359060200135610fe9565b6040805192835260208301919091528051918290030190f35b34801561036457600080fd5b5061030d6004803603602081101561037b57600080fd5b5035611073565b34801561038e57600080fd5b5061030d600480360360208110156103a557600080fd5b810190602081018135600160201b8111156103bf57600080fd5b8201836020820111156103d157600080fd5b803590602001918460208302840111600160201b831117156103f257600080fd5b50909250905061107f565b34801561040957600080fd5b506102c86004803603604081101561042057600080fd5b508035906020013561117a565b34801561043957600080fd5b506104e76004803603608081101561045057600080fd5b81359190810190604081016020820135600160201b81111561047157600080fd5b82018360208201111561048357600080fd5b803590602001918460208302840111600160201b831117156104a457600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295505082359350505060200135611197565b60408051602080825283518183015283519192839290830191858101910280838360005b8381101561052357818101518382015260200161050b565b505050509050019250505060405180910390f35b34801561054357600080fd5b5061030d6004803603602081101561055a57600080fd5b5035611269565b34801561056d57600080fd5b506105766112e6565b604080516001600160e01b03199092168252519081900360200190f35b34801561059f57600080fd5b5061033f600480360360a08110156105b657600080fd5b6001600160a01b038235169160208101359160408201359160608101359181019060a081016080820135600160201b8111156105f157600080fd5b82018360208201111561060357600080fd5b803590602001918460208302840111600160201b8311171561062457600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295506112f2945050505050565b34801561066e57600080fd5b506102c86004803603604081101561068557600080fd5b506001600160a01b038135169060200135611318565b3480156106a757600080fd5b506106b0611335565b604080519115158252519081900360200190f35b3480156106d057600080fd5b506102c8600480360360208110156106e757600080fd5b5035611346565b3480156106fa57600080fd5b506102c86004803603602081101561071157600080fd5b50356001600160a01b031661192e565b34801561072d57600080fd5b506104e7611940565b34801561074257600080fd5b5061033f600480360360a081101561075957600080fd5b6001600160a01b038235169160208101359160408201359160608101359181019060a081016080820135600160201b81111561079457600080fd5b8201836020820111156107a657600080fd5b803590602001918460208302840111600160201b831117156107c757600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295506119a2945050505050565b34801561081157600080fd5b506102c86004803603602081101561082857600080fd5b50356119b2565b34801561083b57600080fd5b5061030d6004803603604081101561085257600080fd5b506001600160a01b03813581169160200135166119c4565b34801561087657600080fd5b506102c8611a78565b34801561088b57600080fd5b506104e7600480360360408110156108a257600080fd5b506001600160a01b0381358116916020013516611a83565b3480156108c657600080fd5b5061030d600480360360208110156108dd57600080fd5b5035611ee1565b3480156108f057600080fd5b506102c8611eea565b34801561090557600080fd5b506102c8600480360360a081101561091c57600080fd5b5080359060208101359060408101359060608101359060800135611ef0565b34801561094757600080fd5b5061030d6004803603602081101561095e57600080fd5b5035611f93565b34801561097157600080fd5b5061030d6004803603602081101561098857600080fd5b810190602081018135600160201b8111156109a257600080fd5b8201836020820111156109b457600080fd5b803590602001918460208302840111600160201b831117156109d557600080fd5b50909250905061202a565b3480156109ec57600080fd5b506102c8612121565b348015610a0157600080fd5b5061030d60048036036060811015610a1857600080fd5b50803590602081013590604001356001600160a01b0316612127565b348015610a4057600080fd5b506102c860048036036040811015610a5757600080fd5b50803590602001356122bf565b348015610a7057600080fd5b506102c860048036036080811015610a8757600080fd5b50803590602081013590604081013590606001356122dc565b348015610aac57600080fd5b5061033f60048036036060811015610ac357600080fd5b5080359060208101359060400135612356565b348015610ae257600080fd5b5061030d60048036036020811015610af957600080fd5b810190602081018135600160201b811115610b1357600080fd5b820183602082011115610b2557600080fd5b803590602001918460208302840111600160201b83111715610b4657600080fd5b5090925090506123ea565b348015610b5d57600080fd5b506104e76124e1565b348015610b7257600080fd5b506106b060048036036060811015610b8957600080fd5b6001600160a01b0382351691602081013591810190606081016040820135600160201b811115610bb857600080fd5b820183602082011115610bca57600080fd5b803590602001918460018302840111600160201b83111715610beb57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612541945050505050565b348015610c3857600080fd5b506102c8612548565b348015610c4d57600080fd5b5061030d60048036036040811015610c6457600080fd5b50803590602001356001600160a01b0316612555565b348015610c8657600080fd5b506102c86125e0565b348015610c9b57600080fd5b506102c86125e6565b348015610cb057600080fd5b506104e76125ec565b348015610cc557600080fd5b506102c860048036036020811015610cdc57600080fd5b50356001600160a01b031661264c565b348015610cf857600080fd5b5061030d61265e565b348015610d0d57600080fd5b50610d16612881565b604080516001600160a01b039092168252519081900360200190f35b348015610d3e57600080fd5b506102c860048036036020811015610d5557600080fd5b5035612890565b348015610d6857600080fd5b50610d166128a2565b348015610d7d57600080fd5b506102c860048036036040811015610d9457600080fd5b50803590602001356128b1565b348015610dad57600080fd5b506104e760048036036020811015610dc457600080fd5b50356128ce565b348015610dd757600080fd5b506102c860048036036040811015610dee57600080fd5b508035906020013561292e565b348015610e0757600080fd5b50610ec660048036036040811015610e1e57600080fd5b810190602081018135600160201b811115610e3857600080fd5b820183602082011115610e4a57600080fd5b803590602001918460208302840111600160201b83111715610e6b57600080fd5b919390929091602081019035600160201b811115610e8857600080fd5b820183602082011115610e9a57600080fd5b803590602001918460208302840111600160201b83111715610ebb57600080fd5b509092509050612949565b604051808060200180602001838103835285818151815260200191508051906020019060200280838360005b83811015610f0a578181015183820152602001610ef2565b50505050905001838103825284818151815260200191508051906020019060200280838360005b83811015610f49578181015183820152602001610f31565b5050505090500194505050505060405180910390f35b348015610f6b57600080fd5b506102c8613211565b602960209081526000928352604080842090915290825290205481565b610f99613217565b6001600160a01b0316336001600160a01b031614610fb657600080fd5b610fbe611335565b610fc757600080fd5b604d80546001600160a01b0319166001600160a01b0392909216919091179055565b6000828152602a6020908152604080832084845282528083205485845260298352818420858552835281842054868552604b84528285208686529093529083205483929061103c908790849084906122dc565b6000878152602260209081526040808320898452909152902054909450611068908790849084906122dc565b925050509250929050565b61107c81611f93565b50565b611087613217565b6001600160a01b0316336001600160a01b0316146110a457600080fd5b6110ac611335565b6110b557600080fd5b60005b60025481101561111157600060016000600284815481106110d557fe5b6000918252602080832091909101546001600160a01b031683528201929092526040019020805460ff19169115159190911790556001016110b8565b61111d60028484614526565b50600090505b8181101561117557600180600085858581811061113c57fe5b602090810292909201356001600160a01b0316835250810191909152604001600020805460ff1916911515919091179055600101611123565b505050565b602260209081526000928352604080842090915290825290205481565b606080836111bf576040805160008152602081019091526111b990849061323c565b90955093505b8515806111ca575083155b156111e4575060408051600081526020810190915261125e565b845160405190808252806020026020018201604052801561120f578160200160208202803883390190505b50905060005b855181101561125c578486828151811061122b57fe5b602002602001015188028161123c57fe5b0482828151811061124957fe5b6020908102919091010152600101611215565b505b90505b949350505050565b3360009081526001602052604090205460ff1661128557600080fd5b8061128f57600080fd5b6021546112a2908263ffffffff6134a316565b6021819055604080518381526020810192909252805133927f619cc90cbd264bea3dfc113e68fd307789a937a8c10ef4b0110607ac7490367392908290030190a250565b63069ad3e560e11b5b90565b60008061130a61130287856134bc565b8887876134d7565b915091509550959350505050565b602460209081526000928352604080842090915290825290205481565b602c546001600160a01b0316151590565b600080602c60009054906101000a90046001600160a01b03166001600160a01b031663ee99205c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561139757600080fd5b505afa1580156113ab573d6000803e3d6000fd5b505050506040513d60208110156113c157600080fd5b505160408051630f29818d60e31b815290519192506000916001600160a01b0384169163794c0c68916004808301926020929190829003018186803b15801561140957600080fd5b505afa15801561141d573d6000803e3d6000fd5b505050506040513d602081101561143357600080fd5b505190508061144757600092505050611929565b602c5460408051639b4a14bf60e01b81526004810187905290516001600160a01b0390921691639b4a14bf91602480820192602092909190829003018186803b15801561149357600080fd5b505afa1580156114a7573d6000803e3d6000fd5b505050506040513d60208110156114bd57600080fd5b50511561150a576000818152602a602090815260408083208784528252808320548484526029835281842088855290925290912054611501918391620f42406122dc565b92505050611929565b602c60009054906101000a90046001600160a01b03166001600160a01b031663b927ef436040518163ffffffff1660e01b815260040160206040518083038186803b15801561155857600080fd5b505afa15801561156c573d6000803e3d6000fd5b505050506040513d602081101561158257600080fd5b50516118285760606000602c60009054906101000a90046001600160a01b03166001600160a01b0316636729c2dc6040518163ffffffff1660e01b815260040160006040518083038186803b1580156115da57600080fd5b505afa1580156115ee573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561161757600080fd5b810190808051600160201b81111561162e57600080fd5b8201602081018481111561164157600080fd5b81518560208202830111600160201b8211171561165d57600080fd5b5090955060009450505050505b81518110156116de5781818151811061167f57fe5b60200260200101518614156116d6576000838152602a60209081526040808320898452825280832054868452602983528184208a8552909252909120546116cb918591620f42406122dc565b945050505050611929565b60010161166a565b602c60009054906101000a90046001600160a01b03166001600160a01b0316630bf480c06040518163ffffffff1660e01b815260040160006040518083038186803b15801561172c57600080fd5b505afa158015611740573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561176957600080fd5b810190808051600160201b81111561178057600080fd5b8201602081018481111561179357600080fd5b81518560208202830111600160201b821117156117af57600080fd5b5090955060009450505050505b8151811015611825578181815181106117d157fe5b602002602001015186141561181d576000838152602a60209081526040808320898452825280832054868452602983528184208a8552909252909120546116cb918591620f42406122dc565b6001016117bc565b50505b60408051630fec687960e21b8152600481018690526000602482015290516119249183916001600160a01b03861691633fb1a1e4916044808301926020929190829003018186803b15801561187c57600080fd5b505afa158015611890573d6000803e3d6000fd5b505050506040513d60208110156118a657600080fd5b505160408051632a8f6ecd60e01b81526004810189905290516001600160a01b03871691632a8f6ecd916024808301926020929190829003018186803b1580156118ef57600080fd5b505afa158015611903573d6000803e3d6000fd5b505050506040513d602081101561191957600080fd5b5051620f42406122dc565b925050505b919050565b60236020526000908152604090205481565b6060600280548060200260200160405190810160405280929190818152602001828054801561199857602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161197a575b5050505050905090565b60008061130a6113028785613578565b60256020526000908152604090205481565b6119cc61359b565b15806119f057506119db613217565b6001600160a01b0316336001600160a01b0316145b6119f957600080fd5b611a01611335565b15611a0b57600080fd5b6001600160a01b038216611a1e57600080fd5b602c80546001600160a01b039384166001600160a01b0319918216179091556000808052602b6020527fe18c65fb8491ea105d3652ed62258476aaccd771ae89682addbba12f33acc62a5560038054929093169116179055565b660b1a2bc2ec500081565b602c546040805163a26301f960e01b81526001600160a01b0385811660048301529151606093600093169163a26301f9916024808301926020929190829003018186803b158015611ad357600080fd5b505afa158015611ae7573d6000803e3d6000fd5b505050506040513d6020811015611afd57600080fd5b505190506001600160a01b038416611b1457600080fd5b6001600160a01b038316611b2757600080fd5b80611b3157600080fd5b602c5460408051633ba6481760e21b815290516000926001600160a01b03169163ee99205c916004808301926020929190829003018186803b158015611b7657600080fd5b505afa158015611b8a573d6000803e3d6000fd5b505050506040513d6020811015611ba057600080fd5b5051905060006001600160a01b038581169087161415611bc1576000611bc3565b845b90506000806001600160a01b03831615611d1157836001600160a01b03166327d89b3a86856040518363ffffffff1660e01b815260040180838152602001826001600160a01b03166001600160a01b031681526020019250505060206040518083038186803b158015611c3557600080fd5b505afa158015611c49573d6000803e3d6000fd5b505050506040513d6020811015611c5f57600080fd5b5051915081611c845750506040805160008152602081019091529350611edb92505050565b836001600160a01b031663381883b086856040518363ffffffff1660e01b815260040180838152602001826001600160a01b03166001600160a01b031681526020019250505060206040518083038186803b158015611ce257600080fd5b505afa158015611cf6573d6000803e3d6000fd5b505050506040513d6020811015611d0c57600080fd5b505190505b600085815260208181526040918290208054835181815281840281019093019093529190606090828015611d4f578160200160208202803883390190505b5090506000805b83811015611e63576000858281548110611d6c57fe5b60009182526020909120015490506001600160a01b03891615611db15787811015611d975750611e5b565b808711158015611da657508615155b15611db15750611e63565b6040805163186dc46f60e01b8152600481018d90526001600160a01b038b81166024830152604482018490529151918c169163186dc46f91606480820192602092909190829003018186803b158015611e0957600080fd5b505afa158015611e1d573d6000803e3d6000fd5b505050506040513d6020811015611e3357600080fd5b5051611e595780848480600101955081518110611e4c57fe5b6020026020010181815250505b505b600101611d56565b81604051908082528060200260200182016040528015611e8d578160200160208202803883390190505b509a50600090505b81811015611ed057828181518110611ea957fe5b60200260200101518b8281518110611ebd57fe5b6020908102919091010152600101611e95565b505050505050505050505b92915050565b61107c81611269565b60265481565b6000841580611efd575083155b80611f06575082155b15611f1357506000611f8a565b60008085851015611f25576000611f29565b8585035b905080611f3b57600092505050611f8a565b6000888152602b6020526040902054818102606482900388021115611f6d578588860281611f6557fe5b049250611f84565b81606402816064038987020281611f8057fe5b0492505b50909150505b95945050505050565b3360009081526046602052604090205460ff1680611fc057503360009081526047602052604090205460ff165b611fc957600080fd5b80611fd357600080fd5b604a54611fe6908263ffffffff6134a316565b604a819055604080518381526020810192909252805133927f412edf02d82089ccd9d6158ca78bb761a19c8f63a840cff791e4ad472bcaa0ac92908290030190a250565b612032613217565b6001600160a01b0316336001600160a01b03161461204f57600080fd5b612057611335565b61206057600080fd5b60005b6049548110156120bc576000604760006049848154811061208057fe5b6000918252602080832091909101546001600160a01b031683528201929092526040019020805460ff1916911515919091179055600101612063565b6120c860498484614526565b50600090505b81811015611175576001604760008585858181106120e857fe5b602090810292909201356001600160a01b0316835250810191909152604001600020805460ff19169115159190911790556001016120ce565b604c5481565b602c60009054906101000a90046001600160a01b03166001600160a01b031663ee99205c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561217557600080fd5b505afa158015612189573d6000803e3d6000fd5b505050506040513d602081101561219f57600080fd5b50516001600160a01b031633146121b557600080fd5b82156122b55760003390506000816001600160a01b0316632d21d2176040518163ffffffff1660e01b815260040160206040518083038186803b1580156121fb57600080fd5b505afa15801561220f573d6000803e3d6000fd5b505050506040513d602081101561222557600080fd5b50516040805163a9059cbb60e01b81526001600160a01b0386811660048301526024820189905291519293509083169163a9059cbb916044808201926020929091908290030181600087803b15801561227d57600080fd5b505af1158015612291573d6000803e3d6000fd5b505050506040513d60208110156122a757600080fd5b50516122b257600080fd5b50505b611175828261359f565b602a60209081526000928352604080842090915290825290205481565b60008315806122e9575082155b156122f657506000611261565b6000808585101561230857600061230c565b8585035b6000888152602b602052604090205490915080820260648290038802111561234157858786028161233957fe5b04925061234a565b60648582020492505b50909695505050505050565b6000828152602a6020908152604080832084845282528083205485845260298352818420858552835281842054868552604b8452828520868652909352908320548392906123ab908790899085908590611ef0565b93506123de86888484602260008c815260200190815260200160002060008b815260200190815260200160002054611ef0565b92505050935093915050565b6123f2613217565b6001600160a01b0316336001600160a01b03161461240f57600080fd5b612417611335565b61242057600080fd5b60005b60485481101561247c576000604660006048848154811061244057fe5b6000918252602080832091909101546001600160a01b031683528201929092526040019020805460ff1916911515919091179055600101612423565b61248860488484614526565b50600090505b81811015611175576001604660008585858181106124a857fe5b602090810292909201356001600160a01b0316835250810191909152604001600020805460ff191691151591909117905560010161248e565b60606048805480602002602001604051908101604052809291908181526020018280548015611998576020028201919060005260206000209081546001600160a01b0316815260019091019060200180831161197a575050505050905090565b6000806000fd5b6004546005540360010190565b3360009081526001602052604090205460ff1661257157600080fd5b8161257b57600080fd5b600354600160a01b900460ff1661259157600080fd5b61259c828233613617565b60408051838152905133916001600160a01b038416917f3c798bbcf33115b42c728b8504cff11dd58736e9fa789f1cda2738db7d696b2a9181900360200190a35050565b60215481565b60285481565b60606049805480602002602001604051908101604052809291908181526020018280548015611998576020028201919060005260206000209081546001600160a01b0316815260019091019060200180831161197a575050505050905090565b60276020526000908152604090205481565b602c546001600160a01b0316331461267557600080fd5b602c5460408051633ba6481760e21b815290516000926001600160a01b03169163ee99205c916004808301926020929190829003018186803b1580156126ba57600080fd5b505afa1580156126ce573d6000803e3d6000fd5b505050506040513d60208110156126e457600080fd5b505160408051630f29818d60e31b815290519192506000916001600160a01b0384169163794c0c68916004808301926020929190829003018186803b15801561272c57600080fd5b505afa158015612740573d6000803e3d6000fd5b505050506040513d602081101561275657600080fd5b5051602c5460408051637f2a23bf60e11b815290519293506060926001600160a01b039092169163fe54477e91600480820192600092909190829003018186803b1580156127a357600080fd5b505afa1580156127b7573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405260208110156127e057600080fd5b810190808051600160201b8111156127f757600080fd5b8201602081018481111561280a57600080fd5b81518560208202830111600160201b8211171561282657600080fd5b50909450600093505050505b815181101561287b57600083815260208052604081208351829085908590811061285857fe5b602090810291909101810151825281019190915260400160002055600101612832565b50505050565b604d546001600160a01b031681565b602b6020526000908152604090205481565b602c546001600160a01b031681565b604b60209081526000928352604080842090915290825290205481565b6000818152602081815260409182902080548351818402810184019094528084526060939283018282801561292257602002820191906000526020600020905b81548152602001906001019080831161290e575b50505050509050919050565b60208080526000928352604080842090915290825290205481565b6060806002600160a01b03331461295f57600080fd5b848314158061296f575060018514155b8061299657508383600081811061298257fe5b9050602002013561ffff1661ffff16600014155b156129c75760408051600080825260208201909252905b506040805160008152602081019091529092509050613208565b602c546001600160a01b03166129ed5760408051600080825260208201909252906129ad565b602c60009054906101000a90046001600160a01b03166001600160a01b031663ccf69e9b6040518163ffffffff1660e01b815260040160206040518083038186803b158015612a3b57600080fd5b505afa158015612a4f573d6000803e3d6000fd5b505050506040513d6020811015612a6557600080fd5b50516040805163109c110760e01b815290516001600160a01b039092169163109c11079160048082019260009290919082900301818387803b158015612aaa57600080fd5b505af1158015612abe573d6000803e3d6000fd5b5050600354600160a01b900460ff169150612afa905057600160045560006005556003805460ff60a01b1916600160a01b179055612afa61368c565b602c5460408051633ba6481760e21b815290516064926000926001600160a01b039091169163ee99205c91600480820192602092909190829003018186803b158015612b4557600080fd5b505afa158015612b59573d6000803e3d6000fd5b505050506040513d6020811015612b6f57600080fd5b505160408051630f29818d60e31b815290519192506000916001600160a01b0384169163794c0c68916004808301926020929190829003018186803b158015612bb757600080fd5b505afa158015612bcb573d6000803e3d6000fd5b505050506040513d6020811015612be157600080fd5b50516040805163461121d760e11b815290519192506000916001600160a01b03851691638c2243ae916004808301926020929190829003018186803b158015612c2957600080fd5b505afa158015612c3d573d6000803e3d6000fd5b505050506040513d6020811015612c5357600080fd5b5051602c546040805163b927ef4360e01b815290519293506000926001600160a01b039092169163b927ef4391600480820192602092909190829003018186803b158015612ca057600080fd5b505afa158015612cb4573d6000803e3d6000fd5b505050506040513d6020811015612cca57600080fd5b505115612e3f578215801590612d7b5750602c546001600160a01b031663a92252ae8c8c600081612cf757fe5b905060200201356001600160a01b03166040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b158015612d4d57600080fd5b505afa158015612d61573d6000803e3d6000fd5b505050506040513d6020811015612d7757600080fd5b5051155b15612e3f57602c546000906001600160a01b0316632bbb7b728d8d8481612d9e57fe5b905060200201356001600160a01b03166040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b158015612df457600080fd5b505afa158015612e08573d6000803e3d6000fd5b505050506040513d6020811015612e1e57600080fd5b50516000858152602080805260408083209383529290522080546001019055505b81612e4861359b565b14156131f4578215612e6257612e5f8484846137ee565b90505b602c60009054906101000a90046001600160a01b03166001600160a01b0316635ccee1de6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015612eb257600080fd5b505af1158015612ec6573d6000803e3d6000fd5b5050602c54604080516319ca70b760e21b81529051600094506001880193506060926001600160a01b031691636729c2dc9160048083019288929190829003018186803b158015612f1657600080fd5b505afa158015612f2a573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526020811015612f5357600080fd5b810190808051600160201b811115612f6a57600080fd5b82016020810184811115612f7d57600080fd5b81518560208202830111600160201b82111715612f9957600080fd5b5060009750909450505050505b8051831015612fd857612fcd8783838681518110612fc057fe5b602002602001015161391c565b600190920191612fa6565b602c60009054906101000a90046001600160a01b03166001600160a01b031663fe54477e6040518163ffffffff1660e01b815260040160006040518083038186803b15801561302657600080fd5b505afa15801561303a573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561306357600080fd5b810190808051600160201b81111561307a57600080fd5b8201602081018481111561308d57600080fd5b81518560208202830111600160201b821117156130a957600080fd5b5060009750909450505050505b80518310156130db576130d08783838681518110612fc057fe5b6001909201916130b6565b602c60009054906101000a90046001600160a01b03166001600160a01b0316630bf480c06040518163ffffffff1660e01b815260040160006040518083038186803b15801561312957600080fd5b505afa15801561313d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561316657600080fd5b810190808051600160201b81111561317d57600080fd5b8201602081018481111561319057600080fd5b81518560208202830111600160201b821117156131ac57600080fd5b5060009750909450505050505b80518310156131de576131d38783838681518110612fc057fe5b6001909201916131b9565b506000908152602b602052604081208190559550505b6131fe8186613a70565b9650965050505050505b94509492505050565b604a5481565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b6060600082516000141561332457602c60009054906101000a90046001600160a01b03166001600160a01b031663fe54477e6040518163ffffffff1660e01b815260040160006040518083038186803b15801561329857600080fd5b505afa1580156132ac573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405260208110156132d557600080fd5b810190808051600160201b8111156132ec57600080fd5b820160208101848111156132ff57600080fd5b81518560208202830111600160201b8211171561331b57600080fd5b50909650505050505b60608351604051908082528060200260200182016040528015613351578160200160208202803883390190505b5090506000805b855181101561349757600086828151811061336f57fe5b60209081029190910181015160008a8152602a8352604080822083835290935291909120549091501580159061341a5750602c5460408051632682240f60e11b81526004810184905290516001600160a01b0390921691634d04481e91602480820192602092909190829003018186803b1580156133ec57600080fd5b505afa158015613400573d6000803e3d6000fd5b505050506040513d602081101561341657600080fd5b5051155b1561345657600088815260208080526040808320848452909152902054845185908490811061344557fe5b602002602001018181525050613471565b600084838151811061346457fe5b6020026020010181815250505b83828151811061347d57fe5b602002602001015183019250508080600101915050613358565b50909590945092505050565b6000828201838110156134b557600080fd5b9392505050565b60006134c88383613c87565b60285460215401019392505050565b600080826135535761354d85866001600160a01b0316638c2243ae6040518163ffffffff1660e01b815260040160206040518083038186803b15801561351c57600080fd5b505afa158015613530573d6000803e3d6000fd5b505050506040513d602081101561354657600080fd5b5051613c8f565b90945092505b60008361356157600061356e565b838588028161356c57fe5b045b9795505050505050565b600061358c8383660b1a2bc2ec5000613e27565b604c54604a5401019392505050565b4390565b81158015906135d057506040516001600160a01b0382169083156108fc029084906000818181858888f19350505050155b156136135781816040516135e390614589565b6001600160a01b039091168152604051908190036020019082f08015801561360f573d6000803e3d6000fd5b5050505b5050565b60058054604080516060810182529586526001600160a01b03938416602080880191825295851687830190815260019384016000818152600690985292909620965187555191860180549285166001600160a01b03199384161790559351600290950180549590931694169390931790559055565b6003546001600160a01b03166136a1576137ec565b60005b600254811015613765576000600282815481106136bd57fe5b6000918252602091829020015460035460408051631694a47d60e31b81526001600160a01b03938416600482018190529151919550919092169263b4a523e892602480840193829003018186803b15801561371757600080fd5b505afa15801561372b573d6000803e3d6000fd5b505050506040513d602081101561374157600080fd5b50516001600160a01b039091166000908152602760205260409020556001016136a4565b50600254156137ec57600360009054906101000a90046001600160a01b03166001600160a01b031663553a5c856040518163ffffffff1660e01b815260040160206040518083038186803b1580156137bc57600080fd5b505afa1580156137d0573d6000803e3d6000fd5b505050506040513d60208110156137e657600080fd5b50516026555b565b60006060602c60009054906101000a90046001600160a01b03166001600160a01b031663fe54477e6040518163ffffffff1660e01b815260040160006040518083038186803b15801561384057600080fd5b505afa158015613854573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561387d57600080fd5b810190808051600160201b81111561389457600080fd5b820160208101848111156138a757600080fd5b81518560208202830111600160201b821117156138c357600080fd5b505092919050505090506000806138da8786613c8f565b91509150606060006138ec888661323c565b915091506138ff89898686898787613f83565b95506139108989868689878761409a565b50505050509392505050565b60008281526029602090815260408083208484529091529020541561394057611175565b6000836001600160a01b0316632a8f6ecd836040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561398657600080fd5b505afa15801561399a573d6000803e3d6000fd5b505050506040513d60208110156139b057600080fd5b50519050806139bf5750611175565b600083815260296020908152604080832085845282528083208490558051630fec687960e21b8152600481018690526024810193909352516001600160a01b03871692633fb1a1e4926044808301939192829003018186803b158015613a2457600080fd5b505afa158015613a38573d6000803e3d6000fd5b505050506040513d6020811015613a4e57600080fd5b50516000848152602a6020908152604080832086845290915290205550505050565b6060806000613a7d612548565b905083811115613a8a5750825b84151580613a99576000613a9c565b60015b60ff168201604051908082528060200260200182016040528015613aca578160200160208202803883390190505b5093508351604051908082528060200260200182016040528015613af8578160200160208202803883390190505b50925060005b82811015613b75576000806000613b13614437565b92509250925081888581518110613b2657fe5b60200260200101906001600160a01b031690816001600160a01b03168152505082878581518110613b5357fe5b602002602001018181525050613b6a8383836144b8565b505050600101613afe565b508015613bc35730848381518110613b8957fe5b60200260200101906001600160a01b031690816001600160a01b03168152505085838381518110613bb657fe5b6020026020010181815250505b7f2834f3daea15e82b5f27095c4b6d08cd437f303149009a0a3304be801d2dd7ce8484604051808060200180602001838103835285818151815260200191508051906020019060200280838360005b83811015613c2a578181015183820152602001613c12565b50505050905001838103825284818151815260200191508051906020019060200280838360005b83811015613c69578181015183820152602001613c51565b5050505090500194505050505060405180910390a150509250929050565b600092915050565b602c546040805163b927ef4360e01b815290516000928392839260019284926001600160a01b039091169163b927ef4391600480820192602092909190829003018186803b158015613ce057600080fd5b505afa158015613cf4573d6000803e3d6000fd5b505050506040513d6020811015613d0a57600080fd5b5051905080156134975760006003602c60009054906101000a90046001600160a01b03166001600160a01b031663714897df6040518163ffffffff1660e01b815260040160206040518083038186803b158015613d6657600080fd5b505afa158015613d7a573d6000803e3d6000fd5b505050506040513d6020811015613d9057600080fd5b505160020281613d9c57fe5b04886001600160a01b0316637069e7466040518163ffffffff1660e01b815260040160206040518083038186803b158015613dd657600080fd5b505afa158015613dea573d6000803e3d6000fd5b505050506040513d6020811015613e0057600080fd5b505101600101905080821015613e14578091505b6001918703820198960301955050505050565b600081613e36575060006134b5565b8251613f1657602c60009054906101000a90046001600160a01b03166001600160a01b031663fe54477e6040518163ffffffff1660e01b815260040160006040518083038186803b158015613e8a57600080fd5b505afa158015613e9e573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526020811015613ec757600080fd5b810190808051600160201b811115613ede57600080fd5b82016020810184811115613ef157600080fd5b81518560208202830111600160201b82111715613f0d57600080fd5b50909650505050505b6000805b8451811015613f6c57602960008781526020019081526020016000206000868381518110613f4457fe5b6020026020010151815260200190815260200160002054820191508080600101915050613f1a565b50670de0b6b3a76400009083020490509392505050565b6000806000613f958a8a8a8a8a6112f2565b915091508060001415613fad5760009250505061408f565b600060218190556060613fc28488888e611197565b90508751815114156140835760005b8851811015614081576000898281518110613fe857fe5b60200260200101519050828281518110613ffe57fe5b60209081029190910181015160008f81526022835260408082208583529093529190912055825183908390811061403157fe5b60200260200101518401935082828151811061404957fe5b602002602001015160001461407857600081815260208181526040822080546001810182559083529120018d90555b50600101613fd1565b505b50908190036028559150505b979650505050505050565b6000806140aa89898989896119a2565b9150915080600014156140be57505061442e565b6000604a819055506000896001600160a01b0316632d21d2176040518163ffffffff1660e01b815260040160206040518083038186803b15801561410157600080fd5b505afa158015614115573d6000803e3d6000fd5b505050506040513d602081101561412b57600080fd5b5051604d549091506000906001600160a01b03161580159061415557506001600160a01b03821615155b156141f757604d5460408051638da5cb5b60e01b815290516001600160a01b0392831692851691638da5cb5b916004808301926020929190829003018186803b1580156141a157600080fd5b505afa1580156141b5573d6000803e3d6000fd5b505050506040513d60208110156141cb57600080fd5b50516001600160a01b031614156141ee5750604d546001600160a01b03166141f2565b5060005b6141fa565b50805b60006001600160a01b038216158015906142895750306001600160a01b0316826001600160a01b03166356b54bae6040518163ffffffff1660e01b815260040160206040518083038186803b15801561425257600080fd5b505afa158015614266573d6000803e3d6000fd5b505050506040513d602081101561427c57600080fd5b50516001600160a01b0316145b1561442457606061429c8689898f611197565b90508851815114156144225760005b89518110156143c2578181815181106142c057fe5b6020026020010151604b60008f815260200190815260200160002060008c84815181106142e957fe5b602002602001015181526020019081526020016000208190555081818151811061430f57fe5b60200260200101518301925081818151811061432757fe5b60200260200101516000141580156143765750602260008e815260200190815260200160002060008b838151811061435b57fe5b60200260200101518152602001908152602001600020546000145b156143ba576000808b838151811061438a57fe5b60209081029190910181015182528181019290925260400160009081208054600181018255908252919020018d90555b6001016142ab565b50826001600160a01b03166391c0aabf836040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b15801561440957600080fd5b505af115801561441d573d6000803e3d6000fd5b505050505b505b909203604c555050505b50505050505050565b60045460055460009182918291908181101561445e576000945060009350600092506144b1565b6000828152600660205260408120805460028201805460018085018054969095556001600160a01b03198087169095559381169091556004805490930190925596506001600160a01b0390811695501692505b5050909192565b60006144c261359b565b6001600160a01b03938416600081815260246020908152604080832085845282528083208990559282526023815282822080548901905592815260258352818120805488019055939094168352602790525020805482019055602680549091019055565b828054828255906000526020600020908101928215614579579160200282015b828111156145795781546001600160a01b0319166001600160a01b03843516178255602090920191600190910190614546565b50614585929150614595565b5090565b6032806145ba83390190565b6112ef91905b808211156145855780546001600160a01b031916815560010161459b56fe60806040526040516032380380603283398181016040526020811015602357600080fd5b50516001600160a01b038116fffea265627a7a7230582062631356e570e39d323d66f88466882635eb13d9b0b483126bb5ca9245d1dedf64736f6c634300050a0032" + }, + "0x3000000000000000000000000000000000000001": { + "balance": "0x0", + "constructor": "0x60806040526040516108053803806108058339818101604052604081101561002657600080fd5b50805160209182015160408051600081529384018082527f656970313936372e70726f78792e696d706c656d656e746174696f6e00000000905251603c81850301902091929091839190600019016000805160206107aa8339815191521461008a57fe5b61009c826001600160e01b036101bd16565b805115610154576000826001600160a01b0316826040518082805190602001908083835b602083106100df5780518252601f1990920191602091820191016100c0565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855af49150503d806000811461013f576040519150601f19603f3d011682016040523d82523d6000602084013e610144565b606091505b505090508061015257600080fd5b505b5050604080517f656970313936372e70726f78792e61646d696e000000000000000000000000008152905190819003601301902060008051602061078a833981519152600019909101146101a457fe5b6101b6816001600160e01b0361023716565b505061024f565b6101d08161024960201b6104801760201c565b610225576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603b8152602001806107ca603b913960400191505060405180910390fd5b6000805160206107aa83398151915255565b60008051602061078a83398151915255565b3b151590565b61052c8061025e6000396000f3fe60806040526004361061004a5760003560e01c80633659cfe6146100545780634f1ef286146100875780635c60da1b146101075780638f28397014610138578063f851a4401461016b575b610052610180565b005b34801561006057600080fd5b506100526004803603602081101561007757600080fd5b50356001600160a01b031661019a565b6100526004803603604081101561009d57600080fd5b6001600160a01b0382351691908101906040810160208201356401000000008111156100c857600080fd5b8201836020820111156100da57600080fd5b803590602001918460018302840111640100000000831117156100fc57600080fd5b5090925090506101cb565b34801561011357600080fd5b5061011c61026f565b604080516001600160a01b039092168252519081900360200190f35b34801561014457600080fd5b506100526004803603602081101561015b57600080fd5b50356001600160a01b031661027e565b34801561017757600080fd5b5061011c61033c565b610188610198565b610198610193610346565b61036b565b565b6101a261038f565b6001600160a01b0316336001600160a01b0316146101bf57600080fd5b6101c8816103b4565b50565b6101d361038f565b6001600160a01b0316336001600160a01b0316146101f057600080fd5b6101f9836103b4565b6000836001600160a01b031683836040518083838082843760405192019450600093509091505080830381855af49150503d8060008114610256576040519150601f19603f3d011682016040523d82523d6000602084013e61025b565b606091505b505090508061026957600080fd5b50505050565b6000610279610346565b905090565b61028661038f565b6001600160a01b0316336001600160a01b0316146102a357600080fd5b6001600160a01b0381166102e85760405162461bcd60e51b81526004018080602001828103825260368152602001806104876036913960400191505060405180910390fd5b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f61031161038f565b604080516001600160a01b03928316815291841660208301528051918290030190a16101c8816103f4565b600061027961038f565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b3660008037600080366000845af43d6000803e80801561038a573d6000f35b3d6000fd5b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b6103bd81610418565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610355565b61042181610480565b61045c5760405162461bcd60e51b815260040180806020018281038252603b8152602001806104bd603b913960400191505060405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc55565b3b15159056fe43616e6e6f74206368616e6765207468652061646d696e206f6620612070726f787920746f20746865207a65726f206164647265737343616e6e6f742073657420612070726f787920696d706c656d656e746174696f6e20746f2061206e6f6e2d636f6e74726163742061646472657373a265627a7a72305820a9aab4b95b654a79b32f5aa284796894f8329aaa083932695296085b196c27bd64736f6c634300050a0032b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc43616e6e6f742073657420612070726f787920696d706c656d656e746174696f6e20746f2061206e6f6e2d636f6e747261637420616464726573730000000000000000000000003000000000000000000000000000000000000000000000000000000000000000b03a86b3126157c039b55e21d378587ccfc04d45" + }, + "0x3000000000000000000000000000000000000000": { + "balance": "0x0", + "constructor": "0x608060405234801561001057600080fd5b50611f2a806100206000396000f3fe6080604052600436106101c25760003560e01c80637a3e286b116100f7578063c64c206411610095578063f2f56ffe11610064578063f2f56ffe146106df578063f58ccc6a14610718578063fd6c1d15146105ad578063fe7d567d14610583576101c2565b8063c64c206414610634578063cc93dab414610649578063de109e2014610675578063dfc8bf4e146106ae576101c2565b806398df67c6116100d157806398df67c614610583578063b6b295ae146105ad578063baf11cab146105e6578063c358ced01461061f576101c2565b80637a3e286b1461054457806383209c3f14610559578063832206261461056e576101c2565b80633afa443c1161016457806363f160e61161013e57806363f160e614610429578063695e89f61461046257806374ce90671461051a57806378ab865d1461052f576101c2565b80633afa443c146103c657806343e7aa1d146103db5780635aca47f6146103f0576101c2565b8063109c1107116101a0578063109c1107146103205780631c77c58c1461033557806328804dbd1461035c578063392e53cd1461039d576101c2565b8063096a113d146101c45780630b402823146102725780630b61ba851461029c575b005b3480156101d057600080fd5b506101fd600480360360408110156101e757600080fd5b50803590602001356001600160a01b031661072d565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561023757818101518382015260200161021f565b50505050905090810190601f1680156102645780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561027e57600080fd5b506101c26004803603602081101561029557600080fd5b5035610853565b3480156102a857600080fd5b506101c2600480360360408110156102bf57600080fd5b813591908101906040810160208201356401000000008111156102e157600080fd5b8201836020820111156102f357600080fd5b8035906020019184600183028401116401000000008311171561031557600080fd5b5090925090506108d2565b34801561032c57600080fd5b506101c2610a08565b34801561034157600080fd5b5061034a6111f7565b60408051918252519081900360200190f35b34801561036857600080fd5b506101c26004803603606081101561037f57600080fd5b508035906001600160a01b03602082013516906040013515156111fd565b3480156103a957600080fd5b506103b2611418565b604080519115158252519081900360200190f35b3480156103d257600080fd5b506103b261142a565b3480156103e757600080fd5b5061034a611433565b3480156103fc57600080fd5b5061034a6004803603604081101561041357600080fd5b50803590602001356001600160a01b0316611447565b34801561043557600080fd5b506103b26004803603604081101561044c57600080fd5b50803590602001356001600160a01b03166114e4565b34801561046e57600080fd5b5061049b6004803603604081101561048557600080fd5b50803590602001356001600160a01b0316611584565b6040518083815260200180602001828103825283818151815260200191508051906020019080838360005b838110156104de5781810151838201526020016104c6565b50505050905090810190601f16801561050b5780820380516001836020036101000a031916815260200191505b50935050505060405180910390f35b34801561052657600080fd5b506103b26116c8565b34801561053b57600080fd5b5061034a6116ee565b34801561055057600080fd5b5061034a6116fd565b34801561056557600080fd5b5061034a611714565b34801561057a57600080fd5b5061034a611742565b34801561058f57600080fd5b506101c2600480360360208110156105a657600080fd5b5035611748565b3480156105b957600080fd5b506103b2600480360360408110156105d057600080fd5b506001600160a01b038135169060200135611765565b3480156105f257600080fd5b506103b26004803603604081101561060957600080fd5b50803590602001356001600160a01b0316611778565b34801561062b57600080fd5b506103b26118d8565b34801561064057600080fd5b5061034a6118e8565b34801561065557600080fd5b506101c26004803603602081101561066c57600080fd5b5035151561191f565b34801561068157600080fd5b506103b26004803603604081101561069857600080fd5b506001600160a01b038135169060200135611957565b3480156106ba57600080fd5b506106c3611a26565b604080516001600160a01b039092168252519081900360200190f35b3480156106eb57600080fd5b5061034a6004803603604081101561070257600080fd5b50803590602001356001600160a01b0316611a35565b34801561072457600080fd5b5061034a611ad2565b600854604080516315ddbdb960e11b81526001600160a01b03848116600483015291516060936000931691632bbb7b72916024808301926020929190829003018186803b15801561077d57600080fd5b505afa158015610791573d6000803e3d6000fd5b505050506040513d60208110156107a757600080fd5b50516000858152602081815260408083208484528252918290208054835160026001831615610100026000190190921691909104601f810184900484028201840190945283815293945091908301828280156108445780601f1061081957610100808354040283529160200191610844565b820191906000526020600020905b81548152906001019060200180831161082757829003601f168201915b50505050509150505b92915050565b6008546001600160a01b0316331461086a57600080fd5b60006108746116fd565b600081815260076020908152604080832086845290915290205490915060ff166108ce576000818152600160209081526040808320858452825280832083905583835282825280832085845290915281206108ce91611df0565b5050565b6108da611418565b6108e357600080fd5b336108ee8185611957565b6108f757600080fd5b806001600160a01b0316610909611ae8565b6001600160a01b03161461091c57600080fd5b60006109266116fd565b600854604080516315ddbdb960e11b81526001600160a01b03868116600483015291519394506000939190921691632bbb7b72916024808301926020929190829003018186803b15801561097957600080fd5b505afa15801561098d573d6000803e3d6000fd5b505050506040513d60208110156109a357600080fd5b5051600083815260016020908152604080832084845282528083208a905585835282825280832084845290915290209091506109e0908686611e34565b5060009182526002602090815260408320805460018101825590845292209091015550505050565b600860009054906101000a90046001600160a01b03166001600160a01b03166356b54bae6040518163ffffffff1660e01b815260040160206040518083038186803b158015610a5657600080fd5b505afa158015610a6a573d6000803e3d6000fd5b505050506040513d6020811015610a8057600080fd5b50516001600160a01b03163314610a9657600080fd5b600354610aa1611aec565b81610aa857fe5b0615610ab3576111f5565b60606000806000600860009054906101000a90046001600160a01b03166001600160a01b031663ee99205c6040518163ffffffff1660e01b815260040160206040518083038186803b158015610b0857600080fd5b505afa158015610b1c573d6000803e3d6000fd5b505050506040513d6020811015610b3257600080fd5b505160408051630f29818d60e31b815290519192506000916001600160a01b0384169163794c0c68916004808301926020929190829003018186803b158015610b7a57600080fd5b505afa158015610b8e573d6000803e3d6000fd5b505050506040513d6020811015610ba457600080fd5b505160408051633834f3a360e11b815290519192506000916001600160a01b03851691637069e746916004808301926020929190829003018186803b158015610bec57600080fd5b505afa158015610c00573d6000803e3d6000fd5b505050506040513d6020811015610c1657600080fd5b50516040805163461121d760e11b815290519192506000916001600160a01b03861691638c2243ae916004808301926020929190829003018186803b158015610c5e57600080fd5b505afa158015610c72573d6000803e3d6000fd5b505050506040513d6020811015610c8857600080fd5b505190506000610c966116fd565b90506003546003028301610ca8611aec565b1115610e6457600860009054906101000a90046001600160a01b03166001600160a01b031663b7ab4db56040518163ffffffff1660e01b815260040160006040518083038186803b158015610cfc57600080fd5b505afa158015610d10573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526020811015610d3957600080fd5b810190808051640100000000811115610d5157600080fd5b82016020810184811115610d6457600080fd5b8151856020820283011164010000000082111715610d8157600080fd5b50909b5060009950505050505b8751861015610e6457878681518110610da357fe5b60200260200101519650610db781886114e4565b610e5957600854604080516315ddbdb960e11b81526001600160a01b038a8116600483015291516000939290921691632bbb7b7291602480820192602092909190829003018186803b158015610e0c57600080fd5b505afa158015610e20573d6000803e3d6000fd5b505050506040513d6020811015610e3657600080fd5b505160008681526006602090815260408083209383529290522080546001019055505b600190950194610d8e565b60055460ff168015610e90575081610e7a611aec565b1480610e90575081600354610e8d611aec565b01115b156111e3576000600354866001600160a01b03166397997ebb6040518163ffffffff1660e01b815260040160206040518083038186803b158015610ed357600080fd5b505afa158015610ee7573d6000803e3d6000fd5b505050506040513d6020811015610efd57600080fd5b505181610f0657fe5b0490506001811115610f1b5760011901610f26565b8015610f2657600019015b600860009054906101000a90046001600160a01b03166001600160a01b031663b7ab4db56040518163ffffffff1660e01b815260040160006040518083038186803b158015610f7457600080fd5b505afa158015610f88573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526020811015610fb157600080fd5b810190808051640100000000811115610fc957600080fd5b82016020810184811115610fdc57600080fd5b8151856020820283011164010000000082111715610ff957600080fd5b5050929190505050985060608951604051908082528060200260200182016040528015611030578160200160208202803883390190505b50600098509050875b8a518910156110ba578a898151811061104e57fe5b60200260200101519950611062848b6114e4565b1580611076575082611074888c611447565b115b156110af578982828060010193508151811061108e57fe5b60200260200101906001600160a01b031690816001600160a01b0316815250505b600190980197611039565b80156111df576060816040519080825280602002602001820160405280156110ec578160200160208202803883390190505b509050600099505b818a101561113f57828a8151811061110857fe5b6020026020010151818b8151811061111c57fe5b6001600160a01b03909216602092830291909101909101526001909901986110f4565b60085460405163018daf6b60e21b81526020600482018181528451602484015284516001600160a01b0390941693630636bdac9386938392604490920191818601910280838360005b838110156111a0578181015183820152602001611188565b5050505090500192505050600060405180830381600087803b1580156111c557600080fd5b505af11580156111d9573d6000803e3d6000fd5b50505050505b5050505b6111ec81611af0565b50505050505050505b565b60035481565b611205611aec565b15806112295750611214611ba7565b6001600160a01b0316336001600160a01b0316145b61123257600080fd5b61123a611418565b1561124457600080fd5b81600284061561125357600080fd5b806001600160a01b031663714897df6040518163ffffffff1660e01b815260040160206040518083038186803b15801561128c57600080fd5b505afa1580156112a0573d6000803e3d6000fd5b505050506040513d60208110156112b657600080fd5b505184816112c057fe5b06156112cb57600080fd5b83816001600160a01b031663ee99205c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561130557600080fd5b505afa158015611319573d6000803e3d6000fd5b505050506040513d602081101561132f57600080fd5b50516040805163d609ea9360e01b815290516001600160a01b039092169163d609ea9391600480820192602092909190829003018186803b15801561137357600080fd5b505afa158015611387573d6000803e3d6000fd5b505050506040513d602081101561139d57600080fd5b5051816113a657fe5b06156113b157600080fd5b600084116113be57600080fd5b600354156113cb57600080fd5b6001600160a01b0383166113de57600080fd5b50600392909255600880546001600160a01b0319166001600160a01b03929092169190911790556005805460ff1916911515919091179055565b6008546001600160a01b031615155b90565b60055460ff1681565b600060026003548161144157fe5b04905090565b600854604080516315ddbdb960e11b81526001600160a01b038481166004830152915160009384931691632bbb7b72916024808301926020929190829003018186803b15801561149657600080fd5b505afa1580156114aa573d6000803e3d6000fd5b505050506040513d60208110156114c057600080fd5b50516000858152600660209081526040808320938352929052205491505092915050565b600854604080516315ddbdb960e11b81526001600160a01b038481166004830152915160009384931691632bbb7b72916024808301926020929190829003018186803b15801561153357600080fd5b505afa158015611547573d6000803e3d6000fd5b505050506040513d602081101561155d57600080fd5b50516000858152600760209081526040808320938352929052205460ff1691505092915050565b600854604080516315ddbdb960e11b81526001600160a01b03848116600483015291516000936060938593911691632bbb7b7291602480820192602092909190829003018186803b1580156115d857600080fd5b505afa1580156115ec573d6000803e3d6000fd5b505050506040513d602081101561160257600080fd5b505160008681526001602081815260408084208585528252808420548a855284835281852086865283529381902080548251600295821615610100026000190190911694909404601f810184900484028501840190925281845294955092939283918301828280156116b55780601f1061168a576101008083540402835291602001916116b5565b820191906000526020600020905b81548152906001019060200180831161169857829003601f168201915b5050505050905092509250509250929050565b60006116d2611433565b60035460016116df611aec565b03816116e757fe5b0610905090565b60006116f8611714565b905090565b6000600354600161170c611aec565b038161144157fe5b60008061171f611aec565b90506000600354600183038161173157fe5b066003540390508082019250505090565b60045481565b611750611418565b61175957600080fd5b61176281611bcc565b50565b60006117718383611cd8565b9392505050565b600854604080516315ddbdb960e11b81526001600160a01b038481166004830152915160009384931691632bbb7b72916024808301926020929190829003018186803b1580156117c757600080fd5b505afa1580156117db573d6000803e3d6000fd5b505050506040513d60208110156117f157600080fd5b50519050801580159061180757506118076116c8565b1561189057600854604080516324b49dad60e21b815281516000936001600160a01b0316926392d276b49260048082019391829003018186803b15801561184d57600080fd5b505afa158015611861573d6000803e3d6000fd5b505050506040513d604081101561187757600080fd5b505190508181141561188e5760019250505061084d565b505b60008481526001602090815260408083208484529091529020541515806118d05750600084815260076020908152604080832084845290915290205460ff165b949350505050565b60006118e26116c8565b15905090565b60006118f26116c8565b1561190f576118ff611433565b611907611ad2565b019050611427565b611917611433565b611907611714565b611927611ba7565b6001600160a01b0316336001600160a01b03161461194457600080fd5b6005805460ff1916911515919091179055565b60006119616116c8565b61196d5750600061084d565b8161197a5750600061084d565b6008546040805163facd743b60e01b81526001600160a01b0386811660048301529151919092169163facd743b916024808301926020929190829003018186803b1580156119c757600080fd5b505afa1580156119db573d6000803e3d6000fd5b505050506040513d60208110156119f157600080fd5b50516119ff5750600061084d565b611a10611a0a6116fd565b84611778565b15611a1d5750600061084d565b50600192915050565b6008546001600160a01b031681565b600854604080516315ddbdb960e11b81526001600160a01b038481166004830152915160009384931691632bbb7b72916024808301926020929190829003018186803b158015611a8457600080fd5b505afa158015611a98573d6000803e3d6000fd5b505050506040513d6020811015611aae57600080fd5b50516000858152600160209081526040808320938352929052205491505092915050565b6000600354611adf6116fd565b02600101905090565b4190565b4390565b80611afa57611762565b60001981016000818152600260205260408120805490915b81811015611b93576000838281548110611b2857fe5b60009182526020808320909101548783528282526040808420828552909252908220909250611b5691611df0565b6000858152600160208181526040808420858552825280842084905588845260078252808420948452939052919020805460ff1916905501611b12565b506000611ba08382611eb2565b5050505050565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b33611bd78183611765565b611be057600080fd5b806001600160a01b0316611bf2611ae8565b6001600160a01b031614611c0557600080fd5b600854604080516315ddbdb960e11b81526001600160a01b03848116600483015291516000939290921691632bbb7b7291602480820192602092909190829003018186803b158015611c5657600080fd5b505afa158015611c6a573d6000803e3d6000fd5b505050506040513d6020811015611c8057600080fd5b5051600480548518905590506000611c966116fd565b60008181526007602090815260408083208684528252808320805460ff1916600190811790915593835292815282822094825293909352822091909155505050565b6000611ce26118d8565b611cee5750600061084d565b604080516020808201859052825180830382018152918301909252805191012080611d1d57600091505061084d565b6008546040805163facd743b60e01b81526001600160a01b0387811660048301529151919092169163facd743b916024808301926020929190829003018186803b158015611d6a57600080fd5b505afa158015611d7e573d6000803e3d6000fd5b505050506040513d6020811015611d9457600080fd5b5051611da457600091505061084d565b6000611dae6116fd565b9050611dba81866114e4565b15611dca5760009250505061084d565b611dd48186611a35565b8214611de55760009250505061084d565b506001949350505050565b50805460018160011615610100020316600290046000825580601f10611e165750611762565b601f0160209004906000526020600020908101906117629190611edb565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10611e755782800160ff19823516178555611ea2565b82800160010185558215611ea2579182015b82811115611ea2578235825591602001919060010190611e87565b50611eae929150611edb565b5090565b815481835581811115611ed657600083815260209020611ed6918101908301611edb565b505050565b61142791905b80821115611eae5760008155600101611ee156fea265627a7a72305820fb070d0efcf95ea5a546d38c7d35a2cc3bb541e53f6853d2b155fd86d1bde23564736f6c634300050a0032" + }, + "0x4000000000000000000000000000000000000001": { + "balance": "0x0", + "constructor": "0x60806040526040516108053803806108058339818101604052604081101561002657600080fd5b50805160209182015160408051600081529384018082527f656970313936372e70726f78792e696d706c656d656e746174696f6e00000000905251603c81850301902091929091839190600019016000805160206107aa8339815191521461008a57fe5b61009c826001600160e01b036101bd16565b805115610154576000826001600160a01b0316826040518082805190602001908083835b602083106100df5780518252601f1990920191602091820191016100c0565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855af49150503d806000811461013f576040519150601f19603f3d011682016040523d82523d6000602084013e610144565b606091505b505090508061015257600080fd5b505b5050604080517f656970313936372e70726f78792e61646d696e000000000000000000000000008152905190819003601301902060008051602061078a833981519152600019909101146101a457fe5b6101b6816001600160e01b0361023716565b505061024f565b6101d08161024960201b6104801760201c565b610225576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603b8152602001806107ca603b913960400191505060405180910390fd5b6000805160206107aa83398151915255565b60008051602061078a83398151915255565b3b151590565b61052c8061025e6000396000f3fe60806040526004361061004a5760003560e01c80633659cfe6146100545780634f1ef286146100875780635c60da1b146101075780638f28397014610138578063f851a4401461016b575b610052610180565b005b34801561006057600080fd5b506100526004803603602081101561007757600080fd5b50356001600160a01b031661019a565b6100526004803603604081101561009d57600080fd5b6001600160a01b0382351691908101906040810160208201356401000000008111156100c857600080fd5b8201836020820111156100da57600080fd5b803590602001918460018302840111640100000000831117156100fc57600080fd5b5090925090506101cb565b34801561011357600080fd5b5061011c61026f565b604080516001600160a01b039092168252519081900360200190f35b34801561014457600080fd5b506100526004803603602081101561015b57600080fd5b50356001600160a01b031661027e565b34801561017757600080fd5b5061011c61033c565b610188610198565b610198610193610346565b61036b565b565b6101a261038f565b6001600160a01b0316336001600160a01b0316146101bf57600080fd5b6101c8816103b4565b50565b6101d361038f565b6001600160a01b0316336001600160a01b0316146101f057600080fd5b6101f9836103b4565b6000836001600160a01b031683836040518083838082843760405192019450600093509091505080830381855af49150503d8060008114610256576040519150601f19603f3d011682016040523d82523d6000602084013e61025b565b606091505b505090508061026957600080fd5b50505050565b6000610279610346565b905090565b61028661038f565b6001600160a01b0316336001600160a01b0316146102a357600080fd5b6001600160a01b0381166102e85760405162461bcd60e51b81526004018080602001828103825260368152602001806104876036913960400191505060405180910390fd5b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f61031161038f565b604080516001600160a01b03928316815291841660208301528051918290030190a16101c8816103f4565b600061027961038f565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b3660008037600080366000845af43d6000803e80801561038a573d6000f35b3d6000fd5b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b6103bd81610418565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610355565b61042181610480565b61045c5760405162461bcd60e51b815260040180806020018281038252603b8152602001806104bd603b913960400191505060405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc55565b3b15159056fe43616e6e6f74206368616e6765207468652061646d696e206f6620612070726f787920746f20746865207a65726f206164647265737343616e6e6f742073657420612070726f787920696d706c656d656e746174696f6e20746f2061206e6f6e2d636f6e74726163742061646472657373a265627a7a72305820a9aab4b95b654a79b32f5aa284796894f8329aaa083932695296085b196c27bd64736f6c634300050a0032b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc43616e6e6f742073657420612070726f787920696d706c656d656e746174696f6e20746f2061206e6f6e2d636f6e747261637420616464726573730000000000000000000000004000000000000000000000000000000000000000000000000000000000000000b03a86b3126157c039b55e21d378587ccfc04d45" + }, + "0x4000000000000000000000000000000000000000": { + "balance": "0x0", + "constructor": "0x608060405234801561001057600080fd5b5061139e806100206000396000f3fe608060405234801561001057600080fd5b50600436106101215760003560e01c806390482d72116100ad578063baddbfa011610071578063baddbfa014610479578063c746c8f4146104a5578063d9eb2d5e146104cb578063dfc8bf4e146104d3578063efc78401146104db57610121565b806390482d72146102b957806394a1fd781461033a5780639d7912aa14610360578063a0a8e46014610386578063b9056afa1461038e57610121565b8063392e53cd116100f4578063392e53cd146101ea578063469ab1e314610206578063471eab5c1461020e57806375d0c0dc146102345780637877a797146102b157610121565b80630651cd86146101265780631a9ebeaa146101545780631b9f67a1146101785780633272b28c14610192575b600080fd5b6101526004803603604081101561013c57600080fd5b506001600160a01b038135169060200135610501565b005b61015c61058b565b604080516001600160a01b039092168252519081900360200190f35b61018061059a565b60408051918252519081900360200190f35b61019a6105a1565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156101d65781810151838201526020016101be565b505050509050019250505060405180910390f35b6101f2610604565b604080519115158252519081900360200190f35b610180610615565b6101526004803603602081101561022457600080fd5b50356001600160a01b0316610691565b61023c6107c5565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561027657818101518382015260200161025e565b50505050905090810190601f1680156102a35780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6101806107f5565b610152600480360360608110156102cf57600080fd5b8101906020810181356401000000008111156102ea57600080fd5b8201836020820111156102fc57600080fd5b8035906020019184602083028401116401000000008311171561031e57600080fd5b91935091506001600160a01b0381358116916020013516610914565b6101806004803603602081101561035057600080fd5b50356001600160a01b03166109e2565b6101806004803603602081101561037657600080fd5b50356001600160a01b03166109f4565b610180610a26565b610459600480360360a08110156103a457600080fd5b6001600160a01b03823581169260208101359091169160408201359160608101359181019060a0810160808201356401000000008111156103e457600080fd5b8201836020820111156103f657600080fd5b8035906020019184600183028401116401000000008311171561041857600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550610a2b945050505050565b6040805163ffffffff909316835290151560208301528051918290030190f35b6101526004803603604081101561048f57600080fd5b506001600160a01b038135169060200135610a4c565b610152600480360360208110156104bb57600080fd5b50356001600160a01b0316610ad6565b610180610b18565b61015c610b1f565b6101f2600480360360208110156104f157600080fd5b50356001600160a01b0316610b2e565b610509610b43565b6001600160a01b0316336001600160a01b03161461052657600080fd5b61052e610604565b61053757600080fd5b6001600160a01b038216600081815260056020908152604091829020849055815184815291517fc8eecc08ae9cffd51fce8871ab6f4c6c8c112f8753fad097a055d51433661a7d9281900390910190a25050565b6001546001600160a01b031681565b623d090081565b606060008054806020026020016040519081016040528092919081815260200182805480156105f957602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116105db575b505050505090505b90565b6003546001600160a01b0316151590565b600061061f6107c5565b6040516020018082805190602001908083835b602083106106515780518252601f199092019160209182019101610632565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405160208183030381529060405280519060200120905090565b610699610b43565b6001600160a01b0316336001600160a01b0316146106b657600080fd5b6106be610604565b6106c757600080fd5b6001600160a01b03811660009081526002602052604090205460ff166106ec57600080fd5b60008054905b818110156107a2576000818154811061070757fe5b6000918252602090912001546001600160a01b038481169116141561079a576000600183038154811061073657fe5b600091825260208220015481546001600160a01b0390911691908390811061075a57fe5b6000918252602082200180546001600160a01b0319166001600160a01b039390931692909217909155805490610794906000198301611322565b506107a2565b6001016106f2565b50506001600160a01b03166000908152600260205260409020805460ff19169055565b604080518082019091526016815275151617d41154935254d4d253d397d0d3d395149050d560521b602082015290565b600080600360009054906101000a90046001600160a01b03166001600160a01b031663ee99205c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561084657600080fd5b505afa15801561085a573d6000803e3d6000fd5b505050506040513d602081101561087057600080fd5b50516040805163461121d760e11b815290519192506000916001600160a01b03841691638c2243ae916004808301926020929190829003018186803b1580156108b857600080fd5b505afa1580156108cc573d6000803e3d6000fd5b505050506040513d60208110156108e257600080fd5b5051905043600019820114806108f757508043145b1561090957623d090092505050610601565b62bebc209250505090565b4315806109395750610924610b43565b6001600160a01b0316336001600160a01b0316145b61094257600080fd5b61094a610604565b1561095457600080fd5b6001600160a01b03821661096757600080fd5b6001600160a01b03811661097a57600080fd5b60005b838110156109b1576109a985858381811061099457fe5b905060200201356001600160a01b0316610b68565b60010161097d565b50600180546001600160a01b039384166001600160a01b031991821617909155600380549290931691161790555050565b60056020526000908152604090205481565b6001600160a01b0381166000908152600460205260408120548015610a1a579050610a21565b6178009150505b919050565b600390565b600080610a3e8787878788600089610c06565b915091509550959350505050565b610a54610b43565b6001600160a01b0316336001600160a01b031614610a7157600080fd5b610a79610604565b610a8257600080fd5b6001600160a01b038216600081815260046020908152604091829020849055815184815291517f89afe3f32b77b643649ede79272f126acd78aa80feeabe1b8c103d0b2f2848969281900390910190a25050565b610ade610b43565b6001600160a01b0316336001600160a01b031614610afb57600080fd5b610b03610604565b610b0c57600080fd5b610b1581610b68565b50565b62bebc2081565b6003546001600160a01b031681565b60026020526000908152604090205460ff1681565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b6001600160a01b03811660009081526002602052604090205460ff1615610b8e57600080fd5b6001600160a01b038116610ba157600080fd5b60008054600181810183557f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56390910180546001600160a01b039094166001600160a01b031990941684179055918152600260205260409020805460ff19169091179055565b6001600160a01b038716600090815260026020526040812054819060ff1615610c38575063ffffffff90506000611316565b6001600160a01b038816158015610c575750610c53896109f4565b8351115b15610c6757506000905080611316565b6004838101516003546040805163ccf69e9b60e01b8152905160e09390931b936001600160a01b039092169263ccf69e9b92828101926020929190829003018186803b158015610cb657600080fd5b505afa158015610cca573d6000803e3d6000fd5b505050506040513d6020811015610ce057600080fd5b50516001600160a01b038a811691161415610e5e576001600160e01b03198116630b61ba8560e01b148015610d16575060248451115b15610db957602484810151604080516306f084f160e51b81526001600160a01b038e81166004830152938101839052905191928c169163de109e2091604480820192602092909190829003018186803b158015610d7257600080fd5b505afa158015610d86573d6000803e3d6000fd5b505050506040513d6020811015610d9c57600080fd5b5051610da9576000610dac565b60025b6000935093505050611316565b6001600160e01b0319811663fe7d567d60e01b1480610de857506001600160e01b03198116634c6fb3e360e11b145b8015610df5575083516024145b15610e51576024848101516040805163fd6c1d1560e01b81526001600160a01b038e81166004830152938101839052905191928c169163fd6c1d1591604480820192602092909190829003018186803b158015610d7257600080fd5b6000809250925050611316565b6003546001600160a01b038a8116911614156110bd576001600160e01b031981166349da712f60e11b1415610f2157600360009054906101000a90046001600160a01b03166001600160a01b0316633d3b54586040518163ffffffff1660e01b815260040160206040518083038186803b158015610edb57600080fd5b505afa158015610eef573d6000803e3d6000fd5b505050506040513d6020811015610f0557600080fd5b5051610f12576000610f15565b60025b60009250925050611316565b6001600160e01b03198116630311db7560e61b148015610f4357506044845110155b156110335760008060248601519150604486015190506000600360009054906101000a90046001600160a01b03166001600160a01b031663a670eb568e85856040518463ffffffff1660e01b815260040180846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b031681526020018281526020019350505050604080518083038186803b158015610fe757600080fd5b505afa158015610ffb573d6000803e3d6000fd5b505050506040513d604081101561101157600080fd5b5051905080611021576000611024565b60025b60009550955050505050611316565b86156110bd576003546040805163facd743b60e01b81526001600160a01b038d811660048301529151919092169163facd743b916024808301926020929190829003018186803b15801561108657600080fd5b505afa15801561109a573d6000803e3d6000fd5b505050506040513d60208110156110b057600080fd5b5051610e51576002610f15565b6003546040805163facd743b60e01b81526001600160a01b038d811660048301529151919092169163facd743b916024808301926020929190829003018186803b15801561110a57600080fd5b505afa15801561111e573d6000803e3d6000fd5b505050506040513d602081101561113457600080fd5b505180156111425750600087115b15611195576001600160e01b0319811663a9059cbb60e01b141561116e57600260009250925050611316565b60008a6001600160a01b03163111611187576000610f15565b600160009250925050611316565b6003546040805163facd743b60e01b81526001600160a01b038c811660048301529151919092169163facd743b916024808301926020929190829003018186803b1580156111e257600080fd5b505afa1580156111f6573d6000803e3d6000fd5b505050506040513d602081101561120c57600080fd5b505115611220576000809250925050611316565b866112ba57600154604080516303a388eb60e61b81526001600160a01b038d811660048301529151919092169163e8e23ac0916024808301926020929190829003018186803b15801561127257600080fd5b505afa158015611286573d6000803e3d6000fd5b505050506040513d602081101561129c57600080fd5b50516112a9576000610f15565b63ffffffff60009250925050611316565b6001600160a01b038a166000908152600560205260409020548710806112f757506001600160a01b038a1660009081526005602052604090205486105b15611309576000809250925050611316565b63ffffffff600092509250505b97509795505050505050565b8154818355818111156113465760008381526020902061134691810190830161134b565b505050565b61060191905b808211156113655760008155600101611351565b509056fea265627a7a72305820de9ee9915ae9231fc972bc7570c92a6e882aae006233dfefbea7769e5545011064736f6c634300050a0032" + }, + "0x4100000000000000000000000000000000000000": { + "balance": "0x0", + "constructor": "0x60806040523480156200001157600080fd5b506040516200232d3803806200232d8339810160408190526200003491620000bd565b6001600160a01b038116620000465750335b6001600160a01b0381166200005a57600080fd5b600880546001600160a01b0319166001600160a01b0383169081179091556040516000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a35062000112565b8051620000b781620000f8565b92915050565b600060208284031215620000d057600080fd5b6000620000de8484620000aa565b949350505050565b60006001600160a01b038216620000b7565b6200010381620000e6565b81146200010f57600080fd5b50565b61220b80620001226000396000f3fe608060405234801561001057600080fd5b50600436106100cf5760003560e01c80638da5cb5b1161008c578063a5b62cb311610066578063a5b62cb314610187578063d13a26531461019a578063f2fde38b146101bc578063f53c7e2f146101cf576100cf565b80638da5cb5b14610157578063a0daeed21461016c578063a2bf0af514610174576100cf565b80630af28392146100d4578063338cd6bd146100e9578063399b6f3e14610107578063662520bd1461011c5780637d616fd31461012f578063879cda7314610144575b600080fd5b6100e76100e2366004611ccd565b6101e2565b005b6100f1610465565b6040516100fe91906120a0565b60405180910390f35b61010f6104c7565b6040516100fe9190612140565b6100e761012a366004611c93565b6104cd565b610137610608565b6040516100fe91906120b1565b6100e7610152366004611c93565b610699565b61015f610915565b6040516100fe9190612058565b610137610924565b6100e7610182366004611d1a565b610a15565b6100e7610195366004611ccd565b610a89565b6101ad6101a8366004611d5c565b610c9c565b6040516100fe93929190612066565b6100e76101ca366004611c6d565b610ccb565b61010f6101dd366004611c93565b610d77565b6008546001600160a01b031633146102155760405162461bcd60e51b815260040161020c90612100565b60405180910390fd5b6001600160a01b03831661023b5760405162461bcd60e51b815260040161020c90612120565b806102585760405162461bcd60e51b815260040161020c90612130565b6001600160a01b03831660009081526004602090815260408083206001600160e01b031986168452909152902054600354811080156102c55750836001600160a01b0316600382815481106102a957fe5b60009182526020909120600290910201546001600160a01b0316145b801561030b5750826001600160e01b031916600382815481106102e457fe5b6000918252602090912060029091020154600160a01b900460e01b6001600160e01b031916145b1561033857816003828154811061031e57fe5b906000526020600020906002020160010181905550610413565b600380546001600160a01b0386811660008181526004602090815260408083206001600160e01b03198b16808552908352818420879055815160608101835294855291840191825283018881526001860187559590915290517fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b6002909402938401805492516001600160a01b0319909316919093161763ffffffff60a01b1916600160a01b60e09290921c9190910217905590517fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85c909101555b826001600160e01b031916846001600160a01b03167f7c3ecffa528bfccc8dd5c2454093da1c08757c960b1e5425afb9cb3b18439028846040516104579190612140565b60405180910390a350505050565b606060028054806020026020016040519081016040528092919081815260200182805480156104bd57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161049f575b5050505050905090565b60055481565b6008546001600160a01b031633146104f75760405162461bcd60e51b815260040161020c90612100565b6001600160a01b03821660009081526007602090815260408083206001600160e01b031985168452909152902054806105425760405162461bcd60e51b815260040161020c906120d0565b61055360008263ffffffff610d9416565b6001600160a01b03831660009081526007602090815260408083206001600160e01b03198616845282528083208390558383526006909152812080546001600160c01b03191681556001908101919091556005546105b091610fc2565b6005556040516001600160e01b03198316906001600160a01b038516907f896fc6a8eb054c92d480f4d32ec773e5ebe77109ad3b179f3e97ac78cf3e7cb7906105fb906000906120c2565b60405180910390a3505050565b60606003805480602002602001604051908101604052809291908181526020016000905b82821015610690576000848152602090819020604080516060810182526002860290920180546001600160a01b0381168452600160a01b900460e01b6001600160e01b0319168385015260019081015491830191909152908352909201910161062c565b50505050905090565b6008546001600160a01b031633146106c35760405162461bcd60e51b815260040161020c90612100565b6001600160a01b03821660009081526004602090815260408083206001600160e01b031985168452909152902054600354811080156107305750826001600160a01b03166003828154811061071457fe5b60009182526020909120600290910201546001600160a01b0316145b80156107765750816001600160e01b0319166003828154811061074f57fe5b6000918252602090912060029091020154600160a01b900460e01b6001600160e01b031916145b156108f857610783611b02565b60038054600019810190811061079557fe5b600091825260209182902060408051606081018252600290930290910180546001600160a01b03811684526001600160e01b0319600160a01b90910460e01b169383019390935260019092015491810191909152600380549192508291849081106107fc57fe5b60009182526020808320845160029093020180548583015160e01c600160a01b0263ffffffff60a01b196001600160a01b039586166001600160a01b031990931692909217919091161781556040948501516001909101558451821683526004808252848420868301516001600160e01b03199081168652908352858520889055928916845281528383209187168352529081205560038054906108a4906000198301611b22565b50826001600160e01b031916846001600160a01b03167f7c3ecffa528bfccc8dd5c2454093da1c08757c960b1e5425afb9cb3b1843902860006040516108ea91906120c2565b60405180910390a350610910565b60405162461bcd60e51b815260040161020c90612110565b505050565b6008546001600160a01b031681565b606060055460405190808252806020026020018201604052801561096257816020015b61094f611b02565b8152602001906001900390816109475790505b50905060006109716000610fdc565b905060005b8115610a1057600554811061098a57600080fd5b600082815260066020908152604091829020825160608101845281546001600160a01b0381168252600160a01b900460e01b6001600160e01b0319169281019290925260019081015492820192909252845191830192909185919081106109ed57fe5b6020908102919091010152610a0960008363ffffffff61101c16565b9150610976565b505090565b6008546001600160a01b03163314610a3f5760405162461bcd60e51b815260040161020c90612100565b610a4b60028383611b4e565b507ff3a1b17f96de235ad0ae63327b65739025bc92dd4bc161c9d8b661cb449ec62d8282604051610a7d92919061208e565b60405180910390a15050565b6008546001600160a01b03163314610ab35760405162461bcd60e51b815260040161020c90612100565b6001600160a01b038316610ad95760405162461bcd60e51b815260040161020c90612120565b80610af65760405162461bcd60e51b815260040161020c906120e0565b6001600160a01b03831660009081526007602090815260408083206001600160e01b0319861684529091529020548015610bac5781811415610b7657826001600160e01b031916846001600160a01b03167f896fc6a8eb054c92d480f4d32ec773e5ebe77109ad3b179f3e97ac78cf3e7cb7846040516108ea9190612140565b610b8760008263ffffffff610d9416565b600081815260066020526040812080546001600160c01b031916815560010155610bc4565b600554610bc090600163ffffffff6110b916565b6005555b610bd560008363ffffffff6110d216565b604080516060810182526001600160a01b038087168083526001600160e01b03198716602080850182815285870189815260008a81526006845288812097518854935160e01c600160a01b0263ffffffff60a01b19919098166001600160a01b031990941693909317929092169590951786559351600190950194909455818352600784528483208184529093529083902085905591519091907f896fc6a8eb054c92d480f4d32ec773e5ebe77109ad3b179f3e97ac78cf3e7cb790610457908690612140565b600660205260009081526040902080546001909101546001600160a01b03821691600160a01b900460e01b9083565b6008546001600160a01b03163314610cf55760405162461bcd60e51b815260040161020c90612100565b6001600160a01b038116610d1b5760405162461bcd60e51b815260040161020c906120f0565b6008546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3600880546001600160a01b0319166001600160a01b0392909216919091179055565b600760209081526000928352604080842090915290825290205481565b80610d9e57600080fd5b610da882826111ec565b610db157600080fd5b6000818152600180840160205260408220015481901580610de357506000838152600185016020526040902060020154155b15610def575081610e37565b5060008281526001840160205260409020600201545b600081815260018086016020526040909120015415610e37576000908152600180850160205260409091200154610e05565b600081815260018086016020526040909120015415610e6b5760008181526001808601602052604090912001549150610e82565b600081815260018501602052604090206002015491505b60008181526001850160205260408082205484835291208190558015610ef4576000818152600180870160205260409091200154821415610ed85760008181526001808701602052604090912001839055610eef565b600081815260018601602052604090206002018390555b610ef8565b8285555b600082815260018601602052604090206003015460ff1615848314610f8257610f2286848761121b565b60008581526001878101602052604080832080830154878552828520938401819055845281842087905560028082015490840181905584529083208690556003908101549286905201805460ff191660ff90921615159190911790559193915b8015610f9257610f928685611292565b5050600090815260019384016020526040812081815593840181905560028401555050600301805460ff19169055565b600082821115610fd157600080fd5b508082035b92915050565b80548015611017575b600081815260018301602052604090206002015415611017576000908152600182016020526040902060020154610fe5565b919050565b60008161102857600080fd5b6000828152600180850160205260409091200154156110675760008281526001808501602052604090912001546110609084906116ad565b9050610fd6565b5060008181526001830160205260409020545b801580159061109b5750600081815260018085016020526040909120015482145b15610fd657600081815260018401602052604090205490915061107a565b6000828201838110156110cb57600080fd5b9392505050565b806110dc57600080fd5b6110e682826111ec565b156110f057600080fd5b81546000905b801561113a5780915080831015611120576000908152600180850160205260409091200154611135565b60009081526001840160205260409020600201545b6110f6565b60408051608081018252838152600060208083018281528385018381526001606086018181528a86528b82019094529590932093518455519383019390935551600282015590516003909101805460ff1916911515919091179055816111a2578284556111dc565b818310156111c557600082815260018086016020526040909120018390556111dc565b600082815260018501602052604090206002018390555b6111e684846116ea565b50505050565b600081158015906110cb575082548214806110cb57505060009081526001919091016020526040902054151590565b600081815260018401602052604080822054848352912081905580611242578284556111e6565b600081815260018086016020526040909120015482141561127857600081815260018086016020526040909120018390556111e6565b600090815260019390930160205250604090912060020155565b60005b825482148015906112ba5750600082815260018401602052604090206003015460ff16155b1561168e5760008281526001808501602052604080832054808452922001548314156114b75760008181526001850160205260408082206002015480835291206003015490925060ff161561135e576000828152600180860160205260408083206003908101805460ff199081169091558585529190932090920180549092161790556113478482611955565b600081815260018501602052604090206002015491505b60008281526001808601602052604080832090910154825290206003015460ff161580156113a95750600082815260018501602052604080822060020154825290206003015460ff16155b156113d657600082815260018581016020526040909120600301805460ff191690911790559150816114b2565b600082815260018501602052604080822060020154825290206003015460ff16611453576000828152600180860160205260408083208083015484529083206003908101805460ff199081169091559386905201805490921617905561143c8483611a2d565b600081815260018501602052604090206002015491505b600081815260018501602052604080822060039081018054868552838520808401805460ff909316151560ff1993841617905582548216909255600290910154845291909220909101805490911690556114ad8482611955565b835492505b611688565b6000818152600180860160205260408083209091015480835291206003015490925060ff1615611536576000828152600180860160205260408083206003908101805460ff1990811690915585855291909320909201805490921617905561151f8482611a2d565b600081815260018086016020526040909120015491505b600082815260018501602052604080822060020154825290206003015460ff16158015611581575060008281526001808601602052604080832090910154825290206003015460ff16155b156115ae57600082815260018581016020526040909120600301805460ff19169091179055915081611688565b60008281526001808601602052604080832090910154825290206003015460ff1661162d57600082815260018086016020526040808320600281015484529083206003908101805460ff19908116909155938690520180549092161790556116168483611955565b600081815260018086016020526040909120015491505b60008181526001808601602052604080832060039081018054878652838620808401805460ff909316151560ff199384161790558254821690925593015484529220909101805490911690556116838482611a2d565b835492505b50611295565b506000908152600190910160205260409020600301805460ff19169055565b60005b6000828152600184016020526040902060020154156116e457600091825260018301602052604090912060020154906116b0565b50919050565b60005b825482148015906117175750600082815260018401602052604080822054825290206003015460ff165b1561193357600082815260018085016020526040808320548084528184205484529220015481141561183a5760008181526001850160205260408082205482528082206002015480835291206003015490925060ff16156117c0576000818152600180860160205260408083206003808201805460ff19908116909155878652838620820180548216905582548652928520018054909216909217905590829052549250611835565b60008181526001850160205260409020600201548314156117e8578092506117e88484611955565b50600082815260018085016020526040808320548084528184206003808201805460ff19908116909155825487529386200180549093169093179091559182905254611835908590611a2d565b61192d565b6000818152600180860160205260408083205483528083209091015480835291206003015490925060ff16156118b8576000818152600180860160205260408083206003808201805460ff1990811690915587865283862082018054821690558254865292852001805490921690921790559082905254925061192d565b60008181526001808601602052604090912001548314156118e0578092506118e08484611a2d565b50600082815260018085016020526040808320548084528184206003808201805460ff1990811690915582548752938620018054909316909317909155918290525461192d908590611955565b506116ed565b505080546000908152600190910160205260409020600301805460ff19169055565b60008181526001808401602052604080832060028101805491548286529285209093015493859052918390559091801561199d57600081815260018601602052604090208490555b60008381526001860160205260409020829055816119bd57828555611a0a565b60008281526001808701602052604090912001548414156119f35760008281526001808701602052604090912001839055611a0a565b600082815260018601602052604090206002018390555b505060008181526001938401602052604080822090940183905591825291902055565b60008181526001808401602052604080832091820180549254838552918420600201549385905283905590918015611a7357600081815260018601602052604090208490555b6000838152600186016020526040902082905581611a9357828555611ae0565b6000828152600186016020526040902060020154841415611ac95760008281526001860160205260409020600201839055611ae0565b600082815260018087016020526040909120018390555b5050600081815260019093016020526040808420600201839055918352912055565b604080516060810182526000808252602082018190529181019190915290565b815481835581811115610910576002028160020283600052602060002091820191016109109190611bb1565b828054828255906000526020600020908101928215611ba1579160200282015b82811115611ba15781546001600160a01b0319166001600160a01b03843516178255602090920191600190910190611b6e565b50611bad929150611bdf565b5090565b611bdc91905b80821115611bad5780546001600160c01b031916815560006001820155600201611bb7565b90565b611bdc91905b80821115611bad5780546001600160a01b0319168155600101611be5565b8035610fd68161219f565b60008083601f840112611c2057600080fd5b50813567ffffffffffffffff811115611c3857600080fd5b602083019150836020820283011115611c5057600080fd5b9250929050565b8035610fd6816121b6565b8035610fd6816121bf565b600060208284031215611c7f57600080fd5b6000611c8b8484611c03565b949350505050565b60008060408385031215611ca657600080fd5b6000611cb28585611c03565b9250506020611cc385828601611c57565b9150509250929050565b600080600060608486031215611ce257600080fd5b6000611cee8686611c03565b9350506020611cff86828701611c57565b9250506040611d1086828701611c62565b9150509250925092565b60008060208385031215611d2d57600080fd5b823567ffffffffffffffff811115611d4457600080fd5b611d5085828601611c0e565b92509250509250929050565b600060208284031215611d6e57600080fd5b6000611c8b8484611c62565b6000611d868383611da2565b505060200190565b6000611d9a838361201c565b505060600190565b611dab81612170565b82525050565b6000611dbd8385612158565b9350611dc882611bdc565b8060005b85811015611dfe57611dde8284612161565b611de88882611d7a565b9750611df38361214e565b925050600101611dcc565b509495945050505050565b6000611e1482612154565b611e1e8185612158565b9350611e298361214e565b8060005b83811015611dfe578151611e418882611d7a565b9750611e4c8361214e565b925050600101611e2d565b6000611e6282612154565b611e6c8185612158565b9350611e778361214e565b8060005b83811015611dfe578151611e8f8882611d8e565b9750611e9a8361214e565b925050600101611e7b565b611dab8161217b565b611dab81612194565b6000611ec4601a83612158565b7f64657374696e6174696f6e20646f6573206e6f74206578697374000000000000815260200192915050565b6000611efd601283612158565b7107765696768742063616e6e6f7420626520360741b815260200192915050565b6000611f2b601d83612158565b7f6e6577206f776e657220697320746865207a65726f2061646472657373000000815260200192915050565b6000611f64601783612158565b7f63616c6c6572206973206e6f7420746865206f776e6572000000000000000000815260200192915050565b6000611f9d600983612158565b681b9bdd08199bdd5b9960ba1b815260200192915050565b6000611fc2601283612158565b7107461726765742063616e6e6f7420626520360741b815260200192915050565b6000611ff0601783612158565b7f6d696e47617350726963652063616e6e6f742062652030000000000000000000815260200192915050565b8051606083019061202d8482611da2565b5060208201516120406020850182611ea5565b5060408201516111e660408501825b611dab81611bdc565b60208101610fd68284611da2565b606081016120748286611da2565b6120816020830185611ea5565b611c8b604083018461204f565b60208082528101611c8b818486611db1565b602080825281016110cb8184611e09565b602080825281016110cb8184611e57565b60208101610fd68284611eae565b60208082528101610fd681611eb7565b60208082528101610fd681611ef0565b60208082528101610fd681611f1e565b60208082528101610fd681611f57565b60208082528101610fd681611f90565b60208082528101610fd681611fb5565b60208082528101610fd681611fe3565b60208101610fd6828461204f565b60200190565b5190565b90815260200190565b60006110cb6020840184611c03565b6000610fd682612188565b6001600160e01b03191690565b6001600160a01b031690565b6000610fd682611bdc565b6121a881612170565b81146121b357600080fd5b50565b6121a88161217b565b6121a881611bdc56fea365627a7a72305820f7014cfc58f43e5dc9f5a4bf6c6a6f5bce8883c71fa0b037ee28c5764fedabab6c6578706572696d656e74616cf564736f6c634300050a0040000000000000000000000000b03a86b3126157c039b55e21d378587ccfc04d45" + }, + "0x5000000000000000000000000000000000000001": { + "balance": "0x0", + "constructor": "0x60806040526040516108053803806108058339818101604052604081101561002657600080fd5b50805160209182015160408051600081529384018082527f656970313936372e70726f78792e696d706c656d656e746174696f6e00000000905251603c81850301902091929091839190600019016000805160206107aa8339815191521461008a57fe5b61009c826001600160e01b036101bd16565b805115610154576000826001600160a01b0316826040518082805190602001908083835b602083106100df5780518252601f1990920191602091820191016100c0565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855af49150503d806000811461013f576040519150601f19603f3d011682016040523d82523d6000602084013e610144565b606091505b505090508061015257600080fd5b505b5050604080517f656970313936372e70726f78792e61646d696e000000000000000000000000008152905190819003601301902060008051602061078a833981519152600019909101146101a457fe5b6101b6816001600160e01b0361023716565b505061024f565b6101d08161024960201b6104801760201c565b610225576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603b8152602001806107ca603b913960400191505060405180910390fd5b6000805160206107aa83398151915255565b60008051602061078a83398151915255565b3b151590565b61052c8061025e6000396000f3fe60806040526004361061004a5760003560e01c80633659cfe6146100545780634f1ef286146100875780635c60da1b146101075780638f28397014610138578063f851a4401461016b575b610052610180565b005b34801561006057600080fd5b506100526004803603602081101561007757600080fd5b50356001600160a01b031661019a565b6100526004803603604081101561009d57600080fd5b6001600160a01b0382351691908101906040810160208201356401000000008111156100c857600080fd5b8201836020820111156100da57600080fd5b803590602001918460018302840111640100000000831117156100fc57600080fd5b5090925090506101cb565b34801561011357600080fd5b5061011c61026f565b604080516001600160a01b039092168252519081900360200190f35b34801561014457600080fd5b506100526004803603602081101561015b57600080fd5b50356001600160a01b031661027e565b34801561017757600080fd5b5061011c61033c565b610188610198565b610198610193610346565b61036b565b565b6101a261038f565b6001600160a01b0316336001600160a01b0316146101bf57600080fd5b6101c8816103b4565b50565b6101d361038f565b6001600160a01b0316336001600160a01b0316146101f057600080fd5b6101f9836103b4565b6000836001600160a01b031683836040518083838082843760405192019450600093509091505080830381855af49150503d8060008114610256576040519150601f19603f3d011682016040523d82523d6000602084013e61025b565b606091505b505090508061026957600080fd5b50505050565b6000610279610346565b905090565b61028661038f565b6001600160a01b0316336001600160a01b0316146102a357600080fd5b6001600160a01b0381166102e85760405162461bcd60e51b81526004018080602001828103825260368152602001806104876036913960400191505060405180910390fd5b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f61031161038f565b604080516001600160a01b03928316815291841660208301528051918290030190a16101c8816103f4565b600061027961038f565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b3660008037600080366000845af43d6000803e80801561038a573d6000f35b3d6000fd5b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b6103bd81610418565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610355565b61042181610480565b61045c5760405162461bcd60e51b815260040180806020018281038252603b8152602001806104bd603b913960400191505060405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc55565b3b15159056fe43616e6e6f74206368616e6765207468652061646d696e206f6620612070726f787920746f20746865207a65726f206164647265737343616e6e6f742073657420612070726f787920696d706c656d656e746174696f6e20746f2061206e6f6e2d636f6e74726163742061646472657373a265627a7a72305820a9aab4b95b654a79b32f5aa284796894f8329aaa083932695296085b196c27bd64736f6c634300050a0032b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc43616e6e6f742073657420612070726f787920696d706c656d656e746174696f6e20746f2061206e6f6e2d636f6e747261637420616464726573730000000000000000000000005000000000000000000000000000000000000000000000000000000000000000b03a86b3126157c039b55e21d378587ccfc04d45" + }, + "0x5000000000000000000000000000000000000000": { + "balance": "0x0", + "constructor": "0x608060405234801561001057600080fd5b50610616806100206000396000f3fe608060405234801561001057600080fd5b506004361061007d5760003560e01c80635d6067d01161005b5780635d6067d014610189578063cc1d4c02146101f9578063dfc8bf4e1461021f578063e8e23ac0146102435761007d565b806305f203d914610082578063392e53cd146100f4578063462d0b2e14610110575b600080fd5b6100f26004803603602081101561009857600080fd5b8101906020810181356401000000008111156100b357600080fd5b8201836020820111156100c557600080fd5b803590602001918460208302840111640100000000831117156100e757600080fd5b509092509050610269565b005b6100fc61033e565b604080519115158252519081900360200190f35b6100f26004803603604081101561012657600080fd5b81019060208101813564010000000081111561014157600080fd5b82018360208201111561015357600080fd5b8035906020019184602083028401116401000000008311171561017557600080fd5b9193509150356001600160a01b031661034f565b6100f26004803603602081101561019f57600080fd5b8101906020810181356401000000008111156101ba57600080fd5b8201836020820111156101cc57600080fd5b803590602001918460208302840111640100000000831117156101ee57600080fd5b5090925090506103fe565b6100fc6004803603602081101561020f57600080fd5b50356001600160a01b0316610456565b61022761050a565b604080516001600160a01b039092168252519081900360200190f35b6100fc6004803603602081101561025957600080fd5b50356001600160a01b0316610519565b610271610537565b6001600160a01b0316336001600160a01b03161461028e57600080fd5b61029661033e565b61029f57600080fd5b60005b818110156103395760008383838181106102b857fe5b602090810292909201356001600160a01b03166000818152928390526040909220549192505060ff166102ea57600080fd5b6001600160a01b038116600081815260208190526040808220805460ff19169055517fb6fa8b8bd5eab60f292eca876e3ef90722275b785309d84b1de113ce0b8c4e749190a2506001016102a2565b505050565b6001546001600160a01b0316151590565b431580610374575061035f610537565b6001600160a01b0316336001600160a01b0316145b61037d57600080fd5b61038561033e565b1561038f57600080fd5b6001600160a01b0381166103a257600080fd5b60005b828110156103d9576103d18484838181106103bc57fe5b905060200201356001600160a01b031661055c565b6001016103a5565b50600180546001600160a01b0319166001600160a01b03929092169190911790555050565b610406610537565b6001600160a01b0316336001600160a01b03161461042357600080fd5b61042b61033e565b61043457600080fd5b60005b818110156103395761044e8383838181106103bc57fe5b600101610437565b6001600160a01b03811660009081526020819052604081205460ff161561047f57506001610505565b6001805460408051639184d0ad60e01b81526001600160a01b038681166004830152602482019490945290519290911691639184d0ad91604480820192602092909190829003018186803b1580156104d657600080fd5b505afa1580156104ea573d6000803e3d6000fd5b505050506040513d602081101561050057600080fd5b505190505b919050565b6001546001600160a01b031681565b6001600160a01b031660009081526020819052604090205460ff1690565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b6001600160a01b03811661056f57600080fd5b6001600160a01b03811660009081526020819052604090205460ff161561059557600080fd5b6001600160a01b038116600081815260208190526040808220805460ff19166001179055517fd415b905d4dd806bfba99a7a0e6351bd0c9db3a9912add21c0e6bef4479f673f9190a25056fea265627a7a72305820f80f64fde129011b547316cf9ce9cd58a9917ae771746100649cc2e4b3ba4edf64736f6c634300050a0032" + }, + "0x6100000000000000000000000000000000000001": { + "balance": "0x0", + "constructor": "0x60806040526040516108053803806108058339818101604052604081101561002657600080fd5b50805160209182015160408051600081529384018082527f656970313936372e70726f78792e696d706c656d656e746174696f6e00000000905251603c81850301902091929091839190600019016000805160206107aa8339815191521461008a57fe5b61009c826001600160e01b036101bd16565b805115610154576000826001600160a01b0316826040518082805190602001908083835b602083106100df5780518252601f1990920191602091820191016100c0565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855af49150503d806000811461013f576040519150601f19603f3d011682016040523d82523d6000602084013e610144565b606091505b505090508061015257600080fd5b505b5050604080517f656970313936372e70726f78792e61646d696e000000000000000000000000008152905190819003601301902060008051602061078a833981519152600019909101146101a457fe5b6101b6816001600160e01b0361023716565b505061024f565b6101d08161024960201b6104801760201c565b610225576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603b8152602001806107ca603b913960400191505060405180910390fd5b6000805160206107aa83398151915255565b60008051602061078a83398151915255565b3b151590565b61052c8061025e6000396000f3fe60806040526004361061004a5760003560e01c80633659cfe6146100545780634f1ef286146100875780635c60da1b146101075780638f28397014610138578063f851a4401461016b575b610052610180565b005b34801561006057600080fd5b506100526004803603602081101561007757600080fd5b50356001600160a01b031661019a565b6100526004803603604081101561009d57600080fd5b6001600160a01b0382351691908101906040810160208201356401000000008111156100c857600080fd5b8201836020820111156100da57600080fd5b803590602001918460018302840111640100000000831117156100fc57600080fd5b5090925090506101cb565b34801561011357600080fd5b5061011c61026f565b604080516001600160a01b039092168252519081900360200190f35b34801561014457600080fd5b506100526004803603602081101561015b57600080fd5b50356001600160a01b031661027e565b34801561017757600080fd5b5061011c61033c565b610188610198565b610198610193610346565b61036b565b565b6101a261038f565b6001600160a01b0316336001600160a01b0316146101bf57600080fd5b6101c8816103b4565b50565b6101d361038f565b6001600160a01b0316336001600160a01b0316146101f057600080fd5b6101f9836103b4565b6000836001600160a01b031683836040518083838082843760405192019450600093509091505080830381855af49150503d8060008114610256576040519150601f19603f3d011682016040523d82523d6000602084013e61025b565b606091505b505090508061026957600080fd5b50505050565b6000610279610346565b905090565b61028661038f565b6001600160a01b0316336001600160a01b0316146102a357600080fd5b6001600160a01b0381166102e85760405162461bcd60e51b81526004018080602001828103825260368152602001806104876036913960400191505060405180910390fd5b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f61031161038f565b604080516001600160a01b03928316815291841660208301528051918290030190a16101c8816103f4565b600061027961038f565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b3660008037600080366000845af43d6000803e80801561038a573d6000f35b3d6000fd5b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b6103bd81610418565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610355565b61042181610480565b61045c5760405162461bcd60e51b815260040180806020018281038252603b8152602001806104bd603b913960400191505060405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc55565b3b15159056fe43616e6e6f74206368616e6765207468652061646d696e206f6620612070726f787920746f20746865207a65726f206164647265737343616e6e6f742073657420612070726f787920696d706c656d656e746174696f6e20746f2061206e6f6e2d636f6e74726163742061646472657373a265627a7a72305820a9aab4b95b654a79b32f5aa284796894f8329aaa083932695296085b196c27bd64736f6c634300050a0032b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc43616e6e6f742073657420612070726f787920696d706c656d656e746174696f6e20746f2061206e6f6e2d636f6e747261637420616464726573730000000000000000000000006100000000000000000000000000000000000000000000000000000000000000b03a86b3126157c039b55e21d378587ccfc04d45" + }, + "0x6100000000000000000000000000000000000000": { + "balance": "0x0", + "constructor": "0x608060405234801561001057600080fd5b50611976806100206000396000f3fe608060405234801561001057600080fd5b50600436106101c45760003560e01c8063b1724b46116100f9578063dfc8bf4e11610097578063f1854e1911610071578063f1854e1914610498578063f9d5ee75146104b5578063fc87bc9e14610531578063ff1ad2d91461054e576101c4565b8063dfc8bf4e1461044f578063e523d61c14610473578063e852faad14610490576101c4565b8063bf8b68da116100d3578063bf8b68da146103d2578063c342a7bf146103ef578063c4d66de81461040c578063cd2ecdf314610432576101c4565b8063b1724b461461039f578063b384abef146103a7578063b6a6d177146103ca576101c4565b80633b79f1a511610166578063518d9fca11610140578063518d9fca1461031757806382c4c9631461033457806388cb91b614610365578063a7debe9d14610382576101c4565b80633b79f1a5146102c057806340e58ee5146102dd5780634e7b4366146102fa576101c4565b8063260f08ad116101a2578063260f08ad1461024c578063280ad39a1461026957806332eac267146102865780633381afbd146102a3576101c4565b806305261aea146101c95780630d13a1c1146101e85780630f045f691461021d575b600080fd5b6101e6600480360360208110156101df57600080fd5b503561056b565b005b61020b600480360360408110156101fe57600080fd5b5080359060200135610589565b60408051918252519081900360200190f35b6101e66004803603608081101561023357600080fd5b50803590602081013590604081013590606001356105a6565b61020b6004803603602081101561026257600080fd5b5035610c1f565b61020b6004803603602081101561027f57600080fd5b5035610c31565b61020b6004803603602081101561029c57600080fd5b5035610c43565b61020b600480360360208110156102b957600080fd5b5035610c55565b61020b600480360360208110156102d657600080fd5b5035610c67565b6101e6600480360360208110156102f357600080fd5b5035610c79565b61020b6004803603602081101561031057600080fd5b5035610e61565b61020b6004803603602081101561032d57600080fd5b5035610e73565b6103516004803603602081101561034a57600080fd5b5035610e85565b604080519115158252519081900360200190f35b61020b6004803603602081101561037b57600080fd5b50356110e8565b61020b6004803603602081101561039857600080fd5b50356110fa565b61020b61110c565b6101e6600480360360408110156103bd57600080fd5b5080359060200135611113565b61020b611375565b61020b600480360360208110156103e857600080fd5b503561137b565b61020b6004803603602081101561040557600080fd5b503561138d565b6101e66004803603602081101561042257600080fd5b50356001600160a01b031661139f565b6103516004803603602081101561044857600080fd5b503561141f565b6104576114e2565b604080516001600160a01b039092168252519081900360200190f35b61020b6004803603602081101561048957600080fd5b50356114f1565b61020b611503565b61020b600480360360208110156104ae57600080fd5b5035611509565b6104d2600480360360208110156104cb57600080fd5b503561151b565b604080519c8d5260208d019b909b528b8b019990995260608b019790975260808a019590955260a089019390935260c088019190915260e087015261010086015261012085015261014084015261016083015251908190036101800190f35b61020b6004803603602081101561054757600080fd5b5035611607565b61020b6004803603602081101561056457600080fd5b5035611619565b61057481610e85565b61057d57600080fd5b6105868161162b565b50565b600f60209081526000928352604080842090915290825290205481565b6011546040805163a26301f960e01b815233600482015290516000926001600160a01b03169163a26301f9916024808301926020929190829003018186803b1580156105f157600080fd5b505afa158015610605573d6000803e3d6000fd5b505050506040513d602081101561061b57600080fd5b505160115460408051639b4a14bf60e01b81526004810189905290519293506001600160a01b0390911691639b4a14bf91602480820192602092909190829003018186803b15801561066c57600080fd5b505afa158015610680573d6000803e3d6000fd5b505050506040513d602081101561069657600080fd5b50516106a157600080fd5b60115460408051639b4a14bf60e01b81526004810184905290516001600160a01b0390921691639b4a14bf91602480820192602092909190829003018186803b1580156106ed57600080fd5b505afa158015610701573d6000803e3d6000fd5b505050506040513d602081101561071757600080fd5b505161072257600080fd5b8085141561072f57600080fd5b6000858152602081905260409020541561074857600080fd5b60115460408051637f2a23bf60e11b815290516000926001600160a01b03169163fe54477e9160048083019286929190829003018186803b15801561078c57600080fd5b505afa1580156107a0573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405260208110156107c957600080fd5b8101908080516401000000008111156107e157600080fd5b820160208101848111156107f457600080fd5b815185602082028301116401000000008211171561081157600080fd5b50505160008681526001602081905260409091208054918201905590945060038504935083119150610844905057600080fd5b61438086101561085357600080fd5b6201518086111561086357600080fd5b716f6674656e20626c6f636b2064656c61797360701b8514806108995750706f6674656e20626c6f636b20736b69707360781b85145b806108b85750716f6674656e2072657665616c20736b69707360701b85145b806108cf5750691d5b9c995d99585b195960b21b85145b6108d857600080fd5b601080546001019081905560006108fd886108f1611810565b9063ffffffff61181416565b60008381526002602090815260408083208d90556003825280832089905560048083528184208590556011548251633ba6481760e21b81529251959650600c956001600160a01b039091169363ee99205c938084019391929190829003018186803b15801561096b57600080fd5b505afa15801561097f573d6000803e3d6000fd5b505050506040513d602081101561099557600080fd5b50516040805163d609ea9360e01b815290519192506000916001600160a01b0384169163d609ea93916004808301926020929190829003018186803b1580156109dd57600080fd5b505afa1580156109f1573d6000803e3d6000fd5b505050506040513d6020811015610a0757600080fd5b50516040805163461121d760e11b815290519192506000916001600160a01b03851691638c2243ae916004808301926020929190829003018186803b158015610a4f57600080fd5b505afa158015610a63573d6000803e3d6000fd5b505050506040513d6020811015610a7957600080fd5b5051905080851115610aaf57610aac60016108f1868186610aa08b8863ffffffff61182f16565b9063ffffffff61184416565b93505b610ac3816108f1868563ffffffff61186616565b600087815260056020526040902055610af7816108f184610aeb88600c63ffffffff61182f16565b9063ffffffff61186616565b6006600088815260200190815260200160002081905550826001600160a01b031663794c0c686040518163ffffffff1660e01b815260040160206040518083038186803b158015610b4757600080fd5b505afa158015610b5b573d6000803e3d6000fd5b505050506040513d6020811015610b7157600080fd5b50516000878152600a6020908152604080832093909355600781528282208e90556009905220600190555060029250869150610baa9050565b6000848152600b60209081526040808320949093046001019093558b81529182905290208290558515610be157610be18287611113565b6040805183815290517f06acbfb32bcf8383f3b0a768b70ac9ec234ea0f2d3b9c77fa6a2de69b919aad19181900360200190a1505050505050505050565b60006020819052908152604090205481565b60036020526000908152604090205481565b600e6020526000908152604090205481565b60076020526000908152604090205481565b60026020526000908152604090205481565b6011546040805163a26301f960e01b815233600482015290516000926001600160a01b03169163a26301f9916024808301926020929190829003018186803b158015610cc457600080fd5b505afa158015610cd8573d6000803e3d6000fd5b505050506040513d6020811015610cee57600080fd5b50516000838152600360205260409020549091508114610d0d57600080fd5b600082815260096020526040902054600114610d2857600080fd5b600082815260046020526040902054610d3f611810565b10610d4957600080fd5b60115460408051639b4a14bf60e01b81526004810184905290516001600160a01b0390921691639b4a14bf91602480820192602092909190829003018186803b158015610d9557600080fd5b505afa158015610da9573d6000803e3d6000fd5b505050506040513d6020811015610dbf57600080fd5b5051610dca57600080fd5b60008281526009602090815260408083206003905583835260019182905290912054610dfb9163ffffffff61182f16565b6000828152600160209081526040808320939093558482526002815282822054808352828252838320929092558251858152925191927f829a8683c544ad289ce92d3ce06e9ebad69b18a6916e60ec766c2c217461d8e9929081900390910190a1505050565b600d6020526000908152604090205481565b60086020526000908152604090205481565b600081815260096020526040812054600114610ea3575060006110e3565b600082815260046020526040902054610eba611810565b10610ec7575060016110e3565b6000828152600a6020908152604091829020546011548351633ba6481760e21b8152935191936001600160a01b039091169263ee99205c92600480840193829003018186803b158015610f1957600080fd5b505afa158015610f2d573d6000803e3d6000fd5b505050506040513d6020811015610f4357600080fd5b505160408051630f29818d60e31b815290516001600160a01b039092169163794c0c6891600480820192602092909190829003018186803b158015610f8757600080fd5b505afa158015610f9b573d6000803e3d6000fd5b505050506040513d6020811015610fb157600080fd5b505114156110df576000828152600c6020908152604080832054600d835281842054600e909352818420546011548351637f2a23bf60e11b815293519295919391926001600160a01b039091169163fe54477e9160048083019286929190829003018186803b15801561102357600080fd5b505afa158015611037573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561106057600080fd5b81019080805164010000000081111561107857600080fd5b8201602081018481111561108b57600080fd5b81518560208202830111640100000000821117156110a857600080fd5b50505193508392506110c891508490506108f1878763ffffffff61181416565b106110da5760019450505050506110e3565b505050505b5060005b919050565b60016020526000908152604090205481565b60066020526000908152604090205481565b6201518081565b60008281526003602052604090205461112b57600080fd5b6011546040805163a26301f960e01b815233600482015290516000926001600160a01b03169163a26301f9916024808301926020929190829003018186803b15801561117657600080fd5b505afa15801561118a573d6000803e3d6000fd5b505050506040513d60208110156111a057600080fd5b505160115460408051639b4a14bf60e01b81526004810184905290519293506001600160a01b0390911691639b4a14bf91602480820192602092909190829003018186803b1580156111f157600080fd5b505afa158015611205573d6000803e3d6000fd5b505050506040513d602081101561121b57600080fd5b505161122657600080fd5b60008381526002602052604090205481141561124157600080fd5b60008381526009602052604090205460011461125c57600080fd5b600083815260046020526040902054611273611810565b1061127d57600080fd5b6000838152600f60209081526040808320848452909152902054156112a157600080fd5b6000838152600f60209081526040808320848452909152902082905560018214156112e0576000838152600c6020526040902080546001019055611322565b6002821415611303576000838152600d6020526040902080546001019055611322565b60038214156101c4576000838152600e60205260409020805460010190555b604080518381529051829185917f5fe8f1cc066896edbe87bedf2e870c54f6311a7d6668c860949e2e1224a0955e9181900360200190a361136283610e85565b15611370576113708361162b565b505050565b61438081565b600a6020526000908152604090205481565b60046020526000908152604090205481565b6113a7611810565b15806113cb57506113b661188d565b6001600160a01b0316336001600160a01b0316145b6113d457600080fd5b6011546001600160a01b0316156113ea57600080fd5b6001600160a01b0381166113fd57600080fd5b601180546001600160a01b0319166001600160a01b0392909216919091179055565b60008181526020819052604081205480158061144a5750600081815260096020526040902054600114155b156114595760009150506110e3565b600081815260046020526040902054611470611810565b10156114805760019150506110e3565b600061148b826118b2565b905060028114156114b8576000828152600660205260409020546114ad611810565b1115925050506110e3565b60038114156114d8576000828152600560205260409020546114ad611810565b5060009392505050565b6011546001600160a01b031681565b60056020526000908152604090205481565b60105481565b600c6020526000908152604090205481565b60008181526002602090815260408083205460038352818420546004845282852054600585528386205460068652848720546007875285882054600988528689205460089098529588205494979396929591949093919291908190819081908190156115955760008d81526008602052604090205461159e565b61159e8d6118b2565b9450600b60008e8152602001908152602001600020549350600c60008e8152602001908152602001600020549250600d60008e8152602001908152602001600020549150600e60008e815260200190815260200160002054905091939597999b5091939597999b565b600b6020526000908152604090205481565b60096020526000908152604090205481565b6011546001600160a01b031661164057600080fd5b600061164b826118b2565b600083815260036020908152604080832054600283528184205460088452828520869055818552600193849052919093205493945091926116919163ffffffff61182f16565b60008381526001602052604090205560028314156117355760115460008581526006602090815260408083205460079092528083205481516305461c8560e01b81526004810187905260248101939093526044830152516001600160a01b03909316926305461c859260648084019391929182900301818387803b15801561171857600080fd5b505af115801561172c573d6000803e3d6000fd5b505050506117c6565b60038314156117c65760115460008581526005602090815260408083205460079092528083205481516305461c8560e01b81526004810187905260248101939093526044830152516001600160a01b03909316926305461c859260648084019391929182900301818387803b1580156117ad57600080fd5b505af11580156117c1573d6000803e3d6000fd5b505050505b60008181526020818152604080832092909255815186815291517f839cf22e1ba87ce2f5b9bbf46cf0175a09eed52febdfaac8852478e68203c7639281900390910190a150505050565b4390565b60008282018381101561182657600080fd5b90505b92915050565b60008282111561183e57600080fd5b50900390565b600080821161185257600080fd5b600082848161185d57fe5b04949350505050565b60008261187557506000611829565b8282028284828161188257fe5b041461182657600080fd5b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b6000818152600c6020908152604080832054600d835281842054600e845282852054600b909452918420549092906118f4826108f1868663ffffffff61181416565b101561190657600193505050506110e3565b600181831115611921578383111561191c575060025b611938565b828211801561192f57508382115b15611938575060035b9594505050505056fea265627a7a723058200623ccf119f7da78633edc0832418c3a32f1244627f261a1dc1d135e3ceccba164736f6c634300050a0032" + }, + "0x6000000000000000000000000000000000000000": { + "balance": "0x0", + "constructor": "0x6080604052600080546001600160a01b03191633179055670de0b6b3a764000060035534801561002e57600080fd5b506040516120943803806120948339818101604052604081101561005157600080fd5b5080516020909101516001600160a01b03821661006d57600080fd5b604080517f736572766963655f7472616e73616374696f6e5f636865636b657200000000008152905190819003601b019020336001600160a01b038316156100cd5750600080546001600160a01b0319166001600160a01b038416179055815b600082815260016020819052604080832080546001600160a01b0386166001600160a01b03199091168117825582517f4100000000000000000000000000000000000000000000000000000000000000815260029092019382019390935290519081900360210181206001600160601b0319606089901b169055909184917f4963513eca575aba66fdcd25f267aae85958fe6fb97e75fa25d783f1a091a2219190a36040805181815260018183018190527f41000000000000000000000000000000000000000000000000000000000000006060830181905260806020840181905283019190915260a0820152905183917fb829c3e412537bbe794c048ccb9e4605bb4aaaa8e4d4c15c1a6e0c2adc1716ea919081900360c00190a250505050611e98806101fc6000396000f3fe60806040526004361061014b5760003560e01c80639890220b116100b6578063df57b7421161006f578063df57b742146105e6578063e30bd74014610610578063eadf9760146106b8578063ef5454d61461073a578063f25eb5c1146107be578063f6d339e4146107d35761014b565b80639890220b146104e4578063ac4e73f9146104f9578063ac72c1201461057d578063c3a3582514610426578063ddca3f43146105a7578063deb931a2146105bc5761014b565b80636795dbcd116101085780636795dbcd1461031057806369fe0e2d146103ae57806379ce9fac146103d85780638da5cb5b1461041157806390b97fc11461042657806392698814146104ba5761014b565b806306b2ff471461015057806313af40351461019757806319362a28146101cc5780633f3935d11461024e578063432ced04146102c95780634f39ca59146102e6575b600080fd5b34801561015c57600080fd5b506101836004803603602081101561017357600080fd5b50356001600160a01b031661085e565b604080519115158252519081900360200190f35b3480156101a357600080fd5b506101ca600480360360208110156101ba57600080fd5b50356001600160a01b031661088d565b005b3480156101d857600080fd5b50610183600480360360608110156101ef57600080fd5b81359190810190604081016020820135600160201b81111561021057600080fd5b82018360208201111561022257600080fd5b803590602001918460018302840111600160201b8311171561024357600080fd5b919350915035610912565b34801561025a57600080fd5b506101836004803603602081101561027157600080fd5b810190602081018135600160201b81111561028b57600080fd5b82018360208201111561029d57600080fd5b803590602001918460018302840111600160201b831117156102be57600080fd5b509092509050610a5b565b610183600480360360208110156102df57600080fd5b5035610be4565b3480156102f257600080fd5b506101836004803603602081101561030957600080fd5b5035610c91565b34801561031c57600080fd5b506103926004803603604081101561033357600080fd5b81359190810190604081016020820135600160201b81111561035457600080fd5b82018360208201111561036657600080fd5b803590602001918460018302840111600160201b8311171561038757600080fd5b509092509050610efa565b604080516001600160a01b039092168252519081900360200190f35b3480156103ba57600080fd5b50610183600480360360208110156103d157600080fd5b5035610f8c565b3480156103e457600080fd5b50610183600480360360408110156103fb57600080fd5b50803590602001356001600160a01b0316610fe4565b34801561041d57600080fd5b506103926110b4565b34801561043257600080fd5b506104a86004803603604081101561044957600080fd5b81359190810190604081016020820135600160201b81111561046a57600080fd5b82018360208201111561047c57600080fd5b803590602001918460018302840111600160201b8311171561049d57600080fd5b5090925090506110c3565b60408051918252519081900360200190f35b3480156104c657600080fd5b50610183600480360360208110156104dd57600080fd5b5035611152565b3480156104f057600080fd5b506101836111bb565b34801561050557600080fd5b506101836004803603604081101561051c57600080fd5b810190602081018135600160201b81111561053657600080fd5b82018360208201111561054857600080fd5b803590602001918460018302840111600160201b8311171561056957600080fd5b9193509150356001600160a01b031661123d565b34801561058957600080fd5b50610183600480360360208110156105a057600080fd5b5035611546565b3480156105b357600080fd5b506104a86115b3565b3480156105c857600080fd5b50610392600480360360208110156105df57600080fd5b50356115b9565b3480156105f257600080fd5b506103926004803603602081101561060957600080fd5b5035611620565b34801561061c57600080fd5b506106436004803603602081101561063357600080fd5b50356001600160a01b031661168b565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561067d578181015183820152602001610665565b50505050905090810190601f1680156106aa5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156106c457600080fd5b50610183600480360360608110156106db57600080fd5b81359190810190604081016020820135600160201b8111156106fc57600080fd5b82018360208201111561070e57600080fd5b803590602001918460018302840111600160201b8311171561072f57600080fd5b919350915035611734565b34801561074657600080fd5b506101836004803603604081101561075d57600080fd5b810190602081018135600160201b81111561077757600080fd5b82018360208201111561078957600080fd5b803590602001918460018302840111600160201b831117156107aa57600080fd5b9193509150356001600160a01b0316611880565b3480156107ca57600080fd5b506101ca6119c4565b3480156107df57600080fd5b50610183600480360360608110156107f657600080fd5b81359190810190604081016020820135600160201b81111561081757600080fd5b82018360208201111561082957600080fd5b803590602001918460018302840111600160201b8311171561084a57600080fd5b9193509150356001600160a01b0316611c30565b6001600160a01b0316600090815260026020819052604090912054600181161561010002600019011604151590565b6000546001600160a01b031633146108a457600080fd5b6001600160a01b0381166108b757600080fd5b600080546040516001600160a01b03808516939216917f70aea8d848e8a90fb7661b227dc522eb6395c3dac71b63cb59edd5c9899b236491a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b6000848152600160208190526040822001548590600160a01b900460ff1615801561095357506000818152600160205260409020546001600160a01b031615155b61095c57600080fd5b60008681526001602052604090205486906001600160a01b0316331461098157600080fd5b83600160008981526020019081526020016000206002018787604051808383808284378083019250505092505050908152602001604051809103902081905550867fb829c3e412537bbe794c048ccb9e4605bb4aaaa8e4d4c15c1a6e0c2adc1716ea878789896040518080602001806020018381038352878782818152602001925080828437600083820152601f01601f191690910184810383528581526020019050858580828437600083820152604051601f909101601f19169092018290039850909650505050505050a25060019695505050505050565b600082828080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201829052508451602080870191909120825260019081905260409091200154600160a01b900460ff161592505081159050610ae6575080516020808301919091206000908152600190915260409020546001600160a01b031615155b610aef57600080fd5b83838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092018290525084516020808701919091208252600190819052604090912001546001600160a01b031633149250610b5491505057600080fd5b336000908152600260205260409020610b6e908686611d8b565b50336001600160a01b03167f098ae8581bb8bd9af1beaf7f2e9f51f31a8e5a8bfada4e303a645d71d9c91920868660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a2506001949350505050565b6000818152600160208190526040822001548290600160a01b900460ff16158015610c2457506000818152600160205260409020546001600160a01b0316155b610c2d57600080fd5b600354341015610c3c57600080fd5b60008381526001602052604080822080546001600160a01b031916339081179091559051909185917f4963513eca575aba66fdcd25f267aae85958fe6fb97e75fa25d783f1a091a2219190a350600192915050565b6000818152600160208190526040822001548290600160a01b900460ff16158015610cd257506000818152600160205260409020546001600160a01b031615155b610cdb57600080fd5b60008381526001602052604090205483906001600160a01b03163314610d0057600080fd5b60008481526001602081815260408084208301546001600160a01b03168452600291829052928390209251835488949391928392859260001991811615610100029190910116048015610d8a5780601f10610d68576101008083540402835291820191610d8a565b820191906000526020600020905b815481529060010190602001808311610d76575b505091505060405180910390201415610ea25760008481526001602081815260408084208301546001600160a01b03168085526002808452948290208251848152815460001996811615610100029690960190951695909504928401839052937f12491ad95fd945e444d88a894ffad3c21959880a4dcd8af99d4ae4ffc71d4abd939092909182919082019084908015610e655780601f10610e3a57610100808354040283529160200191610e65565b820191906000526020600020905b815481529060010190602001808311610e4857829003601f168201915b50509250505060405180910390a26000848152600160208181526040808420909201546001600160a01b03168352600290528120610ea291611e09565b6000848152600160208190526040808320909101805460ff60a01b1916600160a01b17905551339186917fef1961b4d2909dc23643b309bfe5c3e5646842d98c3a58517037ef3871185af39190a35060019392505050565b6000838152600160208190526040822001548490600160a01b900460ff16158015610f3b57506000818152600160205260409020546001600160a01b031615155b610f4457600080fd5b60016000868152602001908152602001600020600201848460405180838380828437919091019485525050604051928390036020019092205460601c93505050509392505050565b600080546001600160a01b03163314610fa457600080fd5b60038290556040805183815290517f6bbc57480a46553fa4d156ce702beef5f3ad66303b0ed1a5d4cb44966c6584c39181900360200190a1506001919050565b6000828152600160208190526040822001548390600160a01b900460ff1615801561102557506000818152600160205260409020546001600160a01b031615155b61102e57600080fd5b60008481526001602052604090205484906001600160a01b0316331461105357600080fd5b60008581526001602052604080822080546001600160a01b0319166001600160a01b03881690811790915590519091339188917f7b97c62130aa09acbbcbf7482630e756592496f1759eaf702f469cf64dfb779491a4506001949350505050565b6000546001600160a01b031681565b6000838152600160208190526040822001548490600160a01b900460ff1615801561110457506000818152600160205260409020546001600160a01b031615155b61110d57600080fd5b60016000868152602001908152602001600020600201848460405180838380828437919091019485525050604051928390036020019092205493505050509392505050565b6000818152600160208190526040822001548290600160a01b900460ff1615801561119357506000818152600160205260409020546001600160a01b031615155b61119c57600080fd5b50506000908152600160205260409020546001600160a01b0316151590565b600080546001600160a01b031633146111d357600080fd5b604080513031815290517fdef931299fe61d176f949118058530c1f3f539dcb6950b4e372c9b835c33ca079181900360200190a16040513390303180156108fc02916000818181858888f19350505050158015611234573d6000803e3d6000fd5b50600190505b90565b600083838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201829052508451602080870191909120825260019081905260409091200154600160a01b900460ff1615925050811590506112c8575080516020808301919091206000908152600190915260409020546001600160a01b031615155b6112d157600080fd5b8484604051808383808284376040805193909101839003909220600081815260016020529290922054919450506001600160a01b031633149150611316905057600080fd5b60008686604051808383808284376040805191909301819003902060008181526001602081905293902090920154919550506001600160a01b0316158015935091506113f89050575060008181526001602081815260408084208301546001600160a01b031684526002918290529283902092518354859493919283928592600019918116156101000291909101160480156113e95780601f106113c75761010080835404028352918201916113e9565b820191906000526020600020905b8154815290600101906020018083116113d5575b50509150506040518091039020145b156114aa576000818152600160208181526040808420909201546001600160a01b0316835260029052812061142c91611e09565b6000818152600160208181526040928390209091015482518281529182018990526001600160a01b0316917f12491ad95fd945e444d88a894ffad3c21959880a4dcd8af99d4ae4ffc71d4abd918a918a919081908101848480828437600083820152604051601f909101601f19169092018290039550909350505050a25b60008181526001602081815260409283902090910180546001600160a01b0319166001600160a01b0389169081179091558251828152918201899052917f728435a0031f6a04538fcdd24922a7e06bc7bc945db03e83d22122d1bc5f28df918a918a919081908101848480828437600083820152604051601f909101601f19169092018290039550909350505050a25060019695505050505050565b6000818152600160208190526040822001548290600160a01b900460ff1615801561158757506000818152600160205260409020546001600160a01b031615155b61159057600080fd5b5050600090815260016020819052604090912001546001600160a01b0316151590565b60035481565b6000818152600160208190526040822001548290600160a01b900460ff161580156115fa57506000818152600160205260409020546001600160a01b031615155b61160357600080fd5b50506000908152600160205260409020546001600160a01b031690565b6000818152600160208190526040822001548290600160a01b900460ff1615801561166157506000818152600160205260409020546001600160a01b031615155b61166a57600080fd5b5050600090815260016020819052604090912001546001600160a01b031690565b6001600160a01b038116600090815260026020818152604092839020805484516001821615610100026000190190911693909304601f810183900483028401830190945283835260609390918301828280156117285780601f106116fd57610100808354040283529160200191611728565b820191906000526020600020905b81548152906001019060200180831161170b57829003601f168201915b50505050509050919050565b6000848152600160208190526040822001548590600160a01b900460ff1615801561177557506000818152600160205260409020546001600160a01b031615155b61177e57600080fd5b60008681526001602052604090205486906001600160a01b031633146117a357600080fd5b8360001b600160008981526020019081526020016000206002018787604051808383808284378083019250505092505050908152602001604051809103902081905550867fb829c3e412537bbe794c048ccb9e4605bb4aaaa8e4d4c15c1a6e0c2adc1716ea878789896040518080602001806020018381038352878782818152602001925080828437600083820152601f01601f191690910184810383528581526020019050858580828437600083820152604051601f909101601f19169092018290039850909650505050505050a25060019695505050505050565b600083838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201829052508451602080870191909120825260019081905260409091200154600160a01b900460ff16159250508115905061190b575080516020808301919091206000908152600190915260409020546001600160a01b031615155b61191457600080fd5b6000546001600160a01b0316331461192b57600080fd5b6001600160a01b038316600090815260026020526040902061194e908686611d8b565b50826001600160a01b03167f098ae8581bb8bd9af1beaf7f2e9f51f31a8e5a8bfada4e303a645d71d9c91920868660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a2506001949350505050565b33600090815260026020818152604092839020805484516001821615610100026000190190911693909304601f8101839004830284018301909452838352919290830182828015611a565780601f10611a2b57610100808354040283529160200191611a56565b820191906000526020600020905b815481529060010190602001808311611a3957829003601f168201915b5050505050600160008280519060200120815260200190815260200160002060010160149054906101000a900460ff16158015611ab4575080516020808301919091206000908152600190915260409020546001600160a01b031615155b611abd57600080fd5b33600081815260026020818152604092839020835182815281546000196101006001831615020116939093049183018290527f12491ad95fd945e444d88a894ffad3c21959880a4dcd8af99d4ae4ffc71d4abd93909291829182019084908015611b685780601f10611b3d57610100808354040283529160200191611b68565b820191906000526020600020905b815481529060010190602001808311611b4b57829003601f168201915b50509250505060405180910390a2336000908152600260208190526040808320905181546001949382918491600019610100838a16150201909116048015611be75780601f10611bc5576101008083540402835291820191611be7565b820191906000526020600020905b815481529060010190602001808311611bd3575b505060408051918290039091208452602080850195909552928301600090812060010180546001600160a01b0319169055338152600290945250508120611c2d91611e09565b50565b6000848152600160208190526040822001548590600160a01b900460ff16158015611c7157506000818152600160205260409020546001600160a01b031615155b611c7a57600080fd5b60008681526001602052604090205486906001600160a01b03163314611c9f57600080fd5b8360601b6bffffffffffffffffffffffff1916600160008981526020019081526020016000206002018787604051808383808284378083019250505092505050908152602001604051809103902081905550867fb829c3e412537bbe794c048ccb9e4605bb4aaaa8e4d4c15c1a6e0c2adc1716ea878789896040518080602001806020018381038352878782818152602001925080828437600083820152601f01601f191690910184810383528581526020019050858580828437600083820152604051601f909101601f19169092018290039850909650505050505050a25060019695505050505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10611dcc5782800160ff19823516178555611df9565b82800160010185558215611df9579182015b82811115611df9578235825591602001919060010190611dde565b50611e05929150611e49565b5090565b50805460018160011615610100020316600290046000825580601f10611e2f5750611c2d565b601f016020900490600052602060002090810190611c2d91905b61123a91905b80821115611e055760008155600101611e4f56fea265627a7a723058206a686f5fa03e765c624a73295db57b5403554102e83af1f6c94d41e196e3939564736f6c634300050a00320000000000000000000000005000000000000000000000000000000000000001000000000000000000000000b03a86b3126157c039b55e21d378587ccfc04d45" + }, + "0x7000000000000000000000000000000000000000": { + "balance": "0x0", + "constructor": "0x608060405234801561001057600080fd5b506040516109dd3803806109dd833981810160405261016081101561003457600080fd5b81019080805164010000000081111561004c57600080fd5b8201602081018481111561005f57600080fd5b815185602082028301116401000000008211171561007c57600080fd5b505060208201516040909201805191949293916401000000008111156100a157600080fd5b820160208101848111156100b457600080fd5b81518560208202830111640100000000821117156100d157600080fd5b505092919060200180516401000000008111156100ed57600080fd5b8201602081018481111561010057600080fd5b815185602082028301116401000000008211171561011d57600080fd5b5050602082015160408301516060840151608085015160a086015160c087015160e0909701518c51969950949750929591949093908b9060009061015d57fe5b60200260200101516001600160a01b0316636e85d53d8c60018151811061018057fe5b60200260200101518d60068151811061019557fe5b60200260200101518e6002815181106101aa57fe5b60200260200101518f6003815181106101bf57fe5b60200260200101518e8e8e6040518863ffffffff1660e01b815260040180886001600160a01b03166001600160a01b03168152602001876001600160a01b03166001600160a01b03168152602001866001600160a01b03166001600160a01b03168152602001856001600160a01b03166001600160a01b03168152602001806020018060200184151515158152602001838103835286818151815260200191508051906020019060200280838360005b8381101561028757818101518382015260200161026f565b50505050905001838103825285818151815260200191508051906020019060200280838360005b838110156102c65781810151838201526020016102ae565b505050509050019950505050505050505050600060405180830381600087803b1580156102f257600080fd5b505af1158015610306573d6000803e3d6000fd5b5050505060608851604051908082528060200260200182016040528015610337578160200160208202803883390190505b50905060005b8151811015610410578c60008151811061035357fe5b60200260200101516001600160a01b031663a26301f98b838151811061037557fe5b60200260200101516040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b1580156103c357600080fd5b505afa1580156103d7573d6000803e3d6000fd5b505050506040513d60208110156103ed57600080fd5b505182518390839081106103fd57fe5b602090810291909101015260010161033d565b508b60038151811061041e57fe5b60200260200101516001600160a01b031663cc4a66678d60008151811061044157fe5b60200260200101518e60068151811061045657fe5b6020026020010151848b8b8b8b8b6040518963ffffffff1660e01b815260040180896001600160a01b03166001600160a01b03168152602001886001600160a01b03166001600160a01b0316815260200180602001878152602001868152602001858152602001848152602001838152602001828103825288818151815260200191508051906020019060200280838360005b838110156105015781810151838201526020016104e9565b505050509050019950505050505050505050600060405180830381600087803b15801561052d57600080fd5b505af1158015610541573d6000803e3d6000fd5b50505050508a60018151811061055357fe5b60200260200101516001600160a01b031663485cc9558c60008151811061057657fe5b602002602001015160006040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b03168152602001826001600160a01b03166001600160a01b0316815260200192505050600060405180830381600087803b1580156105e157600080fd5b505af11580156105f5573d6000803e3d6000fd5b505050508a60028151811061060657fe5b60200260200101516001600160a01b03166328804dbd828d60008151811061062a57fe5b602002602001015160016040518463ffffffff1660e01b815260040180848152602001836001600160a01b03166001600160a01b03168152602001821515151581526020019350505050600060405180830381600087803b15801561068e57600080fd5b505af11580156106a2573d6000803e3d6000fd5b5050604080516001808252818301909252606093509150602080830190803883390190505090508a816000815181106106d757fe5b60200260200101906001600160a01b031690816001600160a01b0316815250508b60048151811061070457fe5b60200260200101516001600160a01b03166390482d72828e60058151811061072857fe5b60200260200101518f60008151811061073d57fe5b60200260200101516040518463ffffffff1660e01b81526004018080602001846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b03168152602001828103825285818151815260200191508051906020019060200280838360005b838110156107c45781810151838201526020016107ac565b50505050905001945050505050600060405180830381600087803b1580156107eb57600080fd5b505af11580156107ff573d6000803e3d6000fd5b505050508b60058151811061081057fe5b60200260200101516001600160a01b031663462d0b2e828e60008151811061083457fe5b60200260200101516040518363ffffffff1660e01b81526004018080602001836001600160a01b03166001600160a01b03168152602001828103825284818151815260200191508051906020019060200280838360005b838110156108a357818101518382015260200161088b565b505050509050019350505050600060405180830381600087803b1580156108c957600080fd5b505af11580156108dd573d6000803e3d6000fd5b505050508b6006815181106108ee57fe5b60200260200101516001600160a01b031663c4d66de88d60008151811061091157fe5b60200260200101516040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b03168152602001915050600060405180830381600087803b15801561096157600080fd5b505af1158015610975573d6000803e3d6000fd5b5050505060004311156109855733ff5b505050505050505050505050603e8061099f6000396000f3fe6080604052600080fdfea265627a7a72305820a55f32c63be7e06dfeb1da79cfe2235ed39ef2873ad64c118154d8cdff8e697e64736f6c634300050a00320000000000000000000000000000000000000000000000000000000000000160000000000000000000000000b03a86b3126157c039b55e21d378587ccfc04d45000000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000000000000000003c00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000000000000000000000000001bc16d674ec800000000000000000000000000000000000000000000000000000000000000000004c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000070000000000000000000000001000000000000000000000000000000000000001000000000000000000000000200000000000000000000000000000000000000100000000000000000000000030000000000000000000000000000000000000010000000000000000000000001100000000000000000000000000000000000001000000000000000000000000400000000000000000000000000000000000000100000000000000000000000050000000000000000000000000000000000000010000000000000000000000006100000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000014747a698ec1227e6753026c08b29b4d5d3bc48400000000000000000000000056d421c0ac39976e89fa400d34ca6579417b84ca0000000000000000000000005cd99ac2f0f8c25a1e670f6bab19d52aad69d87500000000000000000000000060f1cf46b42df059b98acf67c1dd7771b100e124000000000000000000000000655e97ba0f63a56c2b56eb3e84f7bf42b20bae14000000000000000000000000755b6259938d140626301c0b6026c1c00c9ed5d9000000000000000000000000a8010da9cb0ac018c86a06301963853cc371a18c000000000000000000000000e11c7ffea05634889f39a1d997772b73adfd685b000000000000000000000000e621f323f5cb0ca55a041aeea0f025ce338b8aee000000000000000000000000f85bb4a67db28522644cbe63595d1665b64090ef000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000047200b51fcbf7177c24c1a484c960be8bf9abf00000000000000000000000001753f99abe0433fc81e396bc1bdabec6b0f1d49d0000000000000000000000001fd4b06403e95eb0114cb3e8f6b71f7a0cc58d7300000000000000000000000041bec4dcb8dd230cb4e077c5fda61d37798b06d90000000000000000000000004b56e96ad92b4d81f533c5716988f9f3665125d20000000000000000000000005d46a20c7e9bd3556e36d39ea1a931f9fe994519000000000000000000000000cc80dff6b6386b56213a9f2701a67ebeca0bbea8000000000000000000000000dc8a45c55f83ac461bc49662324d2ad2ea811e84000000000000000000000000dd3cd543a443bd405bfbea1165753794906bd994000000000000000000000000fdd90b7d2b52a6232675f54bb2f03a5dfb2e832a" + } +} diff --git a/core/allocs/gnosis.json b/core/allocs/gnosis.json new file mode 100644 index 000000000000..ddb896259ffa --- /dev/null +++ b/core/allocs/gnosis.json @@ -0,0 +1,14 @@ +{ + "0x0000000000000000000000000000000000000001": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000002": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000003": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000004": { + "balance": "0x1" + } +} diff --git a/core/forkid/forkid.go b/core/forkid/forkid.go index 76825d3befc1..f5abe2fda55c 100644 --- a/core/forkid/forkid.go +++ b/core/forkid/forkid.go @@ -293,5 +293,13 @@ func gatherForks(config *params.ChainConfig, genesis uint64) ([]uint64, []uint64 for len(forksByTime) > 0 && forksByTime[0] <= genesis { forksByTime = forksByTime[1:] } - return forksByBlock, forksByTime + // hack-insert the poa reward contract block + var hackedForksByBlock []uint64 + for i := range forksByBlock { + if i > 0 && forksByBlock[i-1] < 9186425 && forksByBlock[i] > 9186425 { + hackedForksByBlock = append(hackedForksByBlock, 9186425) + } + hackedForksByBlock = append(hackedForksByBlock, forksByBlock[i]) + } + return hackedForksByBlock, forksByTime } diff --git a/core/genesis.go b/core/genesis.go index 634be9a9e0b1..dba416992a3a 100644 --- a/core/genesis.go +++ b/core/genesis.go @@ -18,6 +18,7 @@ package core import ( "bytes" + "embed" "encoding/hex" "encoding/json" "errors" @@ -66,6 +67,7 @@ type Genesis struct { BaseFee *big.Int `json:"baseFeePerGas"` // EIP-1559 ExcessBlobGas *uint64 `json:"excessBlobGas"` // EIP-4844 BlobGasUsed *uint64 `json:"blobGasUsed"` // EIP-4844 + AuRaSeal []byte `json:"auraSeal,omitempty"` } func ReadGenesis(db ethdb.Database) (*Genesis, error) { @@ -416,6 +418,10 @@ func (g *Genesis) configOrDefault(ghash common.Hash) *params.ChainConfig { return params.SepoliaChainConfig case ghash == params.GoerliGenesisHash: return params.GoerliChainConfig + case ghash == params.GnosisGenesisHash: + return params.GnosisChainConfig + case ghash == params.ChiadoGenesisHash: + return params.ChiadoChainConfig default: return params.AllEthashProtocolChanges } @@ -445,6 +451,7 @@ func (g *Genesis) ToBlock() *types.Block { Difficulty: g.Difficulty, MixDigest: g.Mixhash, Coinbase: g.Coinbase, + Signature: g.AuRaSeal, Root: root, } if g.GasLimit == 0 { @@ -579,6 +586,46 @@ func DefaultHoleskyGenesisBlock() *Genesis { } } +//go:embed allocs +var allocs embed.FS + +func readPrealloc(filename string) GenesisAlloc { + f, err := allocs.Open(filename) + if err != nil { + panic(fmt.Sprintf("Could not open genesis preallocation for %s: %v", filename, err)) + } + defer f.Close() + decoder := json.NewDecoder(f) + ga := make(GenesisAlloc) + err = decoder.Decode(&ga) + if err != nil { + panic(fmt.Sprintf("Could not parse genesis preallocation for %s: %v", filename, err)) + } + return ga +} + +func DefaultGnosisGenesisBlock() *Genesis { + return &Genesis{ + Config: params.GnosisChainConfig, + Timestamp: 0, + AuRaSeal: common.FromHex("0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), + GasLimit: 0x989680, + Difficulty: big.NewInt(0x20000), + Alloc: readPrealloc("allocs/gnosis.json"), + } +} + +func DefaultChiadoGenesisBlock() *Genesis { + return &Genesis{ + Config: params.ChiadoChainConfig, + Timestamp: 0, + AuRaSeal: common.FromHex("0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), + GasLimit: 0x989680, + Difficulty: big.NewInt(0x20000), + Alloc: readPrealloc("allocs/chiado.json"), + } +} + // DeveloperGenesisBlock returns the 'geth --dev' genesis block. func DeveloperGenesisBlock(gasLimit uint64, faucet *common.Address) *Genesis { // Override the default period to the user requested one diff --git a/core/rawdb/accessors_chain_aura.go b/core/rawdb/accessors_chain_aura.go new file mode 100644 index 000000000000..a5a9e8060923 --- /dev/null +++ b/core/rawdb/accessors_chain_aura.go @@ -0,0 +1,65 @@ +package rawdb + +import ( + "encoding/binary" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethdb" +) + +func ReadEpoch(db ethdb.KeyValueReader, blockNum uint64, blockHash common.Hash) (transitionProof []byte, err error) { + k := make([]byte, 40 /* block num uint64 + block hash */) + binary.BigEndian.PutUint64(k, blockNum) + copy(k[8:], blockHash[:]) + return db.Get(epochKey(k)) +} + +// TODO use sqlite if leveldb doesn't work +func FindEpochBeforeOrEqualNumber(db ethdb.KeyValueStore, n uint64) (blockNum uint64, blockHash common.Hash, transitionProof []byte, err error) { + // seek := make([]byte, 8) + // if n > 1 { + // move to the previous block - but actually this + // could be way older than the previous block number. + // binary.BigEndian.PutUint64(seek, n-1) + // } + + it := db.NewIterator(EpochPrefix, nil) + defer it.Release() + + blockNum = 0 + for it.Next() { + k := it.Key() + k = k[len(EpochPrefix):] + num := binary.BigEndian.Uint64(k) + if num > n { + break + } + + blockNum = num + transitionProof = it.Value() + blockHash = common.BytesToHash(k[8:]) + } + + return +} + +func WriteEpoch(db ethdb.KeyValueWriter, blockNum uint64, blockHash common.Hash, transitionProof []byte) (err error) { + k := make([]byte, 40) + binary.BigEndian.PutUint64(k, blockNum) + copy(k[8:], blockHash[:]) + return db.Put(epochKey(k), transitionProof) +} + +func ReadPendingEpoch(db ethdb.KeyValueReader, blockNum uint64, blockHash common.Hash) (transitionProof []byte, err error) { + k := make([]byte, 8+32) + binary.BigEndian.PutUint64(k, blockNum) + copy(k[8:], blockHash[:]) + return db.Get(pendingEpochKey(k)) +} + +func WritePendingEpoch(db ethdb.KeyValueWriter, blockNum uint64, blockHash common.Hash, transitionProof []byte) (err error) { + k := make([]byte, 8+32) + binary.BigEndian.PutUint64(k, blockNum) + copy(k[8:], blockHash[:]) + return db.Put(pendingEpochKey(k), transitionProof) +} diff --git a/core/rawdb/schema.go b/core/rawdb/schema.go index be037235533a..22ef545fd54d 100644 --- a/core/rawdb/schema.go +++ b/core/rawdb/schema.go @@ -119,6 +119,9 @@ var ( configPrefix = []byte("ethereum-config-") // config prefix for the db genesisPrefix = []byte("ethereum-genesis-") // genesis state prefix for the db + EpochPrefix = []byte("aura-epoch-") + PendingEpochPrefix = []byte("aura-pending-epoch-") + // BloomBitsIndexPrefix is the data table of a chain indexer to track its progress BloomBitsIndexPrefix = []byte("iB") @@ -337,3 +340,11 @@ func IsStorageTrieNode(key []byte) bool { ok, _, _ := ResolveStorageTrieNode(key) return ok } + +func epochKey(key []byte) []byte { + return append(EpochPrefix, key...) +} + +func pendingEpochKey(key []byte) []byte { + return append(PendingEpochPrefix, key...) +} diff --git a/core/state/statedb.go b/core/state/statedb.go index 905944cbb5b9..df687610ab77 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -831,7 +831,7 @@ func (s *StateDB) Finalise(deleteEmptyObjects bool) { // Thus, we can safely ignore it here continue } - if obj.selfDestructed || (deleteEmptyObjects && obj.empty()) { + if obj.selfDestructed || (deleteEmptyObjects && obj.empty() && obj.address != params.SystemAddress) { obj.deleted = true // We need to maintain account deletions explicitly (will remain @@ -1167,7 +1167,7 @@ func (s *StateDB) Commit(block uint64, deleteEmptyObjects bool) (common.Hash, er return common.Hash{}, fmt.Errorf("commit aborted due to earlier error: %v", s.dbErr) } // Finalize any pending changes and merge everything into the tries - s.IntermediateRoot(deleteEmptyObjects) + s.IntermediateRoot(false) // Commit objects to the trie, measuring the elapsed time var ( diff --git a/core/state_processor.go b/core/state_processor.go index 9a4333f72330..efb3d65e692b 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -19,10 +19,13 @@ package core import ( "errors" "fmt" + "math" "math/big" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/consensus" + "github.com/ethereum/go-ethereum/consensus/aura" + "github.com/ethereum/go-ethereum/consensus/beacon" "github.com/ethereum/go-ethereum/consensus/misc" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" @@ -67,6 +70,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg allLogs []*types.Log gp = new(GasPool).AddGas(block.GasLimit()) ) + // Mutate the block and state according to any hard-fork specs if p.config.DAOForkSupport && p.config.DAOForkBlock != nil && p.config.DAOForkBlock.Cmp(block.Number()) == 0 { misc.ApplyDAOHardFork(statedb) @@ -76,6 +80,35 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg vmenv = vm.NewEVM(context, vm.TxContext{}, statedb, p.config, cfg) signer = types.MakeSigner(p.config, header.Number, header.Time) ) + b, ok := p.engine.(*beacon.Beacon) + if ok { + b.SetAuraSyscall(func(contractaddr common.Address, data []byte) ([]byte, error) { + sysaddr := common.HexToAddress("fffffffffffffffffffffffffffffffffffffffe") + msg := &Message{ + To: &contractaddr, + From: sysaddr, + Nonce: 0, + Value: big.NewInt(0), + GasLimit: math.MaxUint64, + GasPrice: big.NewInt(0), + GasFeeCap: nil, + GasTipCap: nil, + Data: data, + AccessList: nil, + BlobHashes: nil, + SkipAccountChecks: false, + } + txctx := NewEVMTxContext(msg) + evm := vm.NewEVM(context, txctx, statedb, p.bc.chainConfig, vm.Config{ /*Debug: true, Tracer: logger.NewJSONLogger(nil, os.Stdout)*/ }) + ret, _, err := evm.Call(vm.AccountRef(sysaddr), contractaddr, data, math.MaxUint64, new(big.Int)) + if err != nil { + panic(err) + } + statedb.Finalise(true) + return ret, err + }) + } + b.AuraPrepare(p.bc, block.Header(), statedb) if beaconRoot := block.BeaconRoot(); beaconRoot != nil { ProcessBeaconBlockRoot(*beaconRoot, vmenv, statedb) } @@ -86,7 +119,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg return nil, nil, 0, fmt.Errorf("could not apply tx %d [%v]: %w", i, tx.Hash().Hex(), err) } statedb.SetTxContext(tx.Hash(), i) - receipt, err := applyTransaction(msg, p.config, gp, statedb, blockNumber, blockHash, tx, usedGas, vmenv) + receipt, err := applyTransaction(msg, p.config, gp, statedb, blockNumber, blockHash, tx, usedGas, vmenv, p.engine) if err != nil { return nil, nil, 0, fmt.Errorf("could not apply tx %d [%v]: %w", i, tx.Hash().Hex(), err) } @@ -99,12 +132,33 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg return nil, nil, 0, errors.New("withdrawals before shanghai") } // Finalize the block, applying any consensus engine specific extras (e.g. block rewards) - p.engine.Finalize(p.bc, header, statedb, block.Transactions(), block.Uncles(), withdrawals) + p.engine.Finalize(p.bc, header, statedb, block.Transactions(), block.Uncles(), withdrawals, receipts) return receipts, allLogs, *usedGas, nil } -func applyTransaction(msg *Message, config *params.ChainConfig, gp *GasPool, statedb *state.StateDB, blockNumber *big.Int, blockHash common.Hash, tx *types.Transaction, usedGas *uint64, evm *vm.EVM) (*types.Receipt, error) { +func applyTransaction(msg *Message, config *params.ChainConfig, gp *GasPool, statedb *state.StateDB, blockNumber *big.Int, blockHash common.Hash, tx *types.Transaction, usedGas *uint64, evm *vm.EVM, engine consensus.Engine) (*types.Receipt, error) { + if config.IsLondon(blockNumber) { + switch engine := engine.(type) { + case *beacon.Beacon: + if a, ok := engine.InnerEngine().(*aura.AuRa); ok && msg.GasFeeCap.BitLen() == 0 { + if a.IsServiceTransaction(msg.From) { + msg.SetFree() + } + } + case *aura.AuRa: + if msg.GasFeeCap.BitLen() == 0 { + if engine.IsServiceTransaction(msg.From) { + msg.SetFree() + } + } + } + if a, ok := engine.(*aura.AuRa); engine != nil && msg.GasFeeCap.BitLen() == 0 && ok { + if a.IsServiceTransaction(msg.From) { + msg.SetFree() + } + } + } // Create a new context to be used in the EVM environment. txContext := NewEVMTxContext(msg) evm.Reset(txContext, statedb) @@ -167,7 +221,7 @@ func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *commo blockContext := NewEVMBlockContext(header, bc, author) txContext := NewEVMTxContext(msg) vmenv := vm.NewEVM(blockContext, txContext, statedb, config, cfg) - return applyTransaction(msg, config, gp, statedb, header.Number, header.Hash(), tx, usedGas, vmenv) + return applyTransaction(msg, config, gp, statedb, header.Number, header.Hash(), tx, usedGas, vmenv, nil) } // ProcessBeaconBlockRoot applies the EIP-4788 system call to the beacon block root diff --git a/core/state_transition.go b/core/state_transition.go index 540f63fda7ea..33572053b7bb 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -144,6 +144,16 @@ type Message struct { // account nonce in state. It also disables checking that the sender is an EOA. // This field will be set to true for operations like RPC eth_call. SkipAccountChecks bool + + isFree bool +} + +func (msg *Message) SetFree() { + msg.isFree = true +} + +func (msg *Message) IsFree() bool { + return msg.isFree } // TransactionToMessage converts a transaction into a Message. @@ -307,7 +317,7 @@ func (st *StateTransition) preCheck() error { } // This will panic if baseFee is nil, but basefee presence is verified // as part of header validation. - if msg.GasFeeCap.Cmp(st.evm.Context.BaseFee) < 0 { + if msg.GasFeeCap.Cmp(st.evm.Context.BaseFee) < 0 && !msg.IsFree() { return fmt.Errorf("%w: address %v, maxFeePerGas: %s, baseFee: %s", ErrFeeCapTooLow, msg.From.Hex(), msg.GasFeeCap, st.evm.Context.BaseFee) } @@ -429,18 +439,24 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) { gasRefund = st.refundGas(params.RefundQuotientEIP3529) } effectiveTip := msg.GasPrice - if rules.IsLondon { + if rules.IsLondon && !msg.IsFree() { effectiveTip = cmath.BigMin(msg.GasTipCap, new(big.Int).Sub(msg.GasFeeCap, st.evm.Context.BaseFee)) } + fee := new(big.Int).SetUint64(st.gasUsed()) + fee.Mul(fee, effectiveTip) + st.state.AddBalance(st.evm.Context.Coinbase, fee) + if st.evm.Config.NoBaseFee && msg.GasFeeCap.Sign() == 0 && msg.GasTipCap.Sign() == 0 { // Skip fee payment when NoBaseFee is set and the fee fields // are 0. This avoids a negative effectiveTip being applied to // the coinbase when simulating calls. } else { - fee := new(big.Int).SetUint64(st.gasUsed()) - fee.Mul(fee, effectiveTip) - st.state.AddBalance(st.evm.Context.Coinbase, fee) + if rules.IsLondon && !msg.IsFree() { + burntContractAddress := *st.evm.ChainConfig().Aura.Eip1559FeeCollector + burnAmount := new(big.Int).Mul(new(big.Int).SetUint64(st.gasUsed()), st.evm.Context.BaseFee) + st.state.AddBalance(burntContractAddress, burnAmount) + } } return &ExecutionResult{ diff --git a/core/types/block.go b/core/types/block.go index 1a357baa3a41..eaff2c36f5cb 100644 --- a/core/types/block.go +++ b/core/types/block.go @@ -78,6 +78,8 @@ type Header struct { Extra []byte `json:"extraData" gencodec:"required"` MixDigest common.Hash `json:"mixHash"` Nonce BlockNonce `json:"nonce"` + Step uint64 `json:"step,omitempty"` + Signature []byte `json:"signature"` // BaseFee was added by EIP-1559 and is ignored in legacy headers. BaseFee *big.Int `json:"baseFeePerGas" rlp:"optional"` diff --git a/core/types/gen_header_rlp.go b/core/types/gen_header_rlp.go index ed6a1a002cdb..0324cdc72974 100644 --- a/core/types/gen_header_rlp.go +++ b/core/types/gen_header_rlp.go @@ -2,8 +2,14 @@ package types -import "github.com/ethereum/go-ethereum/rlp" -import "io" +import ( + "io" + "fmt" + "errors" + + "github.com/ethereum/go-ethereum/rlp" + "github.com/ethereum/go-ethereum/common" +) func (obj *Header) EncodeRLP(_w io.Writer) error { w := rlp.NewEncoderBuffer(_w) @@ -35,8 +41,13 @@ func (obj *Header) EncodeRLP(_w io.Writer) error { w.WriteUint64(obj.GasUsed) w.WriteUint64(obj.Time) w.WriteBytes(obj.Extra) - w.WriteBytes(obj.MixDigest[:]) - w.WriteBytes(obj.Nonce[:]) + if len(obj.Signature) == 0 { + w.WriteBytes(obj.MixDigest[:]) + w.WriteBytes(obj.Nonce[:]) + } else { + w.WriteUint64(obj.Step) + w.WriteBytes(obj.Signature) + } _tmp1 := obj.BaseFee != nil _tmp2 := obj.WithdrawalsHash != nil _tmp3 := obj.BlobGasUsed != nil @@ -83,3 +94,181 @@ func (obj *Header) EncodeRLP(_w io.Writer) error { w.ListEnd(_tmp0) return w.Flush() } + + +func (h *Header) DecodeRLP(s *rlp.Stream) error { + _, err := s.List() + if err != nil { + return err + } + var b []byte + if b, err = s.Bytes(); err != nil { + return fmt.Errorf("read ParentHash: %w", err) + } + if len(b) != 32 { + return fmt.Errorf("wrong size for ParentHash: %d", len(b)) + } + copy(h.ParentHash[:], b) + if b, err = s.Bytes(); err != nil { + return fmt.Errorf("read UncleHash: %w", err) + } + if len(b) != 32 { + return fmt.Errorf("wrong size for UncleHash: %d", len(b)) + } + copy(h.UncleHash[:], b) + if b, err = s.Bytes(); err != nil { + return fmt.Errorf("read Coinbase: %w", err) + } + if len(b) != 20 { + return fmt.Errorf("wrong size for Coinbase: %d", len(b)) + } + copy(h.Coinbase[:], b) + if b, err = s.Bytes(); err != nil { + return fmt.Errorf("read Root: %w", err) + } + if len(b) != 32 { + return fmt.Errorf("wrong size for Root: %d", len(b)) + } + copy(h.Root[:], b) + if b, err = s.Bytes(); err != nil { + return fmt.Errorf("read TxHash: %w", err) + } + if len(b) != 32 { + return fmt.Errorf("wrong size for TxHash: %d", len(b)) + } + copy(h.TxHash[:], b) + if b, err = s.Bytes(); err != nil { + return fmt.Errorf("read ReceiptHash: %w", err) + } + if len(b) != 32 { + return fmt.Errorf("wrong size for ReceiptHash: %d", len(b)) + } + copy(h.ReceiptHash[:], b) + if b, err = s.Bytes(); err != nil { + return fmt.Errorf("read Bloom: %w", err) + } + if len(b) != 256 { + return fmt.Errorf("wrong size for Bloom: %d", len(b)) + } + copy(h.Bloom[:], b) + if h.Difficulty, err = s.BigInt(); err != nil { + return fmt.Errorf("read Difficulty: %w", err) + } + if h.Number, err = s.BigInt(); err != nil { + return fmt.Errorf("read Number: %w", err) + } + if h.GasLimit, err = s.Uint(); err != nil { + return fmt.Errorf("read GasLimit: %w", err) + } + if h.GasUsed, err = s.Uint(); err != nil { + return fmt.Errorf("read GasUsed: %w", err) + } + if h.Time, err = s.Uint(); err != nil { + return fmt.Errorf("read Time: %w", err) + } + if h.Extra, err = s.Bytes(); err != nil { + return fmt.Errorf("read Extra: %w", err) + } + + _, size, err := s.Kind() + if err != nil { + return fmt.Errorf("read MixDigest: %w", err) + } + if size != 32 { // AuRa + if h.Step, err = s.Uint(); err != nil { + return fmt.Errorf("read AuRaStep: %w", err) + } + if h.Signature, err = s.Bytes(); err != nil { + return fmt.Errorf("read AuRaSeal: %w", err) + } + } else { + if b, err = s.Bytes(); err != nil { + return fmt.Errorf("read MixDigest: %w", err) + } + copy(h.MixDigest[:], b) + if b, err = s.Bytes(); err != nil { + return fmt.Errorf("read Nonce: %w", err) + } + if len(b) != 8 { + return fmt.Errorf("wrong size for Nonce: %d", len(b)) + } + copy(h.Nonce[:], b) + } + + // BaseFee + if h.BaseFee, err = s.BigInt(); err != nil { + if errors.Is(err, rlp.EOL) { + h.BaseFee = nil + if err := s.ListEnd(); err != nil { + return fmt.Errorf("close header struct (no BaseFee): %w", err) + } + return nil + } + return fmt.Errorf("read BaseFee: %w", err) + } + + // WithdrawalsHash + if b, err = s.Bytes(); err != nil { + if errors.Is(err, rlp.EOL) { + h.WithdrawalsHash = nil + if err := s.ListEnd(); err != nil { + return fmt.Errorf("close header struct (no WithdrawalsHash): %w", err) + } + return nil + } + return fmt.Errorf("read WithdrawalsHash: %w", err) + } + if len(b) != 32 { + return fmt.Errorf("wrong size for WithdrawalsHash: %d", len(b)) + } + h.WithdrawalsHash = new(common.Hash) + h.WithdrawalsHash.SetBytes(b) + + var blobGasUsed uint64 + if blobGasUsed, err = s.Uint(); err != nil { + if errors.Is(err, rlp.EOL) { + h.BlobGasUsed = nil + if err := s.ListEnd(); err != nil { + return fmt.Errorf("close header struct (no BlobGasUsed): %w", err) + } + return nil + } + return fmt.Errorf("read BlobGasUsed: %w", err) + } + h.BlobGasUsed = &blobGasUsed + + var excessBlobGas uint64 + if excessBlobGas, err = s.Uint(); err != nil { + if errors.Is(err, rlp.EOL) { + h.ExcessBlobGas = nil + if err := s.ListEnd(); err != nil { + return fmt.Errorf("close header struct (no ExcessBlobGas): %w", err) + } + return nil + } + return fmt.Errorf("read ExcessBlobGas: %w", err) + } + h.ExcessBlobGas = &excessBlobGas + + // ParentBeaconBlockRoot + if b, err = s.Bytes(); err != nil { + if errors.Is(err, rlp.EOL) { + h.ParentBeaconRoot = nil + if err := s.ListEnd(); err != nil { + return fmt.Errorf("close header struct (no ParentBeaconBlockRoot): %w", err) + } + return nil + } + return fmt.Errorf("read ParentBeaconBlockRoot: %w", err) + } + if len(b) != 32 { + return fmt.Errorf("wrong size for ParentBeaconBlockRoot: %d", len(b)) + } + h.ParentBeaconRoot= new(common.Hash) + h.ParentBeaconRoot.SetBytes(b) + + if err := s.ListEnd(); err != nil { + return fmt.Errorf("close header struct: %w", err) + } + return nil +} diff --git a/core/vm/evm.go b/core/vm/evm.go index 088b18aaa4ff..0e0e6d6728ea 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -467,7 +467,7 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64, ret, err := evm.interpreter.Run(contract, nil, false) // Check whether the max code size has been exceeded, assign err if the case. - if err == nil && evm.chainRules.IsEIP158 && len(ret) > params.MaxCodeSize { + if err == nil && evm.chainRules.IsShanghai && len(ret) > params.MaxCodeSize { err = ErrMaxCodeSizeExceeded } diff --git a/eth/ethconfig/config.go b/eth/ethconfig/config.go index ad664afb5bd1..0d330daae8bb 100644 --- a/eth/ethconfig/config.go +++ b/eth/ethconfig/config.go @@ -23,6 +23,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/consensus" + "github.com/ethereum/go-ethereum/consensus/aura" "github.com/ethereum/go-ethereum/consensus/beacon" "github.com/ethereum/go-ethereum/consensus/clique" "github.com/ethereum/go-ethereum/consensus/ethash" @@ -169,6 +170,13 @@ func CreateConsensusEngine(config *params.ChainConfig, db ethdb.Database) (conse if config.Clique != nil { return beacon.New(clique.New(config.Clique, db)), nil } + if config.Aura != nil { + a, err := aura.NewAuRa(config.Aura, db) + if err != nil { + return nil, err + } + return beacon.New(a), nil + } // If defaulting to proof-of-work, enforce an already merged network since // we cannot run PoW algorithms anymore, so we cannot even follow a chain // not coordinated by a beacon node. diff --git a/eth/protocols/eth/handshake.go b/eth/protocols/eth/handshake.go index ea16a85b1e1e..b3ee0e9838df 100644 --- a/eth/protocols/eth/handshake.go +++ b/eth/protocols/eth/handshake.go @@ -73,9 +73,10 @@ func (p *Peer) Handshake(network uint64, td *big.Int, head common.Hash, genesis // TD at mainnet block #7753254 is 76 bits. If it becomes 100 million times // larger, it will still fit within 100 bits - if tdlen := p.td.BitLen(); tdlen > 100 { - return fmt.Errorf("too large total difficulty: bitlen %d", tdlen) - } + // GNOSIS: total difficulty on the gnosis chain is way larger than 100 bits + // if tdlen := p.td.BitLen(); tdlen > 100 { + // return fmt.Errorf("too large total difficulty: bitlen %d", tdlen) + // } return nil } diff --git a/go.mod b/go.mod index b4d077fc47f2..c90197ac6afb 100644 --- a/go.mod +++ b/go.mod @@ -110,6 +110,8 @@ require ( github.com/google/pprof v0.0.0-20230207041349-798e818bf904 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-retryablehttp v0.7.4 // indirect + github.com/hashicorp/golang-lru v1.0.2 // indirect + github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/kilic/bls12-381 v0.1.0 // indirect diff --git a/go.sum b/go.sum index bab51b1345a7..8de34ece06c0 100644 --- a/go.sum +++ b/go.sum @@ -334,6 +334,10 @@ github.com/hashicorp/go-retryablehttp v0.7.4/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5 github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c= +github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= +github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/holiman/billy v0.0.0-20230718173358-1c7e68d277a7 h1:3JQNjnMRil1yD0IfZKHF9GxxWKDJGj8I0IqOUol//sw= github.com/holiman/billy v0.0.0-20230718173358-1c7e68d277a7/go.mod h1:5GuXa7vkL8u9FkFuWdVvfR5ix8hRB7DbOAaYULamFpc= diff --git a/miner/worker.go b/miner/worker.go index 2ed91cc18781..6e9df1a9116d 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -26,6 +26,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/consensus" + "github.com/ethereum/go-ethereum/consensus/beacon" "github.com/ethereum/go-ethereum/consensus/misc/eip1559" "github.com/ethereum/go-ethereum/consensus/misc/eip4844" "github.com/ethereum/go-ethereum/core" @@ -704,15 +705,7 @@ func (w *worker) resultLoop() { } // makeEnv creates a new environment for the sealing block. -func (w *worker) makeEnv(parent *types.Header, header *types.Header, coinbase common.Address) (*environment, error) { - // Retrieve the parent state to execute on top and start a prefetcher for - // the miner to speed block sealing up a bit. - state, err := w.chain.StateAt(parent.Root) - if err != nil { - return nil, err - } - state.StartPrefetcher("miner") - +func (w *worker) makeEnv(parent *types.Header, header *types.Header, coinbase common.Address, state *state.StateDB) (*environment, error) { // Note the passed coinbase may be different with header.Coinbase. env := &environment{ signer: types.MakeSigner(w.chainConfig, header.Number, header.Time), @@ -960,15 +953,29 @@ func (w *worker) prepareWork(genParams *generateParams) (*environment, error) { header.ExcessBlobGas = &excessBlobGas header.ParentBeaconRoot = genParams.beaconRoot } + // Retrieve the parent state to execute on top and start a prefetcher for + // the miner to speed block sealing up a bit. + state, err := w.chain.StateAt(parent.Root) + if err != nil { + return nil, err + } + state.StartPrefetcher("miner") + + b, ok := w.engine.(*beacon.Beacon) + if ok { + b.SetAuraSyscall(func(contractaddr common.Address, data []byte) ([]byte, error) { + return nil, nil + }) + } // Run the consensus preparation with the default or customized consensus engine. - if err := w.engine.Prepare(w.chain, header); err != nil { + if err := w.engine.Prepare(w.chain, header, state); err != nil { log.Error("Failed to prepare header for sealing", "err", err) return nil, err } // Could potentially happen if starting to mine in an odd state. // Note genParams.coinbase can be different with header.Coinbase // since clique algorithm can modify the coinbase field in header. - env, err := w.makeEnv(parent, header, genParams.coinbase) + env, err := w.makeEnv(parent, header, genParams.coinbase, state) if err != nil { log.Error("Failed to create sealing context", "err", err) return nil, err diff --git a/params/bootnodes.go b/params/bootnodes.go index 5e2c7c218102..57b13737bd0f 100644 --- a/params/bootnodes.go +++ b/params/bootnodes.go @@ -64,6 +64,22 @@ var GoerliBootnodes = []string{ "enode://d2b720352e8216c9efc470091aa91ddafc53e222b32780f505c817ceef69e01d5b0b0797b69db254c586f493872352f5a022b4d8479a00fc92ec55f9ad46a27e@88.99.70.182:30303", } +// GnosisBootnodes are the enode URLs of the P2P bootstrap nodes running on the +// Gnosis chain network. +var GnosisBootnodes = []string{ + // TODO +} + +// ChiadoBootnodes are the enode URLs of the P2P bootstrap nodes running on the +// Chiado test network. +var ChiadoBootnodes = []string{ + "enode://7dd44af6138120f328bb031eb56e00985c149319d4f1e33275b30be7fddadd8ccd9f7b9c3b35a16136a61e85b2b2d1de073f30ec1d0ddf576a33be8ff48d88d0@139.144.26.89:30303", + "enode://317b9cee65ccf1d747b00e604242bfa3ae367beee8f149e28c5b2b88820f855ea7b5a75eb5327cfc3d8ca97adbf71538468290a46592ed7009f3fb394ec752f1@139.144.26.115:30303", + "enode://b77ae97906155ebbb83fd32c87ab0aa57372a24abbd8aa4bae679f048b726de4a195709f613be4981e44b24640bc89e4824427d94e9a37afc148da8250c8ab2d@139.144.26.101:30303", + "enode://69f8abfa3b0221161f8c19014b90857a18742554af27af73fd779c486728750a0ff11b873975f104fc5276a3a7c3b5b68cb3c26c815e9f78462901895d652124@139.144.26.85:30303", + "enode://ac7fc76f9b2ab343fb2d091365a7f46d17018e525cbedfbf24b247c76657e934ef4df61cc2f6dad6bfcf722425e03e1a8a6e4e4b52743acc2319cb8ebf27d742@170.187.154.239:30303", +} + var V5Bootnodes = []string{ // Teku team's bootnode "enr:-KG4QMOEswP62yzDjSwWS4YEjtTZ5PO6r65CPqYBkgTTkrpaedQ8uEUo1uMALtJIvb2w_WWEVmg5yt1UAuK1ftxUU7QDhGV0aDKQu6TalgMAAAD__________4JpZIJ2NIJpcIQEnfA2iXNlY3AyNTZrMaEDfol8oLr6XJ7FsdAYE7lpJhKMls4G_v6qQOGKJUWGb_uDdGNwgiMog3VkcIIjKA", // # 4.157.240.54 | azure-us-east-virginia diff --git a/params/chainspecs/chiado.json b/params/chainspecs/chiado.json new file mode 100644 index 000000000000..fac44bbd3f14 --- /dev/null +++ b/params/chainspecs/chiado.json @@ -0,0 +1,52 @@ +{ + "ChainName": "chiado", + "chainId": 10200, + "consensus": "aura", + "homesteadBlock": 0, + "eip150Block": 0, + "eip155Block": 0, + "byzantiumBlock": 0, + "constantinopleBlock": 0, + "petersburgBlock": 0, + "istanbulBlock": 0, + "berlinBlock": 0, + "londonBlock": 0, + "eip1559FeeCollectorTransition": 0, + "eip1559FeeCollector": "0x1559000000000000000000000000000000000000", + "terminalTotalDifficulty": 231707791542740786049188744689299064356246512, + "terminalTotalDifficultyPassed": true, + "aura": { + "stepDuration": 5, + "blockReward": 0, + "maximumUncleCountTransition": 0, + "maximumUncleCount": 0, + "validators": { + "multi": { + "0": { + "list": ["0x14747a698Ec1227e6753026C08B29b4d5D3bC484"] + }, + "67334": { + "list": [ + "0x14747a698Ec1227e6753026C08B29b4d5D3bC484", + "0x56D421c0AC39976E89fa400d34ca6579417B84cA", + "0x5CD99ac2F0F8C25a1e670F6BaB19D52Aad69D875", + "0x60F1CF46B42Df059b98Acf67C1dD7771b100e124", + "0x655e97bA0f63A56c2b56EB3e84f7bf42b20Bae14", + "0x755B6259938D140626301c0B6026c1C00C9eD5d9", + "0xa8010da9Cb0AC018C86A06301963853CC371a18c" + ] + } + } + }, + "blockRewardContractAddress": "0x2000000000000000000000000000000000000001", + "blockRewardContractTransition": 0, + "randomnessContractAddress": { + "0": "0x3000000000000000000000000000000000000001" + }, + "posdaoTransition": 0, + "blockGasLimitContractTransitions": { + "0": "0x4000000000000000000000000000000000000001" + }, + "registrar": "0x6000000000000000000000000000000000000000" + } +} diff --git a/params/chainspecs/gnosis.json b/params/chainspecs/gnosis.json new file mode 100644 index 000000000000..44bd8e3cccca --- /dev/null +++ b/params/chainspecs/gnosis.json @@ -0,0 +1,58 @@ +{ + "ChainName": "gnosis", + "chainId": 100, + "consensus": "aura", + "homesteadBlock": 0, + "eip150Block": 0, + "eip155Block": 0, + "eip158Block": 0, + "byzantiumBlock": 0, + "constantinopleBlock": 1604400, + "petersburgBlock": 2508800, + "istanbulBlock": 7298030, + "berlinBlock": 16101500, + "londonBlock": 19040000, + "shanghaiTime": 1690889660, + "cancunTime": 1710181820, + "terminalTotalDifficulty": 8626000000000000000000058750000000000000000000, + "terminalTotalDifficultyPassed": true, + "aura": { + "stepDuration": 5, + "blockReward": 0, + "maximumUncleCountTransition": 0, + "maximumUncleCount": 0, + "validators": { + "multi": { + "0": { + "list": [ + "0xcace5b3c29211740e595850e80478416ee77ca21" + ] + }, + "1300": { + "safeContract": "0x22e1229a2c5b95a60983b5577f745a603284f535" + }, + "9186425": { + "contract": "0xB87BE9f7196F2AE084Ca1DE6af5264292976e013" + } + } + }, + "blockRewardContractAddress": "0x867305d19606aadba405ce534e303d0e225f9556", + "blockRewardContractTransition": 1310, + "blockRewardContractTransitions": { + "9186425": "0x481c034c6d9441db23ea48de68bcae812c5d39ba" + }, + "randomnessContractAddress": { + "9186425": "0x5870b0527DeDB1cFBD9534343Feda1a41Ce47766" + }, + "posdaoTransition": 9186425, + "registrar": "0x6B53721D4f2Fb9514B85f5C49b197D857e36Cf03", + "rewriteBytecode": { + "21735000": { + "0xf8D1677c8a0c961938bf2f9aDc3F3CFDA759A9d9": "0x6080604052600436106101b35763ffffffff60e060020a60003504166305d2035b81146101b857806306fdde03146101e1578063095ea7b31461026b5780630b26cf661461028f57806318160ddd146102b257806323b872dd146102d957806330adf81f14610303578063313ce567146103185780633644e5151461034357806339509351146103585780634000aea01461037c57806340c10f19146103ad57806342966c68146103d157806354fd4d50146103e957806366188463146103fe57806369ffa08a1461042257806370a0823114610449578063715018a61461046a578063726600ce1461047f5780637d64bcb4146104a05780637ecebe00146104b5578063859ba28c146104d65780638da5cb5b146105175780638fcbaf0c1461054857806395d89b4114610586578063a457c2d71461059b578063a9059cbb146105bf578063b753a98c146105e3578063bb35783b14610607578063c6a1dedf14610631578063cd59658314610646578063d505accf1461065b578063d73dd62314610694578063dd62ed3e146106b8578063f2d5d56b146106df578063f2fde38b14610703578063ff9e884d14610724575b600080fd5b3480156101c457600080fd5b506101cd61074b565b604080519115158252519081900360200190f35b3480156101ed57600080fd5b506101f661076c565b6040805160208082528351818301528351919283929083019185019080838360005b83811015610230578181015183820152602001610218565b50505050905090810190601f16801561025d5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561027757600080fd5b506101cd600160a060020a03600435166024356107fa565b34801561029b57600080fd5b506102b0600160a060020a0360043516610810565b005b3480156102be57600080fd5b506102c761086a565b60408051918252519081900360200190f35b3480156102e557600080fd5b506101cd600160a060020a0360043581169060243516604435610870565b34801561030f57600080fd5b506102c7610a38565b34801561032457600080fd5b5061032d610a5c565b6040805160ff9092168252519081900360200190f35b34801561034f57600080fd5b506102c7610a65565b34801561036457600080fd5b506101cd600160a060020a0360043516602435610a6b565b34801561038857600080fd5b506101cd60048035600160a060020a0316906024803591604435918201910135610aac565b3480156103b957600080fd5b506101cd600160a060020a0360043516602435610bbd565b3480156103dd57600080fd5b506102b0600435610cc8565b3480156103f557600080fd5b506101f6610cd5565b34801561040a57600080fd5b506101cd600160a060020a0360043516602435610d0c565b34801561042e57600080fd5b506102b0600160a060020a0360043581169060243516610de9565b34801561045557600080fd5b506102c7600160a060020a0360043516610e0e565b34801561047657600080fd5b506102b0610e29565b34801561048b57600080fd5b506101cd600160a060020a0360043516610e40565b3480156104ac57600080fd5b506101cd610e54565b3480156104c157600080fd5b506102c7600160a060020a0360043516610e5b565b3480156104e257600080fd5b506104eb610e6d565b6040805167ffffffffffffffff9485168152928416602084015292168183015290519081900360600190f35b34801561052357600080fd5b5061052c610e78565b60408051600160a060020a039092168252519081900360200190f35b34801561055457600080fd5b506102b0600160a060020a0360043581169060243516604435606435608435151560ff60a4351660c43560e435610e87565b34801561059257600080fd5b506101f6610fc5565b3480156105a757600080fd5b506101cd600160a060020a036004351660243561101f565b3480156105cb57600080fd5b506101cd600160a060020a0360043516602435611032565b3480156105ef57600080fd5b506102b0600160a060020a0360043516602435611054565b34801561061357600080fd5b506102b0600160a060020a0360043581169060243516604435611064565b34801561063d57600080fd5b506102c7611075565b34801561065257600080fd5b5061052c611099565b34801561066757600080fd5b506102b0600160a060020a036004358116906024351660443560643560ff6084351660a43560c4356110a8565b3480156106a057600080fd5b506101cd600160a060020a0360043516602435611184565b3480156106c457600080fd5b506102c7600160a060020a036004358116906024351661120b565b3480156106eb57600080fd5b506102b0600160a060020a0360043516602435611236565b34801561070f57600080fd5b506102b0600160a060020a0360043516611241565b34801561073057600080fd5b506102c7600160a060020a0360043581169060243516611261565b60065474010000000000000000000000000000000000000000900460ff1681565b6000805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156107f25780601f106107c7576101008083540402835291602001916107f2565b820191906000526020600020905b8154815290600101906020018083116107d557829003601f168201915b505050505081565b600061080733848461127e565b50600192915050565b600654600160a060020a0316331461082757600080fd5b610830816112c0565b151561083b57600080fd5b6007805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b60045490565b600080600160a060020a038516151561088857600080fd5b600160a060020a038416151561089d57600080fd5b600160a060020a0385166000908152600360205260409020546108c6908463ffffffff6112c816565b600160a060020a0380871660009081526003602052604080822093909355908616815220546108fb908463ffffffff6112da16565b600160a060020a038086166000818152600360209081526040918290209490945580518781529051919392891692600080516020611d7283398151915292918290030190a3600160a060020a0385163314610a225761095a853361120b565b905060001981146109c457610975818463ffffffff6112c816565b600160a060020a038616600081815260056020908152604080832033808552908352928190208590558051948552519193600080516020611d92833981519152929081900390910190a3610a22565b600160a060020a0385166000908152600a602090815260408083203384529091529020541580610a175750600160a060020a0385166000908152600a602090815260408083203384529091529020544211155b1515610a2257600080fd5b610a2d8585856112ed565b506001949350505050565b7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b60025460ff1681565b60085481565b336000818152600560209081526040808320600160a060020a03871684529091528120549091610807918590610aa7908663ffffffff6112da16565b61127e565b600084600160a060020a03811615801590610ad05750600160a060020a0381163014155b1515610adb57600080fd5b610ae58686611324565b1515610af057600080fd5b85600160a060020a031633600160a060020a03167fe19260aff97b920c7df27010903aeb9c8d2be5d310a2c67824cf3f15396e4c16878787604051808481526020018060200182810382528484828181526020019250808284376040519201829003965090945050505050a3610b65866112c0565b15610bb157610ba633878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843750611330945050505050565b1515610bb157600080fd5b50600195945050505050565b600654600090600160a060020a03163314610bd757600080fd5b60065474010000000000000000000000000000000000000000900460ff1615610bff57600080fd5b600454610c12908363ffffffff6112da16565b600455600160a060020a038316600090815260036020526040902054610c3e908363ffffffff6112da16565b600160a060020a038416600081815260036020908152604091829020939093558051858152905191927f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d412139688592918290030190a2604080518381529051600160a060020a03851691600091600080516020611d728339815191529181900360200190a350600192915050565b610cd233826114ad565b50565b60408051808201909152600181527f3100000000000000000000000000000000000000000000000000000000000000602082015281565b336000908152600560209081526040808320600160a060020a0386168452909152812054808310610d6057336000908152600560209081526040808320600160a060020a0388168452909152812055610d95565b610d70818463ffffffff6112c816565b336000908152600560209081526040808320600160a060020a03891684529091529020555b336000818152600560209081526040808320600160a060020a038916808552908352928190205481519081529051929392600080516020611d92833981519152929181900390910190a35060019392505050565b600654600160a060020a03163314610e0057600080fd5b610e0a828261159c565b5050565b600160a060020a031660009081526003602052604090205490565b600654600160a060020a031633146101b357600080fd5b600754600160a060020a0390811691161490565b6000806000fd5b60096020526000908152604090205481565b600260056000909192565b600654600160a060020a031681565b600080861580610e975750864211155b1515610ea257600080fd5b604080517fea2aa0a1be11a07ed86d755c93467f4f82362b452371d1ba94d1715123511acb6020820152600160a060020a03808d16828401528b166060820152608081018a905260a0810189905287151560c0808301919091528251808303909101815260e0909101909152610f17906115da565b9150610f25828686866116e1565b600160a060020a038b8116911614610f3c57600080fd5b600160a060020a038a1660009081526009602052604090208054600181019091558814610f6857600080fd5b85610f74576000610f78565b6000195b905085610f86576000610f88565b865b600160a060020a03808c166000908152600a60209081526040808320938e1683529290522055610fb98a8a836118e3565b50505050505050505050565b60018054604080516020600284861615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156107f25780601f106107c7576101008083540402835291602001916107f2565b600061102b8383610d0c565b9392505050565b600061103e8383611324565b151561104957600080fd5b6108073384846112ed565b61105f338383610870565b505050565b61106f838383610870565b50505050565b7fea2aa0a1be11a07ed86d755c93467f4f82362b452371d1ba94d1715123511acb81565b600754600160a060020a031690565b600080428610156110b857600080fd5b600160a060020a03808a1660008181526009602090815260409182902080546001810190915582517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c99281019290925281830193909352928b166060840152608083018a905260a0830182905260c08084018a90528151808503909101815260e090930190529250611149906115da565b9050611157818686866116e1565b600160a060020a038a811691161461116e57600080fd5b61117989898961127e565b505050505050505050565b336000908152600560209081526040808320600160a060020a03861684529091528120546111b8908363ffffffff6112da16565b336000818152600560209081526040808320600160a060020a038916808552908352928190208590558051948552519193600080516020611d92833981519152929081900390910190a350600192915050565b600160a060020a03918216600090815260056020908152604080832093909416825291909152205490565b61105f823383610870565b600654600160a060020a0316331461125857600080fd5b610cd281611a3e565b600a60209081526000928352604080842090915290825290205481565b6112898383836118e3565b60001981141561105f57600160a060020a038084166000908152600a60209081526040808320938616835292905290812055505050565b6000903b1190565b6000828211156112d457fe5b50900390565b818101828110156112e757fe5b92915050565b6112f682610e40565b1561105f5760408051600081526020810190915261131990849084908490611330565b151561105f57600080fd5b600061102b8383611abc565b600083600160a060020a031663a4c0ed3660e060020a028685856040516024018084600160a060020a0316600160a060020a0316815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b838110156113a8578181015183820152602001611390565b50505050905090810190601f1680156113d55780820380516001836020036101000a031916815260200191505b5060408051601f198184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909916989098178852518151919790965086955093509150819050838360005b8381101561146357818101518382015260200161144b565b50505050905090810190601f1680156114905780820380516001836020036101000a031916815260200191505b509150506000604051808303816000865af1979650505050505050565b600160a060020a0382166000908152600360205260409020548111156114d257600080fd5b600160a060020a0382166000908152600360205260409020546114fb908263ffffffff6112c816565b600160a060020a038316600090815260036020526040902055600454611527908263ffffffff6112c816565b600455604080518281529051600160a060020a038416917fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5919081900360200190a2604080518281529051600091600160a060020a03851691600080516020611d728339815191529181900360200190a35050565b80600160a060020a03811615156115b257600080fd5b600160a060020a03831615156115d0576115cb82611b8b565b61105f565b61105f8383611b97565b6000600854826040518082805190602001908083835b6020831061160f5780518252601f1990920191602091820191016115f0565b51815160209384036101000a6000190180199092169116179052604080519290940182900382207f190100000000000000000000000000000000000000000000000000000000000083830152602283019790975260428083019790975283518083039097018752606290910192839052855192945084935085019190508083835b602083106116af5780518252601f199092019160209182019101611690565b5181516020939093036101000a6000190180199091169216919091179052604051920182900390912095945050505050565b6000808460ff16601b14806116f957508460ff16601c145b1515611775576040805160e560020a62461bcd02815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c60448201527f7565000000000000000000000000000000000000000000000000000000000000606482015290519081900360840190fd5b7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115611813576040805160e560020a62461bcd02815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c60448201527f7565000000000000000000000000000000000000000000000000000000000000606482015290519081900360840190fd5b60408051600080825260208083018085528a905260ff8916838501526060830188905260808301879052925160019360a0808501949193601f19840193928390039091019190865af115801561186d573d6000803e3d6000fd5b5050604051601f190151915050600160a060020a03811615156118da576040805160e560020a62461bcd02815260206004820152601860248201527f45434453413a20696e76616c6964207369676e61747572650000000000000000604482015290519081900360640190fd5b95945050505050565b600160a060020a0383161515611968576040805160e560020a62461bcd028152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f7265737300000000000000000000000000000000000000000000000000000000606482015290519081900360840190fd5b600160a060020a03821615156119ee576040805160e560020a62461bcd02815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f7373000000000000000000000000000000000000000000000000000000000000606482015290519081900360840190fd5b600160a060020a0380841660008181526005602090815260408083209487168084529482529182902085905581518581529151600080516020611d928339815191529281900390910190a3505050565b600160a060020a0381161515611a5357600080fd5b600654604051600160a060020a038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a36006805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b33600090815260036020526040812054821115611ad857600080fd5b600160a060020a0383161515611aed57600080fd5b33600090815260036020526040902054611b0d908363ffffffff6112c816565b3360009081526003602052604080822092909255600160a060020a03851681522054611b3f908363ffffffff6112da16565b600160a060020a038416600081815260036020908152604091829020939093558051858152905191923392600080516020611d728339815191529281900390910190a350600192915050565b3031610e0a8282611c44565b604080517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290518391600091600160a060020a038416916370a0823191602480830192602092919082900301818787803b158015611bfc57600080fd5b505af1158015611c10573d6000803e3d6000fd5b505050506040513d6020811015611c2657600080fd5b5051905061106f600160a060020a038516848363ffffffff611cac16565b604051600160a060020a0383169082156108fc029083906000818181858888f193505050501515610e0a578082611c79611d41565b600160a060020a039091168152604051908190036020019082f080158015611ca5573d6000803e3d6000fd5b5050505050565b82600160a060020a031663a9059cbb83836040518363ffffffff1660e060020a0281526004018083600160a060020a0316600160a060020a0316815260200182815260200192505050600060405180830381600087803b158015611d0f57600080fd5b505af1158015611d23573d6000803e3d6000fd5b505050503d1561105f5760206000803e600051151561105f57600080fd5b604051602180611d51833901905600608060405260405160208060218339810160405251600160a060020a038116ff00ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925a165627a7a72305820b96bb0733a3e45fdddafa592f51114d0cf16cad047ad60b9b91ae91eb772c6940029" + } + }, + "eip1559FeeCollectorTransition": 19040000, + "eip1559FeeCollector": "0x6BBe78ee9e474842Dbd4AB4987b3CeFE88426A92", + "withdrawalContractAddress" : "0x0B98057eA310F4d31F2a452B414647007d1645d9" + } +} diff --git a/params/config.go b/params/config.go index 463041bd0161..176e914cc3df 100644 --- a/params/config.go +++ b/params/config.go @@ -34,7 +34,8 @@ var ( func newUint64(val uint64) *uint64 { return &val } var ( - MainnetTerminalTotalDifficulty, _ = new(big.Int).SetString("58_750_000_000_000_000_000_000", 0) + MainnetTerminalTotalDifficulty, _ = new(big.Int).SetString("58_750_000_000_000_000_000_000", 0) + GnosisChainTerminalTotalDifficulty, _ = new(big.Int).SetString("8_626_000_110_427_540_000_000_000_000_000_000_000_000_000_000", 0) // MainnetChainConfig is the chain parameters to run a node on the main network. MainnetChainConfig = &ChainConfig{ @@ -330,6 +331,7 @@ type ChainConfig struct { // Various consensus engines Ethash *EthashConfig `json:"ethash,omitempty"` Clique *CliqueConfig `json:"clique,omitempty"` + Aura *AuRaConfig `json:"aura,omitempty"` } // EthashConfig is the consensus engine configs for proof-of-work based sealing. @@ -378,6 +380,12 @@ func (c *ChainConfig) Description() string { } else { banner += "Consensus: Beacon (proof-of-stake), merged from Clique (proof-of-authority)\n" } + case c.Aura != nil: + if c.TerminalTotalDifficulty == nil { + banner += "Consensus: Aura (proof-of-authority)\n" + } else { + banner += "Consensus: Beacon (proof-of-stake), merged from Aura (proof-of-authority)\n" + } default: banner += "Consensus: unknown\n" } diff --git a/params/config_aura.go b/params/config_aura.go new file mode 100644 index 000000000000..cff5d2a021a1 --- /dev/null +++ b/params/config_aura.go @@ -0,0 +1,75 @@ +package params + +import ( + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" +) + +// Different ways of specifying validators. +type ValidatorSetJson struct { + // A simple list of authorities. + List []common.Address `json:"list"` + // Address of a contract that indicates the list of authorities. + SafeContract *common.Address `json:"safeContract"` + // Address of a contract that indicates the list of authorities and enables reporting of their misbehaviour using transactions. + Contract *common.Address `json:"contract"` + // A map of starting blocks for each validator set. + Multi map[uint64]*ValidatorSetJson `json:"multi"` +} + +// AuRaConfig is the consensus engine configs for proof-of-authority based sealing. +type AuRaConfig struct { + StepDuration *uint64 `json:"stepDuration"` // Block duration, in seconds. + Validators *ValidatorSetJson `json:"validators"` // Valid authorities + + // Starting step. Determined automatically if not specified. + // To be used for testing only. + StartStep *uint64 `json:"startStep"` + ValidateScoreTransition *uint64 `json:"validateScoreTransition"` // Block at which score validation should start. + ValidateStepTransition *uint64 `json:"validateStepTransition"` // Block from which monotonic steps start. + ImmediateTransitions *bool `json:"immediateTransitions"` // Whether transitions should be immediate. + BlockReward *uint64 `json:"blockReward"` // Reward per block in wei. + // Block at which the block reward contract should start being used. This option allows one to + // add a single block reward contract transition and is compatible with the multiple address + // option `block_reward_contract_transitions` below. + BlockRewardContractTransition *uint64 `json:"blockRewardContractTransition"` + /// Block reward contract address which overrides the `block_reward` setting. This option allows + /// one to add a single block reward contract address and is compatible with the multiple + /// address option `block_reward_contract_transitions` below. + BlockRewardContractAddress *common.Address `json:"blockRewardContractAddress"` + // Block reward contract addresses with their associated starting block numbers. + // + // Setting the block reward contract overrides `block_reward`. If the single block reward + // contract address is also present then it is added into the map at the block number stored in + // `block_reward_contract_transition` or 0 if that block number is not provided. Therefore both + // a single block reward contract transition and a map of reward contract transitions can be + // used simultaneously in the same configuration. In such a case the code requires that the + // block number of the single transition is strictly less than any of the block numbers in the + // map. + BlockRewardContractTransitions map[uint]common.Address `json:"blockRewardContractTransitions"` + // Block at which maximum uncle count should be considered. + MaximumUncleCountTransition *uint64 `json:"maximumUncleCountTransition"` + // Maximum number of accepted uncles. + MaximumUncleCount *uint `json:"maximumUncleCount"` + // Strict validation of empty steps transition block. + StrictEmptyStepsTransition *uint `json:"strictEmptyStepsTransition"` + // The random number contract's address, or a map of contract transitions. + RandomnessContractAddress map[uint64]common.Address `json:"randomnessContractAddress"` + // The addresses of contracts that determine the block gas limit starting from the block number + // associated with each of those contracts. + BlockGasLimitContractTransitions map[uint64]common.Address `json:"blockGasLimitContractTransitions"` + // The block number at which the consensus engine switches from AuRa to AuRa with POSDAO + // modifications. + PosdaoTransition *uint64 `json:"PosdaoTransition"` + // Stores human-readable keys associated with addresses, like DNS information. + // This contract is primarily required to store the address of the Certifier contract. + Registrar *common.Address `json:"registrar"` + + // See https://github.com/gnosischain/specs/blob/master/execution/withdrawals.md + WithdrawalContractAddress *common.Address `json:"withdrawalContractAddress"` + + RewriteBytecode map[uint64]map[common.Address]hexutil.Bytes `json:"rewriteBytecode"` + + // Burn contract address + Eip1559FeeCollector *common.Address `json:"eip1559FeeCollector"` +} diff --git a/params/gnosis_config.go b/params/gnosis_config.go new file mode 100644 index 000000000000..66000afd1599 --- /dev/null +++ b/params/gnosis_config.go @@ -0,0 +1,37 @@ +package params + +import ( + "embed" + "encoding/json" + "fmt" + + "github.com/ethereum/go-ethereum/common" +) + +//go:embed chainspecs +var chainspecs embed.FS + +func readChainSpec(filename string) *ChainConfig { + f, err := chainspecs.Open(filename) + if err != nil { + panic(fmt.Sprintf("Could not open chainspec for %s: %v", filename, err)) + } + defer f.Close() + decoder := json.NewDecoder(f) + spec := &ChainConfig{} + err = decoder.Decode(&spec) + if err != nil { + panic(fmt.Sprintf("Could not parse chainspec for %s: %v", filename, err)) + } + return spec +} + +var ( + GnosisGenesisHash = common.HexToHash("0x4f1dd23188aab3a76b463e4af801b52b1248ef073c648cbdc4c9333d3da79756") + ChiadoGenesisHash = common.HexToHash("0xada44fd8d2ecab8b08f256af07ad3e777f17fb434f8f8e678b312f576212ba9a") + + GnosisChainConfig = readChainSpec("chainspecs/gnosis.json") + ChiadoChainConfig = readChainSpec("chainspecs/chiado.json") + + GnosisForkBlock = uint64(25349536) +)