diff --git a/consensus/parlia/abi.go b/consensus/parlia/abi.go index 0d9ab54cd5..59e9e71ae4 100644 --- a/consensus/parlia/abi.go +++ b/consensus/parlia/abi.go @@ -1015,6 +1015,19 @@ const validatorSetABIBeforeLuban = ` "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "getTurnTerm", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { diff --git a/consensus/parlia/haberfork.go b/consensus/parlia/haberfork.go new file mode 100644 index 0000000000..ca220a3f3d --- /dev/null +++ b/consensus/parlia/haberfork.go @@ -0,0 +1,47 @@ +package parlia + +import ( + "context" + "math/big" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/common/math" + "github.com/ethereum/go-ethereum/core/systemcontracts" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/internal/ethapi" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/rpc" +) + +func (p *Parlia) getTurnTerm(header *types.Header) (turnTerm *big.Int, err error) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + method := "getTurnTerm" + toAddress := common.HexToAddress(systemcontracts.ValidatorContract) + gas := (hexutil.Uint64)(uint64(math.MaxUint64 / 2)) + + data, err := p.validatorSetABI.Pack(method) + if err != nil { + log.Error("Unable to pack tx for getTurnTerm", "error", err) + return nil, err + } + msgData := (hexutil.Bytes)(data) + + blockNr := rpc.BlockNumberOrHashWithHash(header.Hash(), false) + result, err := p.ethAPI.Call(ctx, ethapi.TransactionArgs{ + Gas: &gas, + To: &toAddress, + Data: &msgData, + }, &blockNr, nil, nil) + if err != nil { + return nil, err + } + + if err := p.validatorSetABI.UnpackIntoInterface(&turnTerm, method, result); err != nil { + return nil, err + } + + return turnTerm, nil +} diff --git a/consensus/parlia/parlia.go b/consensus/parlia/parlia.go index 69b82d408c..b9eec6f3c5 100644 --- a/consensus/parlia/parlia.go +++ b/consensus/parlia/parlia.go @@ -54,10 +54,12 @@ const ( checkpointInterval = 1024 // Number of blocks after which to save the snapshot to the database defaultEpochLength = uint64(100) // Default number of blocks of checkpoint to update validatorSet from contract + defaultTurnTerm = uint64(1) // Default consecutive number of blocks a validator receives priority for block production extraVanity = 32 // Fixed number of extra-data prefix bytes reserved for signer vanity extraSeal = 65 // Fixed number of extra-data suffix bytes reserved for signer seal nextForkHashSize = 4 // Fixed number of extra-data suffix bytes reserved for nextForkHash. + turnTermSize = 1 // Fixed number of extra-data suffix bytes reserved for turnTerm validatorBytesLengthBeforeLuban = common.AddressLength validatorBytesLength = common.AddressLength + types.BLSPublicKeyLength @@ -136,6 +138,10 @@ var ( // list of validators different than the one the local node calculated. errMismatchingEpochValidators = errors.New("mismatching validator list on epoch block") + // errMismatchingEpochTurnTerm is returned if a sprint block contains a + // turn term different than the one the local node calculated. + errMismatchingEpochTurnTerm = errors.New("mismatching turn term on epoch block") + // errInvalidDifficulty is returned if the difficulty of a block is missing. errInvalidDifficulty = errors.New("invalid difficulty") @@ -365,6 +371,7 @@ func (p *Parlia) VerifyHeaders(chain consensus.ChainHeaderReader, headers []*typ // On luban fork, we introduce vote attestation into the header's extra field, so extra format is different from before. // Before luban fork: |---Extra Vanity---|---Validators Bytes (or Empty)---|---Extra Seal---| // After luban fork: |---Extra Vanity---|---Validators Number and Validators Bytes (or Empty)---|---Vote Attestation (or Empty)---|---Extra Seal---| +// After haber fork: |---Extra Vanity---|---Validators Number and Validators Bytes (or Empty)---|---Turn Term (or Empty)---|---Vote Attestation (or Empty)---|---Extra Seal---| func getValidatorBytesFromHeader(header *types.Header, chainConfig *params.ChainConfig, parliaConfig *params.ParliaConfig) []byte { if len(header.Extra) <= extraVanity+extraSeal { return nil @@ -381,11 +388,11 @@ func getValidatorBytesFromHeader(header *types.Header, chainConfig *params.Chain return nil } num := int(header.Extra[extraVanity]) - if num == 0 || len(header.Extra) <= extraVanity+extraSeal+num*validatorBytesLength { - return nil - } start := extraVanity + validatorNumberSize end := start + num*validatorBytesLength + if num == 0 || len(header.Extra) < end+extraSeal { + return nil + } return header.Extra[start:end] } @@ -404,11 +411,14 @@ func getVoteAttestationFromHeader(header *types.Header, chainConfig *params.Chai attestationBytes = header.Extra[extraVanity : len(header.Extra)-extraSeal] } else { num := int(header.Extra[extraVanity]) - if len(header.Extra) <= extraVanity+extraSeal+validatorNumberSize+num*validatorBytesLength { - return nil, nil - } start := extraVanity + validatorNumberSize + num*validatorBytesLength + if chainConfig.IsHaber(header.Number, header.Time) { + start += turnTermSize + } end := len(header.Extra) - extraSeal + if end <= start { + return nil, nil + } attestationBytes = header.Extra[start:end] } @@ -884,6 +894,33 @@ func (p *Parlia) prepareValidators(header *types.Header) error { return nil } +func (p *Parlia) prepareTurnTerm(chain consensus.ChainHeaderReader, header *types.Header) error { + if header.Number.Uint64()%p.config.Epoch != 0 || + !p.chainConfig.IsHaber(header.Number, header.Time) { + return nil + } + + parent := chain.GetHeaderByHash(header.ParentHash) + if parent == nil { + return errors.New("parent not found") + } + + if p.chainConfig.IsHaber(parent.Number, parent.Time) { + turnTerm, err := p.getTurnTerm(parent) + if err != nil { + return err + } + if turnTerm == nil { + return errors.New("unexpected error when getTurnTerm") + } + header.Extra = append(header.Extra, byte(int(turnTerm.Int64()))) + } else { + header.Extra = append(header.Extra, byte(int(defaultTurnTerm))) + } + + return nil +} + func (p *Parlia) assembleVoteAttestation(chain consensus.ChainHeaderReader, header *types.Header) error { if !p.chainConfig.IsLuban(header.Number) || header.Number.Uint64() < 2 { return nil @@ -1015,6 +1052,9 @@ func (p *Parlia) Prepare(chain consensus.ChainHeaderReader, header *types.Header return err } + if err := p.prepareTurnTerm(chain, header); err != nil { + return err + } // add extra seal space header.Extra = append(header.Extra, make([]byte, extraSeal)...) @@ -1065,6 +1105,40 @@ func (p *Parlia) verifyValidators(header *types.Header) error { return nil } +func (p *Parlia) verifyTurnTerm(chain consensus.ChainHeaderReader, header *types.Header) error { + if header.Number.Uint64()%p.config.Epoch != 0 || + !p.chainConfig.IsHaber(header.Number, header.Time) { + return nil + } + + turnTermFromHeader, err := parseTurnTerm(header, p.chainConfig, p.config) + if err != nil { + return err + } + if turnTermFromHeader != nil { + parent := chain.GetHeaderByHash(header.ParentHash) + if parent == nil { + return errors.New("parent not found") + } + + if p.chainConfig.IsHaber(parent.Number, parent.Time) { + turnTermFromContract, err := p.getTurnTerm(parent) + if err != nil { + return err + } + if turnTermFromContract != nil && uint8(turnTermFromContract.Int64()) == *turnTermFromHeader { + return nil + } + } else { + if uint8(defaultTurnTerm) == *turnTermFromHeader { + return nil + } + } + } + + return errMismatchingEpochTurnTerm +} + func (p *Parlia) distributeFinalityReward(chain consensus.ChainHeaderReader, state *state.StateDB, header *types.Header, cx core.ChainContext, txs *[]*types.Transaction, receipts *[]*types.Receipt, systemTxs *[]*types.Transaction, usedGas *uint64, mining bool) error { @@ -1159,6 +1233,10 @@ func (p *Parlia) Finalize(chain consensus.ChainHeaderReader, header *types.Heade return err } + if err := p.verifyTurnTerm(chain, header); err != nil { + return err + } + cx := chainContext{Chain: chain, parlia: p} parent := chain.GetHeaderByHash(header.ParentHash) @@ -1185,7 +1263,7 @@ func (p *Parlia) Finalize(chain consensus.ChainHeaderReader, header *types.Heade } } if header.Difficulty.Cmp(diffInTurn) != 0 { - spoiledVal := snap.supposeValidator() + spoiledVal := snap.inturnValidator() signedRecently := false if p.chainConfig.IsPlato(header.Number) { signedRecently = snap.SignRecently(spoiledVal) @@ -1276,7 +1354,7 @@ func (p *Parlia) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header * if err != nil { return nil, nil, err } - spoiledVal := snap.supposeValidator() + spoiledVal := snap.inturnValidator() signedRecently := false if p.chainConfig.IsPlato(header.Number) { signedRecently = snap.SignRecently(spoiledVal) @@ -1905,26 +1983,15 @@ func (p *Parlia) backOffTime(snap *Snapshot, header *types.Header, val common.Ad delay := initialBackOffTime validators := snap.validators() if p.chainConfig.IsPlanck(header.Number) { - // reverse the key/value of snap.Recents to get recentsMap - recentsMap := make(map[common.Address]uint64, len(snap.Recents)) - bound := uint64(0) - if n, limit := header.Number.Uint64(), uint64(len(validators)/2+1); n > limit { - bound = n - limit - } - for seen, recent := range snap.Recents { - if seen <= bound { - continue - } - recentsMap[recent] = seen - } + counts := snap.countRecents() // The backOffTime does not matter when a validator has signed recently. - if _, ok := recentsMap[val]; ok { + if snap.signRecentlyByCounts(val, counts) { return 0 } - inTurnAddr := validators[(snap.Number+1)%uint64(len(validators))] - if _, ok := recentsMap[inTurnAddr]; ok { + inTurnAddr := snap.inturnValidator() + if snap.signRecentlyByCounts(inTurnAddr, counts) { log.Debug("in turn validator has recently signed, skip initialBackOffTime", "inTurnAddr", inTurnAddr) delay = 0 @@ -1933,7 +2000,7 @@ func (p *Parlia) backOffTime(snap *Snapshot, header *types.Header, val common.Ad // Exclude the recently signed validators temp := make([]common.Address, 0, len(validators)) for _, addr := range validators { - if _, ok := recentsMap[addr]; ok { + if snap.signRecentlyByCounts(addr, counts) { continue } temp = append(temp, addr) diff --git a/consensus/parlia/snapshot.go b/consensus/parlia/snapshot.go index 0da0929e7c..51a401785d 100644 --- a/consensus/parlia/snapshot.go +++ b/consensus/parlia/snapshot.go @@ -43,6 +43,7 @@ type Snapshot struct { Number uint64 `json:"number"` // Block number where the snapshot was created Hash common.Hash `json:"hash"` // Block hash where the snapshot was created + TurnTerm uint64 `json:"turn_term"` // The consecutive number of blocks a validator receives priority for block production Validators map[common.Address]*ValidatorInfo `json:"validators"` // Set of authorized validators at this moment Recents map[uint64]common.Address `json:"recents"` // Set of recent validators for spam protections RecentForkHashes map[uint64]string `json:"recent_fork_hashes"` // Set of recent forkHash @@ -72,6 +73,7 @@ func newSnapshot( sigCache: sigCache, Number: number, Hash: hash, + TurnTerm: defaultTurnTerm, Recents: make(map[uint64]common.Address), RecentForkHashes: make(map[uint64]string), Validators: make(map[common.Address]*ValidatorInfo), @@ -114,6 +116,10 @@ func loadSnapshot(config *params.ParliaConfig, sigCache *lru.ARCCache, db ethdb. if err := json.Unmarshal(blob, snap); err != nil { return nil, err } + if snap.TurnTerm == 0 { // no TurnTerm field in old snapshots + snap.TurnTerm = defaultTurnTerm + } + snap.config = config snap.sigCache = sigCache snap.ethAPI = ethAPI @@ -138,6 +144,7 @@ func (s *Snapshot) copy() *Snapshot { sigCache: s.sigCache, Number: s.Number, Hash: s.Hash, + TurnTerm: s.TurnTerm, Validators: make(map[common.Address]*ValidatorInfo), Recents: make(map[uint64]common.Address), RecentForkHashes: make(map[uint64]string), @@ -210,17 +217,40 @@ func (s *Snapshot) updateAttestation(header *types.Header, chainConfig *params.C } } -func (s *Snapshot) SignRecently(validator common.Address) bool { +func (s *Snapshot) minerHistoryCheck() uint64 { + return uint64(len(s.Validators)) / 2 * s.TurnTerm +} + +func (s *Snapshot) countRecents() map[common.Address]uint64 { + leftHistoryBound := uint64(0) // the bound is excluded + checkHistoryLength := s.minerHistoryCheck() + if s.Number >= checkHistoryLength { + leftHistoryBound = s.Number - checkHistoryLength + } + counts := make(map[common.Address]uint64, len(s.Validators)) for seen, recent := range s.Recents { - if recent == validator { - if limit := uint64(len(s.Validators)/2 + 1); s.Number+1 < limit || seen > s.Number+1-limit { - return true - } + if seen > leftHistoryBound { + counts[recent] += 1 + } + } + return counts +} + +func (s *Snapshot) signRecentlyByCounts(validator common.Address, counts map[common.Address]uint64) bool { + if seenTimes, ok := counts[validator]; ok && seenTimes >= s.TurnTerm { + if seenTimes > s.TurnTerm { + log.Warn("produce more blocks than expected!", "validator", validator, "seenTimes", seenTimes) } + return true } + return false } +func (s *Snapshot) SignRecently(validator common.Address) bool { + return s.signRecentlyByCounts(validator, s.countRecents()) +} + func (s *Snapshot) apply(headers []*types.Header, chain consensus.ChainHeaderReader, parents []*types.Header, chainConfig *params.ChainConfig) (*Snapshot, error) { // Allow passing in no headers for cleaner code if len(headers) == 0 { @@ -247,10 +277,8 @@ func (s *Snapshot) apply(headers []*types.Header, chain consensus.ChainHeaderRea for _, header := range headers { number := header.Number.Uint64() // Delete the oldest validator from the recent list to allow it signing again - if limit := uint64(len(snap.Validators)/2 + 1); number >= limit { + if limit := s.minerHistoryCheck() + 1; number >= limit { // `+1` for genesis block which has no miner delete(snap.Recents, number-limit) - } - if limit := uint64(len(snap.Validators)); number >= limit { delete(snap.RecentForkHashes, number-limit) } // Resolve the authorization key and check against signers @@ -261,19 +289,34 @@ func (s *Snapshot) apply(headers []*types.Header, chain consensus.ChainHeaderRea if _, ok := snap.Validators[validator]; !ok { return nil, errUnauthorizedValidator(validator.String()) } - for _, recent := range snap.Recents { - if recent == validator { + if chainConfig.IsHaber(header.Number, header.Time) { + if snap.SignRecently(validator) { return nil, errRecentlySigned } + } else { + for _, recent := range snap.Recents { + if recent == validator { + return nil, errRecentlySigned + } + } } - snap.Recents[number] = validator // change validator set - if number > 0 && number%s.config.Epoch == uint64(len(snap.Validators)/2) { - checkpointHeader := FindAncientHeader(header, uint64(len(snap.Validators)/2), chain, parents) + if number > 0 && number%s.config.Epoch == s.minerHistoryCheck() { + checkpointHeader := FindAncientHeader(header, s.minerHistoryCheck(), chain, parents) if checkpointHeader == nil { return nil, consensus.ErrUnknownAncestor } + oldLimit := s.minerHistoryCheck() + 1 + // get turnTerm from headers and use that for new turnTerm + turnTerm, err := parseTurnTerm(checkpointHeader, chainConfig, s.config) + if err != nil { + return nil, err + } + if turnTerm != nil { + s.TurnTerm = uint64(*turnTerm) + } + // get validators from headers and use that for new validator set newValArr, voteAddrs, err := parseValidators(checkpointHeader, chainConfig, s.config) if err != nil { @@ -289,20 +332,6 @@ func (s *Snapshot) apply(headers []*types.Header, chain consensus.ChainHeaderRea } } } - oldLimit := len(snap.Validators)/2 + 1 - newLimit := len(newVals)/2 + 1 - if newLimit < oldLimit { - for i := 0; i < oldLimit-newLimit; i++ { - delete(snap.Recents, number-uint64(newLimit)-uint64(i)) - } - } - oldLimit = len(snap.Validators) - newLimit = len(newVals) - if newLimit < oldLimit { - for i := 0; i < oldLimit-newLimit; i++ { - delete(snap.RecentForkHashes, number-uint64(newLimit)-uint64(i)) - } - } snap.Validators = newVals if chainConfig.IsLuban(header.Number) { validators := snap.validators() @@ -310,10 +339,21 @@ func (s *Snapshot) apply(headers []*types.Header, chain consensus.ChainHeaderRea snap.Validators[val].Index = idx + 1 // offset by 1 } } + + newLimit := s.minerHistoryCheck() + 1 + for i := newLimit; i < oldLimit; i++ { + delete(snap.Recents, number-i) + delete(snap.RecentForkHashes, number-i) + } + + if chainConfig.IsHaber(header.Number, header.Time) { + // without this logic, there will be several off-turn blocks when do validator set switch + snap.Recents = make(map[uint64]common.Address) + } } snap.updateAttestation(header, chainConfig, s.config) - + snap.Recents[number] = validator snap.RecentForkHashes[number] = hex.EncodeToString(header.Extra[extraVanity-nextForkHashSize : extraVanity]) } snap.Number += uint64(len(headers)) @@ -333,15 +373,13 @@ func (s *Snapshot) validators() []common.Address { // inturn returns if a validator at a given block height is in-turn or not. func (s *Snapshot) inturn(validator common.Address) bool { - validators := s.validators() - offset := (s.Number + 1) % uint64(len(validators)) - return validators[offset] == validator + return s.inturnValidator() == validator } // inturnValidator returns the validator at a given block height. func (s *Snapshot) inturnValidator() common.Address { validators := s.validators() - offset := (s.Number + 1) % uint64(len(validators)) + offset := (s.Number + 1) / s.TurnTerm % uint64(len(validators)) return validators[offset] } @@ -379,12 +417,6 @@ func (s *Snapshot) indexOfVal(validator common.Address) int { return -1 } -func (s *Snapshot) supposeValidator() common.Address { - validators := s.validators() - index := (s.Number + 1) % uint64(len(validators)) - return validators[index] -} - func parseValidators(header *types.Header, chainConfig *params.ChainConfig, parliaConfig *params.ParliaConfig) ([]common.Address, []types.BLSPublicKey, error) { validatorsBytes := getValidatorBytesFromHeader(header, chainConfig, parliaConfig) if len(validatorsBytes) == 0 { @@ -410,6 +442,24 @@ func parseValidators(header *types.Header, chainConfig *params.ChainConfig, parl return cnsAddrs, voteAddrs, nil } +func parseTurnTerm(header *types.Header, chainConfig *params.ChainConfig, parliaConfig *params.ParliaConfig) (*uint8, error) { + if header.Number.Uint64()%parliaConfig.Epoch != 0 || + !chainConfig.IsHaber(header.Number, header.Time) { + return nil, nil + } + + if len(header.Extra) <= extraVanity+extraSeal { + return nil, errors.New("invalid turnTerm") + } + num := int(header.Extra[extraVanity]) + pos := extraVanity + validatorNumberSize + num*validatorBytesLength + if len(header.Extra) <= pos { + return nil, errors.New("invalid turnTerm") + } + turnterm := header.Extra[pos] + return &turnterm, nil +} + func FindAncientHeader(header *types.Header, ite uint64, chain consensus.ChainHeaderReader, candidateParents []*types.Header) *types.Header { ancient := header for i := uint64(1); i <= ite; i++ { diff --git a/core/systemcontracts/haber/chapel/ValidatorContract b/core/systemcontracts/haber/chapel/ValidatorContract new file mode 100644 index 0000000000..e69de29bb2 diff --git a/core/systemcontracts/haber/mainnet/ValidatorContract b/core/systemcontracts/haber/mainnet/ValidatorContract new file mode 100644 index 0000000000..e69de29bb2 diff --git a/core/systemcontracts/haber/rialto/ValidatorContract b/core/systemcontracts/haber/rialto/ValidatorContract new file mode 100644 index 0000000000..37b4bca0c1 --- /dev/null +++ b/core/systemcontracts/haber/rialto/ValidatorContract @@ -0,0 +1 @@ +60806040526004361061051c5760003560e01c80638a7beb01116102a2578063c81b166211610165578063ea321e49116100cc578063f92eb86b11610085578063f92eb86b14610d8d578063f9a2bbc714610da2578063fc3e590814610db7578063fccc281314610dcc578063fd4ad81f14610de1578063fd6a687914610e1057610523565b8063ea321e4914610cfb578063eb57e20214610d1b578063ec12e4b114610d3b578063eda5868c14610d50578063f1fad10414610d65578063f340fa0114610d7a57610523565b8063db2713db1161011e578063db2713db14610c7d578063dc927faf14610c92578063df8079e914610ca7578063e086c7b114610cbc578063e1c7392a14610cd1578063e40716a114610ce657610523565b8063c81b166214610c09578063c8509d81146109ae578063ce910b0c14610c1e578063d68fb56a14610c3e578063d86222d514610c53578063daacdb6614610c6857610523565b8063aa82dce111610209578063aef198a9116101c2578063aef198a914610b93578063b7ab4db514610ba8578063b8cf4ef114610bca578063bf9f49951461071f578063c466689d14610bdf578063c6d3394514610bf457610523565b8063aa82dce114610aff578063aad5606314610b14578063aaf5eb6814610b29578063ab51bb9614610b3e578063ac43175114610b53578063ad3c9da614610b7357610523565b80639dc092621161025b5780639dc0926214610a815780639fe0f81614610a96578063a0dc275814610aab578063a1a11bf514610ac0578063a5422d5c14610ad5578063a78abc1614610aea57610523565b80638a7beb01146109f85780638b5ad0c914610a0d5780638d19a41014610a225780638d49230614610a425780639369d7de14610a5757806396713da914610a6c57610523565b80635192c82c116103ea578063718a8aa81161035157806381650b621161030a57806381650b6214610984578063820dcaa814610999578063831d65d1146109ae578063853230aa1461093057806386249882146109ce57806388b32f11146109e357610523565b8063718a8aa81461090657806375d47a0a1461091b57806378dfed4a146109305780637942fd05146109455780637a84ca2a1461095a5780637e434d541461096f57610523565b80635d77156c116103a35780635d77156c1461086057806360eba4fe1461087557806362b72cf5146108955780636969a25c146108aa5780636e47b482146108dc57806370fd5bad146108f157610523565b80635192c82c146107cc57806351b4dce3146107e157806351e80672146107f657806355614fcc1461080b578063565c56b31461082b5780635667515a1461084b57610523565b8063300c35671161048e57806343756e5c1161044757806343756e5c1461074157806345cf9daf14610756578063493279b11461076b5780634bf6c8821461078d5780634d97cdce146107a25780634df6e0c3146107b757610523565b8063300c35671461067c578063321d398a1461069c5780633365af3a146106bc57806335409f7f146106dc5780633b071dcc146106fc5780633dffc3871461071f57610523565b8063152ad3b8116104e0578063152ad3b8146105db5780631e4c1524146105fd5780631ff180691461061d578063219f22d51461063257806328087028146106475780632a0ffb6e1461065c57610523565b806304c4fec61461052857806307a568471461053f5780630bee7a671461056a5780630e2374a51461058c5780631182b875146105ae57610523565b3661052357005b600080fd5b34801561053457600080fd5b5061053d610e25565b005b34801561054b57600080fd5b50610554610e97565b6040516105619190619444565b60405180910390f35b34801561057657600080fd5b5061057f610e9d565b604051610561919061946e565b34801561059857600080fd5b506105a1610ea2565b60405161056191906185a7565b3480156105ba57600080fd5b506105ce6105c936600461848d565b610ea8565b604051610561919061873a565b3480156105e757600080fd5b506105f06111a4565b604051610561919061872f565b34801561060957600080fd5b5061053d61061836600461829b565b6111ad565b34801561062957600080fd5b50610554611883565b34801561063e57600080fd5b5061057f611889565b34801561065357600080fd5b506105a161188e565b34801561066857600080fd5b5061053d6106773660046181fb565b611894565b34801561068857600080fd5b5061053d610697366004618233565b611941565b3480156106a857600080fd5b506105f06106b736600461843a565b611c8a565b3480156106c857600080fd5b506105f06106d736600461843a565b611d59565b3480156106e857600080fd5b5061053d6106f73660046181fb565b611e0a565b34801561070857600080fd5b50610711611f6f565b604051610561929190618645565b34801561072b57600080fd5b5061073461224b565b604051610561919061947f565b34801561074d57600080fd5b506105a1612250565b34801561076257600080fd5b50610554612256565b34801561077757600080fd5b5061078061225c565b6040516105619190619435565b34801561079957600080fd5b50610734612262565b3480156107ae57600080fd5b50610554612267565b3480156107c357600080fd5b5061071161226d565b3480156107d857600080fd5b506105546123f9565b3480156107ed57600080fd5b506105a16123ff565b34801561080257600080fd5b506105a1612405565b34801561081757600080fd5b506105f06108263660046181fb565b61240b565b34801561083757600080fd5b506105546108463660046181fb565b612440565b34801561085757600080fd5b50610734612491565b34801561086c57600080fd5b5061057f612496565b34801561088157600080fd5b506105ce61089036600461843a565b61249b565b3480156108a157600080fd5b50610554612541565b3480156108b657600080fd5b506108ca6108c536600461843a565b612547565b604051610561969594939291906185d4565b3480156108e857600080fd5b506105a16125ab565b3480156108fd57600080fd5b506107346125b1565b34801561091257600080fd5b506107346125b6565b34801561092757600080fd5b506105a16125bb565b34801561093c57600080fd5b506105546125c1565b34801561095157600080fd5b506107346125c7565b34801561096657600080fd5b506105546125cc565b34801561097b57600080fd5b506105a16125d2565b34801561099057600080fd5b5061057f6125d8565b3480156109a557600080fd5b506105546125dd565b3480156109ba57600080fd5b5061053d6109c936600461848d565b6125e3565b3480156109da57600080fd5b50610554612644565b3480156109ef57600080fd5b5061055461264a565b348015610a0457600080fd5b506105f0612650565b348015610a1957600080fd5b50610554612659565b348015610a2e57600080fd5b50610554610a3d3660046181fb565b61265f565b348015610a4e57600080fd5b5061055461269f565b348015610a6357600080fd5b5061053d6126a5565b348015610a7857600080fd5b506107346127b9565b348015610a8d57600080fd5b506105a16127be565b348015610aa257600080fd5b506105546127c4565b348015610ab757600080fd5b506105546127c9565b348015610acc57600080fd5b506105a16127ce565b348015610ae157600080fd5b506105ce6127d4565b348015610af657600080fd5b506105f06127f3565b348015610b0b57600080fd5b506105a16127fc565b348015610b2057600080fd5b506105a1612802565b348015610b3557600080fd5b50610554612808565b348015610b4a57600080fd5b5061057f612491565b348015610b5f57600080fd5b5061053d610b6e3660046183de565b612811565b348015610b7f57600080fd5b50610554610b8e3660046181fb565b613308565b348015610b9f57600080fd5b5061055461331a565b348015610bb457600080fd5b50610bbd613327565b6040516105619190618632565b348015610bd657600080fd5b50610554613413565b348015610beb57600080fd5b50610554613418565b348015610c0057600080fd5b506105546125b1565b348015610c1557600080fd5b506105a161341e565b348015610c2a57600080fd5b506105ce610c3936600461843a565b613424565b348015610c4a57600080fd5b50610554613431565b348015610c5f57600080fd5b50610554613470565b348015610c7457600080fd5b5061055461347c565b348015610c8957600080fd5b50610554613482565b348015610c9e57600080fd5b506105a1613488565b348015610cb357600080fd5b506105a161348e565b348015610cc857600080fd5b50610554610e9d565b348015610cdd57600080fd5b5061053d613494565b348015610cf257600080fd5b50610554613728565b348015610d0757600080fd5b506105f0610d1636600461839f565b61372e565b348015610d2757600080fd5b5061053d610d363660046181fb565b6138b4565b348015610d4757600080fd5b506105546139b8565b348015610d5c57600080fd5b5061057f6139d4565b348015610d7157600080fd5b506107346139d9565b61053d610d883660046181fb565b6139de565b348015610d9957600080fd5b50610554613d94565b348015610dae57600080fd5b506105a1613d9a565b348015610dc357600080fd5b506107346127c4565b348015610dd857600080fd5b506105a1613da0565b348015610ded57600080fd5b50610e01610dfc36600461843a565b613da6565b6040516105619392919061944d565b348015610e1c57600080fd5b506105a1613e68565b6000610e303361265f565b9050600b8181548110610e3f57fe5b600091825260209091206001601690920201015460ff16610e7b5760405162461bcd60e51b8152600401610e7290618f93565b60405180910390fd5b6000610e85613431565b9050610e92338383613e6e565b505050565b60095481565b606481565b61200181565b60005460609060ff16610ecd5760405162461bcd60e51b8152600401610e7290618946565b600b54610f8b57610edc617da7565b60015460005b81811015610f8757600b805460018101825560009190915283516000805160206197b583398151915260169092029182019081556020808601516000805160206197f58339815191528401805460ff1916911515919091179055604086015180518794610f63936000805160206197d5833981519152909101920190617dd6565b506060820151610f799060038301906013617e50565b505050806001019050610ee2565b5050505b610f93617e7d565b6000610fd485858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061413392505050565b9150915080610ff057610fe760646142ef565b9250505061119d565b815160009060ff166110155761100e83602001518460400151614350565b9050611169565b825160ff16600114156111655782602001515160011461105a5760008051602061953183398151915260405161104a90618e4c565b60405180910390a1506067611160565b6000836020015160008151811061106d57fe5b602090810291909101810151516001600160a01b038116600090815260049092526040909120549091508015806110ce57506001808203815481106110ae57fe5b9060005260206000209060040201600201601c9054906101000a900460ff165b1561110c576040516001600160a01b038316907fe209c46bebf57cf265d5d9009a00870e256d9150f3ed5281ab9d9eb3cec6e4be90600090a2611159565b600061111b8360018403615512565b905080611157576040516001600160a01b038416907fe209c46bebf57cf265d5d9009a00870e256d9150f3ed5281ab9d9eb3cec6e4be90600090a25b505b6000925050505b611169565b5060655b63ffffffff811661118e575050604080516000815260208101909152915061119d9050565b611197816142ef565b93505050505b9392505050565b60075460ff1681565b3341146111cc5760405162461bcd60e51b8152600401610e7290619255565b3a156111ea5760405162461bcd60e51b8152600401610e7290618ed2565b825160408051828152602080840282010190915260609082801561122857816020015b611215617ea1565b81526020019060019003908161120d5790505b50905060005b828110156112d2576040518060c0016040528087838151811061124d57fe5b60200260200101516001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b0316815260200186838151811061128f57fe5b60200260200101516001600160401b0316815260200160001515815260200160008152508282815181106112bf57fe5b602090810291909101015260010161122e565b5060405163d31f968d60e01b81526120009063d31f968d906112fd9061100090600890600401618616565b60206040518083038186803b15801561131557600080fd5b505afa158015611329573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061134d919061837f565b15611670578051601554818111156113ef57815b818110156113ed57601580548061137457fe5b60008281526020812060046000199093019283020180546001600160a01b0319908116825560018201805490911690556002810180546001600160e81b031916905560030155905560168054806113c757fe5b6001900381819060005260206000200160006113e39190617ed6565b9055600101611361565b505b60005b8281101561162f5781811061151757601584828151811061140f57fe5b602090810291909101810151825460018181018555600094855293839020825160049092020180546001600160a01b039283166001600160a01b0319918216178255938301519481018054958316958516959095179094556040820151600285018054606085015160808601511515600160e01b0260ff60e01b196001600160401b03909216600160a01b0267ffffffffffffffff60a01b199590961692909716919091179290921692909217169290921790915560a0015160039091015585516016908790839081106114df57fe5b602090810291909101810151825460018101845560009384529282902081516115119491909101929190910190617dd6565b50611627565b83818151811061152357fe5b60200260200101516015828154811061153857fe5b6000918252602091829020835160049092020180546001600160a01b039283166001600160a01b0319918216178255928401516001820180549184169185169190911790556040840151600282018054606087015160808801511515600160e01b0260ff60e01b196001600160401b03909216600160a01b0267ffffffffffffffff60a01b1995909716929097169190911792909216939093171692909217905560a09091015160039091015585518690829081106115f357fe5b60200260200101516016828154811061160857fe5b906000526020600020019080519060200190611625929190617dd6565b505b6001016113f2565b507fb8e726330a0dad1cf3d04e925663b17e391f1ed547d79b7f4e5f344119b442468260405161165f9190619444565b60405180910390a150505050610e92565b60608061167d83866158d5565b9150915060005b6001548110156117735760006001828154811061169d57fe5b90600052602060002090600402016003015490508060001461176a576000600183815481106116c857fe5b9060005260206000209060040201600301819055506120026001600160a01b031663092193ab82600185815481106116fc57fe5b60009182526020909120600491820201546040516001600160e01b031960e086901b168152611737926001600160a01b0390921691016185a7565b6000604051808303818588803b15801561175057600080fd5b505af1158015611764573d6000803e3d6000fd5b50505050505b50600101611684565b5047156117e1577f6ecc855f9440a9282c90913bbc91619fd44f5ec0b462af28d127b116f130aa4d476040516117a99190619444565b60405180910390a1604051611002904780156108fc02916000818181858888f193505050501580156117df573d6000803e3d6000fd5b505b600060038190556005558151156117fc576117fc8282615dbc565b6110016001600160a01b031663fc4333cd6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561183957600080fd5b505af115801561184d573d6000803e3d6000fd5b50506040517fedd8d7296956dd970ab4de3f2fc03be2b0ffc615d20cd4c72c6e44f928630ebf925060009150a150505050505050565b60035481565b606881565b61200581565b33612002146118b55760405162461bcd60e51b8152600401610e72906193fe565b60005b60155481101561193d57816001600160a01b0316601582815481106118d957fe5b60009182526020909120600490910201546001600160a01b031614156119355760016015828154811061190857fe5b9060005260206000209060040201600201601c6101000a81548160ff02191690831515021790555061193d565b6001016118b8565b5050565b3341146119605760405162461bcd60e51b8152600401610e7290619255565b60105443116119815760405162461bcd60e51b8152600401610e7290618ad9565b3a1561199f5760405162461bcd60e51b8152600401610e7290618ed2565b60005460ff166119c15760405162461bcd60e51b8152600401610e7290618946565b60006110023168056bc75e2d631000008111156119f8576119f18168056bc75e2d6310000063ffffffff6165ab16565b91506119ff565b5050611c80565b6040516309a99b4f60e41b815261100290639a99b4f090611a2690309086906004016185bb565b602060405180830381600087803b158015611a4057600080fd5b505af1158015611a54573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a789190618452565b915081611a86575050611c80565b6000805b84811015611ab457858582818110611a9e57fe5b9050602002013582019150806001019050611a8a565b5080611ac257505050611c80565b6000806000805b89811015611c785784898983818110611ade57fe5b90506020020135880281611aee57fe5b0493508a8a82818110611afd57fe5b9050602002016020810190611b1291906181fb565b6001600160a01b03811660009081526004602052604090205490935091508115611c2e576000600180840381548110611b4757fe5b9060005260206000209060040201905080600201601c9054906101000a900460ff1615611bb457836001600160a01b03167fb9c75cbbfde137c4281689580799ef5f52144e78858f776a5979b2b212137d8586604051611ba79190619444565b60405180910390a2611c28565b600354611bc7908663ffffffff6165ed16565b6003908155810154611bdf908663ffffffff6165ed16565b60038201556040516001600160a01b038516907fcb0aad6cf9cd03bdf6137e359f541c42f38b39f007cae8e89e88aa7d8c6617b290611c1f908890619444565b60405180910390a25b50611c70565b826001600160a01b03167fb9c75cbbfde137c4281689580799ef5f52144e78858f776a5979b2b212137d8585604051611c679190619444565b60405180910390a25b600101611ac9565b505050505050505b5050436010555050565b6001546000908210611c9e57506000611d54565b60006001600160a01b031660018381548110611cb657fe5b60009182526020909120600490910201546001600160a01b03161480611ce657506008541580611ce65750600a54155b80611cf5575060085460095410155b80611d065750611d0482611d59565b155b80611d2f57506000600b8381548110611d1b57fe5b906000526020600020906016020160000154115b80611d4357506001611d3f613327565b5111155b15611d5057506000611d54565b5060015b919050565b6001546000908210611d6d57506000611d54565b600b548210611daa5760018281548110611d8357fe5b9060005260206000209060040201600201601c9054906101000a900460ff16159050611d54565b60018281548110611db757fe5b9060005260206000209060040201600201601c9054906101000a900460ff16158015611e045750600b8281548110611deb57fe5b600091825260209091206001601690920201015460ff16155b92915050565b600b54611ec857611e19617da7565b60015460005b81811015611ec457600b805460018101825560009190915283516000805160206197b583398151915260169092029182019081556020808601516000805160206197f58339815191528401805460ff1916911515919091179055604086015180518794611ea0936000805160206197d5833981519152909101920190617dd6565b506060820151611eb69060038301906013617e50565b505050806001019050611e1f565b5050505b336110011480611ed9575033612002145b611ef55760405162461bcd60e51b8152600401610e729061897d565b6001600160a01b03811660009081526004602052604090205480611f195750611f6c565b6001810390506000600b8281548110611f2e57fe5b600091825260209091206001601690920201015460ff169050611f518383615512565b8015611f5a5750805b15610e92576009805460001901905550505b50565b60015460609081906000805b82811015611fc25760018181548110611f9057fe5b9060005260206000209060040201600201601c9054906101000a900460ff16611fba576001909101905b600101611f7b565b50606081604051908082528060200260200182016040528015611fef578160200160208202803683370190505b50905060608260405190808252806020026020018201604052801561202857816020015b60608152602001906001900390816120135790505b50600b54600094509091508414156121a35760005b8481101561219d576001818154811061205257fe5b9060005260206000209060040201600201601c9054906101000a900460ff16612195576001818154811061208257fe5b600091825260209091206004909102015483516001600160a01b03909116908490869081106120ad57fe5b60200260200101906001600160a01b031690816001600160a01b031681525050600b81815481106120da57fe5b600091825260209182902060026016909202018101805460408051601f6000196101006001861615020190931694909404918201859004850284018501905280835291929091908301828280156121725780601f1061214757610100808354040283529160200191612172565b820191906000526020600020905b81548152906001019060200180831161215557829003601f168201915b505050505082858151811061218357fe5b60209081029190910101526001909301925b60010161203d565b5061223f565b60005b8481101561223d57600181815481106121bb57fe5b9060005260206000209060040201600201601c9054906101000a900460ff1661223557600181815481106121eb57fe5b600091825260209091206004909102015483516001600160a01b039091169084908690811061221657fe5b6001600160a01b03909216602092830291909101909101526001909301925b6001016121a6565b505b909450925050505b9091565b600181565b61100181565b60085481565b6102ca81565b600881565b600f5481565b6060806000600e549050600080600c541161228957601561228d565b600c545b90506060612299613327565b905060606122a682616612565b9050828251116122bd579094509250612247915050565b838383510310156122cf578282510393505b83156123055760c843046122eb83838388880360008a8a616780565b6123038383838888038989038a8b8b8b510301616780565b505b606083604051908082528060200260200182016040528015612331578160200160208202803683370190505b50905060608460405190808252806020026020018201604052801561236a57816020015b60608152602001906001900390816123555790505b50905060005b858110156123eb5784818151811061238457fe5b602002602001015183828151811061239857fe5b60200260200101906001600160a01b031690816001600160a01b0316815250508381815181106123c457fe5b60200260200101518282815181106123d857fe5b6020908102919091010152600101612370565b509096509450505050509091565b60065481565b61200681565b61200081565b6001600160a01b03811660009081526004602052604081205480612433576000915050611d54565b6000190161119d81611d59565b6001600160a01b03811660009081526004602052604081205480612468576000915050611d54565b60018082038154811061247757fe5b906000526020600020906004020160030154915050919050565b600081565b606781565b601281815481106124a857fe5b600091825260209182902001805460408051601f60026000196101006001871615020190941693909304928301859004850281018501909152818152935090918301828280156125395780601f1061250e57610100808354040283529160200191612539565b820191906000526020600020905b81548152906001019060200180831161251c57829003601f168201915b505050505081565b60105481565b6001818154811061255457fe5b600091825260209091206004909102018054600182015460028301546003909301546001600160a01b0392831694509082169291821691600160a01b81046001600160401b031691600160e01b90910460ff169086565b61100581565b600281565b601081565b61100881565b6103e881565b600b81565b600c5481565b61200381565b606681565b61271081565b33612000146126045760405162461bcd60e51b8152600401610e7290619177565b7f41ce201247b6ceb957dcdb217d0b8acb50b9ea0e12af9af4f5e7f389021016058383836040516126379392919061948d565b60405180910390a1505050565b60025481565b60115481565b60145460ff1681565b600a5481565b6001600160a01b038116600090815260046020526040812054806126955760405162461bcd60e51b8152600401610e72906190b4565b6000190192915050565b60175481565b600b54612763576126b4617da7565b60015460005b8181101561275f57600b805460018101825560009190915283516000805160206197b583398151915260169092029182019081556020808601516000805160206197f58339815191528401805460ff191691151591909117905560408601518051879461273b936000805160206197d5833981519152909101920190617dd6565b5060608201516127519060038301906013617e50565b5050508060010190506126ba565b5050505b6008546127705760036008555b600a5461277d576002600a555b60006127883361265f565b905061279381611c8a565b6127af5760405162461bcd60e51b8152600401610e7290618e09565b611f6c33826168d7565b600981565b61100781565b600381565b60c881565b61100681565b604051806102a001604052806102648152602001619551610264913981565b60005460ff1681565b61200281565b61300081565b6402540be40081565b60005460ff166128335760405162461bcd60e51b8152600401610e7290618946565b33611007146128545760405162461bcd60e51b8152600401610e7290618f00565b6128be84848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080518082019091526013815272065787069726554696d655365636f6e6447617606c1b6020820152915061696f9050565b1561295b57602081146128e35760405162461bcd60e51b8152600401610e729061906e565b604080516020601f8401819004810282018101909252828152600091612921918585808385018382808284376000920191909152506169c892505050565b9050606481101580156129375750620186a08111155b6129535760405162461bcd60e51b8152600401610e7290618cb1565b6002556132c5565b6129bb84848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260098152686275726e526174696f60b81b6020820152915061696f9050565b15612a7057602081146129e05760405162461bcd60e51b8152600401610e729061877f565b604080516020601f8401819004810282018101909252828152600091612a1e918585808385018382808284376000920191909152506169c892505050565b9050612710612a4a601854612a3e600f54856165ed90919063ffffffff16565b9063ffffffff6165ed16565b1115612a685760405162461bcd60e51b8152600401610e7290618b43565b6006556132c5565b612ada84848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260138152726d61784e756d4f664d61696e7461696e696e6760681b6020820152915061696f9050565b15612b745760208114612aff5760405162461bcd60e51b8152600401610e7290618803565b604080516020601f8401819004810282018101909252828152600091612b3d918585808385018382808284376000920191909152506169c892505050565b600c5490915080612b4c575060155b808210612b6b5760405162461bcd60e51b8152600401610e7290618bd2565b506008556132c5565b612bdd84848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260128152716d61696e7461696e536c6173685363616c6560701b6020820152915061696f9050565b15612c765760208114612c025760405162461bcd60e51b8152600401610e72906188cc565b604080516020601f8401819004810282018101909252828152600091612c40918585808385018382808284376000920191909152506169c892505050565b9050600081118015612c525750600a81105b612c6e5760405162461bcd60e51b8152600401610e72906192a2565b600a556132c5565b612cea84848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152601981527f6d61784e756d4f66576f726b696e6743616e64696461746573000000000000006020820152915061696f9050565b15612d795760208114612d0f5760405162461bcd60e51b8152600401610e7290618880565b604080516020601f8401819004810282018101909252828152600091612d4d918585808385018382808284376000920191909152506169c892505050565b9050600d54811115612d715760405162461bcd60e51b8152600401610e7290618d27565b600e556132c5565b612de284848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260128152716d61784e756d4f6643616e6469646174657360701b6020820152915061696f9050565b15612e645760208114612e075760405162461bcd60e51b8152600401610e7290618f4e565b604080516020601f8401819004810282018101909252828152600091612e45918585808385018382808284376000920191909152506169c892505050565b600d819055600e54909150811015612e5e57600d54600e555b506132c5565b612ec884848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152600d81526c6e756d4f66436162696e65747360981b6020820152915061696f9050565b15612f765760208114612eed5760405162461bcd60e51b8152600401610e7290618911565b604080516020601f8401819004810282018101909252828152600091612f2b918585808385018382808284376000920191909152506169c892505050565b905060008111612f4d5760405162461bcd60e51b8152600401610e72906189eb565b6064811115612f6e5760405162461bcd60e51b8152600401610e7290618a33565b600c556132c5565b612fe284848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080518082019091526015815274696e697453797374656d526577617264526174696f60581b6020820152915061696f9050565b1561308b57602081146130075760405162461bcd60e51b8152600401610e7290618d96565b604080516020601f8401819004810282018101909252828152600091613045918585808385018382808284376000920191909152506169c892505050565b9050612710613065601854612a3e600654856165ed90919063ffffffff16565b11156130835760405162461bcd60e51b8152600401610e72906192ff565b600f556132c5565b6130ff84848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152601881527f616e74694d455653797374656d526577617264526174696f00000000000000006020820152915061696f9050565b156131a857602081146131245760405162461bcd60e51b8152600401610e72906190eb565b604080516020601f8401819004810282018101909252828152600091613162918585808385018382808284376000920191909152506169c892505050565b9050612710613182600f54612a3e600654856165ed90919063ffffffff16565b11156131a05760405162461bcd60e51b8152600401610e72906191c6565b6018556132c5565b61320784848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260088152677475726e5465726d60c01b6020820152915061696f9050565b156132ad576020811461322c5760405162461bcd60e51b8152600401610e7290618c7a565b604080516020601f840181900481028201810190925282815260009161326a918585808385018382808284376000920191909152506169c892505050565b90506003811015801561327e575060098111155b806132895750806001145b6132a55760405162461bcd60e51b8152600401610e72906187b6565b6017556132c5565b60405162461bcd60e51b8152600401610e729061938e565b7f6cdb0ac70ab7f2e2d035cca5be60d89906f2dede7648ddbd7402189c1eeed17a848484846040516132fa949392919061874d565b60405180910390a150505050565b60046020526000908152604090205481565b68056bc75e2d6310000081565b6001546060906000805b828110156133565761334281611d59565b1561334e578160010191505b600101613331565b50606081604051908082528060200260200182016040528015613383578160200160208202803683370190505b5090506000915060005b8381101561340a5761339e81611d59565b1561340257600181815481106133b057fe5b600091825260209091206004909102015482516001600160a01b03909116908390859081106133db57fe5b60200260200101906001600160a01b031690816001600160a01b0316815250508260010192505b60010161338d565b50925050505b90565b601581565b61027181565b61100281565b601381815481106124a857fe5b600061343b613327565b519050600080600c5411613450576015613454565b600c545b905080821115613462578091505b8161346c57600191505b5090565b67016345785d8a000081565b60055481565b60185481565b61100381565b61200481565b60005460ff16156134b75760405162461bcd60e51b8152600401610e7290619000565b6134bf617e7d565b60006134e5604051806102a0016040528061026481526020016195516102649139614133565b91509150806135065760405162461bcd60e51b8152600401610e7290619136565b61350e617da7565b60005b83602001515181101561370f57600b805460018101825560009190915282516000805160206197b583398151915260169092029182019081556020808501516000805160206197f58339815191528401805460ff1916911515919091179055604085015180518694613597936000805160206197d5833981519152909101920190617dd6565b5060608201516135ad9060038301906013617e50565b505050836040015181815181106135c057fe5b6020026020010151600b82815481106135d557fe5b906000526020600020906016020160020190805190602001906135f9929190617dd6565b5060018460200151828151811061360c57fe5b60209081029190910181015182546001818101855560009485528385208351600493840290910180546001600160a01b039283166001600160a01b03199182161782558587015182850180549185169183169190911790556040860151600283018054606089015160808a01511515600160e01b0260ff60e01b196001600160401b03909216600160a01b0267ffffffffffffffff60a01b199590981692909516919091179290921694909417161790915560a0909301516003909301929092559187015180519185019391859081106136e257fe5b602090810291909101810151516001600160a01b0316825281019190915260400160002055600101613511565b50506103e860025550506000805460ff19166001179055565b600d5481565b601354600090815b818110156138375761381f85858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060138054909250859150811061378757fe5b600091825260209182902001805460408051601f60026000196101006001871615020190941693909304928301859004850281018501909152818152928301828280156138155780601f106137ea57610100808354040283529160200191613815565b820191906000526020600020905b8154815290600101906020018083116137f857829003601f168201915b50505050506169cd565b1561382f57600192505050611e04565b600101613736565b5060125460005b818110156138a85761388f86868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060128054909250859150811061378757fe5b156138a05760019350505050611e04565b60010161383e565b50600095945050505050565b33611001146138d55760405162461bcd60e51b8152600401610e72906193b5565b600b54613993576138e4617da7565b60015460005b8181101561398f57600b805460018101825560009190915283516000805160206197b583398151915260169092029182019081556020808601516000805160206197f58339815191528401805460ff191691151591909117905560408601518051879461396b936000805160206197d5833981519152909101920190617dd6565b5060608201516139819060038301906013617e50565b5050508060010190506138ea565b5050505b600061399e82616a31565b90506139a981611c8a565b1561193d5761193d82826168d7565b6000601754600014156139cd57506001613410565b5060175490565b606581565b601181565b3341146139fd5760405162461bcd60e51b8152600401610e7290619255565b60005460ff16613a1f5760405162461bcd60e51b8152600401610e7290618946565b60003411613a3f5760405162461bcd60e51b8152600401610e7290618cf8565b3a15613a5d5760405162461bcd60e51b8152600401610e7290618ed2565b6001600160a01b03811660009081526004602052604090205460145434919060ff16613a9d57610271600f556103e86006556014805460ff191660011790555b600f546017546001108015613ab457506000601854115b15613ad9576001601754036017544381613aca57fe5b066018540281613ad657fe5b04015b600083118015613ae95750600081115b15613b96576000613b12612710613b06348563ffffffff616bb416565b9063ffffffff616bee16565b90508015613b94576040516110029082156108fc029083906000818181858888f19350505050158015613b49573d6000803e3d6000fd5b507f6ecc855f9440a9282c90913bbc91619fd44f5ec0b462af28d127b116f130aa4d81604051613b799190619444565b60405180910390a1613b91848263ffffffff6165ab16565b93505b505b600083118015613ba857506000600654115b15613c4e576000613bca612710613b0660065434616bb490919063ffffffff16565b90508015613c4c5760405161dead9082156108fc029083906000818181858888f19350505050158015613c01573d6000803e3d6000fd5b507f627059660ea01c4733a328effb2294d2f86905bf806da763a89cee254de8bee581604051613c319190619444565b60405180910390a1613c49848263ffffffff6165ab16565b93505b505b8115613d4c576000600180840381548110613c6557fe5b9060005260206000209060040201905080600201601c9054906101000a900460ff1615613cd257846001600160a01b03167ff177e5d6c5764d79c32883ed824111d9b13f5668cf6ab1cc12dd36791dd955b485604051613cc59190619444565b60405180910390a2613d46565b600354613ce5908563ffffffff6165ed16565b6003908155810154613cfd908563ffffffff6165ed16565b60038201556040516001600160a01b038616907f93a090ecc682c002995fad3c85b30c5651d7fd29b0be5da9d784a3302aedc05590613d3d908790619444565b60405180910390a25b50613d8e565b836001600160a01b03167ff177e5d6c5764d79c32883ed824111d9b13f5668cf6ab1cc12dd36791dd955b484604051613d859190619444565b60405180910390a25b50505050565b600e5481565b61100081565b61dead81565b600b8181548110613db357fe5b6000918252602091829020601691909102018054600180830154600280850180546040805161010096831615969096026000190190911692909204601f810188900488028501880190925281845293965060ff90911694919291830182828015613e5e5780601f10613e3357610100808354040283529160200191613e5e565b820191906000526020600020905b815481529060010190602001808311613e4157829003601f168201915b5050505050905083565b61100481565b6000600a5460001480613e7f575081155b80613e8a5750600954155b15613e975750600061119d565b6000613ed1600a54613b0685613b06600b8981548110613eb357fe5b6000918252602090912060169091020154439063ffffffff6165ab16565b90506000806110016001600160a01b0316638256ace66040518163ffffffff1660e01b8152600401604080518083038186803b158015613f1057600080fd5b505afa158015613f24573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613f48919061846a565b91509150600093508083106140a757613f618787615512565b5060405163436aa28360e11b8152600090612002906386d5450690613f8a908b906004016185a7565b60206040518083038186803b158015613fa257600080fd5b505afa158015613fb6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613fda9190618217565b6001600160a01b031614614046576040516313d13bdb60e31b815261100190639e89ded89061400f908a9087906004016185bb565b600060405180830381600087803b15801561402957600080fd5b505af115801561403d573d6000803e3d6000fd5b5050505061409e565b6040516305bfb49960e41b815261100190635bfb49909061406b908a906004016185a7565b600060405180830381600087803b15801561408557600080fd5b505af1158015614099573d6000803e3d6000fd5b505050505b600193506140b9565b8183106140b9576140b787616a31565b505b60098054600019019055600b805460009190889081106140d557fe5b60009182526020822060169190910201600101805460ff1916921515929092179091556040516001600160a01b038916917fb9d38178dc641ff1817967a63c9078cbcd955a9f1fcd75e0e3636de615d44d3b91a25050509392505050565b61413b617e7d565b6000614145617e7d565b61414d617f1a565b61415e61415986616c30565b616c55565b90506000805b61416d83616c9f565b156142e157806141925761418861418384616cc0565b616d0e565b60ff1684526142d9565b80600114156142d45760606141ae6141a985616cc0565b616d8e565b905080516040519080825280602002602001820160405280156141eb57816020015b6141d8617ea1565b8152602001906001900390816141d05790505b508560200181905250805160405190808252806020026020018201604052801561422957816020015b60608152602001906001900390816142145790505b50604086015260005b81518110156142c957614243617ea1565b6060600061426385858151811061425657fe5b6020026020010151616e5f565b92509250925080614283578860009a509a505050505050505050506142ea565b828960200151858151811061429457fe5b602002602001018190525081896040015185815181106142b057fe5b6020026020010181905250505050806001019050614232565b5060019250506142d9565b6142e1565b600101614164565b50919350909150505b915091565b604080516001808252818301909252606091829190816020015b606081526020019060019003908161430957905050905061432f8363ffffffff16616f79565b8160008151811061433c57fe5b602002602001018190525061119d81616f8c565b60006064835111156143875760008051602061953183398151915260405161437790618a90565b60405180910390a1506066611e04565b60005b83518110156144255760005b8181101561441c578481815181106143aa57fe5b6020026020010151600001516001600160a01b03168583815181106143cb57fe5b6020026020010151600001516001600160a01b031614156144145760008051602061953183398151915260405161440190618c2f565b60405180910390a1606692505050611e04565b600101614396565b5060010161438a565b5060608060606015805480602002602001604051908101604052809291908181526020016000905b828210156144d75760008481526020908190206040805160c0810182526004860290920180546001600160a01b039081168452600180830154821685870152600283015491821693850193909352600160a01b81046001600160401b03166060850152600160e01b900460ff16151560808401526003015460a0830152908352909201910161444d565b50505050905060606016805480602002602001604051908101604052809291908181526020016000905b828210156145ac5760008481526020908190208301805460408051601f60026000196101006001871615020190941693909304928301859004850281018501909152818152928301828280156145985780601f1061456d57610100808354040283529160200191614598565b820191906000526020600020905b81548152906001019060200180831161457b57829003601f168201915b505050505081526020019060010190614501565b50505050905060005b8251811015614609578281815181106145ca57fe5b6020026020010151606001516003028382815181106145e557fe5b60209081029190910101516001600160401b039091166060909101526001016145b5565b5060608061461989898686617016565b9150915061462782826158d5565b60015460408051828152602080840282010190915292985090965060009550859450925060609150828015614666578160200160208202803683370190505b50905060005b828110156147f75760006001600160a01b03166120026001600160a01b03166386d545066001848154811061469d57fe5b60009182526020909120600491820201546040516001600160e01b031960e085901b1681526146d8926001600160a01b0390921691016185a7565b60206040518083038186803b1580156146f057600080fd5b505afa158015614704573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906147289190618217565b6001600160a01b03161461478a57600182828151811061474457fe5b602002602001019060ff16908160ff16815250506001818154811061476557fe5b906000526020600020906004020160030154600014614785578360010193505b6147ef565b67016345785d8a0000600182815481106147a057fe5b906000526020600020906004020160030154106147c2578460010194506147ef565b600181815481106147cf57fe5b9060005260206000209060040201600301546000146147ef578360010193505b60010161466c565b50606084604051908082528060200260200182016040528015614824578160200160208202803683370190505b509050606085604051908082528060200260200182016040528015614853578160200160208202803683370190505b509050606086604051908082528060200260200182016040528015614882578160200160208202803683370190505b5090506060876040519080825280602002602001820160405280156148b1578160200160208202803683370190505b50905060006060886040519080825280602002602001820160405280156148e2578160200160208202803683370190505b509050606089604051908082528060200260200182016040528015614911578160200160208202803683370190505b50905060009a506000995060006110046001600160a01b031663149d14d96040518163ffffffff1660e01b815260040160206040518083038186803b15801561495957600080fd5b505afa15801561496d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906149919190618452565b905067016345785d8a00008111156149dd576000805160206195318339815191526040516149be90618fbf565b60405180910390a160689e505050505050505050505050505050611e04565b60005b8a811015614d71578981815181106149f457fe5b602002602001015160ff1660011415614aea5760018181548110614a1457fe5b906000526020600020906004020160030154600014614ae55760018181548110614a3a57fe5b600091825260209091206004909102015484516001600160a01b039091169085908e908110614a6557fe5b60200260200101906001600160a01b031690816001600160a01b03168152505060018181548110614a9257fe5b906000526020600020906004020160030154838d81518110614ab057fe5b60200260200101818152505060018a8d81518110614aca57fe5b602002602001019060ff16908160ff16815250508b6001019b505b614d69565b67016345785d8a000060018281548110614b0057fe5b90600052602060002090600402016003015410614c855760018181548110614b2457fe5b906000526020600020906004020160020160009054906101000a90046001600160a01b0316898e81518110614b5557fe5b60200260200101906001600160a01b031690816001600160a01b03168152505060006402540be40060018381548110614b8a57fe5b90600052602060002090600402016003015481614ba357fe5b0660018381548110614bb157fe5b906000526020600020906004020160030154039050614bd983826165ab90919063ffffffff16565b898f81518110614be557fe5b60200260200101818152505060018281548110614bfe57fe5b906000526020600020906004020160010160009054906101000a90046001600160a01b0316878f81518110614c2f57fe5b60200260200101906001600160a01b031690816001600160a01b03168152505081888f81518110614c5c57fe5b6020908102919091010152614c77868263ffffffff6165ed16565b95508d6001019d5050614d69565b60018181548110614c9257fe5b906000526020600020906004020160030154600014614d695760018181548110614cb857fe5b906000526020600020906004020160010160009054906101000a90046001600160a01b0316848d81518110614ce957fe5b60200260200101906001600160a01b031690816001600160a01b03168152505060018181548110614d1657fe5b906000526020600020906004020160030154838d81518110614d3457fe5b60200260200101818152505060008a8d81518110614d4e57fe5b602002602001019060ff16908160ff16815250508b6001019b505b6001016149e0565b5060008415614fe7576002546040516303702b2960e51b815261100491636e056520918891614dab918e918e918d914201906004016186b5565b6020604051808303818588803b158015614dc457600080fd5b505af193505050508015614df5575060408051601f3d908101601f19168201909252614df29181019061837f565b60015b614f6c576040516000815260443d1015614e1157506000614eac565b60046000803e60005160e01c6308c379a08114614e32576000915050614eac565b60043d036004833e81513d60248201116001600160401b0382111715614e5d57600092505050614eac565b80830180516001600160401b03811115614e7e576000945050505050614eac565b8060208301013d8601811115614e9c57600095505050505050614eac565b601f01601f191660405250925050505b80614eb75750614ef9565b60019150857fa7cdeed7d0db45e3219a6e5d60838824c16f1d39991fcfe3f963029c844bf28082604051614eeb919061873a565b60405180910390a250614f67565b3d808015614f23576040519150601f19603f3d011682016040523d82523d6000602084013e614f28565b606091505b5060019150857fbfa884552dd8921b6ce90bfe906952ae5b3b29be0cc1a951d4f62697635a3a4582604051614f5d919061873a565b60405180910390a2505b614fe7565b8015614fae577fa217d08e65f80c73121cd9db834d81652d544bfbf452f6d04922b16c90a37b7086604051614fa19190619444565b60405180910390a1614fe5565b857fa7cdeed7d0db45e3219a6e5d60838824c16f1d39991fcfe3f963029c844bf280604051614fdc90618849565b60405180910390a25b505b801561519d5760005b875181101561519b57600088828151811061500757fe5b6020026020010151905060006001828154811061502057fe5b60009182526020909120600160049092020181015481546001600160a01b03909116916108fc918590811061505157fe5b9060005260206000209060040201600301549081150290604051600060405180830381858888f193505050509050801561510d576001828154811061509257fe5b60009182526020909120600160049092020181015481546001600160a01b03909116917f6c61d60f69a7beb3e1c80db7f39f37b208537cbb19da3174511b477812b2fc7d91859081106150e157fe5b9060005260206000209060040201600301546040516151009190619444565b60405180910390a2615191565b6001828154811061511a57fe5b60009182526020909120600160049092020181015481546001600160a01b03909116917f25d0ce7d2f0cec669a8c17efe49d195c13455bb8872b65fa610ac7f53fe4ca7d918590811061516957fe5b9060005260206000209060040201600301546040516151889190619444565b60405180910390a25b5050600101614ff0565b505b8351156153935760005b8451811015615391578a81815181106151bc57fe5b602002602001015160ff166001141561525b576120026001600160a01b031663092193ab8583815181106151ec57fe5b602002602001015187848151811061520057fe5b60200260200101516040518363ffffffff1660e01b815260040161522491906185a7565b6000604051808303818588803b15801561523d57600080fd5b505af1158015615251573d6000803e3d6000fd5b5050505050615389565b600085828151811061526957fe5b60200260200101516001600160a01b03166108fc86848151811061528957fe5b60200260200101519081150290604051600060405180830381858888f193505050509050801561531f578582815181106152bf57fe5b60200260200101516001600160a01b03167f6c61d60f69a7beb3e1c80db7f39f37b208537cbb19da3174511b477812b2fc7d8684815181106152fd57fe5b60200260200101516040516153129190619444565b60405180910390a2615387565b85828151811061532b57fe5b60200260200101516001600160a01b03167f25d0ce7d2f0cec669a8c17efe49d195c13455bb8872b65fa610ac7f53fe4ca7d86848151811061536957fe5b602002602001015160405161537e9190619444565b60405180910390a25b505b6001016151a7565b505b5050505050505050505050505060005b60015481101561540057600181815481106153ba57fe5b9060005260206000209060040201600301546000146153f8576000600182815481106153e257fe5b9060005260206000209060040201600301819055505b6001016153a3565b50471561546e577f6ecc855f9440a9282c90913bbc91619fd44f5ec0b462af28d127b116f130aa4d476040516154369190619444565b60405180910390a1604051611002904780156108fc02916000818181858888f1935050505015801561546c573d6000803e3d6000fd5b505b60006003819055600555815115615489576154898282615dbc565b6110016001600160a01b031663fc4333cd6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156154c657600080fd5b505af11580156154da573d6000803e3d6000fd5b50506040517fedd8d7296956dd970ab4de3f2fc03be2b0ffc615d20cd4c72c6e44f928630ebf925060009150a1506000949350505050565b6000806001838154811061552257fe5b9060005260206000209060040201600301549050600060018080549050039050600161554c613327565b51116155815760006001858154811061556157fe5b906000526020600020906004020160030181905550600092505050611e04565b846001600160a01b03167f3b6f9ef90462b512a1293ecec018670bf7b7f1876fb727590a8a6d7643130a70836040516155ba9190619444565b60405180910390a26001600160a01b038516600090815260046020526040812055835b600154600019018110156157a757600181600101815481106155fb57fe5b90600052602060002090600402016001828154811061561657fe5b60009182526020909120825460049092020180546001600160a01b03199081166001600160a01b0393841617825560018085015481840180548416918616919091179055600280860180549185018054909416919095161780835584546001600160401b03600160a01b91829004160267ffffffffffffffff60a01b1990911617808355935460ff600160e01b918290041615150260ff60e01b19909416939093179055600392830154920191909155600b8054909183019081106156d757fe5b9060005260206000209060160201600b82815481106156f257fe5b600091825260209091208254601690920201908155600180830154818301805460ff909216151560ff1990921691909117905560028084018054615749938386019390821615610100026000190190911604617f3a565b5061575c60038281019084016013617faf565b5090505080600101600460006001848154811061577557fe5b600091825260208083206004909202909101546001600160a01b031683528201929092526040019020556001016155dd565b5060018054806157b357fe5b60008281526020812060046000199093019283020180546001600160a01b0319908116825560018201805490911690556002810180546001600160e81b0319169055600301559055600b80548061580657fe5b60008281526020812060166000199093019283020181815560018101805460ff19169055906158386002830182617ed6565b615846600383016000617fd9565b50509055600081838161585557fe5b04905080156158c95760015460005b818110156158c65761589d836001838154811061587d57fe5b9060005260206000209060040201600301546165ed90919063ffffffff16565b600182815481106158aa57fe5b6000918252602090912060036004909202010155600101615864565b50505b50600195945050505050565b6060806000808080806158e6613431565b6001549091505b8015615b1557600181039250600b838154811061590657fe5b600091825260209091206001601690920201015460ff1661592657615b0c565b6001838154811061593357fe5b60009182526020909120600490910201546001600160a01b0316945061595a858484613e6e565b93508361596657615b0c565b60405163436aa28360e11b81526000908190612002906386d5450690615990908a906004016185a7565b60206040518083038186803b1580156159a857600080fd5b505afa1580156159bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906159e09190618217565b90506001600160a01b03811615615a69576040516302ceee9160e11b81526120029063059ddd2290615a169084906004016185a7565b60206040518083038186803b158015615a2e57600080fd5b505afa158015615a42573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190615a669190618217565b91505b60005b8c51811015615b0857876001600160a01b03168d8281518110615a8b57fe5b6020026020010151600001516001600160a01b03161480615ad45750826001600160a01b03168d8281518110615abd57fe5b6020026020010151600001516001600160a01b0316145b15615b005760018d8281518110615ae757fe5b6020908102919091010151901515608090910152615b08565b600101615a6c565b5050505b600019016158ed565b5060005b8951811015615b8257898181518110615b2e57fe5b60200260200101516080015180615b6e575060006001600160a01b03168a8281518110615b5757fe5b6020026020010151600001516001600160a01b0316145b15615b7a578560010195505b600101615b19565b5088518510615c6a5760408051600180825281830190925290816020015b615ba8617ea1565b815260200190600190039081615ba0575050604080516001808252818301909252919850602082015b6060815260200190600190039081615bd157905050955088600081518110615bf557fe5b602002602001015187600081518110615c0a57fe5b602002602001018190525087600081518110615c2257fe5b602002602001015186600081518110615c3757fe5b6020026020010181905250600087600081518110615c5157fe5b6020908102919091010151901515608090910152615daf565b84895103604051908082528060200260200182016040528015615ca757816020015b615c94617ea1565b815260200190600190039081615c8c5790505b50965084895103604051908082528060200260200182016040528015615ce157816020015b6060815260200190600190039081615ccc5790505b5095506000915060005b8951811015615dad57898181518110615d0057fe5b602002602001015160800151158015615d43575060006001600160a01b03168a8281518110615d2b57fe5b6020026020010151600001516001600160a01b031614155b15615da557898181518110615d5457fe5b6020026020010151888481518110615d6857fe5b6020026020010181905250888181518110615d7f57fe5b6020026020010151878481518110615d9357fe5b60200260200101819052508260010192505b600101615ceb565b505b50505050505b9250929050565b600154825160005b82811015615ed9576001615dd6617ea1565b60018381548110615de357fe5b600091825260208083206040805160c08101825260049490940290910180546001600160a01b0390811685526001820154811693850193909352600281015492831691840191909152600160a01b82046001600160401b03166060840152600160e01b90910460ff16151560808301526003015460a082015291505b84811015615ead57878181518110615e7357fe5b6020026020010151600001516001600160a01b031682600001516001600160a01b03161415615ea55760009250615ead565b600101615e5f565b508115615ecf5780516001600160a01b03166000908152600460205260408120555b5050600101615dc4565b5080821115615f9857805b82811015615f96576001805480615ef757fe5b60008281526020812060046000199093019283020180546001600160a01b0319908116825560018201805490911690556002810180546001600160e81b0319169055600301559055600b805480615f4a57fe5b60008281526020812060166000199093019283020181815560018101805460ff1916905590615f7c6002830182617ed6565b615f8a600383016000617fd9565b50509055600101615ee4565b505b6000818310615fa75781615fa9565b825b905060005b8181101561634d5761605b868281518110615fc557fe5b602002602001015160018381548110615fda57fe5b60009182526020918290206040805160c08101825260049390930290910180546001600160a01b0390811684526001820154811694840194909452600281015493841691830191909152600160a01b83046001600160401b03166060830152600160e01b90920460ff161515608082015260039091015460a08201526173e2565b61620f57806001016004600088848151811061607357fe5b6020026020010151600001516001600160a01b03166001600160a01b03168152602001908152602001600020819055508581815181106160af57fe5b6020026020010151600182815481106160c457fe5b6000918252602091829020835160049092020180546001600160a01b039283166001600160a01b0319918216178255928401516001820180549184169185169190911790556040840151600282018054606087015160808801511515600160e01b0260ff60e01b196001600160401b03909216600160a01b0267ffffffffffffffff60a01b1995909716929097169190911792909216939093171692909217905560a090910151600390910155845185908290811061617f57fe5b6020026020010151600b828154811061619457fe5b906000526020600020906016020160020190805190602001906161b8929190617dd6565b506000600b82815481106161c857fe5b60009182526020822060169190910201600101805460ff191692151592909217909155600b8054839081106161f957fe5b6000918252602090912060169091020155616345565b85818151811061621b57fe5b6020026020010151606001516001828154811061623457fe5b906000526020600020906004020160020160146101000a8154816001600160401b0302191690836001600160401b031602179055506162fa85828151811061627857fe5b6020026020010151600b838154811061628d57fe5b600091825260209182902060026016909202018101805460408051601f6000196101006001861615020190931694909404918201859004850284018501905280835291929091908301828280156138155780601f106137ea57610100808354040283529160200191613815565b6163455784818151811061630a57fe5b6020026020010151600b828154811061631f57fe5b90600052602060002090601602016002019080519060200190616343929190617dd6565b505b600101615fae565b50828211156165255761635e617da7565b835b838110156165225785818151811061637457fe5b60200260200101518260400181905250600187828151811061639257fe5b6020908102919091018101518254600181810185556000948552838520835160049093020180546001600160a01b039384166001600160a01b0319918216178255848601518284018054918616918316919091179055604080860151600284018054606089015160808a01511515600160e01b0260ff60e01b196001600160401b03909216600160a01b0267ffffffffffffffff60a01b1995909a1692909616919091179290921696909617169190911790935560a090930151600390930192909255600b80549283018155909352845160169091026000805160206197b58339815191528101918255858301516000805160206197f58339815191528201805491151560ff19909216919091179055928501518051869492936164c8936000805160206197d583398151915201920190617dd6565b5060608201516164de9060038301906013617e50565b50505080600101600460008984815181106164f557fe5b602090810291909101810151516001600160a01b0316825281019190915260400160002055600101616360565b50505b61652d61743e565b616535617620565b6000600981905560015493505b838110156165a3576000600b828154811061655957fe5b60009182526020822060169190910201600101805460ff191692151592909217909155600b80548390811061658a57fe5b6000918252602090912060169091020155600101616542565b505050505050565b600061119d83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f77000081525061780e565b60008282018381101561119d5760405162461bcd60e51b8152600401610e72906189b4565b60015481516040805182815260208084028201019091526060929190839082801561665157816020015b606081526020019060019003908161663c5790505b50600b549091508314616668579250611d54915050565b60005b8281101561677757600b60016004600089858151811061668757fe5b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205403815481106166bb57fe5b600091825260209182902060026016909202018101805460408051601f6000196101006001861615020190931694909404918201859004850284018501905280835291929091908301828280156167535780601f1061672857610100808354040283529160200191616753565b820191906000526020600020905b81548152906001019060200180831161673657829003601f168201915b505050505082828151811061676457fe5b602090810291909101015260010161666b565b50949350505050565b60005b828110156168cd57600082878388016040516020016167a3929190618599565b6040516020818303038152906040528051906020012060001c816167c357fe5b069050808501828701146168c457600089838801815181106167e157fe5b60200260200101519050606089848901815181106167fb57fe5b602002602001015190508a8388018151811061681357fe5b60200260200101518b858a018151811061682957fe5b60200260200101906001600160a01b031690816001600160a01b031681525050818b8489018151811061685857fe5b60200260200101906001600160a01b031690816001600160a01b031681525050898388018151811061688657fe5b60200260200101518a858a018151811061689c57fe5b6020026020010181905250808a848901815181106168b657fe5b602002602001018190525050505b50600101616783565b5050505050505050565b600980546001908101909155600b8054839081106168f157fe5b906000526020600020906016020160010160006101000a81548160ff02191690831515021790555043600b828154811061692757fe5b600091825260208220601690910201919091556040516001600160a01b038416917ff62981a567ec3cec866c6fa93c55bcdf841d6292d18b8d522ececa769375d82d91a25050565b600081604051602001616982919061857d565b60405160208183030381529060405280519060200120836040516020016169a9919061857d565b6040516020818303038152906040528051906020012014905092915050565b015190565b8151815160009160019181148083146169e95760009250616a27565b600160208701838101602088015b600284838510011415616a22578051835114616a165760009650600093505b602092830192016169f7565b505050505b5090949350505050565b6001600160a01b03811660009081526004602052604081205480616a5a57506000199050611d54565b600181039050600060018281548110616a6f57fe5b9060005260206000209060040201600301549050600060018381548110616a9257fe5b6000918252602090912060036004909202010155600154604051600019909101906001600160a01b038616907f8cd4e147d8af98a9e3b6724021b8bf6aed2e5dac71c38f2dce8161b82585b25d90616aeb908590619444565b60405180910390a280616b0357829350505050611d54565b6000818381616b0e57fe5b0490508015616baa5760005b84811015616b5c57616b33826001838154811061587d57fe5b60018281548110616b4057fe5b6000918252602090912060036004909202010155600101616b1a565b50600180549085015b81811015616ba757616b7e836001838154811061587d57fe5b60018281548110616b8b57fe5b6000918252602090912060036004909202010155600101616b65565b50505b5091949350505050565b600082616bc357506000611e04565b82820282848281616bd057fe5b041461119d5760405162461bcd60e51b8152600401610e7290618e91565b600061119d83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f00000000000081525061783a565b616c38617fe8565b506040805180820190915281518152602082810190820152919050565b616c5d617f1a565b616c6682617871565b616c6f57600080fd5b6000616c7e83602001516178ab565b60208085015160408051808201909152868152920190820152915050919050565b6000616ca9617fe8565b505080518051602091820151919092015191011190565b616cc8617fe8565b616cd182616c9f565b616cda57600080fd5b60208201516000616cea8261790e565b80830160209586015260408051808201909152908152938401919091525090919050565b805160009015801590616d2357508151602110155b616d2c57600080fd5b6000616d3b83602001516178ab565b90508083600001511015616d615760405162461bcd60e51b8152600401610e7290619037565b82516020808501518301805192849003929183101561677757506020919091036101000a90049392505050565b6060616d9982617871565b616da257600080fd5b6000616dad836179ef565b9050606081604051908082528060200260200182016040528015616deb57816020015b616dd8617fe8565b815260200190600190039081616dd05790505b5090506000616dfd85602001516178ab565b60208601510190506000805b84811015616e5457616e1a8361790e565b9150604051806040016040528083815260200184815250848281518110616e3d57fe5b602090810291909101015291810191600101616e09565b509195945050505050565b616e67617ea1565b60606000616e73617ea1565b6060616e7d617f1a565b616e8687616c55565b90506000805b616e9583616c9f565b15616f6a5780616ec057616eb0616eab84616cc0565b617a4b565b6001600160a01b03168552616f62565b8060011415616ee857616ed5616eab84616cc0565b6001600160a01b03166020860152616f62565b8060021415616f1057616efd616eab84616cc0565b6001600160a01b03166040860152616f62565b8060031415616f3c57616f2561418384616cc0565b6001600160401b0316606086015260019150616f62565b8060041415616f5d57616f56616f5184616cc0565b617a65565b9350616f62565b616f6a565b600101616e8c565b50929791965091945092505050565b6060611e04616f8783617ad5565b617bbb565b6060815160001415616fad5750604080516000815260208101909152611d54565b606082600081518110616fbc57fe5b602002602001015190506000600190505b8351811015616ffd57616ff382858381518110616fe657fe5b6020026020010151617c0d565b9150600101616fcd565b5061119d617010825160c060ff16617c8a565b82617c0d565b60608060006120026001600160a01b031663c473318f6040518163ffffffff1660e01b815260040160206040518083038186803b15801561705657600080fd5b505afa15801561706a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061708e9190618452565b905080855188510110156170a3575083518651015b6060816040519080825280602002602001820160405280156170df57816020015b6170cc617ea1565b8152602001906001900390816170c45790505b50905060608260405190808252806020026020018201604052801561711857816020015b60608152602001906001900390816171035790505b50905060008060005b8b518310806171305750895182105b801561713b57508581105b156173d0578b518314156171ab5789828151811061715557fe5b602002602001015185828151811061716957fe5b602002602001018190525088828151811061718057fe5b602002602001015184828151811061719457fe5b602090810291909101015260019182019101617121565b8951821415617216578b83815181106171c057fe5b60200260200101518582815181106171d457fe5b60200260200101819052508a83815181106171eb57fe5b60200260200101518482815181106171ff57fe5b602090810291909101015260019283019201617121565b89828151811061722257fe5b6020026020010151606001516001600160401b03168c848151811061724357fe5b6020026020010151606001516001600160401b031611156172bf578b838151811061726a57fe5b602002602001015185828151811061727e57fe5b60200260200101819052508a838151811061729557fe5b60200260200101518482815181106172a957fe5b60200260200101819052508260010192506173c8565b8982815181106172cb57fe5b6020026020010151606001516001600160401b03168c84815181106172ec57fe5b6020026020010151606001516001600160401b031610156173685789828151811061731357fe5b602002602001015185828151811061732757fe5b602002602001018190525088828151811061733e57fe5b602002602001015184828151811061735257fe5b60200260200101819052508160010191506173c8565b89828151811061737457fe5b6020026020010151600001516001600160a01b03168c848151811061739557fe5b6020026020010151600001516001600160a01b031610156173bc578b838151811061726a57fe5b89828151811061715557fe5b600101617121565b50929a91995090975050505050505050565b805182516000916001600160a01b03918216911614801561741c575081602001516001600160a01b031683602001516001600160a01b0316145b801561119d5750506040908101519101516001600160a01b0390811691161490565b6012546013548082111561748957805b8281101561748757601280548061746157fe5b60019003818190600052602060002001600061747d9190617ed6565b905560010161744e565b505b6000818310617498578161749a565b825b905060005b818110156175b257617557601282815481106174b757fe5b600091825260209182902001805460408051601f60026000196101006001871615020190941693909304928301859004850281018501909152818152928301828280156175455780601f1061751a57610100808354040283529160200191617545565b820191906000526020600020905b81548152906001019060200180831161752857829003601f168201915b50505050506013838154811061378757fe5b6175aa576013818154811061756857fe5b906000526020600020016012828154811061757f57fe5b9060005260206000200190805460018160011615610100020316600290046175a8929190617f3a565b505b60010161749f565b5082821115610e9257825b82811015613d8e576012601382815481106175d457fe5b6000918252602080832084546001818101875595855291909320929091018054617617949390920192909160026101009282161592909202600019011604617f3a565b506001016175bd565b601354600b548082111561766b57805b8281101561766957601380548061764357fe5b60019003818190600052602060002001600061765f9190617ed6565b9055600101617630565b505b600081831061767a578161767c565b825b905060005b8181101561779b576177396013828154811061769957fe5b600091825260209182902001805460408051601f60026000196101006001871615020190941693909304928301859004850281018501909152818152928301828280156177275780601f106176fc57610100808354040283529160200191617727565b820191906000526020600020905b81548152906001019060200180831161770a57829003601f168201915b5050505050600b838154811061628d57fe5b61779357600b818154811061774a57fe5b90600052602060002090601602016002016013828154811061776857fe5b906000526020600020019080546001816001161561010002031660029004617791929190617f3a565b505b600101617681565b5082821115610e9257825b82811015613d8e576013600b82815481106177bd57fe5b60009182526020808320845460018082018755958552919093206016929092029092016002908101805461780595939094019390926000199082161561010002011604617f3a565b506001016177a6565b600081848411156178325760405162461bcd60e51b8152600401610e72919061873a565b505050900390565b6000818361785b5760405162461bcd60e51b8152600401610e72919061873a565b50600083858161786757fe5b0495945050505050565b805160009061788257506000611d54565b6020820151805160001a9060c08210156178a157600092505050611d54565b5060019392505050565b8051600090811a60808110156178c5576000915050611d54565b60b88110806178e0575060c081108015906178e0575060f881105b156178ef576001915050611d54565b60c08110156179035760b519019050611d54565b60f519019050611d54565b80516000908190811a608081101561792957600191506179e8565b60b881101561793e57607e19810191506179e8565b60c081101561798f57600060b78203600186019550806020036101000a8651049150600181018201935050808310156179895760405162461bcd60e51b8152600401610e7290618dde565b506179e8565b60f88110156179a45760be19810191506179e8565b600060f78203600186019550806020036101000a8651049150600181018201935050808310156179e65760405162461bcd60e51b8152600401610e7290618dde565b505b5092915050565b8051600090617a0057506000611d54565b60008090506000617a1484602001516178ab565b602085015185519181019250015b80821015617a4257617a338261790e565b82019150826001019250617a22565b50909392505050565b8051600090601514617a5c57600080fd5b611e0482616d0e565b8051606090617a7357600080fd5b6000617a8283602001516178ab565b83516040805191839003808352601f19601f8201168301602001909152919250606090828015617ab9576020820181803683370190505b5090506000816020019050616777848760200151018285617d5c565b604080516020808252818301909252606091829190602082018180368337505050602081018490529050600067ffffffffffffffff198416617b1957506018617b3d565b6fffffffffffffffffffffffffffffffff198416617b3957506010617b3d565b5060005b6020811015617b7357818181518110617b5257fe5b01602001516001600160f81b03191615617b6b57617b73565b600101617b3d565b60008160200390506060816040519080825280601f01601f191660200182016040528015617ba8576020820181803683370190505b5080830196909652508452509192915050565b606081516001148015617bed5750607f60f81b82600081518110617bdb57fe5b01602001516001600160f81b03191611155b15617bf9575080611d54565b611e04617c0b8351608060ff16617c8a565b835b6060806040519050835180825260208201818101602087015b81831015617c3e578051835260209283019201617c26565b50855184518101855292509050808201602086015b81831015617c6b578051835260209283019201617c53565b508651929092011591909101601f01601f191660405250905092915050565b6060680100000000000000008310617cb45760405162461bcd60e51b8152600401610e7290618b1b565b60408051600180825281830190925260609160208201818036833701905050905060378411617d0e5782840160f81b81600081518110617cf057fe5b60200101906001600160f81b031916908160001a9053509050611e04565b6060617d1985617ad5565b90508381510160370160f81b82600081518110617d3257fe5b60200101906001600160f81b031916908160001a905350617d538282617c0d565b95945050505050565b80617d6657610e92565b5b60208110617d86578251825260209283019290910190601f1901617d67565b915181516020939093036101000a6000190180199091169216919091179052565b60405180608001604052806000815260200160001515815260200160608152602001617dd1618002565b905290565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10617e1757805160ff1916838001178555617e44565b82800160010185558215617e44579182015b82811115617e44578251825591602001919060010190617e29565b5061346c929150618021565b8260138101928215617e445791602002820182811115617e44578251825591602001919060010190617e29565b6040518060600160405280600060ff16815260200160608152602001606081525090565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a081019190915290565b50805460018160011615610100020316600290046000825580601f10617efc5750611f6c565b601f016020900490600052602060002090810190611f6c9190618021565b6040518060400160405280617f2d617fe8565b8152602001600081525090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10617f735780548555617e44565b82800160010185558215617e4457600052602060002091601f016020900482015b82811115617e44578254825591600101919060010190617f94565b8260138101928215617e445791820182811115617e44578254825591600101919060010190617f94565b50611f6c906013810190618021565b604051806040016040528060008152602001600081525090565b6040518061026001604052806013906020820280368337509192915050565b61341091905b8082111561346c5760008155600101618027565b8035611e048161951b565b60008083601f840112618057578182fd5b5081356001600160401b0381111561806d578182fd5b6020830191508360208083028501011115615db557600080fd5b6000601f8381840112618098578182fd5b82356180ab6180a6826194d0565b6194aa565b818152925060208084019085810160005b8481101561813d578135880189603f8201126180d757600080fd5b838101356001600160401b038111156180ef57600080fd5b618100818901601f191686016194aa565b81815260408c8184860101111561811657600080fd5b828185018884013750600091810186019190915285525092820192908201906001016180bc565b50505050505092915050565b600082601f830112618159578081fd5b81356181676180a6826194d0565b81815291506020808301908481018184028601820187101561818857600080fd5b6000805b8581101561813d5782356001600160401b03811681146181aa578283fd5b8552938301939183019160010161818c565b60008083601f8401126181cd578182fd5b5081356001600160401b038111156181e3578182fd5b602083019150836020828501011115615db557600080fd5b60006020828403121561820c578081fd5b813561119d8161951b565b600060208284031215618228578081fd5b815161119d8161951b565b60008060008060408587031215618248578283fd5b84356001600160401b038082111561825e578485fd5b61826a88838901618046565b90965094506020870135915080821115618282578384fd5b5061828f87828801618046565b95989497509550505050565b6000806000606084860312156182af578283fd5b83356001600160401b03808211156182c5578485fd5b81860187601f8201126182d6578586fd5b803592506182e66180a6846194d0565b80848252602080830192508084018b82838902870101111561830657898afd5b8994505b868510156183305761831c8c8261803b565b84526001949094019392810192810161830a565b509097508801359350505080821115618347578384fd5b61835387838801618149565b93506040860135915080821115618368578283fd5b5061837586828701618087565b9150509250925092565b600060208284031215618390578081fd5b8151801515811461119d578182fd5b600080602083850312156183b1578182fd5b82356001600160401b038111156183c6578283fd5b6183d2858286016181bc565b90969095509350505050565b600080600080604085870312156183f3578384fd5b84356001600160401b0380821115618409578586fd5b618415888389016181bc565b9096509450602087013591508082111561842d578384fd5b5061828f878288016181bc565b60006020828403121561844b578081fd5b5035919050565b600060208284031215618463578081fd5b5051919050565b6000806040838503121561847c578182fd5b505080516020909101519092909150565b6000806000604084860312156184a1578081fd5b833560ff811681146184b1578182fd5b925060208401356001600160401b038111156184cb578182fd5b6184d7868287016181bc565b9497909650939450505050565b6000815180845260208085019450808401835b8381101561851c5781516001600160a01b0316875295820195908201906001016184f7565b509495945050505050565b60008284528282602086013780602084860101526020601f19601f85011685010190509392505050565b600081518084526185698160208601602086016194ef565b601f01601f19169290920160200192915050565b6000825161858f8184602087016194ef565b9190910192915050565b918252602082015260400190565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b03968716815294861660208601529290941660408401526001600160401b03166060830152911515608082015260a081019190915260c00190565b6001600160a01b0392909216825260ff16602082015260400190565b60006020825261119d60208301846184e4565b60006040825261865860408301856184e4565b602083820381850152818551808452828401915082838202850101838801865b838110156186a657601f19878403018552618694838351618551565b94860194925090850190600101618678565b50909998505050505050505050565b6000608082526186c860808301876184e4565b828103602084810191909152865180835287820192820190845b818110156186fe578451835293830193918301916001016186e2565b5050848103604086015261871281886184e4565b93505050506001600160401b038316606083015295945050505050565b901515815260200190565b60006020825261119d6020830184618551565b600060408252618761604083018688618527565b8281036020840152618774818587618527565b979650505050505050565b6020808252601c908201527f6c656e677468206f66206275726e526174696f206d69736d6174636800000000604082015260600190565b6020808252602d908201527f746865207475726e5465726d2073686f756c6420626520696e205b332c395d2060408201526c6f7220657175616c20746f203160981b606082015260800190565b60208082526026908201527f6c656e677468206f66206d61784e756d4f664d61696e7461696e696e67206d696040820152650e6dac2e8c6d60d31b606082015260800190565b6020808252601b908201527f6261746368207472616e736665722072657475726e2066616c73650000000000604082015260600190565b6020808252602c908201527f6c656e677468206f66206d61784e756d4f66576f726b696e6743616e6469646160408201526b0e8cae640dad2e6dac2e8c6d60a31b606082015260800190565b60208082526025908201527f6c656e677468206f66206d61696e7461696e536c6173685363616c65206d69736040820152640dac2e8c6d60db1b606082015260800190565b6020808252818101527f6c656e677468206f66206e756d4f66436162696e657473206d69736d61746368604082015260600190565b60208082526019908201527f74686520636f6e7472616374206e6f7420696e69742079657400000000000000604082015260600190565b6020808252601f908201527f6f6e6c7920736c617368206f72207374616b6548756220636f6e747261637400604082015260600190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b60208082526028908201527f746865206e756d4f66436162696e657473206d75737420626520677265617465604082015267072207468616e20360c41b606082015260800190565b60208082526039908201527f746865206e756d4f66436162696e657473206d757374206265206c657373207460408201527f68616e204d41585f4e554d5f4f465f56414c494441544f525300000000000000606082015260800190565b60208082526029908201527f746865206e756d626572206f662076616c696461746f727320657863656564206040820152681d1a19481b1a5b5a5d60ba1b606082015260800190565b60208082526022908201527f63616e206e6f7420646f207468697320747769636520696e206f6e6520626c6f604082015261636b60f01b606082015260800190565b6020808252600e908201526d696e70757420746f6f206c6f6e6760901b604082015260600190565b60208082526063908201527f746865206275726e526174696f20706c757320696e697453797374656d52657760408201527f617264526174696f20616e6420616e74694d455653797374656d52657761726460608201527f526174696f206d757374206265206e6f2067726561746572207468616e20313060808201526203030360ec1b60a082015260c00190565b60208082526037908201527f746865206d61784e756d4f664d61696e7461696e696e67206d7573742062652060408201527f6c657373207468616e206e756d4f66436162696e657473000000000000000000606082015260800190565b6020808252602b908201527f6475706c696361746520636f6e73656e7375732061646472657373206f66207660408201526a185b1a59185d1bdc94d95d60aa1b606082015260800190565b6020808252601b908201527f6c656e677468206f66207475726e5465726d206d69736d617463680000000000604082015260600190565b60208082526027908201527f7468652065787069726554696d655365636f6e64476170206973206f7574206f604082015266662072616e676560c81b606082015260800190565b6020808252601590820152746465706f7369742076616c7565206973207a65726f60581b604082015260600190565b60208082526049908201527f746865206d61784e756d4f66576f726b696e6743616e64696461746573206d7560408201527f7374206265206e6f742067726561746572207468616e206d61784e756d4f6643606082015268616e6469646174657360b81b608082015260a00190565b60208082526028908201527f6c656e677468206f6620696e697453797374656d526577617264526174696f206040820152670dad2e6dac2e8c6d60c31b606082015260800190565b6020808252601190820152706164646974696f6e206f766572666c6f7760781b604082015260600190565b60208082526023908201527f63616e206e6f7420656e7465722054656d706f72617279204d61696e74656e616040820152626e636560e81b606082015260800190565b60208082526025908201527f6c656e677468206f66206a61696c2076616c696461746f7273206d757374206260408201526465206f6e6560d81b606082015260800190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b6020808252601490820152736761737072696365206973206e6f74207a65726f60601b604082015260600190565b6020808252602e908201527f746865206d6573736167652073656e646572206d75737420626520676f76657260408201526d1b985b98d94818dbdb9d1c9858dd60921b606082015260800190565b60208082526025908201527f6c656e677468206f66206d61784e756d4f6643616e64696461746573206d69736040820152640dac2e8c6d60db1b606082015260800190565b6020808252601290820152716e6f7420696e206d61696e74656e616e636560701b604082015260600190565b60208082526021908201527f666565206973206c6172676572207468616e2044555354595f494e434f4d494e6040820152604760f81b606082015260800190565b60208082526019908201527f74686520636f6e747261637420616c726561647920696e697400000000000000604082015260600190565b6020808252601a908201527f6c656e677468206973206c657373207468616e206f6666736574000000000000604082015260600190565b60208082526026908201527f6c656e677468206f662065787069726554696d655365636f6e64476170206d696040820152650e6dac2e8c6d60d31b606082015260800190565b60208082526017908201527f6f6e6c792063757272656e742076616c696461746f7273000000000000000000604082015260600190565b6020808252602b908201527f6c656e677468206f6620616e74694d455653797374656d52657761726452617460408201526a0d2de40dad2e6dac2e8c6d60ab1b606082015260800190565b60208082526021908201527f6661696c656420746f20706172736520696e69742076616c696461746f7253656040820152601d60fa1b606082015260800190565b6020808252602f908201527f746865206d6573736167652073656e646572206d7573742062652063726f737360408201526e0818da185a5b8818dbdb9d1c9858dd608a1b606082015260800190565b60208082526063908201527f74686520616e74694d455653797374656d526577617264526174696f20706c7560408201527f73206275726e526174696f20616e6420696e697453797374656d52657761726460608201527f526174696f206d757374206265206e6f2067726561746572207468616e20313060808201526203030360ec1b60a082015260c00190565b6020808252602d908201527f746865206d6573736167652073656e646572206d75737420626520746865206260408201526c3637b1b590383937b23ab1b2b960991b606082015260800190565b6020808252603e908201527f746865206d61696e7461696e536c6173685363616c65206d757374206265206760408201527f726561746572207468616e203020616e64206c657373207468616e2031300000606082015260800190565b60208082526063908201527f74686520696e697453797374656d526577617264526174696f20706c7573206260408201527f75726e526174696f20616e6420616e74694d455653797374656d52657761726460608201527f526174696f206d757374206265206e6f2067726561746572207468616e20313060808201526203030360ec1b60a082015260c00190565b6020808252600d908201526c756e6b6e6f776e20706172616d60981b604082015260600190565b60208082526029908201527f746865206d6573736167652073656e646572206d75737420626520736c6173686040820152680818dbdb9d1c9858dd60ba1b606082015260800190565b6020808252601f908201527f746865206d73672073656e646572206d757374206265207374616b6548756200604082015260600190565b61ffff91909116815260200190565b90815260200190565b6000848252831515602083015260606040830152617d536060830184618551565b63ffffffff91909116815260200190565b60ff91909116815260200190565b600060ff8516825260406020830152617d53604083018486618527565b6040518181016001600160401b03811182821017156194c857600080fd5b604052919050565b60006001600160401b038211156194e5578081fd5b5060209081020190565b60005b8381101561950a5781810151838201526020016194f2565b83811115613d8e5750506000910152565b6001600160a01b0381168114611f6c57600080fdfe70e72399380dcfb0338abc03dc8d47f9f470ada8e769c9a78d644ea97385ecb2f9026180f9025df87794bcdd0d2cda5f6423e57b6a4dcd75decbe31aecf094bcdd0d2cda5f6423e57b6a4dcd75decbe31aecf094bcdd0d2cda5f6423e57b6a4dcd75decbe31aecf08601d1a94a2000b0b3baf71dc234890671fc3292afde45e20ce83cb8cd65c614be9fa29932c34051a75cbc1e25b968cc72142c91a56b521af87794bbd1acc20bd8304309d31d8fd235210d0efc049d94bbd1acc20bd8304309d31d8fd235210d0efc049d94bbd1acc20bd8304309d31d8fd235210d0efc049d8601d1a94a2000b08f124155128c0f4ff8c2b0803c3390bf672e6d26480af4f9648b8d2214d642a6dc2c25c9a37ccc576766e5838d71f52af877945e2a531a825d8b61bcc305a35a7433e9a8920f0f945e2a531a825d8b61bcc305a35a7433e9a8920f0f945e2a531a825d8b61bcc305a35a7433e9a8920f0f8601d1a94a2000b0a42d8fd0af73dc1c2a0238545985c0dba04fd57bc2f66573c86cfbb9f2a3cd5c10d6ddb6a588500ef80f2f5b56b8a21bf877943ad55d1d552cc55dee90c0faf0335383b2e6c5ce943ad55d1d552cc55dee90c0faf0335383b2e6c5ce943ad55d1d552cc55dee90c0faf0335383b2e6c5ce8601d1a94a2000b0ae5844366094dca50e2769381b1f4bd5b7b40545655322395c25787ad5992a17324cc466a0ed1b1d91433f3299f5fbe4f87794fe02c8ff2374583c47b1d62fdf3e1b72c20ebe2994fe02c8ff2374583c47b1d62fdf3e1b72c20ebe2994fe02c8ff2374583c47b1d62fdf3e1b72c20ebe298601d1a94a2000b08aa632a469439c7ba660bc4419eba498f9ff489b62d53779d257b964bca8af2abf5f797ef746d1e12c031e3640c8b8fb0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db90175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01dbb0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01dbaa164736f6c6343000604000a \ No newline at end of file diff --git a/core/systemcontracts/haber/types.go b/core/systemcontracts/haber/types.go new file mode 100644 index 0000000000..9f2a9a77a9 --- /dev/null +++ b/core/systemcontracts/haber/types.go @@ -0,0 +1,21 @@ +package haber + +import _ "embed" + +// contract codes for Mainnet upgrade +var ( + //go:embed mainnet/ValidatorContract + MainnetValidatorContract string +) + +// contract codes for Chapel upgrade +var ( + //go:embed chapel/ValidatorContract + ChapelValidatorContract string +) + +// contract codes for Rialto upgrade +var ( + //go:embed rialto/ValidatorContract + RialtoValidatorContract string +) diff --git a/core/systemcontracts/upgrade.go b/core/systemcontracts/upgrade.go index 393b529113..e5f2ae7ee5 100644 --- a/core/systemcontracts/upgrade.go +++ b/core/systemcontracts/upgrade.go @@ -15,6 +15,7 @@ import ( "github.com/ethereum/go-ethereum/core/systemcontracts/feynman" feynmanFix "github.com/ethereum/go-ethereum/core/systemcontracts/feynman_fix" "github.com/ethereum/go-ethereum/core/systemcontracts/gibbs" + "github.com/ethereum/go-ethereum/core/systemcontracts/haber" "github.com/ethereum/go-ethereum/core/systemcontracts/kepler" "github.com/ethereum/go-ethereum/core/systemcontracts/luban" "github.com/ethereum/go-ethereum/core/systemcontracts/mirror" @@ -75,6 +76,8 @@ var ( feynmanUpgrade = make(map[string]*Upgrade) feynmanFixUpgrade = make(map[string]*Upgrade) + + haberUpgrade = make(map[string]*Upgrade) ) func init() { @@ -701,6 +704,17 @@ func init() { }, }, } + + haberUpgrade[rialtoNet] = &Upgrade{ + UpgradeName: "haber", + Configs: []*UpgradeConfig{ + { + ContractAddr: common.HexToAddress(ValidatorContract), + CommitUrl: "https://github.com/NathanBSC/bsc-genesis-contract/commit/0844e7e8acc01eae7a5a27a7fc1f886d313ff455", + Code: haber.RialtoValidatorContract, + }, + }, + } } func UpgradeBuildInSystemContract(config *params.ChainConfig, blockNumber *big.Int, lastBlockTime uint64, blockTime uint64, statedb *state.StateDB) { @@ -777,6 +791,10 @@ func UpgradeBuildInSystemContract(config *params.ChainConfig, blockNumber *big.I applySystemContractUpgrade(feynmanFixUpgrade[network], blockNumber, statedb, logger) } + if config.IsOnHaber(blockNumber, lastBlockTime, blockTime) { + applySystemContractUpgrade(haberUpgrade[network], blockNumber, statedb, logger) + } + /* apply other upgrades */ diff --git a/params/config.go b/params/config.go index 610afc470f..a27694d99d 100644 --- a/params/config.go +++ b/params/config.go @@ -929,6 +929,15 @@ func (c *ChainConfig) IsHaber(num *big.Int, time uint64) bool { return c.IsLondon(num) && isTimestampForked(c.HaberTime, time) } +// IsOnHaber returns whether currentBlockTime is either equal to the Haber fork time or greater firstly. +func (c *ChainConfig) IsOnHaber(currentBlockNumber *big.Int, lastBlockTime uint64, currentBlockTime uint64) bool { + lastBlockNumber := new(big.Int) + if currentBlockNumber.Cmp(big.NewInt(1)) >= 0 { + lastBlockNumber.Sub(currentBlockNumber, big.NewInt(1)) + } + return !c.IsHaber(lastBlockNumber, lastBlockTime) && c.IsHaber(currentBlockNumber, currentBlockTime) +} + // IsPrague returns whether num is either equal to the Prague fork time or greater. func (c *ChainConfig) IsPrague(num *big.Int, time uint64) bool { return c.IsLondon(num) && isTimestampForked(c.PragueTime, time)