diff --git a/cmd/extradump/extradump_test.go b/cmd/extradump/extradump_test.go index f203d322e6..1c41fb7ec9 100644 --- a/cmd/extradump/extradump_test.go +++ b/cmd/extradump/extradump_test.go @@ -43,7 +43,42 @@ func TestExtraParse(t *testing.T) { } } - // case 3, |---Extra Vanity---|---Empty---|---Vote Attestation---|---Extra Seal---| + // case 3, |---Extra Vanity---|---Validators Number and Validators Bytes---|---Turn Term---|---Empty---|---Extra Seal---| + { + extraData := "0xd983010209846765746889676f312e31392e3131856c696e75780000a6bf97c1152465176c461afb316ebc773c61faee85a6515daa8a923564c6ffd37fb2fe9f118ef88092e8762c7addb526ab7eb1e772baef85181f892c731be0c1891a50e6b06262c816295e26495cef6f69dfa69911d9d8e4f3bbadb89b977cf58294f7239d515e15b24cfeb82494056cf691eaf729b165f32c9757c429dba5051155903067e56ebe3698678e912d4c407bbe49438ed859fe965b140dcf1aab71a993c1f7f6929d1fe2a17b4e14614ef9fc5bdc713d6631d675403fbeefac55611bf612700b1b65f4744861b80b0f7d6ab03f349bbafec1551819b8be1efea2fc46ca749aa184248a459464eec1a21e7fc7b71a053d9644e9bb8da4853b8f872cd7c1d6b324bf1922829830646ceadfb658d3de009a61dd481a114a2e761c554b641742c973867899d300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000069c77a677c40c7fbea129d4b171a39b7a8ddabfab2317f59d86abfaf690850223d90e9e7593d91a29331dfc2f84d5adecc75fc39ecab4632c1b4400a3dd1e1298835bcca70f657164e5b75689b64b7fd1fa275f334f28e1896a26afa1295da81418593bd12814463d9f6e45c36a0e47eb4cd3e5b6af29c41e2a3a5636430155a466e216585af3ba772b61c6014342d914470ec7ac2975be345796c2b81db0422a5fd08e40db1fc2368d2245e4b18b1d0b85c921aaaafd2e341760e29fc613edd39f71254614e2055c3287a517ae2f5b9e386cd1b50a4550696d957cb4900f03ab84f83ff2df44193496793b847f64e9d6db1b3953682bb95edd096eb1e69bbd357c200992ca78050d0cbe180cfaa018e8b6c8fd93d6f4cea42bbb345dbc6f0dfdb5bec73a8a257074e82b881cfa06ef3eb4efeca060c2531359abd0eab8af1e3edfa2025fca464ac9c3fd123f6c24a0d78869485a6f79b60359f141df90a0c745125b131caaffd12000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b218c5d6af1f979ac42bc68d98a5a0d796c6ab01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b4dd66d7c2c7e57f628210187192fb89d4b99dd4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000be807dddb074639cd9fa61b47676c064fc50d62cb1f2c71577def3144fabeb75a8a1c8cb5b51d1d1b4a05eec67988b8685008baa17459ec425dbaebc852f496dc92196cdcc8e6d00c17eb431350c6c50d8b8f05176b90b11b3a3d4feb825ae9702711566df5dbf38e82add4dd1b573b95d2466fa6501ccb81e9d26a352b96150ccbf7b697fd0a419d1d6bf74282782b0b3eb1413c901d6ecf02e8e28000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2d3a739effcd3a99387d015e260eefac72ebea1956c470ddff48cb49300200b5f83497f3a3ccb3aeb83c5edd9818569038e61d197184f4aa6939ea5e9911e3e98ac6d21e9ae3261a475a27bb1028f140bc2a7c843318afd000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ea0a6e3c511bbd10f4519ece37dc24887e11b55db2d4c6283c44a1c7bd503aaba7666e9f0c830e0ff016c1c750a5e48757a713d0836b1cabfd5c281b1de3b77d1c192183ee226379db83cffc681495730c11fdde79ba4c0c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ef0274e31810c9df02f98fafde0f841f4e66a1cd00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004e99f701bb14cb7dfb68b90bd3e6d1ca656964630de71beffc7f33f7f08ec99d336ec51ad9fad0ac84ae77ca2e8ad9512acc56e0d7c93f3c2ce7de1b69149a5a400" + extra, err := parseExtra(extraData) + assert.NoError(t, err) + { + var have = extra.ValidatorSize + var want = uint8(21) + if have != want { + t.Fatalf("extra.ValidatorSize mismatch, have %d, want %d", have, want) + } + } + { + var have = common.Bytes2Hex(extra.Validators[14].Address[:]) + var want = "cc8e6d00c17eb431350c6c50d8b8f05176b90b11" + if have != want { + t.Fatalf("extra.Validators[14].Address mismatch, have %s, want %s", have, want) + } + } + { + var have = common.Bytes2Hex(extra.Validators[18].BLSPublicKey[:]) + var want = "b2d4c6283c44a1c7bd503aaba7666e9f0c830e0ff016c1c750a5e48757a713d0836b1cabfd5c281b1de3b77d1c192183" + if have != want { + t.Fatalf("extra.Validators[18].BLSPublicKey mismatch, have %s, want %s", have, want) + } + } + { + var have = extra.TurnTerm + var want = uint8(4) + if *have != want { + t.Fatalf("extra.TurnTerm mismatch, have %d, want %d", *have, want) + } + } + } + + // case 4, |---Extra Vanity---|---Empty---|---Vote Attestation---|---Extra Seal---| { extraData := "0xd883010205846765746888676f312e32302e35856c696e75780000002995c52af8b5830563efb86089cf168dcf4c5d3cb057926628ad1bf0f03ea67eef1458485578a4f8489afa8a853ecc7af45e2d145c21b70641c4b29f0febd2dd2c61fa1ba174be3fd47f1f5fa2ab9b5c318563d8b70ca58d0d51e79ee32b2fb721649e2cb9d36538361fba11f84c8401d14bb7a0fa67ddb3ba654d6006bf788710032247aa4d1be0707273e696b422b3ff72e9798401d14bbaa01225f505f5a0e1aefadcd2913b7aac9009fe4fb3d1bf57399e0b9dce5947f94280fe6d3647276c4127f437af59eb7c7985b2ae1ebe432619860695cb6106b80cc66c735bc1709afd11f233a2c97409d38ebaf7178aa53e895aea2fe0a229f71ec601" extra, err := parseExtra(extraData) @@ -64,9 +99,51 @@ func TestExtraParse(t *testing.T) { } } - // case 4, |---Extra Vanity---|---Validators Number and Validators Bytes---|---Vote Attestation---|---Extra Seal---| + // case 5, |---Extra Vanity---|---Validators Number and Validators Bytes---|---Vote Attestation---|---Extra Seal---| + { + extraData := "0xd883010209846765746888676f312e31392e38856c696e7578000000dc55905c071284214b9b9c85549ab3d2b972df0deef66ac2c98e82934ca974fdcd97f3309de967d3c9c43fa711a8d673af5d75465844bf8969c8d1948d903748ac7b8b1720fa64e50c35552c16704d214347f29fa77f77da6d75d7c752b742ad4855bae330426b823e742da31f816cc83bc16d69a9134be0cfb4a1d17ec34f1b5b32d5c20440b8536b1e88f0f247788386d0ed6c748e03a53160b4b30ed3748cc5000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000980a75ecd1309ea12fa2ed87a8744fbfc9b863d589037a9ace3b590165ea1c0c5ac72bf600b7c88c1e435f41932c1132aae1bfa0bb68e46b96ccb12c3415e4d82af717d8a2959d3f95eae5dc7d70144ce1b73b403b7eb6e0b973c2d38487e58fd6e145491b110080fb14ac915a0411fc78f19e09a399ddee0d20c63a75d8f930f1694544ad2dc01bb71b214cb885500844365e95cd9942c7276e7fd8a2750ec6dded3dcdc2f351782310b0eadc077db59abca0f0cd26776e2e7acb9f3bce40b1fa5221fd1561226c6263cc5ff474cf03cceff28abc65c9cbae594f725c80e12d96c9b86c3400e529bfe184056e257c07940bb664636f689e8d2027c834681f8f878b73445261034e946bb2d901b4b878f8b27bb8608c11016739b3f8a19e54ab8c7abacd936cfeba200f3645a98b65adb0dd3692b69ce0b3ae10e7176b9a4b0d83f04065b1042b4bcb646a34b75c550f92fc34b8b2b1db0fa0d3172db23ba92727c80bcd306320d0ff411bf858525fde13bc8e0370f84c8401e9c2e6a0820dc11d63176a0eb1b828bc5376867b275579112b7013358da40317e7bab6e98401e9c2e7a00edc71ce80105a3220a87bea2792fa340d66c59002f02b0a09349ed1ed28407080048b972fac2b9077a4dcb6fc37093799a652858016c99142b227500c844fa97ec22e3f9d3b1e982f14bcd999a7453e89ce5ef5c55f1c7f8f74ba904186cd67828200" + extra, err := parseExtra(extraData) + assert.NoError(t, err) + { + var have = common.Bytes2Hex(extra.Validators[0].Address[:]) + var want = "1284214b9b9c85549ab3d2b972df0deef66ac2c9" + if have != want { + t.Fatalf("extra.Validators[0].Address mismatch, have %s, want %s", have, want) + } + } + { + var have = common.Bytes2Hex(extra.Validators[0].BLSPublicKey[:]) + var want = "8e82934ca974fdcd97f3309de967d3c9c43fa711a8d673af5d75465844bf8969c8d1948d903748ac7b8b1720fa64e50c" + if have != want { + t.Fatalf("extra.Validators[0].BLSPublicKey mismatch, have %s, want %s", have, want) + } + } + { + var have = extra.Validators[0].VoteIncluded + var want = true + if have != want { + t.Fatalf("extra.Validators[0].VoteIncluded mismatch, have %t, want %t", have, want) + } + } + { + var have = common.Bytes2Hex(extra.Data.TargetHash[:]) + var want = "0edc71ce80105a3220a87bea2792fa340d66c59002f02b0a09349ed1ed284070" + if have != want { + t.Fatalf("extra.Data.TargetHash mismatch, have %s, want %s", have, want) + } + } + { + var have = extra.Data.TargetNumber + var want = uint64(32096999) + if have != want { + t.Fatalf("extra.Data.TargetNumber mismatch, have %d, want %d", have, want) + } + } + } + + // case 6, |---Extra Vanity---|---Validators Number and Validators Bytes---|---Turn Term---|---Vote Attestation---|---Extra Seal---| { - extraData := "0xd883010209846765746888676f312e31392e38856c696e7578000000dc55905c071284214b9b9c85549ab3d2b972df0deef66ac2c98e82934ca974fdcd97f3309de967d3c9c43fa711a8d673af5d75465844bf8969c8d1948d903748ac7b8b1720fa64e50c35552c16704d214347f29fa77f77da6d75d7c752b742ad4855bae330426b823e742da31f816cc83bc16d69a9134be0cfb4a1d17ec34f1b5b32d5c20440b8536b1e88f0f247788386d0ed6c748e03a53160b4b30ed3748cc5000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000980a75ecd1309ea12fa2ed87a8744fbfc9b863d589037a9ace3b590165ea1c0c5ac72bf600b7c88c1e435f41932c1132aae1bfa0bb68e46b96ccb12c3415e4d82af717d8a2959d3f95eae5dc7d70144ce1b73b403b7eb6e0b973c2d38487e58fd6e145491b110080fb14ac915a0411fc78f19e09a399ddee0d20c63a75d8f930f1694544ad2dc01bb71b214cb885500844365e95cd9942c7276e7fd8a2750ec6dded3dcdc2f351782310b0eadc077db59abca0f0cd26776e2e7acb9f3bce40b1fa5221fd1561226c6263cc5ff474cf03cceff28abc65c9cbae594f725c80e12d96c9b86c3400e529bfe184056e257c07940bb664636f689e8d2027c834681f8f878b73445261034e946bb2d901b4b878f8b27bb8608c11016739b3f8a19e54ab8c7abacd936cfeba200f3645a98b65adb0dd3692b69ce0b3ae10e7176b9a4b0d83f04065b1042b4bcb646a34b75c550f92fc34b8b2b1db0fa0d3172db23ba92727c80bcd306320d0ff411bf858525fde13bc8e0370f84c8401e9c2e6a0820dc11d63176a0eb1b828bc5376867b275579112b7013358da40317e7bab6e98401e9c2e7a00edc71ce80105a3220a87bea2792fa340d66c59002f02b0a09349ed1ed284070808b972fac2b9077a4dcb6fc37093799a652858016c99142b227500c844fa97ec22e3f9d3b1e982f14bcd999a7453e89ce5ef5c55f1c7f8f74ba904186cd67828200" + extraData := "0xd883010209846765746888676f312e31392e38856c696e7578000000dc55905c071284214b9b9c85549ab3d2b972df0deef66ac2c98e82934ca974fdcd97f3309de967d3c9c43fa711a8d673af5d75465844bf8969c8d1948d903748ac7b8b1720fa64e50c35552c16704d214347f29fa77f77da6d75d7c752b742ad4855bae330426b823e742da31f816cc83bc16d69a9134be0cfb4a1d17ec34f1b5b32d5c20440b8536b1e88f0f247788386d0ed6c748e03a53160b4b30ed3748cc5000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000980a75ecd1309ea12fa2ed87a8744fbfc9b863d589037a9ace3b590165ea1c0c5ac72bf600b7c88c1e435f41932c1132aae1bfa0bb68e46b96ccb12c3415e4d82af717d8a2959d3f95eae5dc7d70144ce1b73b403b7eb6e0b973c2d38487e58fd6e145491b110080fb14ac915a0411fc78f19e09a399ddee0d20c63a75d8f930f1694544ad2dc01bb71b214cb885500844365e95cd9942c7276e7fd8a2750ec6dded3dcdc2f351782310b0eadc077db59abca0f0cd26776e2e7acb9f3bce40b1fa5221fd1561226c6263cc5ff474cf03cceff28abc65c9cbae594f725c80e12d96c9b86c3400e529bfe184056e257c07940bb664636f689e8d2027c834681f8f878b73445261034e946bb2d901b4b87804f8b27bb8608c11016739b3f8a19e54ab8c7abacd936cfeba200f3645a98b65adb0dd3692b69ce0b3ae10e7176b9a4b0d83f04065b1042b4bcb646a34b75c550f92fc34b8b2b1db0fa0d3172db23ba92727c80bcd306320d0ff411bf858525fde13bc8e0370f84c8401e9c2e6a0820dc11d63176a0eb1b828bc5376867b275579112b7013358da40317e7bab6e98401e9c2e7a00edc71ce80105a3220a87bea2792fa340d66c59002f02b0a09349ed1ed28407080048b972fac2b9077a4dcb6fc37093799a652858016c99142b227500c844fa97ec22e3f9d3b1e982f14bcd999a7453e89ce5ef5c55f1c7f8f74ba904186cd67828200" extra, err := parseExtra(extraData) assert.NoError(t, err) { @@ -104,5 +181,12 @@ func TestExtraParse(t *testing.T) { t.Fatalf("extra.Data.TargetNumber mismatch, have %d, want %d", have, want) } } + { + var have = extra.TurnTerm + var want = uint8(4) + if *have != want { + t.Fatalf("extra.TurnTerm mismatch, have %d, want %d", *have, want) + } + } } } diff --git a/cmd/extradump/main.go b/cmd/extradump/main.go index bb06735147..aaec5ea80a 100644 --- a/cmd/extradump/main.go +++ b/cmd/extradump/main.go @@ -24,7 +24,7 @@ const ( BLSPublicKeyLength = 48 // follow order in extra field - // |---Extra Vanity---|---Validators Number and Validators Bytes (or Empty)---|---Vote Attestation (or Empty)---|---Extra Seal---| + // |---Extra Vanity---|---Validators Number and Validators Bytes (or Empty)---|---Turn Term (or Empty)---|---Vote Attestation (or Empty)---|---Extra Seal---| extraVanityLength = 32 // Fixed number of extra-data prefix bytes reserved for signer vanity validatorNumberSize = 1 // Fixed number of extra prefix bytes reserved for validator number after Luban validatorBytesLength = common.AddressLength + types.BLSPublicKeyLength @@ -35,6 +35,7 @@ type Extra struct { ExtraVanity string ValidatorSize uint8 Validators validatorsAscending + TurnTerm *uint8 *types.VoteAttestation ExtraSeal []byte } @@ -113,6 +114,15 @@ func parseExtra(hexData string) (*Extra, error) { sort.Sort(extra.Validators) data = data[validatorBytesTotalLength-validatorNumberSize:] dataLength = len(data) + + // parse TurnTerm + if dataLength > 0 { + if data[0] != '\xf8' { + extra.TurnTerm = &data[0] + data = data[1:] + dataLength = len(data) + } + } } // parse Vote Attestation @@ -148,6 +158,10 @@ func prettyExtra(extra Extra) { } } + if extra.TurnTerm != nil { + fmt.Printf("TurnTerm : %d\n", *extra.TurnTerm) + } + if extra.VoteAttestation != nil { fmt.Printf("Attestation :\n") fmt.Printf("\tVoteAddressSet : %b, %d\n", extra.VoteAddressSet, bitset.From([]uint64{uint64(extra.VoteAddressSet)}).Count()) diff --git a/cmd/geth/config.go b/cmd/geth/config.go index e535dc8155..7ad20539e0 100644 --- a/cmd/geth/config.go +++ b/cmd/geth/config.go @@ -214,6 +214,9 @@ func makeFullNode(ctx *cli.Context) (*node.Node, ethapi.Backend) { if ctx.IsSet(utils.OverrideBreatheBlockInterval.Name) { params.BreatheBlockInterval = ctx.Uint64(utils.OverrideBreatheBlockInterval.Name) } + if ctx.IsSet(utils.OverrideUseRandTurnTerm.Name) { + params.UseRandTurnTerm = ctx.Bool(utils.OverrideUseRandTurnTerm.Name) + } backend, eth := utils.RegisterEthService(stack, &cfg.Eth) diff --git a/cmd/geth/main.go b/cmd/geth/main.go index 9763794f7e..172752da3e 100644 --- a/cmd/geth/main.go +++ b/cmd/geth/main.go @@ -80,6 +80,7 @@ var ( utils.OverrideMinBlocksForBlobRequests, utils.OverrideDefaultExtraReserveForBlobRequests, utils.OverrideBreatheBlockInterval, + utils.OverrideUseRandTurnTerm, utils.EnablePersonal, utils.TxPoolLocalsFlag, utils.TxPoolNoLocalsFlag, diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 8707840692..c929a0bae2 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -349,6 +349,12 @@ var ( Value: params.BreatheBlockInterval, Category: flags.EthCategory, } + OverrideUseRandTurnTerm = &cli.BoolFlag{ + Name: "override.useRandTurnTerm", + Usage: "It use random values for turn terms instead of reading from the contract, only for testing purpose", + Value: params.UseRandTurnTerm, + Category: flags.EthCategory, + } SyncModeFlag = &flags.TextMarshalerFlag{ Name: "syncmode", Usage: `Blockchain sync mode ("snap" or "full")`, diff --git a/consensus/beacon/consensus.go b/consensus/beacon/consensus.go index 9e1c39b99a..ecabe15959 100644 --- a/consensus/beacon/consensus.go +++ b/consensus/beacon/consensus.go @@ -333,6 +333,11 @@ func (beacon *Beacon) verifyHeaders(chain consensus.ChainHeaderReader, headers [ return abort, results } +// CurrentTurnTerm return the turnTerm at the latest block +func (beacon *Beacon) CurrentTurnTerm(chain consensus.ChainHeaderReader) (turnTerm *uint64, err error) { + return nil, errors.New("not implemented") +} + // NextInTurnValidator return the next in-turn validator for header func (beacon *Beacon) NextInTurnValidator(chain consensus.ChainHeaderReader, header *types.Header) (common.Address, error) { return common.Address{}, errors.New("not implemented") diff --git a/consensus/clique/clique.go b/consensus/clique/clique.go index ddacbc2e6e..cc83ef1786 100644 --- a/consensus/clique/clique.go +++ b/consensus/clique/clique.go @@ -511,6 +511,11 @@ func (c *Clique) verifySeal(snap *Snapshot, header *types.Header, parents []*typ return nil } +// CurrentTurnTerm return the turnTerm at the latest block +func (c *Clique) CurrentTurnTerm(chain consensus.ChainHeaderReader) (turnTerm *uint64, err error) { + return nil, errors.New("not implemented") +} + // NextInTurnValidator return the next in-turn validator for header func (c *Clique) NextInTurnValidator(chain consensus.ChainHeaderReader, header *types.Header) (common.Address, error) { return common.Address{}, errors.New("not implemented") diff --git a/consensus/consensus.go b/consensus/consensus.go index 7c65acb359..fb4cd63a23 100644 --- a/consensus/consensus.go +++ b/consensus/consensus.go @@ -97,6 +97,9 @@ type Engine interface { // rules of a given engine. VerifyUncles(chain ChainReader, block *types.Block) error + // CurrentTurnTerm return the turnTerm at the latest block + CurrentTurnTerm(chain ChainHeaderReader) (turnTerm *uint64, err error) + // NextInTurnValidator return the next in-turn validator for header NextInTurnValidator(chain ChainHeaderReader, header *types.Header) (common.Address, error) diff --git a/consensus/ethash/consensus.go b/consensus/ethash/consensus.go index db730fab29..c9234e2ce7 100644 --- a/consensus/ethash/consensus.go +++ b/consensus/ethash/consensus.go @@ -489,6 +489,11 @@ var FrontierDifficultyCalculator = calcDifficultyFrontier var HomesteadDifficultyCalculator = calcDifficultyHomestead var DynamicDifficultyCalculator = makeDifficultyCalculator +// CurrentTurnTerm return the turnTerm at the latest block +func (ethash *Ethash) CurrentTurnTerm(chain consensus.ChainHeaderReader) (turnTerm *uint64, err error) { + return nil, errors.New("not implemented") +} + // NextInTurnValidator return the next in-turn validator for header func (ethash *Ethash) NextInTurnValidator(chain consensus.ChainHeaderReader, header *types.Header) (common.Address, error) { return common.Address{}, errors.New("not implemented") diff --git a/consensus/parlia/abi.go b/consensus/parlia/abi.go index 0d9ab54cd5..401db48911 100644 --- a/consensus/parlia/abi.go +++ b/consensus/parlia/abi.go @@ -2306,6 +2306,19 @@ const validatorSetABI = ` ], "stateMutability": "view" }, + { + "inputs": [], + "name": "getTurnTerm", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, { "type": "function", "name": "getValidators", diff --git a/consensus/parlia/bohrFork.go b/consensus/parlia/bohrFork.go new file mode 100644 index 0000000000..2b712b3216 --- /dev/null +++ b/consensus/parlia/bohrFork.go @@ -0,0 +1,61 @@ +package parlia + +import ( + "context" + "math/big" + mrand "math/rand" + + "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/params" + "github.com/ethereum/go-ethereum/rpc" +) + +func (p *Parlia) getTurnTerm(header *types.Header) (turnTerm *big.Int, err error) { + if params.UseRandTurnTerm { + return p.getRandTurnTerm(header) + } + + 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 +} + +// getRandTurnTerm returns a random valid value, used to test switching turn terms +func (p *Parlia) getRandTurnTerm(header *types.Header) (turnTerm *big.Int, err error) { + turnTerms := [8]uint8{1, 3, 4, 5, 6, 7, 8, 9} + r := mrand.New(mrand.NewSource(int64(header.Time))) + termIndex := int(r.Int31n(int32(len(turnTerms)))) + return big.NewInt(int64(turnTerms[termIndex])), nil +} diff --git a/consensus/parlia/parlia.go b/consensus/parlia/parlia.go index 69b82d408c..6f99dec037 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 bohr 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,15 @@ 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 + extraMinLen := end + extraSeal + if chainConfig.IsBohr(header.Number, header.Time) { + extraMinLen += turnTermSize + } + if num == 0 || len(header.Extra) < extraMinLen { + return nil + } return header.Extra[start:end] } @@ -404,11 +415,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.IsBohr(header.Number, header.Time) { + start += turnTermSize + } end := len(header.Extra) - extraSeal + if end <= start { + return nil, nil + } attestationBytes = header.Extra[start:end] } @@ -884,6 +898,35 @@ 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.IsBohr(header.Number, header.Time) { + return nil + } + + parent := chain.GetHeaderByHash(header.ParentHash) + if parent == nil { + return errors.New("parent not found") + } + + if p.chainConfig.IsBohr(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()))) + log.Debug("prepareTurnTerm", "turnTerm", turnTerm.Int64()) + } else { + log.Debug("prepareTurnTerm", "turnTerm", "defaultTurnTerm") + 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 @@ -967,6 +1010,16 @@ func (p *Parlia) assembleVoteAttestation(chain consensus.ChainHeaderReader, head return nil } +// CurrentTurnTerm return the turnTerm at the latest block +func (p *Parlia) CurrentTurnTerm(chain consensus.ChainHeaderReader) (turnTerm *uint64, err error) { + currentHeader := chain.CurrentHeader() + snap, err := p.snapshot(chain, currentHeader.Number.Uint64(), currentHeader.Hash(), nil) + if err != nil { + return nil, err + } + return &snap.TurnTerm, nil +} + // NextInTurnValidator return the next in-turn validator for header func (p *Parlia) NextInTurnValidator(chain consensus.ChainHeaderReader, header *types.Header) (common.Address, error) { snap, err := p.snapshot(chain, header.Number.Uint64(), header.Hash(), nil) @@ -1015,6 +1068,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 +1121,42 @@ 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.IsBohr(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.IsBohr(parent.Number, parent.Time) { + turnTermFromContract, err := p.getTurnTerm(parent) + if err != nil { + return err + } + if turnTermFromContract != nil && uint8(turnTermFromContract.Int64()) == *turnTermFromHeader { + log.Debug("verifyTurnTerm", "turnTerm", turnTermFromContract.Int64()) + return nil + } + } else { + if uint8(defaultTurnTerm) == *turnTermFromHeader { + log.Debug("verifyTurnTerm", "turnTerm", "defaultTurnTerm") + 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 +1251,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 +1281,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 +1372,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) @@ -1900,31 +1996,24 @@ func (p *Parlia) GetFinalizedHeader(chain consensus.ChainHeaderReader, header *t // =========================== utility function ========================== func (p *Parlia) backOffTime(snap *Snapshot, header *types.Header, val common.Address) uint64 { if snap.inturn(val) { + log.Debug("backOffTime", "blockNumber", header.Number, "in turn validator", val) return 0 } else { 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() + for addr, seenTimes := range counts { + log.Debug("backOffTime", "blockNumber", header.Number, "validator", addr, "seenTimes", seenTimes) } // 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 +2022,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..86793e8bc4 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,45 @@ func (s *Snapshot) updateAttestation(header *types.Header, chainConfig *params.C } } -func (s *Snapshot) SignRecently(validator common.Address) bool { +func (s *Snapshot) versionHistoryCheckLen() uint64 { + return uint64(len(s.Validators)) * s.TurnTerm +} + +func (s *Snapshot) minerHistoryCheckLen() 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.minerHistoryCheckLen() + 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 || recent == (common.Address{}) { + continue } + 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 +282,10 @@ 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 := snap.minerHistoryCheckLen() + 1; number >= limit { // `+1` for genesis block which has no miner delete(snap.Recents, number-limit) } - if limit := uint64(len(snap.Validators)); number >= limit { + if limit := snap.versionHistoryCheckLen(); number >= limit { delete(snap.RecentForkHashes, number-limit) } // Resolve the authorization key and check against signers @@ -261,19 +296,36 @@ 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.IsBohr(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 == snap.minerHistoryCheckLen() { + checkpointHeader := FindAncientHeader(header, snap.minerHistoryCheckLen(), chain, parents) if checkpointHeader == nil { return nil, consensus.ErrUnknownAncestor } + oldVersionsLen := snap.versionHistoryCheckLen() + // 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 { + snap.TurnTerm = uint64(*turnTerm) + log.Debug("validator set switch", "turnTerm", *turnTerm) + } + // get validators from headers and use that for new validator set newValArr, voteAddrs, err := parseValidators(checkpointHeader, chainConfig, s.config) if err != nil { @@ -289,18 +341,25 @@ 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)) + if chainConfig.IsBohr(header.Number, header.Time) { + getClearKey := func(blockNumber uint64) uint64 { + return 1<<63 | (blockNumber / s.config.Epoch) // impossible used as a block number } - } - 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)) + epochClearKey := getClearKey(number) + // in a epoch, after the first validator set switch, minerHistoryCheckLen() may become larger, + // so the unexpected second switch will happen, don't clear up the `Recents` in this kind of scene. + if _, ok := snap.Recents[epochClearKey]; !ok { + snap.Recents = make(map[uint64]common.Address) // without this logic, there will be several off-turn blocks when do validator set switch + snap.Recents[epochClearKey] = common.Address{} + log.Debug("Recents are cleared up", "blockNumber", number) + } + } else { + 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)) + } } } snap.Validators = newVals @@ -310,10 +369,12 @@ func (s *Snapshot) apply(headers []*types.Header, chain consensus.ChainHeaderRea snap.Validators[val].Index = idx + 1 // offset by 1 } } + for i := snap.versionHistoryCheckLen(); i < oldVersionsLen; i++ { + delete(snap.RecentForkHashes, number-i) + } } snap.updateAttestation(header, chainConfig, s.config) - snap.RecentForkHashes[number] = hex.EncodeToString(header.Extra[extraVanity-nextForkHashSize : extraVanity]) } snap.Number += uint64(len(headers)) @@ -333,15 +394,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 +438,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 +463,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.IsBohr(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/bohr/chapel/ValidatorContract b/core/systemcontracts/bohr/chapel/ValidatorContract new file mode 100644 index 0000000000..e69de29bb2 diff --git a/core/systemcontracts/bohr/mainnet/ValidatorContract b/core/systemcontracts/bohr/mainnet/ValidatorContract new file mode 100644 index 0000000000..e69de29bb2 diff --git a/core/systemcontracts/bohr/rialto/ValidatorContract b/core/systemcontracts/bohr/rialto/ValidatorContract new file mode 100644 index 0000000000..8592bc9d84 --- /dev/null +++ b/core/systemcontracts/bohr/rialto/ValidatorContract @@ -0,0 +1 @@ +60806040526004361061051c5760003560e01c80638a7beb01116102a2578063c81b166211610165578063ea321e49116100cc578063f92eb86b11610085578063f92eb86b14610d8d578063f9a2bbc714610da2578063fc3e590814610db7578063fccc281314610dcc578063fd4ad81f14610de1578063fd6a687914610e1057610523565b8063ea321e4914610cfb578063eb57e20214610d1b578063ec12e4b114610d3b578063eda5868c14610d50578063f1fad10414610d65578063f340fa0114610d7a57610523565b8063daacdb661161011e578063daacdb6614610c7d578063dc927faf14610c92578063df8079e914610ca7578063e086c7b114610cbc578063e1c7392a14610cd1578063e40716a114610ce657610523565b8063c81b166214610c09578063c8509d81146109ae578063ce910b0c14610c1e578063d58918ae14610c3e578063d68fb56a14610c53578063d86222d514610c6857610523565b8063aa82dce111610209578063aef198a9116101c2578063aef198a914610b93578063b7ab4db514610ba8578063b8cf4ef114610bca578063bf9f499514610734578063c466689d14610bdf578063c6d3394514610bf457610523565b8063aa82dce114610aff578063aad5606314610b14578063aaf5eb6814610b29578063ab51bb9614610b3e578063ac43175114610b53578063ad3c9da614610b7357610523565b80639dc092621161025b5780639dc0926214610a815780639fe0f81614610a96578063a0dc275814610aab578063a1a11bf514610ac0578063a5422d5c14610ad5578063a78abc1614610aea57610523565b80638a7beb01146109f85780638b5ad0c914610a0d5780638d19a41014610a225780638d49230614610a425780639369d7de14610a5757806396713da914610a6c57610523565b80635192c82c116103ea578063718a8aa81161035157806381650b621161030a57806381650b6214610984578063820dcaa814610999578063831d65d1146109ae578063853230aa1461093057806386249882146109ce57806388b32f11146109e357610523565b8063718a8aa81461090657806375d47a0a1461091b57806378dfed4a146109305780637942fd05146109455780637a84ca2a1461095a5780637e434d541461096f57610523565b80635d77156c116103a35780635d77156c1461086057806360eba4fe1461087557806362b72cf5146108955780636969a25c146108aa5780636e47b482146108dc57806370fd5bad146108f157610523565b80635192c82c146107cc57806351b4dce3146107e157806351e80672146107f657806355614fcc1461080b578063565c56b31461082b5780635667515a1461084b57610523565b80632a0ffb6e1161048e5780633dffc387116104475780633dffc3871461073457806343756e5c1461075657806345cf9daf1461076b578063493279b1146107805780634bf6c882146107a25780634df6e0c3146107b757610523565b80632a0ffb6e14610671578063300c356714610691578063321d398a146106b15780633365af3a146106d157806335409f7f146106f15780633b071dcc1461071157610523565b8063152ad3b8116104e0578063152ad3b8146105db5780631bd14ed8146105fd5780631e4c1524146106125780631ff1806914610632578063219f22d514610647578063280870281461065c57610523565b806304c4fec61461052857806307a568471461053f5780630bee7a671461056a5780630e2374a51461058c5780631182b875146105ae57610523565b3661052357005b600080fd5b34801561053457600080fd5b5061053d610e25565b005b34801561054b57600080fd5b50610554610e97565b6040516105619190619444565b60405180910390f35b34801561057657600080fd5b5061057f610e9d565b604051610561919061946e565b34801561059857600080fd5b506105a1610ea2565b60405161056191906185a7565b3480156105ba57600080fd5b506105ce6105c936600461848d565b610ea8565b604051610561919061873a565b3480156105e757600080fd5b506105f06111a4565b604051610561919061872f565b34801561060957600080fd5b506105546111ad565b34801561061e57600080fd5b5061053d61062d36600461829b565b6111b3565b34801561063e57600080fd5b50610554611889565b34801561065357600080fd5b5061057f61188f565b34801561066857600080fd5b506105a1611894565b34801561067d57600080fd5b5061053d61068c3660046181fb565b61189a565b34801561069d57600080fd5b5061053d6106ac366004618233565b611947565b3480156106bd57600080fd5b506105f06106cc36600461843a565b611c90565b3480156106dd57600080fd5b506105f06106ec36600461843a565b611d5f565b3480156106fd57600080fd5b5061053d61070c3660046181fb565b611e10565b34801561071d57600080fd5b50610726611f75565b604051610561929190618645565b34801561074057600080fd5b50610749612251565b604051610561919061947f565b34801561076257600080fd5b506105a1612256565b34801561077757600080fd5b5061055461225c565b34801561078c57600080fd5b50610795612262565b6040516105619190619435565b3480156107ae57600080fd5b50610749612268565b3480156107c357600080fd5b5061072661226d565b3480156107d857600080fd5b506105546123f9565b3480156107ed57600080fd5b506105a16123ff565b34801561080257600080fd5b506105a1612405565b34801561081757600080fd5b506105f06108263660046181fb565b61240b565b34801561083757600080fd5b506105546108463660046181fb565b612440565b34801561085757600080fd5b50610749612491565b34801561086c57600080fd5b5061057f612496565b34801561088157600080fd5b506105ce61089036600461843a565b61249b565b3480156108a157600080fd5b50610554612541565b3480156108b657600080fd5b506108ca6108c536600461843a565b612547565b604051610561969594939291906185d4565b3480156108e857600080fd5b506105a16125ab565b3480156108fd57600080fd5b506107496125b1565b34801561091257600080fd5b506107496125b6565b34801561092757600080fd5b506105a16125bb565b34801561093c57600080fd5b506105546125c1565b34801561095157600080fd5b506107496125c7565b34801561096657600080fd5b506105546125cc565b34801561097b57600080fd5b506105a16125d2565b34801561099057600080fd5b5061057f6125d8565b3480156109a557600080fd5b506105546125dd565b3480156109ba57600080fd5b5061053d6109c936600461848d565b6125e3565b3480156109da57600080fd5b50610554612644565b3480156109ef57600080fd5b5061055461264a565b348015610a0457600080fd5b506105f0612650565b348015610a1957600080fd5b50610554612659565b348015610a2e57600080fd5b50610554610a3d3660046181fb565b61265f565b348015610a4e57600080fd5b5061055461269f565b348015610a6357600080fd5b5061053d6126a5565b348015610a7857600080fd5b506107496127b9565b348015610a8d57600080fd5b506105a16127be565b348015610aa257600080fd5b506105546127c4565b348015610ab757600080fd5b506105546127c9565b348015610acc57600080fd5b506105a16127ce565b348015610ae157600080fd5b506105ce6127d4565b348015610af657600080fd5b506105f06127f3565b348015610b0b57600080fd5b506105a16127fc565b348015610b2057600080fd5b506105a1612802565b348015610b3557600080fd5b50610554612808565b348015610b4a57600080fd5b5061057f612491565b348015610b5f57600080fd5b5061053d610b6e3660046183de565b612811565b348015610b7f57600080fd5b50610554610b8e3660046181fb565b613308565b348015610b9f57600080fd5b5061055461331a565b348015610bb457600080fd5b50610bbd613327565b6040516105619190618632565b348015610bd657600080fd5b50610554613413565b348015610beb57600080fd5b50610554613418565b348015610c0057600080fd5b506105546125b1565b348015610c1557600080fd5b506105a161341e565b348015610c2a57600080fd5b506105ce610c3936600461843a565b613424565b348015610c4a57600080fd5b50610554613431565b348015610c5f57600080fd5b50610554613437565b348015610c7457600080fd5b50610554613476565b348015610c8957600080fd5b50610554613482565b348015610c9e57600080fd5b506105a1613488565b348015610cb357600080fd5b506105a161348e565b348015610cc857600080fd5b50610554610e9d565b348015610cdd57600080fd5b5061053d613494565b348015610cf257600080fd5b50610554613728565b348015610d0757600080fd5b506105f0610d1636600461839f565b61372e565b348015610d2757600080fd5b5061053d610d363660046181fb565b6138b4565b348015610d4757600080fd5b506105546139b8565b348015610d5c57600080fd5b5061057f6139d4565b348015610d7157600080fd5b506107496139d9565b61053d610d883660046181fb565b6139de565b348015610d9957600080fd5b50610554613d94565b348015610dae57600080fd5b506105a1613d9a565b348015610dc357600080fd5b506107496127c4565b348015610dd857600080fd5b506105a1613da0565b348015610ded57600080fd5b50610e01610dfc36600461843a565b613da6565b6040516105619392919061944d565b348015610e1c57600080fd5b506105a1613e68565b6000610e303361265f565b9050600b8181548110610e3f57fe5b600091825260209091206001601690920201015460ff16610e7b5760405162461bcd60e51b8152600401610e72906190b4565b60405180910390fd5b6000610e85613437565b9050610e92338383613e6e565b505050565b60095481565b606481565b61200181565b60005460609060ff16610ecd5760405162461bcd60e51b8152600401610e7290618946565b600b54610f8b57610edc617da7565b60015460005b81811015610f8757600b805460018101825560009190915283516000805160206197b583398151915260169092029182019081556020808601516000805160206197f58339815191528401805460ff1916911515919091179055604086015180518794610f63936000805160206197d5833981519152909101920190617dd6565b506060820151610f799060038301906013617e50565b505050806001019050610ee2565b5050505b610f93617e7d565b6000610fd485858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061413392505050565b9150915080610ff057610fe760646142ef565b9250505061119d565b815160009060ff166110155761100e83602001518460400151614350565b9050611169565b825160ff16600114156111655782602001515160011461105a5760008051602061953183398151915260405161104a90618f6d565b60405180910390a1506067611160565b6000836020015160008151811061106d57fe5b602090810291909101810151516001600160a01b038116600090815260049092526040909120549091508015806110ce57506001808203815481106110ae57fe5b9060005260206000209060040201600201601c9054906101000a900460ff165b1561110c576040516001600160a01b038316907fe209c46bebf57cf265d5d9009a00870e256d9150f3ed5281ab9d9eb3cec6e4be90600090a2611159565b600061111b8360018403615512565b905080611157576040516001600160a01b038416907fe209c46bebf57cf265d5d9009a00870e256d9150f3ed5281ab9d9eb3cec6e4be90600090a25b505b6000925050505b611169565b5060655b63ffffffff811661118e575050604080516000815260208101909152915061119d9050565b611197816142ef565b93505050505b9392505050565b60075460ff1681565b600f5481565b3341146111d25760405162461bcd60e51b8152600401610e729061929c565b3a156111f05760405162461bcd60e51b8152600401610e7290618ff3565b825160408051828152602080840282010190915260609082801561122e57816020015b61121b617ea1565b8152602001906001900390816112135790505b50905060005b828110156112d8576040518060c0016040528087838151811061125357fe5b60200260200101516001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b0316815260200186838151811061129557fe5b60200260200101516001600160401b0316815260200160001515815260200160008152508282815181106112c557fe5b6020908102919091010152600101611234565b5060405163d31f968d60e01b81526120009063d31f968d906113039061100090600890600401618616565b60206040518083038186803b15801561131b57600080fd5b505afa15801561132f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611353919061837f565b15611676578051601554818111156113f557815b818110156113f357601580548061137a57fe5b60008281526020812060046000199093019283020180546001600160a01b0319908116825560018201805490911690556002810180546001600160e81b031916905560030155905560168054806113cd57fe5b6001900381819060005260206000200160006113e99190617ed6565b9055600101611367565b505b60005b828110156116355781811061151d57601584828151811061141557fe5b602090810291909101810151825460018181018555600094855293839020825160049092020180546001600160a01b039283166001600160a01b0319918216178255938301519481018054958316958516959095179094556040820151600285018054606085015160808601511515600160e01b0260ff60e01b196001600160401b03909216600160a01b0267ffffffffffffffff60a01b199590961692909716919091179290921692909217169290921790915560a0015160039091015585516016908790839081106114e557fe5b602090810291909101810151825460018101845560009384529282902081516115179491909101929190910190617dd6565b5061162d565b83818151811061152957fe5b60200260200101516015828154811061153e57fe5b6000918252602091829020835160049092020180546001600160a01b039283166001600160a01b0319918216178255928401516001820180549184169185169190911790556040840151600282018054606087015160808801511515600160e01b0260ff60e01b196001600160401b03909216600160a01b0267ffffffffffffffff60a01b1995909716929097169190911792909216939093171692909217905560a09091015160039091015585518690829081106115f957fe5b60200260200101516016828154811061160e57fe5b90600052602060002001908051906020019061162b929190617dd6565b505b6001016113f8565b507fb8e726330a0dad1cf3d04e925663b17e391f1ed547d79b7f4e5f344119b44246826040516116659190619444565b60405180910390a150505050610e92565b60608061168383866158d5565b9150915060005b600154811015611779576000600182815481106116a357fe5b906000526020600020906004020160030154905080600014611770576000600183815481106116ce57fe5b9060005260206000209060040201600301819055506120026001600160a01b031663092193ab826001858154811061170257fe5b60009182526020909120600491820201546040516001600160e01b031960e086901b16815261173d926001600160a01b0390921691016185a7565b6000604051808303818588803b15801561175657600080fd5b505af115801561176a573d6000803e3d6000fd5b50505050505b5060010161168a565b5047156117e7577f6ecc855f9440a9282c90913bbc91619fd44f5ec0b462af28d127b116f130aa4d476040516117af9190619444565b60405180910390a1604051611002904780156108fc02916000818181858888f193505050501580156117e5573d6000803e3d6000fd5b505b60006003819055600555815115611802576118028282615dbc565b6110016001600160a01b031663fc4333cd6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561183f57600080fd5b505af1158015611853573d6000803e3d6000fd5b50506040517fedd8d7296956dd970ab4de3f2fc03be2b0ffc615d20cd4c72c6e44f928630ebf925060009150a150505050505050565b60035481565b606881565b61200581565b33612002146118bb5760405162461bcd60e51b8152600401610e72906193fe565b60005b60155481101561194357816001600160a01b0316601582815481106118df57fe5b60009182526020909120600490910201546001600160a01b0316141561193b5760016015828154811061190e57fe5b9060005260206000209060040201600201601c6101000a81548160ff021916908315150217905550611943565b6001016118be565b5050565b3341146119665760405162461bcd60e51b8152600401610e729061929c565b60105443116119875760405162461bcd60e51b8152600401610e7290618b68565b3a156119a55760405162461bcd60e51b8152600401610e7290618ff3565b60005460ff166119c75760405162461bcd60e51b8152600401610e7290618946565b60006110023168056bc75e2d631000008111156119fe576119f78168056bc75e2d6310000063ffffffff6165ab16565b9150611a05565b5050611c86565b6040516309a99b4f60e41b815261100290639a99b4f090611a2c90309086906004016185bb565b602060405180830381600087803b158015611a4657600080fd5b505af1158015611a5a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a7e9190618452565b915081611a8c575050611c86565b6000805b84811015611aba57858582818110611aa457fe5b9050602002013582019150806001019050611a90565b5080611ac857505050611c86565b6000806000805b89811015611c7e5784898983818110611ae457fe5b90506020020135880281611af457fe5b0493508a8a82818110611b0357fe5b9050602002016020810190611b1891906181fb565b6001600160a01b03811660009081526004602052604090205490935091508115611c34576000600180840381548110611b4d57fe5b9060005260206000209060040201905080600201601c9054906101000a900460ff1615611bba57836001600160a01b03167fb9c75cbbfde137c4281689580799ef5f52144e78858f776a5979b2b212137d8586604051611bad9190619444565b60405180910390a2611c2e565b600354611bcd908663ffffffff6165ed16565b6003908155810154611be5908663ffffffff6165ed16565b60038201556040516001600160a01b038516907fcb0aad6cf9cd03bdf6137e359f541c42f38b39f007cae8e89e88aa7d8c6617b290611c25908890619444565b60405180910390a25b50611c76565b826001600160a01b03167fb9c75cbbfde137c4281689580799ef5f52144e78858f776a5979b2b212137d8585604051611c6d9190619444565b60405180910390a25b600101611acf565b505050505050505b5050436010555050565b6001546000908210611ca457506000611d5a565b60006001600160a01b031660018381548110611cbc57fe5b60009182526020909120600490910201546001600160a01b03161480611cec57506008541580611cec5750600a54155b80611cfb575060085460095410155b80611d0c5750611d0a82611d5f565b155b80611d3557506000600b8381548110611d2157fe5b906000526020600020906016020160000154115b80611d4957506001611d45613327565b5111155b15611d5657506000611d5a565b5060015b919050565b6001546000908210611d7357506000611d5a565b600b548210611db05760018281548110611d8957fe5b9060005260206000209060040201600201601c9054906101000a900460ff16159050611d5a565b60018281548110611dbd57fe5b9060005260206000209060040201600201601c9054906101000a900460ff16158015611e0a5750600b8281548110611df157fe5b600091825260209091206001601690920201015460ff16155b92915050565b600b54611ece57611e1f617da7565b60015460005b81811015611eca57600b805460018101825560009190915283516000805160206197b583398151915260169092029182019081556020808601516000805160206197f58339815191528401805460ff1916911515919091179055604086015180518794611ea6936000805160206197d5833981519152909101920190617dd6565b506060820151611ebc9060038301906013617e50565b505050806001019050611e25565b5050505b336110011480611edf575033612002145b611efb5760405162461bcd60e51b8152600401610e729061897d565b6001600160a01b03811660009081526004602052604090205480611f1f5750611f72565b6001810390506000600b8281548110611f3457fe5b600091825260209091206001601690920201015460ff169050611f578383615512565b8015611f605750805b15610e92576009805460001901905550505b50565b60015460609081906000805b82811015611fc85760018181548110611f9657fe5b9060005260206000209060040201600201601c9054906101000a900460ff16611fc0576001909101905b600101611f81565b50606081604051908082528060200260200182016040528015611ff5578160200160208202803683370190505b50905060608260405190808252806020026020018201604052801561202e57816020015b60608152602001906001900390816120195790505b50600b54600094509091508414156121a95760005b848110156121a3576001818154811061205857fe5b9060005260206000209060040201600201601c9054906101000a900460ff1661219b576001818154811061208857fe5b600091825260209091206004909102015483516001600160a01b03909116908490869081106120b357fe5b60200260200101906001600160a01b031690816001600160a01b031681525050600b81815481106120e057fe5b600091825260209182902060026016909202018101805460408051601f6000196101006001861615020190931694909404918201859004850284018501905280835291929091908301828280156121785780601f1061214d57610100808354040283529160200191612178565b820191906000526020600020905b81548152906001019060200180831161215b57829003601f168201915b505050505082858151811061218957fe5b60209081029190910101526001909301925b600101612043565b50612245565b60005b8481101561224357600181815481106121c157fe5b9060005260206000209060040201600201601c9054906101000a900460ff1661223b57600181815481106121f157fe5b600091825260209091206004909102015483516001600160a01b039091169084908690811061221c57fe5b6001600160a01b03909216602092830291909101909101526001909301925b6001016121ac565b505b909450925050505b9091565b600181565b61100181565b60085481565b6102ca81565b600881565b6060806000600e549050600080600c541161228957601561228d565b600c545b90506060612299613327565b905060606122a682616612565b9050828251116122bd57909450925061224d915050565b838383510310156122cf578282510393505b83156123055760c843046122eb83838388880360008a8a616780565b6123038383838888038989038a8b8b8b510301616780565b505b606083604051908082528060200260200182016040528015612331578160200160208202803683370190505b50905060608460405190808252806020026020018201604052801561236a57816020015b60608152602001906001900390816123555790505b50905060005b858110156123eb5784818151811061238457fe5b602002602001015183828151811061239857fe5b60200260200101906001600160a01b031690816001600160a01b0316815250508381815181106123c457fe5b60200260200101518282815181106123d857fe5b6020908102919091010152600101612370565b509096509450505050509091565b60065481565b61200681565b61200081565b6001600160a01b03811660009081526004602052604081205480612433576000915050611d5a565b6000190161119d81611d5f565b6001600160a01b03811660009081526004602052604081205480612468576000915050611d5a565b60018082038154811061247757fe5b906000526020600020906004020160030154915050919050565b600081565b606781565b601281815481106124a857fe5b600091825260209182902001805460408051601f60026000196101006001871615020190941693909304928301859004850281018501909152818152935090918301828280156125395780601f1061250e57610100808354040283529160200191612539565b820191906000526020600020905b81548152906001019060200180831161251c57829003601f168201915b505050505081565b60105481565b6001818154811061255457fe5b600091825260209091206004909102018054600182015460028301546003909301546001600160a01b0392831694509082169291821691600160a01b81046001600160401b031691600160e01b90910460ff169086565b61100581565b600281565b601081565b61100881565b6103e881565b600b81565b600c5481565b61200381565b606681565b61271081565b33612000146126045760405162461bcd60e51b8152600401610e729061924d565b7f41ce201247b6ceb957dcdb217d0b8acb50b9ea0e12af9af4f5e7f389021016058383836040516126379392919061948d565b60405180910390a1505050565b60025481565b60115481565b60145460ff1681565b600a5481565b6001600160a01b038116600090815260046020526040812054806126955760405162461bcd60e51b8152600401610e72906191d5565b6000190192915050565b60175481565b600b54612763576126b4617da7565b60015460005b8181101561275f57600b805460018101825560009190915283516000805160206197b583398151915260169092029182019081556020808601516000805160206197f58339815191528401805460ff191691151591909117905560408601518051879461273b936000805160206197d5833981519152909101920190617dd6565b5060608201516127519060038301906013617e50565b5050508060010190506126ba565b5050505b6008546127705760036008555b600a5461277d576002600a555b60006127883361265f565b905061279381611c90565b6127af5760405162461bcd60e51b8152600401610e7290618f2a565b611f7233826168d7565b600981565b61100781565b600381565b60c881565b61100681565b604051806102a001604052806102648152602001619551610264913981565b60005460ff1681565b61200281565b61300081565b6402540be40081565b60005460ff166128335760405162461bcd60e51b8152600401610e7290618946565b33611007146128545760405162461bcd60e51b8152600401610e7290619021565b6128be84848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080518082019091526013815272065787069726554696d655365636f6e6447617606c1b6020820152915061696f9050565b1561295b57602081146128e35760405162461bcd60e51b8152600401610e729061918f565b604080516020601f8401819004810282018101909252828152600091612921918585808385018382808284376000920191909152506169c892505050565b9050606481101580156129375750620186a08111155b6129535760405162461bcd60e51b8152600401610e7290618d8b565b6002556132c5565b6129bb84848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260098152686275726e526174696f60b81b6020820152915061696f9050565b15612a7057602081146129e05760405162461bcd60e51b8152600401610e729061877f565b604080516020601f8401819004810282018101909252828152600091612a1e918585808385018382808284376000920191909152506169c892505050565b9050612710612a4a601854612a3e600f54856165ed90919063ffffffff16565b9063ffffffff6165ed16565b1115612a685760405162461bcd60e51b8152600401610e7290618cb1565b6006556132c5565b612ada84848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260138152726d61784e756d4f664d61696e7461696e696e6760681b6020820152915061696f9050565b15612b745760208114612aff5760405162461bcd60e51b8152600401610e7290618803565b604080516020601f8401819004810282018101909252828152600091612b3d918585808385018382808284376000920191909152506169c892505050565b600c5490915080612b4c575060155b808210612b6b5760405162461bcd60e51b8152600401610e7290618bd2565b506008556132c5565b612bdd84848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260128152716d61696e7461696e536c6173685363616c6560701b6020820152915061696f9050565b15612c765760208114612c025760405162461bcd60e51b8152600401610e72906188cc565b604080516020601f8401819004810282018101909252828152600091612c40918585808385018382808284376000920191909152506169c892505050565b9050600081118015612c525750600a81105b612c6e5760405162461bcd60e51b8152600401610e7290619331565b600a556132c5565b612cea84848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152601981527f6d61784e756d4f66576f726b696e6743616e64696461746573000000000000006020820152915061696f9050565b15612d795760208114612d0f5760405162461bcd60e51b8152600401610e7290618880565b604080516020601f8401819004810282018101909252828152600091612d4d918585808385018382808284376000920191909152506169c892505050565b9050600d54811115612d715760405162461bcd60e51b8152600401610e7290618e01565b600e556132c5565b612de284848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260128152716d61784e756d4f6643616e6469646174657360701b6020820152915061696f9050565b15612e645760208114612e075760405162461bcd60e51b8152600401610e729061906f565b604080516020601f8401819004810282018101909252828152600091612e45918585808385018382808284376000920191909152506169c892505050565b600d819055600e54909150811015612e5e57600d54600e555b506132c5565b612ec884848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152600d81526c6e756d4f66436162696e65747360981b6020820152915061696f9050565b15612f765760208114612eed5760405162461bcd60e51b8152600401610e7290618911565b604080516020601f8401819004810282018101909252828152600091612f2b918585808385018382808284376000920191909152506169c892505050565b905060008111612f4d5760405162461bcd60e51b8152600401610e7290618a7a565b6064811115612f6e5760405162461bcd60e51b8152600401610e7290618ac2565b600c556132c5565b612fe284848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152601581527473797374656d52657761726442617365526174696f60581b6020820152915061696f9050565b1561308b57602081146130075760405162461bcd60e51b8152600401610e72906192e9565b604080516020601f8401819004810282018101909252828152600091613045918585808385018382808284376000920191909152506169c892505050565b9050612710613065601854612a3e600654856165ed90919063ffffffff16565b11156130835760405162461bcd60e51b8152600401610e72906189eb565b600f556132c5565b6130ff84848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152601881527f73797374656d526577617264416e74694d4556526174696f00000000000000006020820152915061696f9050565b156131a857602081146131245760405162461bcd60e51b8152600401610e7290618d40565b604080516020601f8401819004810282018101909252828152600091613162918585808385018382808284376000920191909152506169c892505050565b9050612710613182600f54612a3e600654856165ed90919063ffffffff16565b11156131a05760405162461bcd60e51b8152600401610e7290618e9b565b6018556132c5565b61320784848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260088152677475726e5465726d60c01b6020820152915061696f9050565b156132ad576020811461322c5760405162461bcd60e51b8152600401610e7290618c7a565b604080516020601f840181900481028201810190925282815260009161326a918585808385018382808284376000920191909152506169c892505050565b90506003811015801561327e575060098111155b806132895750806001145b6132a55760405162461bcd60e51b8152600401610e72906187b6565b6017556132c5565b60405162461bcd60e51b8152600401610e729061938e565b7f6cdb0ac70ab7f2e2d035cca5be60d89906f2dede7648ddbd7402189c1eeed17a848484846040516132fa949392919061874d565b60405180910390a150505050565b60046020526000908152604090205481565b68056bc75e2d6310000081565b6001546060906000805b828110156133565761334281611d5f565b1561334e578160010191505b600101613331565b50606081604051908082528060200260200182016040528015613383578160200160208202803683370190505b5090506000915060005b8381101561340a5761339e81611d5f565b1561340257600181815481106133b057fe5b600091825260209091206004909102015482516001600160a01b03909116908390859081106133db57fe5b60200260200101906001600160a01b031690816001600160a01b0316815250508260010192505b60010161338d565b50925050505b90565b601581565b61027181565b61100281565b601381815481106124a857fe5b60185481565b6000613441613327565b519050600080600c541161345657601561345a565b600c545b905080821115613468578091505b8161347257600191505b5090565b67016345785d8a000081565b60055481565b61100381565b61200481565b60005460ff16156134b75760405162461bcd60e51b8152600401610e7290619121565b6134bf617e7d565b60006134e5604051806102a0016040528061026481526020016195516102649139614133565b91509150806135065760405162461bcd60e51b8152600401610e729061920c565b61350e617da7565b60005b83602001515181101561370f57600b805460018101825560009190915282516000805160206197b583398151915260169092029182019081556020808501516000805160206197f58339815191528401805460ff1916911515919091179055604085015180518694613597936000805160206197d5833981519152909101920190617dd6565b5060608201516135ad9060038301906013617e50565b505050836040015181815181106135c057fe5b6020026020010151600b82815481106135d557fe5b906000526020600020906016020160020190805190602001906135f9929190617dd6565b5060018460200151828151811061360c57fe5b60209081029190910181015182546001818101855560009485528385208351600493840290910180546001600160a01b039283166001600160a01b03199182161782558587015182850180549185169183169190911790556040860151600283018054606089015160808a01511515600160e01b0260ff60e01b196001600160401b03909216600160a01b0267ffffffffffffffff60a01b199590981692909516919091179290921694909417161790915560a0909301516003909301929092559187015180519185019391859081106136e257fe5b602090810291909101810151516001600160a01b0316825281019190915260400160002055600101613511565b50506103e860025550506000805460ff19166001179055565b600d5481565b601354600090815b818110156138375761381f85858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060138054909250859150811061378757fe5b600091825260209182902001805460408051601f60026000196101006001871615020190941693909304928301859004850281018501909152818152928301828280156138155780601f106137ea57610100808354040283529160200191613815565b820191906000526020600020905b8154815290600101906020018083116137f857829003601f168201915b50505050506169cd565b1561382f57600192505050611e0a565b600101613736565b5060125460005b818110156138a85761388f86868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060128054909250859150811061378757fe5b156138a05760019350505050611e0a565b60010161383e565b50600095945050505050565b33611001146138d55760405162461bcd60e51b8152600401610e72906193b5565b600b54613993576138e4617da7565b60015460005b8181101561398f57600b805460018101825560009190915283516000805160206197b583398151915260169092029182019081556020808601516000805160206197f58339815191528401805460ff191691151591909117905560408601518051879461396b936000805160206197d5833981519152909101920190617dd6565b5060608201516139819060038301906013617e50565b5050508060010190506138ea565b5050505b600061399e82616a31565b90506139a981611c90565b156119435761194382826168d7565b6000601754600014156139cd57506001613410565b5060175490565b606581565b601181565b3341146139fd5760405162461bcd60e51b8152600401610e729061929c565b60005460ff16613a1f5760405162461bcd60e51b8152600401610e7290618946565b60003411613a3f5760405162461bcd60e51b8152600401610e7290618dd2565b3a15613a5d5760405162461bcd60e51b8152600401610e7290618ff3565b6001600160a01b03811660009081526004602052604090205460145434919060ff16613a9d57610271600f556103e86006556014805460ff191660011790555b600f546017546001108015613ab457506000601854115b15613ad9576001601754036017544381613aca57fe5b066018540281613ad657fe5b04015b600083118015613ae95750600081115b15613b96576000613b12612710613b06348563ffffffff616bb416565b9063ffffffff616bee16565b90508015613b94576040516110029082156108fc029083906000818181858888f19350505050158015613b49573d6000803e3d6000fd5b507f6ecc855f9440a9282c90913bbc91619fd44f5ec0b462af28d127b116f130aa4d81604051613b799190619444565b60405180910390a1613b91848263ffffffff6165ab16565b93505b505b600083118015613ba857506000600654115b15613c4e576000613bca612710613b0660065434616bb490919063ffffffff16565b90508015613c4c5760405161dead9082156108fc029083906000818181858888f19350505050158015613c01573d6000803e3d6000fd5b507f627059660ea01c4733a328effb2294d2f86905bf806da763a89cee254de8bee581604051613c319190619444565b60405180910390a1613c49848263ffffffff6165ab16565b93505b505b8115613d4c576000600180840381548110613c6557fe5b9060005260206000209060040201905080600201601c9054906101000a900460ff1615613cd257846001600160a01b03167ff177e5d6c5764d79c32883ed824111d9b13f5668cf6ab1cc12dd36791dd955b485604051613cc59190619444565b60405180910390a2613d46565b600354613ce5908563ffffffff6165ed16565b6003908155810154613cfd908563ffffffff6165ed16565b60038201556040516001600160a01b038616907f93a090ecc682c002995fad3c85b30c5651d7fd29b0be5da9d784a3302aedc05590613d3d908790619444565b60405180910390a25b50613d8e565b836001600160a01b03167ff177e5d6c5764d79c32883ed824111d9b13f5668cf6ab1cc12dd36791dd955b484604051613d859190619444565b60405180910390a25b50505050565b600e5481565b61100081565b61dead81565b600b8181548110613db357fe5b6000918252602091829020601691909102018054600180830154600280850180546040805161010096831615969096026000190190911692909204601f810188900488028501880190925281845293965060ff90911694919291830182828015613e5e5780601f10613e3357610100808354040283529160200191613e5e565b820191906000526020600020905b815481529060010190602001808311613e4157829003601f168201915b5050505050905083565b61100481565b6000600a5460001480613e7f575081155b80613e8a5750600954155b15613e975750600061119d565b6000613ed1600a54613b0685613b06600b8981548110613eb357fe5b6000918252602090912060169091020154439063ffffffff6165ab16565b90506000806110016001600160a01b0316638256ace66040518163ffffffff1660e01b8152600401604080518083038186803b158015613f1057600080fd5b505afa158015613f24573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613f48919061846a565b91509150600093508083106140a757613f618787615512565b5060405163436aa28360e11b8152600090612002906386d5450690613f8a908b906004016185a7565b60206040518083038186803b158015613fa257600080fd5b505afa158015613fb6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613fda9190618217565b6001600160a01b031614614046576040516313d13bdb60e31b815261100190639e89ded89061400f908a9087906004016185bb565b600060405180830381600087803b15801561402957600080fd5b505af115801561403d573d6000803e3d6000fd5b5050505061409e565b6040516305bfb49960e41b815261100190635bfb49909061406b908a906004016185a7565b600060405180830381600087803b15801561408557600080fd5b505af1158015614099573d6000803e3d6000fd5b505050505b600193506140b9565b8183106140b9576140b787616a31565b505b60098054600019019055600b805460009190889081106140d557fe5b60009182526020822060169190910201600101805460ff1916921515929092179091556040516001600160a01b038916917fb9d38178dc641ff1817967a63c9078cbcd955a9f1fcd75e0e3636de615d44d3b91a25050509392505050565b61413b617e7d565b6000614145617e7d565b61414d617f1a565b61415e61415986616c30565b616c55565b90506000805b61416d83616c9f565b156142e157806141925761418861418384616cc0565b616d0e565b60ff1684526142d9565b80600114156142d45760606141ae6141a985616cc0565b616d8e565b905080516040519080825280602002602001820160405280156141eb57816020015b6141d8617ea1565b8152602001906001900390816141d05790505b508560200181905250805160405190808252806020026020018201604052801561422957816020015b60608152602001906001900390816142145790505b50604086015260005b81518110156142c957614243617ea1565b6060600061426385858151811061425657fe5b6020026020010151616e5f565b92509250925080614283578860009a509a505050505050505050506142ea565b828960200151858151811061429457fe5b602002602001018190525081896040015185815181106142b057fe5b6020026020010181905250505050806001019050614232565b5060019250506142d9565b6142e1565b600101614164565b50919350909150505b915091565b604080516001808252818301909252606091829190816020015b606081526020019060019003908161430957905050905061432f8363ffffffff16616f79565b8160008151811061433c57fe5b602002602001018190525061119d81616f8c565b60006064835111156143875760008051602061953183398151915260405161437790618b1f565b60405180910390a1506066611e0a565b60005b83518110156144255760005b8181101561441c578481815181106143aa57fe5b6020026020010151600001516001600160a01b03168583815181106143cb57fe5b6020026020010151600001516001600160a01b031614156144145760008051602061953183398151915260405161440190618c2f565b60405180910390a1606692505050611e0a565b600101614396565b5060010161438a565b5060608060606015805480602002602001604051908101604052809291908181526020016000905b828210156144d75760008481526020908190206040805160c0810182526004860290920180546001600160a01b039081168452600180830154821685870152600283015491821693850193909352600160a01b81046001600160401b03166060850152600160e01b900460ff16151560808401526003015460a0830152908352909201910161444d565b50505050905060606016805480602002602001604051908101604052809291908181526020016000905b828210156145ac5760008481526020908190208301805460408051601f60026000196101006001871615020190941693909304928301859004850281018501909152818152928301828280156145985780601f1061456d57610100808354040283529160200191614598565b820191906000526020600020905b81548152906001019060200180831161457b57829003601f168201915b505050505081526020019060010190614501565b50505050905060005b8251811015614609578281815181106145ca57fe5b6020026020010151606001516003028382815181106145e557fe5b60209081029190910101516001600160401b039091166060909101526001016145b5565b5060608061461989898686617016565b9150915061462782826158d5565b60015460408051828152602080840282010190915292985090965060009550859450925060609150828015614666578160200160208202803683370190505b50905060005b828110156147f75760006001600160a01b03166120026001600160a01b03166386d545066001848154811061469d57fe5b60009182526020909120600491820201546040516001600160e01b031960e085901b1681526146d8926001600160a01b0390921691016185a7565b60206040518083038186803b1580156146f057600080fd5b505afa158015614704573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906147289190618217565b6001600160a01b03161461478a57600182828151811061474457fe5b602002602001019060ff16908160ff16815250506001818154811061476557fe5b906000526020600020906004020160030154600014614785578360010193505b6147ef565b67016345785d8a0000600182815481106147a057fe5b906000526020600020906004020160030154106147c2578460010194506147ef565b600181815481106147cf57fe5b9060005260206000209060040201600301546000146147ef578360010193505b60010161466c565b50606084604051908082528060200260200182016040528015614824578160200160208202803683370190505b509050606085604051908082528060200260200182016040528015614853578160200160208202803683370190505b509050606086604051908082528060200260200182016040528015614882578160200160208202803683370190505b5090506060876040519080825280602002602001820160405280156148b1578160200160208202803683370190505b50905060006060886040519080825280602002602001820160405280156148e2578160200160208202803683370190505b509050606089604051908082528060200260200182016040528015614911578160200160208202803683370190505b50905060009a506000995060006110046001600160a01b031663149d14d96040518163ffffffff1660e01b815260040160206040518083038186803b15801561495957600080fd5b505afa15801561496d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906149919190618452565b905067016345785d8a00008111156149dd576000805160206195318339815191526040516149be906190e0565b60405180910390a160689e505050505050505050505050505050611e0a565b60005b8a811015614d71578981815181106149f457fe5b602002602001015160ff1660011415614aea5760018181548110614a1457fe5b906000526020600020906004020160030154600014614ae55760018181548110614a3a57fe5b600091825260209091206004909102015484516001600160a01b039091169085908e908110614a6557fe5b60200260200101906001600160a01b031690816001600160a01b03168152505060018181548110614a9257fe5b906000526020600020906004020160030154838d81518110614ab057fe5b60200260200101818152505060018a8d81518110614aca57fe5b602002602001019060ff16908160ff16815250508b6001019b505b614d69565b67016345785d8a000060018281548110614b0057fe5b90600052602060002090600402016003015410614c855760018181548110614b2457fe5b906000526020600020906004020160020160009054906101000a90046001600160a01b0316898e81518110614b5557fe5b60200260200101906001600160a01b031690816001600160a01b03168152505060006402540be40060018381548110614b8a57fe5b90600052602060002090600402016003015481614ba357fe5b0660018381548110614bb157fe5b906000526020600020906004020160030154039050614bd983826165ab90919063ffffffff16565b898f81518110614be557fe5b60200260200101818152505060018281548110614bfe57fe5b906000526020600020906004020160010160009054906101000a90046001600160a01b0316878f81518110614c2f57fe5b60200260200101906001600160a01b031690816001600160a01b03168152505081888f81518110614c5c57fe5b6020908102919091010152614c77868263ffffffff6165ed16565b95508d6001019d5050614d69565b60018181548110614c9257fe5b906000526020600020906004020160030154600014614d695760018181548110614cb857fe5b906000526020600020906004020160010160009054906101000a90046001600160a01b0316848d81518110614ce957fe5b60200260200101906001600160a01b031690816001600160a01b03168152505060018181548110614d1657fe5b906000526020600020906004020160030154838d81518110614d3457fe5b60200260200101818152505060008a8d81518110614d4e57fe5b602002602001019060ff16908160ff16815250508b6001019b505b6001016149e0565b5060008415614fe7576002546040516303702b2960e51b815261100491636e056520918891614dab918e918e918d914201906004016186b5565b6020604051808303818588803b158015614dc457600080fd5b505af193505050508015614df5575060408051601f3d908101601f19168201909252614df29181019061837f565b60015b614f6c576040516000815260443d1015614e1157506000614eac565b60046000803e60005160e01c6308c379a08114614e32576000915050614eac565b60043d036004833e81513d60248201116001600160401b0382111715614e5d57600092505050614eac565b80830180516001600160401b03811115614e7e576000945050505050614eac565b8060208301013d8601811115614e9c57600095505050505050614eac565b601f01601f191660405250925050505b80614eb75750614ef9565b60019150857fa7cdeed7d0db45e3219a6e5d60838824c16f1d39991fcfe3f963029c844bf28082604051614eeb919061873a565b60405180910390a250614f67565b3d808015614f23576040519150601f19603f3d011682016040523d82523d6000602084013e614f28565b606091505b5060019150857fbfa884552dd8921b6ce90bfe906952ae5b3b29be0cc1a951d4f62697635a3a4582604051614f5d919061873a565b60405180910390a2505b614fe7565b8015614fae577fa217d08e65f80c73121cd9db834d81652d544bfbf452f6d04922b16c90a37b7086604051614fa19190619444565b60405180910390a1614fe5565b857fa7cdeed7d0db45e3219a6e5d60838824c16f1d39991fcfe3f963029c844bf280604051614fdc90618849565b60405180910390a25b505b801561519d5760005b875181101561519b57600088828151811061500757fe5b6020026020010151905060006001828154811061502057fe5b60009182526020909120600160049092020181015481546001600160a01b03909116916108fc918590811061505157fe5b9060005260206000209060040201600301549081150290604051600060405180830381858888f193505050509050801561510d576001828154811061509257fe5b60009182526020909120600160049092020181015481546001600160a01b03909116917f6c61d60f69a7beb3e1c80db7f39f37b208537cbb19da3174511b477812b2fc7d91859081106150e157fe5b9060005260206000209060040201600301546040516151009190619444565b60405180910390a2615191565b6001828154811061511a57fe5b60009182526020909120600160049092020181015481546001600160a01b03909116917f25d0ce7d2f0cec669a8c17efe49d195c13455bb8872b65fa610ac7f53fe4ca7d918590811061516957fe5b9060005260206000209060040201600301546040516151889190619444565b60405180910390a25b5050600101614ff0565b505b8351156153935760005b8451811015615391578a81815181106151bc57fe5b602002602001015160ff166001141561525b576120026001600160a01b031663092193ab8583815181106151ec57fe5b602002602001015187848151811061520057fe5b60200260200101516040518363ffffffff1660e01b815260040161522491906185a7565b6000604051808303818588803b15801561523d57600080fd5b505af1158015615251573d6000803e3d6000fd5b5050505050615389565b600085828151811061526957fe5b60200260200101516001600160a01b03166108fc86848151811061528957fe5b60200260200101519081150290604051600060405180830381858888f193505050509050801561531f578582815181106152bf57fe5b60200260200101516001600160a01b03167f6c61d60f69a7beb3e1c80db7f39f37b208537cbb19da3174511b477812b2fc7d8684815181106152fd57fe5b60200260200101516040516153129190619444565b60405180910390a2615387565b85828151811061532b57fe5b60200260200101516001600160a01b03167f25d0ce7d2f0cec669a8c17efe49d195c13455bb8872b65fa610ac7f53fe4ca7d86848151811061536957fe5b602002602001015160405161537e9190619444565b60405180910390a25b505b6001016151a7565b505b5050505050505050505050505060005b60015481101561540057600181815481106153ba57fe5b9060005260206000209060040201600301546000146153f8576000600182815481106153e257fe5b9060005260206000209060040201600301819055505b6001016153a3565b50471561546e577f6ecc855f9440a9282c90913bbc91619fd44f5ec0b462af28d127b116f130aa4d476040516154369190619444565b60405180910390a1604051611002904780156108fc02916000818181858888f1935050505015801561546c573d6000803e3d6000fd5b505b60006003819055600555815115615489576154898282615dbc565b6110016001600160a01b031663fc4333cd6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156154c657600080fd5b505af11580156154da573d6000803e3d6000fd5b50506040517fedd8d7296956dd970ab4de3f2fc03be2b0ffc615d20cd4c72c6e44f928630ebf925060009150a1506000949350505050565b6000806001838154811061552257fe5b9060005260206000209060040201600301549050600060018080549050039050600161554c613327565b51116155815760006001858154811061556157fe5b906000526020600020906004020160030181905550600092505050611e0a565b846001600160a01b03167f3b6f9ef90462b512a1293ecec018670bf7b7f1876fb727590a8a6d7643130a70836040516155ba9190619444565b60405180910390a26001600160a01b038516600090815260046020526040812055835b600154600019018110156157a757600181600101815481106155fb57fe5b90600052602060002090600402016001828154811061561657fe5b60009182526020909120825460049092020180546001600160a01b03199081166001600160a01b0393841617825560018085015481840180548416918616919091179055600280860180549185018054909416919095161780835584546001600160401b03600160a01b91829004160267ffffffffffffffff60a01b1990911617808355935460ff600160e01b918290041615150260ff60e01b19909416939093179055600392830154920191909155600b8054909183019081106156d757fe5b9060005260206000209060160201600b82815481106156f257fe5b600091825260209091208254601690920201908155600180830154818301805460ff909216151560ff1990921691909117905560028084018054615749938386019390821615610100026000190190911604617f3a565b5061575c60038281019084016013617faf565b5090505080600101600460006001848154811061577557fe5b600091825260208083206004909202909101546001600160a01b031683528201929092526040019020556001016155dd565b5060018054806157b357fe5b60008281526020812060046000199093019283020180546001600160a01b0319908116825560018201805490911690556002810180546001600160e81b0319169055600301559055600b80548061580657fe5b60008281526020812060166000199093019283020181815560018101805460ff19169055906158386002830182617ed6565b615846600383016000617fd9565b50509055600081838161585557fe5b04905080156158c95760015460005b818110156158c65761589d836001838154811061587d57fe5b9060005260206000209060040201600301546165ed90919063ffffffff16565b600182815481106158aa57fe5b6000918252602090912060036004909202010155600101615864565b50505b50600195945050505050565b6060806000808080806158e6613437565b6001549091505b8015615b1557600181039250600b838154811061590657fe5b600091825260209091206001601690920201015460ff1661592657615b0c565b6001838154811061593357fe5b60009182526020909120600490910201546001600160a01b0316945061595a858484613e6e565b93508361596657615b0c565b60405163436aa28360e11b81526000908190612002906386d5450690615990908a906004016185a7565b60206040518083038186803b1580156159a857600080fd5b505afa1580156159bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906159e09190618217565b90506001600160a01b03811615615a69576040516302ceee9160e11b81526120029063059ddd2290615a169084906004016185a7565b60206040518083038186803b158015615a2e57600080fd5b505afa158015615a42573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190615a669190618217565b91505b60005b8c51811015615b0857876001600160a01b03168d8281518110615a8b57fe5b6020026020010151600001516001600160a01b03161480615ad45750826001600160a01b03168d8281518110615abd57fe5b6020026020010151600001516001600160a01b0316145b15615b005760018d8281518110615ae757fe5b6020908102919091010151901515608090910152615b08565b600101615a6c565b5050505b600019016158ed565b5060005b8951811015615b8257898181518110615b2e57fe5b60200260200101516080015180615b6e575060006001600160a01b03168a8281518110615b5757fe5b6020026020010151600001516001600160a01b0316145b15615b7a578560010195505b600101615b19565b5088518510615c6a5760408051600180825281830190925290816020015b615ba8617ea1565b815260200190600190039081615ba0575050604080516001808252818301909252919850602082015b6060815260200190600190039081615bd157905050955088600081518110615bf557fe5b602002602001015187600081518110615c0a57fe5b602002602001018190525087600081518110615c2257fe5b602002602001015186600081518110615c3757fe5b6020026020010181905250600087600081518110615c5157fe5b6020908102919091010151901515608090910152615daf565b84895103604051908082528060200260200182016040528015615ca757816020015b615c94617ea1565b815260200190600190039081615c8c5790505b50965084895103604051908082528060200260200182016040528015615ce157816020015b6060815260200190600190039081615ccc5790505b5095506000915060005b8951811015615dad57898181518110615d0057fe5b602002602001015160800151158015615d43575060006001600160a01b03168a8281518110615d2b57fe5b6020026020010151600001516001600160a01b031614155b15615da557898181518110615d5457fe5b6020026020010151888481518110615d6857fe5b6020026020010181905250888181518110615d7f57fe5b6020026020010151878481518110615d9357fe5b60200260200101819052508260010192505b600101615ceb565b505b50505050505b9250929050565b600154825160005b82811015615ed9576001615dd6617ea1565b60018381548110615de357fe5b600091825260208083206040805160c08101825260049490940290910180546001600160a01b0390811685526001820154811693850193909352600281015492831691840191909152600160a01b82046001600160401b03166060840152600160e01b90910460ff16151560808301526003015460a082015291505b84811015615ead57878181518110615e7357fe5b6020026020010151600001516001600160a01b031682600001516001600160a01b03161415615ea55760009250615ead565b600101615e5f565b508115615ecf5780516001600160a01b03166000908152600460205260408120555b5050600101615dc4565b5080821115615f9857805b82811015615f96576001805480615ef757fe5b60008281526020812060046000199093019283020180546001600160a01b0319908116825560018201805490911690556002810180546001600160e81b0319169055600301559055600b805480615f4a57fe5b60008281526020812060166000199093019283020181815560018101805460ff1916905590615f7c6002830182617ed6565b615f8a600383016000617fd9565b50509055600101615ee4565b505b6000818310615fa75781615fa9565b825b905060005b8181101561634d5761605b868281518110615fc557fe5b602002602001015160018381548110615fda57fe5b60009182526020918290206040805160c08101825260049390930290910180546001600160a01b0390811684526001820154811694840194909452600281015493841691830191909152600160a01b83046001600160401b03166060830152600160e01b90920460ff161515608082015260039091015460a08201526173e2565b61620f57806001016004600088848151811061607357fe5b6020026020010151600001516001600160a01b03166001600160a01b03168152602001908152602001600020819055508581815181106160af57fe5b6020026020010151600182815481106160c457fe5b6000918252602091829020835160049092020180546001600160a01b039283166001600160a01b0319918216178255928401516001820180549184169185169190911790556040840151600282018054606087015160808801511515600160e01b0260ff60e01b196001600160401b03909216600160a01b0267ffffffffffffffff60a01b1995909716929097169190911792909216939093171692909217905560a090910151600390910155845185908290811061617f57fe5b6020026020010151600b828154811061619457fe5b906000526020600020906016020160020190805190602001906161b8929190617dd6565b506000600b82815481106161c857fe5b60009182526020822060169190910201600101805460ff191692151592909217909155600b8054839081106161f957fe5b6000918252602090912060169091020155616345565b85818151811061621b57fe5b6020026020010151606001516001828154811061623457fe5b906000526020600020906004020160020160146101000a8154816001600160401b0302191690836001600160401b031602179055506162fa85828151811061627857fe5b6020026020010151600b838154811061628d57fe5b600091825260209182902060026016909202018101805460408051601f6000196101006001861615020190931694909404918201859004850284018501905280835291929091908301828280156138155780601f106137ea57610100808354040283529160200191613815565b6163455784818151811061630a57fe5b6020026020010151600b828154811061631f57fe5b90600052602060002090601602016002019080519060200190616343929190617dd6565b505b600101615fae565b50828211156165255761635e617da7565b835b838110156165225785818151811061637457fe5b60200260200101518260400181905250600187828151811061639257fe5b6020908102919091018101518254600181810185556000948552838520835160049093020180546001600160a01b039384166001600160a01b0319918216178255848601518284018054918616918316919091179055604080860151600284018054606089015160808a01511515600160e01b0260ff60e01b196001600160401b03909216600160a01b0267ffffffffffffffff60a01b1995909a1692909616919091179290921696909617169190911790935560a090930151600390930192909255600b80549283018155909352845160169091026000805160206197b58339815191528101918255858301516000805160206197f58339815191528201805491151560ff19909216919091179055928501518051869492936164c8936000805160206197d583398151915201920190617dd6565b5060608201516164de9060038301906013617e50565b50505080600101600460008984815181106164f557fe5b602090810291909101810151516001600160a01b0316825281019190915260400160002055600101616360565b50505b61652d61743e565b616535617620565b6000600981905560015493505b838110156165a3576000600b828154811061655957fe5b60009182526020822060169190910201600101805460ff191692151592909217909155600b80548390811061658a57fe5b6000918252602090912060169091020155600101616542565b505050505050565b600061119d83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f77000081525061780e565b60008282018381101561119d5760405162461bcd60e51b8152600401610e72906189b4565b60015481516040805182815260208084028201019091526060929190839082801561665157816020015b606081526020019060019003908161663c5790505b50600b549091508314616668579250611d5a915050565b60005b8281101561677757600b60016004600089858151811061668757fe5b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205403815481106166bb57fe5b600091825260209182902060026016909202018101805460408051601f6000196101006001861615020190931694909404918201859004850284018501905280835291929091908301828280156167535780601f1061672857610100808354040283529160200191616753565b820191906000526020600020905b81548152906001019060200180831161673657829003601f168201915b505050505082828151811061676457fe5b602090810291909101015260010161666b565b50949350505050565b60005b828110156168cd57600082878388016040516020016167a3929190618599565b6040516020818303038152906040528051906020012060001c816167c357fe5b069050808501828701146168c457600089838801815181106167e157fe5b60200260200101519050606089848901815181106167fb57fe5b602002602001015190508a8388018151811061681357fe5b60200260200101518b858a018151811061682957fe5b60200260200101906001600160a01b031690816001600160a01b031681525050818b8489018151811061685857fe5b60200260200101906001600160a01b031690816001600160a01b031681525050898388018151811061688657fe5b60200260200101518a858a018151811061689c57fe5b6020026020010181905250808a848901815181106168b657fe5b602002602001018190525050505b50600101616783565b5050505050505050565b600980546001908101909155600b8054839081106168f157fe5b906000526020600020906016020160010160006101000a81548160ff02191690831515021790555043600b828154811061692757fe5b600091825260208220601690910201919091556040516001600160a01b038416917ff62981a567ec3cec866c6fa93c55bcdf841d6292d18b8d522ececa769375d82d91a25050565b600081604051602001616982919061857d565b60405160208183030381529060405280519060200120836040516020016169a9919061857d565b6040516020818303038152906040528051906020012014905092915050565b015190565b8151815160009160019181148083146169e95760009250616a27565b600160208701838101602088015b600284838510011415616a22578051835114616a165760009650600093505b602092830192016169f7565b505050505b5090949350505050565b6001600160a01b03811660009081526004602052604081205480616a5a57506000199050611d5a565b600181039050600060018281548110616a6f57fe5b9060005260206000209060040201600301549050600060018381548110616a9257fe5b6000918252602090912060036004909202010155600154604051600019909101906001600160a01b038616907f8cd4e147d8af98a9e3b6724021b8bf6aed2e5dac71c38f2dce8161b82585b25d90616aeb908590619444565b60405180910390a280616b0357829350505050611d5a565b6000818381616b0e57fe5b0490508015616baa5760005b84811015616b5c57616b33826001838154811061587d57fe5b60018281548110616b4057fe5b6000918252602090912060036004909202010155600101616b1a565b50600180549085015b81811015616ba757616b7e836001838154811061587d57fe5b60018281548110616b8b57fe5b6000918252602090912060036004909202010155600101616b65565b50505b5091949350505050565b600082616bc357506000611e0a565b82820282848281616bd057fe5b041461119d5760405162461bcd60e51b8152600401610e7290618fb2565b600061119d83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f00000000000081525061783a565b616c38617fe8565b506040805180820190915281518152602082810190820152919050565b616c5d617f1a565b616c6682617871565b616c6f57600080fd5b6000616c7e83602001516178ab565b60208085015160408051808201909152868152920190820152915050919050565b6000616ca9617fe8565b505080518051602091820151919092015191011190565b616cc8617fe8565b616cd182616c9f565b616cda57600080fd5b60208201516000616cea8261790e565b80830160209586015260408051808201909152908152938401919091525090919050565b805160009015801590616d2357508151602110155b616d2c57600080fd5b6000616d3b83602001516178ab565b90508083600001511015616d615760405162461bcd60e51b8152600401610e7290619158565b82516020808501518301805192849003929183101561677757506020919091036101000a90049392505050565b6060616d9982617871565b616da257600080fd5b6000616dad836179ef565b9050606081604051908082528060200260200182016040528015616deb57816020015b616dd8617fe8565b815260200190600190039081616dd05790505b5090506000616dfd85602001516178ab565b60208601510190506000805b84811015616e5457616e1a8361790e565b9150604051806040016040528083815260200184815250848281518110616e3d57fe5b602090810291909101015291810191600101616e09565b509195945050505050565b616e67617ea1565b60606000616e73617ea1565b6060616e7d617f1a565b616e8687616c55565b90506000805b616e9583616c9f565b15616f6a5780616ec057616eb0616eab84616cc0565b617a4b565b6001600160a01b03168552616f62565b8060011415616ee857616ed5616eab84616cc0565b6001600160a01b03166020860152616f62565b8060021415616f1057616efd616eab84616cc0565b6001600160a01b03166040860152616f62565b8060031415616f3c57616f2561418384616cc0565b6001600160401b0316606086015260019150616f62565b8060041415616f5d57616f56616f5184616cc0565b617a65565b9350616f62565b616f6a565b600101616e8c565b50929791965091945092505050565b6060611e0a616f8783617ad5565b617bbb565b6060815160001415616fad5750604080516000815260208101909152611d5a565b606082600081518110616fbc57fe5b602002602001015190506000600190505b8351811015616ffd57616ff382858381518110616fe657fe5b6020026020010151617c0d565b9150600101616fcd565b5061119d617010825160c060ff16617c8a565b82617c0d565b60608060006120026001600160a01b031663c473318f6040518163ffffffff1660e01b815260040160206040518083038186803b15801561705657600080fd5b505afa15801561706a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061708e9190618452565b905080855188510110156170a3575083518651015b6060816040519080825280602002602001820160405280156170df57816020015b6170cc617ea1565b8152602001906001900390816170c45790505b50905060608260405190808252806020026020018201604052801561711857816020015b60608152602001906001900390816171035790505b50905060008060005b8b518310806171305750895182105b801561713b57508581105b156173d0578b518314156171ab5789828151811061715557fe5b602002602001015185828151811061716957fe5b602002602001018190525088828151811061718057fe5b602002602001015184828151811061719457fe5b602090810291909101015260019182019101617121565b8951821415617216578b83815181106171c057fe5b60200260200101518582815181106171d457fe5b60200260200101819052508a83815181106171eb57fe5b60200260200101518482815181106171ff57fe5b602090810291909101015260019283019201617121565b89828151811061722257fe5b6020026020010151606001516001600160401b03168c848151811061724357fe5b6020026020010151606001516001600160401b031611156172bf578b838151811061726a57fe5b602002602001015185828151811061727e57fe5b60200260200101819052508a838151811061729557fe5b60200260200101518482815181106172a957fe5b60200260200101819052508260010192506173c8565b8982815181106172cb57fe5b6020026020010151606001516001600160401b03168c84815181106172ec57fe5b6020026020010151606001516001600160401b031610156173685789828151811061731357fe5b602002602001015185828151811061732757fe5b602002602001018190525088828151811061733e57fe5b602002602001015184828151811061735257fe5b60200260200101819052508160010191506173c8565b89828151811061737457fe5b6020026020010151600001516001600160a01b03168c848151811061739557fe5b6020026020010151600001516001600160a01b031610156173bc578b838151811061726a57fe5b89828151811061715557fe5b600101617121565b50929a91995090975050505050505050565b805182516000916001600160a01b03918216911614801561741c575081602001516001600160a01b031683602001516001600160a01b0316145b801561119d5750506040908101519101516001600160a01b0390811691161490565b6012546013548082111561748957805b8281101561748757601280548061746157fe5b60019003818190600052602060002001600061747d9190617ed6565b905560010161744e565b505b6000818310617498578161749a565b825b905060005b818110156175b257617557601282815481106174b757fe5b600091825260209182902001805460408051601f60026000196101006001871615020190941693909304928301859004850281018501909152818152928301828280156175455780601f1061751a57610100808354040283529160200191617545565b820191906000526020600020905b81548152906001019060200180831161752857829003601f168201915b50505050506013838154811061378757fe5b6175aa576013818154811061756857fe5b906000526020600020016012828154811061757f57fe5b9060005260206000200190805460018160011615610100020316600290046175a8929190617f3a565b505b60010161749f565b5082821115610e9257825b82811015613d8e576012601382815481106175d457fe5b6000918252602080832084546001818101875595855291909320929091018054617617949390920192909160026101009282161592909202600019011604617f3a565b506001016175bd565b601354600b548082111561766b57805b8281101561766957601380548061764357fe5b60019003818190600052602060002001600061765f9190617ed6565b9055600101617630565b505b600081831061767a578161767c565b825b905060005b8181101561779b576177396013828154811061769957fe5b600091825260209182902001805460408051601f60026000196101006001871615020190941693909304928301859004850281018501909152818152928301828280156177275780601f106176fc57610100808354040283529160200191617727565b820191906000526020600020905b81548152906001019060200180831161770a57829003601f168201915b5050505050600b838154811061628d57fe5b61779357600b818154811061774a57fe5b90600052602060002090601602016002016013828154811061776857fe5b906000526020600020019080546001816001161561010002031660029004617791929190617f3a565b505b600101617681565b5082821115610e9257825b82811015613d8e576013600b82815481106177bd57fe5b60009182526020808320845460018082018755958552919093206016929092029092016002908101805461780595939094019390926000199082161561010002011604617f3a565b506001016177a6565b600081848411156178325760405162461bcd60e51b8152600401610e72919061873a565b505050900390565b6000818361785b5760405162461bcd60e51b8152600401610e72919061873a565b50600083858161786757fe5b0495945050505050565b805160009061788257506000611d5a565b6020820151805160001a9060c08210156178a157600092505050611d5a565b5060019392505050565b8051600090811a60808110156178c5576000915050611d5a565b60b88110806178e0575060c081108015906178e0575060f881105b156178ef576001915050611d5a565b60c08110156179035760b519019050611d5a565b60f519019050611d5a565b80516000908190811a608081101561792957600191506179e8565b60b881101561793e57607e19810191506179e8565b60c081101561798f57600060b78203600186019550806020036101000a8651049150600181018201935050808310156179895760405162461bcd60e51b8152600401610e7290618e70565b506179e8565b60f88110156179a45760be19810191506179e8565b600060f78203600186019550806020036101000a8651049150600181018201935050808310156179e65760405162461bcd60e51b8152600401610e7290618e70565b505b5092915050565b8051600090617a0057506000611d5a565b60008090506000617a1484602001516178ab565b602085015185519181019250015b80821015617a4257617a338261790e565b82019150826001019250617a22565b50909392505050565b8051600090601514617a5c57600080fd5b611e0a82616d0e565b8051606090617a7357600080fd5b6000617a8283602001516178ab565b83516040805191839003808352601f19601f8201168301602001909152919250606090828015617ab9576020820181803683370190505b5090506000816020019050616777848760200151018285617d5c565b604080516020808252818301909252606091829190602082018180368337505050602081018490529050600067ffffffffffffffff198416617b1957506018617b3d565b6fffffffffffffffffffffffffffffffff198416617b3957506010617b3d565b5060005b6020811015617b7357818181518110617b5257fe5b01602001516001600160f81b03191615617b6b57617b73565b600101617b3d565b60008160200390506060816040519080825280601f01601f191660200182016040528015617ba8576020820181803683370190505b5080830196909652508452509192915050565b606081516001148015617bed5750607f60f81b82600081518110617bdb57fe5b01602001516001600160f81b03191611155b15617bf9575080611d5a565b611e0a617c0b8351608060ff16617c8a565b835b6060806040519050835180825260208201818101602087015b81831015617c3e578051835260209283019201617c26565b50855184518101855292509050808201602086015b81831015617c6b578051835260209283019201617c53565b508651929092011591909101601f01601f191660405250905092915050565b6060680100000000000000008310617cb45760405162461bcd60e51b8152600401610e7290618baa565b60408051600180825281830190925260609160208201818036833701905050905060378411617d0e5782840160f81b81600081518110617cf057fe5b60200101906001600160f81b031916908160001a9053509050611e0a565b6060617d1985617ad5565b90508381510160370160f81b82600081518110617d3257fe5b60200101906001600160f81b031916908160001a905350617d538282617c0d565b95945050505050565b80617d6657610e92565b5b60208110617d86578251825260209283019290910190601f1901617d67565b915181516020939093036101000a6000190180199091169216919091179052565b60405180608001604052806000815260200160001515815260200160608152602001617dd1618002565b905290565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10617e1757805160ff1916838001178555617e44565b82800160010185558215617e44579182015b82811115617e44578251825591602001919060010190617e29565b50613472929150618021565b8260138101928215617e445791602002820182811115617e44578251825591602001919060010190617e29565b6040518060600160405280600060ff16815260200160608152602001606081525090565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a081019190915290565b50805460018160011615610100020316600290046000825580601f10617efc5750611f72565b601f016020900490600052602060002090810190611f729190618021565b6040518060400160405280617f2d617fe8565b8152602001600081525090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10617f735780548555617e44565b82800160010185558215617e4457600052602060002091601f016020900482015b82811115617e44578254825591600101919060010190617f94565b8260138101928215617e445791820182811115617e44578254825591600101919060010190617f94565b50611f72906013810190618021565b604051806040016040528060008152602001600081525090565b6040518061026001604052806013906020820280368337509192915050565b61341091905b808211156134725760008155600101618027565b8035611e0a8161951b565b60008083601f840112618057578182fd5b5081356001600160401b0381111561806d578182fd5b6020830191508360208083028501011115615db557600080fd5b6000601f8381840112618098578182fd5b82356180ab6180a6826194d0565b6194aa565b818152925060208084019085810160005b8481101561813d578135880189603f8201126180d757600080fd5b838101356001600160401b038111156180ef57600080fd5b618100818901601f191686016194aa565b81815260408c8184860101111561811657600080fd5b828185018884013750600091810186019190915285525092820192908201906001016180bc565b50505050505092915050565b600082601f830112618159578081fd5b81356181676180a6826194d0565b81815291506020808301908481018184028601820187101561818857600080fd5b6000805b8581101561813d5782356001600160401b03811681146181aa578283fd5b8552938301939183019160010161818c565b60008083601f8401126181cd578182fd5b5081356001600160401b038111156181e3578182fd5b602083019150836020828501011115615db557600080fd5b60006020828403121561820c578081fd5b813561119d8161951b565b600060208284031215618228578081fd5b815161119d8161951b565b60008060008060408587031215618248578283fd5b84356001600160401b038082111561825e578485fd5b61826a88838901618046565b90965094506020870135915080821115618282578384fd5b5061828f87828801618046565b95989497509550505050565b6000806000606084860312156182af578283fd5b83356001600160401b03808211156182c5578485fd5b81860187601f8201126182d6578586fd5b803592506182e66180a6846194d0565b80848252602080830192508084018b82838902870101111561830657898afd5b8994505b868510156183305761831c8c8261803b565b84526001949094019392810192810161830a565b509097508801359350505080821115618347578384fd5b61835387838801618149565b93506040860135915080821115618368578283fd5b5061837586828701618087565b9150509250925092565b600060208284031215618390578081fd5b8151801515811461119d578182fd5b600080602083850312156183b1578182fd5b82356001600160401b038111156183c6578283fd5b6183d2858286016181bc565b90969095509350505050565b600080600080604085870312156183f3578384fd5b84356001600160401b0380821115618409578586fd5b618415888389016181bc565b9096509450602087013591508082111561842d578384fd5b5061828f878288016181bc565b60006020828403121561844b578081fd5b5035919050565b600060208284031215618463578081fd5b5051919050565b6000806040838503121561847c578182fd5b505080516020909101519092909150565b6000806000604084860312156184a1578081fd5b833560ff811681146184b1578182fd5b925060208401356001600160401b038111156184cb578182fd5b6184d7868287016181bc565b9497909650939450505050565b6000815180845260208085019450808401835b8381101561851c5781516001600160a01b0316875295820195908201906001016184f7565b509495945050505050565b60008284528282602086013780602084860101526020601f19601f85011685010190509392505050565b600081518084526185698160208601602086016194ef565b601f01601f19169290920160200192915050565b6000825161858f8184602087016194ef565b9190910192915050565b918252602082015260400190565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b03968716815294861660208601529290941660408401526001600160401b03166060830152911515608082015260a081019190915260c00190565b6001600160a01b0392909216825260ff16602082015260400190565b60006020825261119d60208301846184e4565b60006040825261865860408301856184e4565b602083820381850152818551808452828401915082838202850101838801865b838110156186a657601f19878403018552618694838351618551565b94860194925090850190600101618678565b50909998505050505050505050565b6000608082526186c860808301876184e4565b828103602084810191909152865180835287820192820190845b818110156186fe578451835293830193918301916001016186e2565b5050848103604086015261871281886184e4565b93505050506001600160401b038316606083015295945050505050565b901515815260200190565b60006020825261119d6020830184618551565b600060408252618761604083018688618527565b8281036020840152618774818587618527565b979650505050505050565b6020808252601c908201527f6c656e677468206f66206275726e526174696f206d69736d6174636800000000604082015260600190565b6020808252602d908201527f746865207475726e5465726d2073686f756c6420626520696e205b332c395d2060408201526c6f7220657175616c20746f203160981b606082015260800190565b60208082526026908201527f6c656e677468206f66206d61784e756d4f664d61696e7461696e696e67206d696040820152650e6dac2e8c6d60d31b606082015260800190565b6020808252601b908201527f6261746368207472616e736665722072657475726e2066616c73650000000000604082015260600190565b6020808252602c908201527f6c656e677468206f66206d61784e756d4f66576f726b696e6743616e6469646160408201526b0e8cae640dad2e6dac2e8c6d60a31b606082015260800190565b60208082526025908201527f6c656e677468206f66206d61696e7461696e536c6173685363616c65206d69736040820152640dac2e8c6d60db1b606082015260800190565b6020808252818101527f6c656e677468206f66206e756d4f66436162696e657473206d69736d61746368604082015260600190565b60208082526019908201527f74686520636f6e7472616374206e6f7420696e69742079657400000000000000604082015260600190565b6020808252601f908201527f6f6e6c7920736c617368206f72207374616b6548756220636f6e747261637400604082015260600190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b60208082526063908201527f7468652073797374656d52657761726442617365526174696f20706c7573206260408201527f75726e526174696f20616e642073797374656d526577617264416e74694d455660608201527f526174696f206d757374206265206e6f2067726561746572207468616e20313060808201526203030360ec1b60a082015260c00190565b60208082526028908201527f746865206e756d4f66436162696e657473206d75737420626520677265617465604082015267072207468616e20360c41b606082015260800190565b60208082526039908201527f746865206e756d4f66436162696e657473206d757374206265206c657373207460408201527f68616e204d41585f4e554d5f4f465f56414c494441544f525300000000000000606082015260800190565b60208082526029908201527f746865206e756d626572206f662076616c696461746f727320657863656564206040820152681d1a19481b1a5b5a5d60ba1b606082015260800190565b60208082526022908201527f63616e206e6f7420646f207468697320747769636520696e206f6e6520626c6f604082015261636b60f01b606082015260800190565b6020808252600e908201526d696e70757420746f6f206c6f6e6760901b604082015260600190565b60208082526037908201527f746865206d61784e756d4f664d61696e7461696e696e67206d7573742062652060408201527f6c657373207468616e206e756d4f66436162696e657473000000000000000000606082015260800190565b6020808252602b908201527f6475706c696361746520636f6e73656e7375732061646472657373206f66207660408201526a185b1a59185d1bdc94d95d60aa1b606082015260800190565b6020808252601b908201527f6c656e677468206f66207475726e5465726d206d69736d617463680000000000604082015260600190565b60208082526063908201527f746865206275726e526174696f20706c75732073797374656d5265776172644260408201527f617365526174696f20616e642073797374656d526577617264416e74694d455660608201527f526174696f206d757374206265206e6f2067726561746572207468616e20313060808201526203030360ec1b60a082015260c00190565b6020808252602b908201527f6c656e677468206f662073797374656d526577617264416e74694d455652617460408201526a0d2de40dad2e6dac2e8c6d60ab1b606082015260800190565b60208082526027908201527f7468652065787069726554696d655365636f6e64476170206973206f7574206f604082015266662072616e676560c81b606082015260800190565b6020808252601590820152746465706f7369742076616c7565206973207a65726f60581b604082015260600190565b60208082526049908201527f746865206d61784e756d4f66576f726b696e6743616e64696461746573206d7560408201527f7374206265206e6f742067726561746572207468616e206d61784e756d4f6643606082015268616e6469646174657360b81b608082015260a00190565b6020808252601190820152706164646974696f6e206f766572666c6f7760781b604082015260600190565b60208082526063908201527f7468652073797374656d526577617264416e74694d4556526174696f20706c7560408201527f73206275726e526174696f20616e642073797374656d5265776172644261736560608201527f526174696f206d757374206265206e6f2067726561746572207468616e20313060808201526203030360ec1b60a082015260c00190565b60208082526023908201527f63616e206e6f7420656e7465722054656d706f72617279204d61696e74656e616040820152626e636560e81b606082015260800190565b60208082526025908201527f6c656e677468206f66206a61696c2076616c696461746f7273206d757374206260408201526465206f6e6560d81b606082015260800190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b6020808252601490820152736761737072696365206973206e6f74207a65726f60601b604082015260600190565b6020808252602e908201527f746865206d6573736167652073656e646572206d75737420626520676f76657260408201526d1b985b98d94818dbdb9d1c9858dd60921b606082015260800190565b60208082526025908201527f6c656e677468206f66206d61784e756d4f6643616e64696461746573206d69736040820152640dac2e8c6d60db1b606082015260800190565b6020808252601290820152716e6f7420696e206d61696e74656e616e636560701b604082015260600190565b60208082526021908201527f666565206973206c6172676572207468616e2044555354595f494e434f4d494e6040820152604760f81b606082015260800190565b60208082526019908201527f74686520636f6e747261637420616c726561647920696e697400000000000000604082015260600190565b6020808252601a908201527f6c656e677468206973206c657373207468616e206f6666736574000000000000604082015260600190565b60208082526026908201527f6c656e677468206f662065787069726554696d655365636f6e64476170206d696040820152650e6dac2e8c6d60d31b606082015260800190565b60208082526017908201527f6f6e6c792063757272656e742076616c696461746f7273000000000000000000604082015260600190565b60208082526021908201527f6661696c656420746f20706172736520696e69742076616c696461746f7253656040820152601d60fa1b606082015260800190565b6020808252602f908201527f746865206d6573736167652073656e646572206d7573742062652063726f737360408201526e0818da185a5b8818dbdb9d1c9858dd608a1b606082015260800190565b6020808252602d908201527f746865206d6573736167652073656e646572206d75737420626520746865206260408201526c3637b1b590383937b23ab1b2b960991b606082015260800190565b60208082526028908201527f6c656e677468206f662073797374656d52657761726442617365526174696f206040820152670dad2e6dac2e8c6d60c31b606082015260800190565b6020808252603e908201527f746865206d61696e7461696e536c6173685363616c65206d757374206265206760408201527f726561746572207468616e203020616e64206c657373207468616e2031300000606082015260800190565b6020808252600d908201526c756e6b6e6f776e20706172616d60981b604082015260600190565b60208082526029908201527f746865206d6573736167652073656e646572206d75737420626520736c6173686040820152680818dbdb9d1c9858dd60ba1b606082015260800190565b6020808252601f908201527f746865206d73672073656e646572206d757374206265207374616b6548756200604082015260600190565b61ffff91909116815260200190565b90815260200190565b6000848252831515602083015260606040830152617d536060830184618551565b63ffffffff91909116815260200190565b60ff91909116815260200190565b600060ff8516825260406020830152617d53604083018486618527565b6040518181016001600160401b03811182821017156194c857600080fd5b604052919050565b60006001600160401b038211156194e5578081fd5b5060209081020190565b60005b8381101561950a5781810151838201526020016194f2565b83811115613d8e5750506000910152565b6001600160a01b0381168114611f7257600080fdfe70e72399380dcfb0338abc03dc8d47f9f470ada8e769c9a78d644ea97385ecb2f9026180f9025df87794bcdd0d2cda5f6423e57b6a4dcd75decbe31aecf094bcdd0d2cda5f6423e57b6a4dcd75decbe31aecf094bcdd0d2cda5f6423e57b6a4dcd75decbe31aecf08601d1a94a2000b0b3baf71dc234890671fc3292afde45e20ce83cb8cd65c614be9fa29932c34051a75cbc1e25b968cc72142c91a56b521af87794bbd1acc20bd8304309d31d8fd235210d0efc049d94bbd1acc20bd8304309d31d8fd235210d0efc049d94bbd1acc20bd8304309d31d8fd235210d0efc049d8601d1a94a2000b08f124155128c0f4ff8c2b0803c3390bf672e6d26480af4f9648b8d2214d642a6dc2c25c9a37ccc576766e5838d71f52af877945e2a531a825d8b61bcc305a35a7433e9a8920f0f945e2a531a825d8b61bcc305a35a7433e9a8920f0f945e2a531a825d8b61bcc305a35a7433e9a8920f0f8601d1a94a2000b0a42d8fd0af73dc1c2a0238545985c0dba04fd57bc2f66573c86cfbb9f2a3cd5c10d6ddb6a588500ef80f2f5b56b8a21bf877943ad55d1d552cc55dee90c0faf0335383b2e6c5ce943ad55d1d552cc55dee90c0faf0335383b2e6c5ce943ad55d1d552cc55dee90c0faf0335383b2e6c5ce8601d1a94a2000b0ae5844366094dca50e2769381b1f4bd5b7b40545655322395c25787ad5992a17324cc466a0ed1b1d91433f3299f5fbe4f87794fe02c8ff2374583c47b1d62fdf3e1b72c20ebe2994fe02c8ff2374583c47b1d62fdf3e1b72c20ebe2994fe02c8ff2374583c47b1d62fdf3e1b72c20ebe298601d1a94a2000b08aa632a469439c7ba660bc4419eba498f9ff489b62d53779d257b964bca8af2abf5f797ef746d1e12c031e3640c8b8fb0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db90175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01dbb0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01dbaa164736f6c6343000604000a \ No newline at end of file diff --git a/core/systemcontracts/bohr/types.go b/core/systemcontracts/bohr/types.go new file mode 100644 index 0000000000..16264ee30f --- /dev/null +++ b/core/systemcontracts/bohr/types.go @@ -0,0 +1,21 @@ +package bohr + +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..ed026cad8d 100644 --- a/core/systemcontracts/upgrade.go +++ b/core/systemcontracts/upgrade.go @@ -10,6 +10,7 @@ import ( "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" + "github.com/ethereum/go-ethereum/core/systemcontracts/bohr" "github.com/ethereum/go-ethereum/core/systemcontracts/bruno" "github.com/ethereum/go-ethereum/core/systemcontracts/euler" "github.com/ethereum/go-ethereum/core/systemcontracts/feynman" @@ -75,6 +76,8 @@ var ( feynmanUpgrade = make(map[string]*Upgrade) feynmanFixUpgrade = make(map[string]*Upgrade) + + bohrUpgrade = make(map[string]*Upgrade) ) func init() { @@ -701,6 +704,17 @@ func init() { }, }, } + + bohrUpgrade[rialtoNet] = &Upgrade{ + UpgradeName: "bohr", + Configs: []*UpgradeConfig{ + { + ContractAddr: common.HexToAddress(ValidatorContract), + CommitUrl: "https://github.com/NathanBSC/bsc-genesis-contract/commit/a977759455de71f40a3c86943205121f6efc1b71", + Code: bohr.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.IsOnBohr(blockNumber, lastBlockTime, blockTime) { + applySystemContractUpgrade(bohrUpgrade[network], blockNumber, statedb, logger) + } + /* apply other upgrades */ diff --git a/core/vote/vote_manager.go b/core/vote/vote_manager.go index a7eaf10b09..8f6bf1fc33 100644 --- a/core/vote/vote_manager.go +++ b/core/vote/vote_manager.go @@ -3,6 +3,7 @@ package vote import ( "bytes" "fmt" + "math/big" "sync" "github.com/ethereum/go-ethereum/common" @@ -17,7 +18,13 @@ import ( const blocksNumberSinceMining = 5 // the number of blocks need to wait before voting, counting from the validator begin to mine +var diffInTurn = big.NewInt(2) // Block difficulty for in-turn signatures var votesManagerCounter = metrics.NewRegisteredCounter("votesManager/local", nil) +var notJustified = metrics.NewRegisteredCounter("votesManager/notJustified", nil) +var inTurnJustified = metrics.NewRegisteredCounter("votesManager/inTurnJustified", nil) +var notInTurnJustified = metrics.NewRegisteredCounter("votesManager/notInTurnJustified", nil) +var continuousJustified = metrics.NewRegisteredCounter("votesManager/continuousJustified", nil) +var notContinuousJustified = metrics.NewRegisteredCounter("votesManager/notContinuousJustified", nil) // Backend wraps all methods required for voting. type Backend interface { @@ -144,7 +151,7 @@ func (voteManager *VoteManager) loop() { func(bLSPublicKey *types.BLSPublicKey) bool { return bytes.Equal(voteManager.signer.PubKey[:], bLSPublicKey[:]) }) { - log.Debug("cur validator is not within the validatorSet at curHead") + log.Debug("local validator with voteKey is not within the validatorSet at curHead") continue } @@ -191,6 +198,36 @@ func (voteManager *VoteManager) loop() { voteManager.pool.PutVote(voteMessage) votesManagerCounter.Inc(1) } + + // check the latest justified block, which indicating the stability of the network + curJustifiedNumber, _, err := voteManager.engine.GetJustifiedNumberAndHash(voteManager.chain, []*types.Header{curHead}) + if err == nil && curJustifiedNumber != 0 { + if curJustifiedNumber+1 != curHead.Number.Uint64() { + log.Debug("not justified", "blockNumber", curHead.Number.Uint64()-1) + notJustified.Inc(1) + } else { + parent := voteManager.chain.GetHeaderByHash(curHead.ParentHash) + if parent != nil { + if parent.Difficulty.Cmp(diffInTurn) == 0 { + inTurnJustified.Inc(1) + } else { + log.Debug("not in turn block justified", "blockNumber", parent.Number.Int64(), "blockHash", parent.Hash()) + notInTurnJustified.Inc(1) + } + + lastJustifiedNumber, _, err := voteManager.engine.GetJustifiedNumberAndHash(voteManager.chain, []*types.Header{parent}) + if err == nil { + if lastJustifiedNumber == 0 || lastJustifiedNumber+1 == curJustifiedNumber { + continuousJustified.Inc(1) + } else { + log.Debug("not continuous block justified", "lastJustified", lastJustifiedNumber, "curJustified", curJustifiedNumber) + notContinuousJustified.Inc(1) + } + } + } + } + } + case event := <-voteManager.syncVoteCh: voteMessage := event.Vote if voteManager.eth.IsMining() || !bytes.Equal(voteManager.signer.PubKey[:], voteMessage.VoteAddress[:]) { diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index e31cee15ec..188f99fb3a 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -870,7 +870,10 @@ func (s *BlockChainAPI) GetFinalizedHeader(ctx context.Context, probabilisticFin return nil, fmt.Errorf("%d out of range [2,21]", probabilisticFinalized) } - var err error + currentTurnTerm, err := s.b.Engine().CurrentTurnTerm(s.b.Chain()) + if err != nil { // impossible + return nil, err + } fastFinalizedHeader, err := s.b.HeaderByNumber(ctx, rpc.FinalizedBlockNumber) if err != nil { // impossible return nil, err @@ -879,7 +882,7 @@ func (s *BlockChainAPI) GetFinalizedHeader(ctx context.Context, probabilisticFin if err != nil { // impossible return nil, err } - finalizedBlockNumber := max(fastFinalizedHeader.Number.Int64(), latestHeader.Number.Int64()-probabilisticFinalized) + finalizedBlockNumber := max(fastFinalizedHeader.Number.Int64(), latestHeader.Number.Int64()-probabilisticFinalized*int64((*currentTurnTerm))) return s.GetHeaderByNumber(ctx, rpc.BlockNumber(finalizedBlockNumber)) } @@ -894,7 +897,10 @@ func (s *BlockChainAPI) GetFinalizedBlock(ctx context.Context, probabilisticFina return nil, fmt.Errorf("%d out of range [2,21]", probabilisticFinalized) } - var err error + currentTurnTerm, err := s.b.Engine().CurrentTurnTerm(s.b.Chain()) + if err != nil { // impossible + return nil, err + } fastFinalizedHeader, err := s.b.HeaderByNumber(ctx, rpc.FinalizedBlockNumber) if err != nil { // impossible return nil, err @@ -903,7 +909,7 @@ func (s *BlockChainAPI) GetFinalizedBlock(ctx context.Context, probabilisticFina if err != nil { // impossible return nil, err } - finalizedBlockNumber := max(fastFinalizedHeader.Number.Int64(), latestHeader.Number.Int64()-probabilisticFinalized) + finalizedBlockNumber := max(fastFinalizedHeader.Number.Int64(), latestHeader.Number.Int64()-probabilisticFinalized*int64((*currentTurnTerm))) return s.GetBlockByNumber(ctx, rpc.BlockNumber(finalizedBlockNumber), fullTx) } diff --git a/params/protocol_params.go b/params/protocol_params.go index 2ecb92bc61..a6c08a9e42 100644 --- a/params/protocol_params.go +++ b/params/protocol_params.go @@ -192,6 +192,7 @@ var ( MinBlocksForBlobRequests uint64 = 524288 // it keeps blob data available for ~18.2 days in local, ref: https://github.com/bnb-chain/BEPs/blob/master/BEPs/BEP-336.md#51-parameters. DefaultExtraReserveForBlobRequests uint64 = 1 * (24 * 3600) / 3 // it adds more time for expired blobs for some request cases, like expiry blob when remote peer is syncing, default 1 day. BreatheBlockInterval uint64 = 86400 // Controls the interval for updateValidatorSetV2 + UseRandTurnTerm bool = false // Use random values to test switching turn terms ) // Gas discount table for BLS12-381 G1 and G2 multi exponentiation operations