diff --git a/CHANGELOG.md b/CHANGELOG.md index 62341d56d3..b524e23341 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,47 @@ # Changelog +## v1.5.13 +### FEATURE +[\#3019](https://github.com/bnb-chain/bsc/pull/3019) BEP-524: Short Block Interval Phase Two: 0.75 seconds +[\#3044](https://github.com/bnb-chain/bsc/pull/3044) params: double FullImmutabilityThreshold for BEP-520 & BEP-524 +[\#3045](https://github.com/bnb-chain/bsc/pull/3045) Feature: StakeHub Contract Interface Implementation +[\#3040](https://github.com/bnb-chain/bsc/pull/3040) bsc: add new block fetching mechanism +[\#3043](https://github.com/bnb-chain/bsc/pull/3043) p2p: support new msg broadcast features +[\#3070](https://github.com/bnb-chain/bsc/pull/3070) chore: renaming for evn and some optmization +[\#3073](https://github.com/bnb-chain/bsc/pull/3073) evn: add support for node id removal +[\#3072](https://github.com/bnb-chain/bsc/pull/3072) config: support more evn configuration in tool +[\#3075](https://github.com/bnb-chain/bsc/pull/3075) config: apply two default miner option +[\#3083](https://github.com/bnb-chain/bsc/pull/3083) evn: improve node ID management with better error handling +[\#3084](https://github.com/bnb-chain/bsc/pull/3084) metrics: add more monitor metrics for EVN +[\#3087](https://github.com/bnb-chain/bsc/pull/3087) bsc2: fix block sidecar fetching issue +[\#3090](https://github.com/bnb-chain/bsc/pull/3090) chore: update maxwell contrats addresses +[\#3091](https://github.com/bnb-chain/bsc/pull/3091) chore: fix several occasional issues for EVN +[\#3049](https://github.com/bnb-chain/bsc/pull/3049) upstream: pick bugfix and feature from latest geth v1.5.9 +[\#3096](https://github.com/bnb-chain/bsc/pull/3096) config: update BSC Testnet hardfork time: Maxwell + +### BUGFIX +[\#3050](https://github.com/bnb-chain/bsc/pull/3050) miner: fix memory leak caused by no discard env +[\#3061](https://github.com/bnb-chain/bsc/pull/3061) p2p: fix bscExt checking logic + +### IMPROVEMENT +[\#3034](https://github.com/bnb-chain/bsc/pull/3034) miner: optimize clear up logic for envs +[\#3039](https://github.com/bnb-chain/bsc/pull/3039) Revert "miner: limit block size to eth protocol msg size (#2696)" +[\#3041](https://github.com/bnb-chain/bsc/pull/3041) feat: add json-rpc-api.md +[\#3057](https://github.com/bnb-chain/bsc/pull/3057) eth/protocols/bsc: adjust vote reception limit +[\#3067](https://github.com/bnb-chain/bsc/pull/3067) ethclient/gethclient: add deduplication and max keys limit to GetProof +[\#3063](https://github.com/bnb-chain/bsc/pull/3063) rpc: add method name length limit and configurable message size limit +[\#3077](https://github.com/bnb-chain/bsc/pull/3077) performance: track large tx execution cost +[\#3074](https://github.com/bnb-chain/bsc/pull/3074) jsutils: add tool GetLargeTxs +[\#3082](https://github.com/bnb-chain/bsc/pull/3082) metrics: optimize mev metrics +[\#3081](https://github.com/bnb-chain/bsc/pull/3081) miner: reset recommit timer on new block +[\#3062](https://github.com/bnb-chain/bsc/pull/3062) refactor: use slices.Contains to simplify code +[\#3088](https://github.com/bnb-chain/bsc/pull/3088) core/vote: change waiting blocks for voting since start mining +[\#3089](https://github.com/bnb-chain/bsc/pull/3089) core/systemcontracts: remove lorentz/rialto +[\#3085](https://github.com/bnb-chain/bsc/pull/0000) miner: fix goroutine leak + +## v1.5.12 +### BUGFIX +[\#3057](https://github.com/bnb-chain/bsc/pull/3057) eth/protocols/bsc: adjust vote reception limit + ## v1.5.11 ### FEATURE [\#3008](https://github.com/bnb-chain/bsc/pull/3008) params: add MaxwellTime diff --git a/README.md b/README.md index 54905b2834..5915fc4548 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ The goal of BNB Smart Chain is to bring programmability and interoperability to BNB Beacon Chain. In order to embrace the existing popular community and advanced technology, it will bring huge benefits by staying compatible with all the existing smart contracts on Ethereum and Ethereum tooling. And to achieve that, the easiest solution is to develop based on go-ethereum fork, as we respect the great work of Ethereum very much. -BNB Smart Chain starts its development based on go-ethereum fork. So you may see many toolings, binaries and also docs are based on Ethereum ones, such as the name “geth”. +BNB Smart Chain starts its development based on go-ethereum fork. So you may see many toolings, binaries and also docs are based on Ethereum ones, such as the name "geth". [![API Reference]( https://pkg.go.dev/badge/github.com/ethereum/go-ethereum @@ -194,8 +194,8 @@ $ geth --your-favourite-flags dumpconfig As a developer, sooner rather than later you'll want to start interacting with `geth` and the BSC network via your own programs and not manually through the console. To aid -this, `geth` has built-in support for a JSON-RPC based APIs ([standard APIs](https://ethereum.github.io/execution-apis/api-documentation/) -and [`geth` specific APIs](https://geth.ethereum.org/docs/interacting-with-geth/rpc)). +this, `geth` has built-in support for a JSON-RPC based APIs ([standard APIs](https://ethereum.github.io/execution-apis/api-documentation/), +[`geth` specific APIs](https://geth.ethereum.org/docs/interacting-with-geth/rpc), and [BSC's JSON-RPC API Reference](rpc/json-rpc-api.md)). These can be exposed via HTTP, WebSockets and IPC (UNIX sockets on UNIX based platforms, and named pipes on Windows). diff --git a/accounts/abi/argument.go b/accounts/abi/argument.go index 227a088b7d..e48f763890 100644 --- a/accounts/abi/argument.go +++ b/accounts/abi/argument.go @@ -77,18 +77,18 @@ func (arguments Arguments) isTuple() bool { } // Unpack performs the operation hexdata -> Go format. -func (arguments Arguments) Unpack(data []byte) ([]interface{}, error) { +func (arguments Arguments) Unpack(data []byte) ([]any, error) { if len(data) == 0 { if len(arguments.NonIndexed()) != 0 { return nil, errors.New("abi: attempting to unmarshal an empty string while arguments are expected") } - return make([]interface{}, 0), nil + return make([]any, 0), nil } return arguments.UnpackValues(data) } // UnpackIntoMap performs the operation hexdata -> mapping of argument name to argument value. -func (arguments Arguments) UnpackIntoMap(v map[string]interface{}, data []byte) error { +func (arguments Arguments) UnpackIntoMap(v map[string]any, data []byte) error { // Make sure map is not nil if v == nil { return errors.New("abi: cannot unpack into a nil map") @@ -110,7 +110,7 @@ func (arguments Arguments) UnpackIntoMap(v map[string]interface{}, data []byte) } // Copy performs the operation go format -> provided struct. -func (arguments Arguments) Copy(v interface{}, values []interface{}) error { +func (arguments Arguments) Copy(v any, values []any) error { // make sure the passed value is arguments pointer if reflect.Ptr != reflect.ValueOf(v).Kind() { return fmt.Errorf("abi: Unpack(non-pointer %T)", v) @@ -128,7 +128,7 @@ func (arguments Arguments) Copy(v interface{}, values []interface{}) error { } // copyAtomic copies ( hexdata -> go ) a single value -func (arguments Arguments) copyAtomic(v interface{}, marshalledValues interface{}) error { +func (arguments Arguments) copyAtomic(v any, marshalledValues any) error { dst := reflect.ValueOf(v).Elem() src := reflect.ValueOf(marshalledValues) @@ -139,7 +139,7 @@ func (arguments Arguments) copyAtomic(v interface{}, marshalledValues interface{ } // copyTuple copies a batch of values from marshalledValues to v. -func (arguments Arguments) copyTuple(v interface{}, marshalledValues []interface{}) error { +func (arguments Arguments) copyTuple(v any, marshalledValues []any) error { value := reflect.ValueOf(v).Elem() nonIndexedArgs := arguments.NonIndexed() @@ -181,11 +181,17 @@ func (arguments Arguments) copyTuple(v interface{}, marshalledValues []interface // UnpackValues can be used to unpack ABI-encoded hexdata according to the ABI-specification, // without supplying a struct to unpack into. Instead, this method returns a list containing the // values. An atomic argument will be a list with one element. -func (arguments Arguments) UnpackValues(data []byte) ([]interface{}, error) { - nonIndexedArgs := arguments.NonIndexed() - retval := make([]interface{}, 0, len(nonIndexedArgs)) - virtualArgs := 0 - for index, arg := range nonIndexedArgs { +func (arguments Arguments) UnpackValues(data []byte) ([]any, error) { + var ( + retval = make([]any, 0) + virtualArgs = 0 + index = 0 + ) + + for _, arg := range arguments { + if arg.Indexed { + continue + } marshalledValue, err := toGoType((index+virtualArgs)*32, arg.Type, data) if err != nil { return nil, err @@ -208,18 +214,19 @@ func (arguments Arguments) UnpackValues(data []byte) ([]interface{}, error) { virtualArgs += getTypeSize(arg.Type)/32 - 1 } retval = append(retval, marshalledValue) + index++ } return retval, nil } // PackValues performs the operation Go format -> Hexdata. // It is the semantic opposite of UnpackValues. -func (arguments Arguments) PackValues(args []interface{}) ([]byte, error) { +func (arguments Arguments) PackValues(args []any) ([]byte, error) { return arguments.Pack(args...) } // Pack performs the operation Go format -> Hexdata. -func (arguments Arguments) Pack(args ...interface{}) ([]byte, error) { +func (arguments Arguments) Pack(args ...any) ([]byte, error) { // Make sure arguments match up and pack them abiArgs := arguments if len(args) != len(abiArgs) { diff --git a/accounts/abi/bind/base.go b/accounts/abi/bind/base.go index 0504089c71..68d3681c32 100644 --- a/accounts/abi/bind/base.go +++ b/accounts/abi/bind/base.go @@ -366,13 +366,14 @@ func (c *BoundContract) estimateGasLimit(opts *TransactOpts, contract *common.Ad } } msg := ethereum.CallMsg{ - From: opts.From, - To: contract, - GasPrice: gasPrice, - GasTipCap: gasTipCap, - GasFeeCap: gasFeeCap, - Value: value, - Data: input, + From: opts.From, + To: contract, + GasPrice: gasPrice, + GasTipCap: gasTipCap, + GasFeeCap: gasFeeCap, + Value: value, + Data: input, + AccessList: opts.AccessList, } return c.transactor.EstimateGas(ensureContext(opts.Context), msg) } diff --git a/accounts/abi/unpack_test.go b/accounts/abi/unpack_test.go index 7df7b9c403..74db298b3f 100644 --- a/accounts/abi/unpack_test.go +++ b/accounts/abi/unpack_test.go @@ -31,6 +31,46 @@ import ( "github.com/stretchr/testify/require" ) +func BenchmarkUnpack(b *testing.B) { + testCases := []struct { + def string + packed string + }{ + { + def: `[{"type": "uint32"}]`, + packed: "0000000000000000000000000000000000000000000000000000000000000001", + }, + { + def: `[{"type": "uint32[]"}]`, + packed: "0000000000000000000000000000000000000000000000000000000000000020" + + "0000000000000000000000000000000000000000000000000000000000000002" + + "0000000000000000000000000000000000000000000000000000000000000001" + + "0000000000000000000000000000000000000000000000000000000000000002", + }, + } + for i, test := range testCases { + b.Run(strconv.Itoa(i), func(b *testing.B) { + def := fmt.Sprintf(`[{ "name" : "method", "type": "function", "outputs": %s}]`, test.def) + abi, err := JSON(strings.NewReader(def)) + if err != nil { + b.Fatalf("invalid ABI definition %s: %v", def, err) + } + encb, err := hex.DecodeString(test.packed) + if err != nil { + b.Fatalf("invalid hex %s: %v", test.packed, err) + } + + b.ResetTimer() + + var result any + for range b.N { + result, _ = abi.Unpack("method", encb) + } + _ = result + }) + } +} + // TestUnpack tests the general pack/unpack tests in packing_test.go func TestUnpack(t *testing.T) { t.Parallel() diff --git a/cmd/geth/chaincmd.go b/cmd/geth/chaincmd.go index 5ea3fa7277..613ac253c8 100644 --- a/cmd/geth/chaincmd.go +++ b/cmd/geth/chaincmd.go @@ -84,6 +84,16 @@ It expects the genesis file as argument.`, utils.InitNetworkPort, utils.InitNetworkSize, utils.InitNetworkIps, + utils.InitSentryNodeSize, + utils.InitSentryNodeIPs, + utils.InitSentryNodePorts, + utils.InitFullNodeSize, + utils.InitFullNodeIPs, + utils.InitFullNodePorts, + utils.InitEVNSentryWhitelist, + utils.InitEVNValidatorWhitelist, + utils.InitEVNSentryRegister, + utils.InitEVNValidatorRegister, configFileFlag, }, Category: "BLOCKCHAIN COMMANDS", @@ -231,6 +241,11 @@ Therefore, you must specify the blockNumber or blockHash that locates in diffLay } ) +const ( + DefaultSentryP2PPort = 30411 + DefaultFullNodeP2PPort = 30511 +) + // initGenesis will initialise the given JSON format genesis file and writes it as // the zero'd block (i.e. genesis) or will fail hard if it can't succeed. func initGenesis(ctx *cli.Context) error { @@ -327,6 +342,38 @@ func parseIps(ipStr string, size int) ([]string, error) { return ips, nil } +func parsePorts(portStr string, defaultPort int, size int) ([]int, error) { + var ports []int + if strings.Contains(portStr, ",") { + portParts := strings.Split(portStr, ",") + if len(portParts) != size { + return nil, errors.New("mismatch of size and length of ports") + } + for i := 0; i < size; i++ { + port, err := strconv.Atoi(portParts[i]) + if err != nil { + return nil, errors.New("invalid format of port") + } + ports[i] = port + } + } else if len(portStr) != 0 { + startPort, err := strconv.Atoi(portStr) + if err != nil { + return nil, errors.New("invalid format of port") + } + ports = make([]int, size) + for i := 0; i < size; i++ { + ports[i] = startPort + i + } + } else { + ports = make([]int, size) + for i := 0; i < size; i++ { + ports[i] = defaultPort + } + } + return ports, nil +} + func createPorts(ipStr string, port int, size int) []int { ports := make([]int, size) if len(ipStr) == 0 { // localhost , so different ports @@ -342,41 +389,23 @@ func createPorts(ipStr string, port int, size int) []int { } // Create config for node i in the cluster -func createNodeConfig(baseConfig gethConfig, enodes []*enode.Node, ip string, port int, size int, i int) gethConfig { +func createNodeConfig(baseConfig gethConfig, ip string, port int, enodes []*enode.Node, index int, staticConnect bool) gethConfig { baseConfig.Node.HTTPHost = ip baseConfig.Node.P2P.ListenAddr = fmt.Sprintf(":%d", port) - baseConfig.Node.P2P.BootstrapNodes = make([]*enode.Node, size-1) - // Set the P2P connections between this node and the other nodes - for j := 0; j < i; j++ { - baseConfig.Node.P2P.BootstrapNodes[j] = enodes[j] - } - for j := i + 1; j < size; j++ { - baseConfig.Node.P2P.BootstrapNodes[j-1] = enodes[j] + connectEnodes := make([]*enode.Node, 0, len(enodes)-1) + for j := 0; j < index; j++ { + connectEnodes = append(connectEnodes, enodes[j]) } - return baseConfig -} - -// Create configs for nodes in the cluster -func createNodeConfigs(baseConfig gethConfig, initDir string, ips []string, ports []int, size int) ([]gethConfig, error) { - // Create the nodes - enodes := make([]*enode.Node, size) - for i := 0; i < size; i++ { - nodeConfig := baseConfig.Node - nodeConfig.DataDir = path.Join(initDir, fmt.Sprintf("node%d", i)) - stack, err := node.New(&nodeConfig) - if err != nil { - return nil, err - } - pk := stack.Config().NodeKey() - enodes[i] = enode.NewV4(&pk.PublicKey, net.ParseIP(ips[i]), ports[i], ports[i]) + for j := index + 1; j < len(enodes); j++ { + connectEnodes = append(connectEnodes, enodes[j]) } - - // Create the configs - configs := make([]gethConfig, size) - for i := 0; i < size; i++ { - configs[i] = createNodeConfig(baseConfig, enodes, ips[i], ports[i], size, i) + // Set the P2P connections between this node and the other nodes + if staticConnect { + baseConfig.Node.P2P.StaticNodes = connectEnodes + } else { + baseConfig.Node.P2P.BootstrapNodes = connectEnodes } - return configs, nil + return baseConfig } // initNetwork will bootstrap and initialize a new genesis block, and nodekey, config files for network nodes @@ -429,38 +458,196 @@ func initNetwork(ctx *cli.Context) error { if err != nil { return err } + enableSentryNode := ctx.Int(utils.InitSentryNodeSize.Name) > 0 + var ( + sentryConfigs []gethConfig + sentryEnodes []*enode.Node + sentryNodeIDs []enode.ID + connectOneExtraEnodes bool + staticConnect bool + ) + if enableSentryNode { + sentryConfigs, sentryEnodes, err = createSentryNodeConfigs(ctx, config, initDir) + if err != nil { + utils.Fatalf("Failed to create sentry node configs: %v", err) + } + sentryNodeIDs = make([]enode.ID, len(sentryEnodes)) + for i := 0; i < len(sentryEnodes); i++ { + sentryNodeIDs[i] = sentryEnodes[i].ID() + } + connectOneExtraEnodes = true + staticConnect = true + } - configs, err := createNodeConfigs(config, initDir, ips, ports, size) + configs, enodes, err := createConfigs(config, initDir, "node", ips, ports, sentryEnodes, connectOneExtraEnodes, staticConnect) if err != nil { utils.Fatalf("Failed to create node configs: %v", err) } - for i := 0; i < size; i++ { - // Write config.toml - configBytes, err := tomlSettings.Marshal(configs[i]) + nodeIDs := make([]enode.ID, len(enodes)) + for i := 0; i < len(enodes); i++ { + nodeIDs[i] = enodes[i].ID() + } + // add more feature configs + if ctx.Bool(utils.InitEVNValidatorWhitelist.Name) { + for i := 0; i < size; i++ { + configs[i].Node.P2P.EVNNodeIdsWhitelist = nodeIDs + } + } + if ctx.Bool(utils.InitEVNValidatorRegister.Name) { + for i := 0; i < size; i++ { + configs[i].Eth.EVNNodeIDsToAdd = []enode.ID{nodeIDs[i]} + } + } + if enableSentryNode && ctx.Bool(utils.InitEVNSentryWhitelist.Name) { + for i := 0; i < len(sentryConfigs); i++ { + sentryConfigs[i].Node.P2P.EVNNodeIdsWhitelist = sentryNodeIDs + } + } + if enableSentryNode && ctx.Bool(utils.InitEVNSentryRegister.Name) { + for i := 0; i < size; i++ { + configs[i].Eth.EVNNodeIDsToAdd = append(configs[i].Eth.EVNNodeIDsToAdd, sentryNodeIDs[i]) + } + } + + // write node & sentry configs + for i, config := range configs { + err = writeConfig(inGenesisFile, config, path.Join(initDir, fmt.Sprintf("node%d", i))) if err != nil { return err } - configFile, err := os.OpenFile(path.Join(initDir, fmt.Sprintf("node%d", i), "config.toml"), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644) + } + for i, config := range sentryConfigs { + err = writeConfig(inGenesisFile, config, path.Join(initDir, fmt.Sprintf("sentry%d", i))) if err != nil { return err } - defer configFile.Close() - configFile.Write(configBytes) + } - // Write the input genesis.json to the node's directory - outGenesisFile, err := os.OpenFile(path.Join(initDir, fmt.Sprintf("node%d", i), "genesis.json"), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644) + if ctx.Int(utils.InitFullNodeSize.Name) > 0 { + var extraEnodes []*enode.Node + if enableSentryNode { + extraEnodes = sentryEnodes + } else { + extraEnodes = enodes + } + _, _, err := createAndSaveFullNodeConfigs(ctx, inGenesisFile, config, initDir, extraEnodes) if err != nil { - return err + utils.Fatalf("Failed to create full node configs: %v", err) } - _, err = inGenesisFile.Seek(0, io.SeekStart) + } + + return nil +} + +func createSentryNodeConfigs(ctx *cli.Context, baseConfig gethConfig, initDir string) ([]gethConfig, []*enode.Node, error) { + size := ctx.Int(utils.InitSentryNodeSize.Name) + if size <= 0 { + utils.Fatalf("size should be greater than 0") + } + ipStr := ctx.String(utils.InitSentryNodeIPs.Name) + portStr := ctx.String(utils.InitSentryNodePorts.Name) + ips, err := parseIps(ipStr, size) + if err != nil { + utils.Fatalf("Failed to parse ips: %v", err) + } + ports, err := parsePorts(portStr, DefaultSentryP2PPort, size) + if err != nil { + utils.Fatalf("Failed to parse ports: %v", err) + } + + return createConfigs(baseConfig, initDir, "sentry", ips, ports, nil, false, true) +} + +func createAndSaveFullNodeConfigs(ctx *cli.Context, inGenesisFile *os.File, baseConfig gethConfig, initDir string, extraEnodes []*enode.Node) ([]gethConfig, []*enode.Node, error) { + size := ctx.Int(utils.InitFullNodeSize.Name) + if size <= 0 { + utils.Fatalf("size should be greater than 0") + } + ipStr := ctx.String(utils.InitFullNodeIPs.Name) + portStr := ctx.String(utils.InitFullNodePorts.Name) + ips, err := parseIps(ipStr, size) + if err != nil { + utils.Fatalf("Failed to parse ips: %v", err) + } + ports, err := parsePorts(portStr, DefaultFullNodeP2PPort, size) + if err != nil { + utils.Fatalf("Failed to parse ports: %v", err) + } + + configs, enodes, err := createConfigs(baseConfig, initDir, "fullnode", ips, ports, extraEnodes, false, false) + if err != nil { + utils.Fatalf("Failed to create config: %v", err) + } + + // write configs + for i := 0; i < len(configs); i++ { + err := writeConfig(inGenesisFile, configs[i], path.Join(initDir, fmt.Sprintf("fullnode%d", i))) if err != nil { - return err + utils.Fatalf("Failed to write config: %v", err) } - _, err = io.Copy(outGenesisFile, inGenesisFile) + } + return configs, enodes, nil +} + +func createConfigs(base gethConfig, initDir string, prefix string, ips []string, ports []int, extraEnodes []*enode.Node, connectOneExtraEnodes bool, staticConnect bool) ([]gethConfig, []*enode.Node, error) { + if len(ips) != len(ports) { + return nil, nil, errors.New("mismatch of size and length of ports") + } + size := len(ips) + enodes := make([]*enode.Node, size) + for i := 0; i < size; i++ { + nodeConfig := base.Node + nodeConfig.DataDir = path.Join(initDir, fmt.Sprintf("%s%d", prefix, i)) + stack, err := node.New(&nodeConfig) if err != nil { - return err + return nil, nil, err + } + pk := stack.Config().NodeKey() + enodes[i] = enode.NewV4(&pk.PublicKey, net.ParseIP(ips[i]), ports[i], ports[i]) + } + + allEnodes := append(enodes, extraEnodes...) + configs := make([]gethConfig, size) + for i := 0; i < size; i++ { + index := i + if connectOneExtraEnodes { + // only connect to one extra enode with same index + allEnodes = []*enode.Node{enodes[i], extraEnodes[i]} + index = 0 } + configs[i] = createNodeConfig(base, ips[i], ports[i], allEnodes, index, staticConnect) + } + return configs, enodes, nil +} + +func writeConfig(inGenesisFile *os.File, config gethConfig, dir string) error { + configBytes, err := tomlSettings.Marshal(config) + if err != nil { + return err + } + configFile, err := os.OpenFile(path.Join(dir, "config.toml"), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644) + if err != nil { + return err + } + defer configFile.Close() + _, err = configFile.Write(configBytes) + if err != nil { + return err + } + + // Write the input genesis.json to the node's directory + outGenesisFile, err := os.OpenFile(path.Join(dir, "genesis.json"), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644) + if err != nil { + return err + } + _, err = inGenesisFile.Seek(0, io.SeekStart) + if err != nil { + return err + } + _, err = io.Copy(outGenesisFile, inGenesisFile) + if err != nil { + return err } return nil } diff --git a/cmd/geth/config.go b/cmd/geth/config.go index 55799e7937..f5111cc432 100644 --- a/cmd/geth/config.go +++ b/cmd/geth/config.go @@ -226,7 +226,7 @@ func makeFullNode(ctx *cli.Context) (*node.Node, ethapi.Backend) { } if ctx.IsSet(utils.OverrideMinBlocksForBlobRequests.Name) { params.MinBlocksForBlobRequests = ctx.Uint64(utils.OverrideMinBlocksForBlobRequests.Name) - params.MinTimeDurationForBlobRequests = uint64(float64(params.MinBlocksForBlobRequests) * 1.5 /*lorentzBlockInterval*/) + params.MinTimeDurationForBlobRequests = uint64(float64(params.MinBlocksForBlobRequests) * 0.75 /*maxwellBlockInterval*/) } if ctx.IsSet(utils.OverrideDefaultExtraReserveForBlobRequests.Name) { params.DefaultExtraReserveForBlobRequests = ctx.Uint64(utils.OverrideDefaultExtraReserveForBlobRequests.Name) diff --git a/cmd/geth/geth b/cmd/geth/geth deleted file mode 100755 index 9054c0c36a..0000000000 Binary files a/cmd/geth/geth and /dev/null differ diff --git a/cmd/jsutils/getchainstatus.js b/cmd/jsutils/getchainstatus.js index ceb7ae4eaa..eae8eb77bc 100644 --- a/cmd/jsutils/getchainstatus.js +++ b/cmd/jsutils/getchainstatus.js @@ -6,9 +6,10 @@ program.option("--startNum ", "start num"); program.option("--endNum ", "end num"); program.option("--miner ", "miner", ""); program.option("--num ", "validator num", 21); -program.option("--turnLength ", "the consecutive block length", 4); +program.option("--turnLength ", "the consecutive block length", 8); program.option("--topNum ", "top num of address to be displayed", 20); program.option("--blockNum ", "block num", 0); +program.option("--gasUsedThreshold ", "gas used threshold", 5000000); program.option("-h, --help", ""); function printUsage() { @@ -25,6 +26,7 @@ function printUsage() { console.log(" GetFaucetStatus: get faucet status of BSC testnet"); console.log(" GetKeyParameters: dump some key governance parameter"); console.log(" GetMevStatus: get mev blocks of a block range"); + console.log(" GetLargeTxs: get large txs of a block range"); console.log("\nOptions:"); console.log(" --rpc specify the url of RPC endpoint"); console.log(" --startNum the start block number"); @@ -45,6 +47,7 @@ function printUsage() { console.log(" node getchainstatus.js GetKeyParameters --rpc https://bsc-testnet-dataseed.bnbchain.org"); // default: latest block console.log(" node getchainstatus.js GetEip7623 --rpc https://bsc-testnet-dataseed.bnbchain.org --startNum 40000001 --endNum 40000010"); console.log(" node getchainstatus.js GetMevStatus --rpc https://bsc-testnet-dataseed.bnbchain.org --startNum 40000001 --endNum 40000010"); + console.log(" node getchainstatus.js GetLargeTxs --rpc https://bsc-testnet-dataseed.bnbchain.org --startNum 40000001 --num 100 --gasUsedThreshold 5000000"); } program.usage = printUsage; @@ -152,6 +155,7 @@ const validatorMap = new Map([ ["0x0dC5e1CAe4d364d0C79C9AE6BDdB5DA49b10A7d9", "ListaDAO"], ["0xE554F591cCFAc02A84Cf9a5165DDF6C1447Cc67D", "ListaDAO2"], ["0x059a8BFd798F29cE665816D12D56400Fa47DE028", "ListaDAO3"], + ["0xEC3C2D51b8A6ca9Cf244F709EA3AdE0c7B21238F", "GlobalStk"], // Chapel ["0x08265dA01E1A65d62b903c7B34c08cB389bF3D99", "Ararat"], ["0x7f5f2cF1aec83bF0c74DF566a41aa7ed65EA84Ea", "Kita"], @@ -404,8 +408,10 @@ async function getPerformanceData() { let gasUsedTotal = 0; let inturnBlocks = 0; let justifiedBlocks = 0; - let turnLength = 1; + let turnLength = 4; + let lastTimestamp = null; let parliaEnabled = true; + try { turnLength = await provider.send("parlia_getTurnLength", [ethers.toQuantity(program.startNum)]); } catch (error) { @@ -426,14 +432,7 @@ async function getPerformanceData() { inturnBlocks += 1; } let timestamp = eval(eval(header.milliTimestamp).toString(10)); - if (parliaEnabled) { - let justifiedNumber = await provider.send("parlia_getJustifiedNumber", [ethers.toQuantity(i)]); - if (justifiedNumber + 1 == i) { - justifiedBlocks += 1; - } else { - console.log("justified unexpected", "BlockNumber =", i, "justifiedNumber", justifiedNumber); - } - } + let blockInterval = lastTimestamp !== null ? timestamp - lastTimestamp : null; console.log( "BlockNumber =", i, @@ -448,8 +447,20 @@ async function getPerformanceData() { "gasUsed", gasUsed, "timestamp", - timestamp + timestamp, + "blockInterval", + blockInterval !== null ? blockInterval : "N/A" ); + lastTimestamp = timestamp; + + if (parliaEnabled) { + let justifiedNumber = await provider.send("parlia_getJustifiedNumber", [ethers.toQuantity(i)]); + if (justifiedNumber + 1 == i) { + justifiedBlocks += 1; + } else { + console.log("justified unexpected", "BlockNumber =", i, "justifiedNumber", justifiedNumber); + } + } } let blockCount = program.endNum - program.startNum; let txCountPerBlock = txCountTotal / blockCount; @@ -809,6 +820,125 @@ async function getMevStatus() { }); } +// 11.cmd: "getLargeTxs", usage: +// node getchainstatus.js GetLargeTxs \ +// --rpc https://bsc-testnet-dataseed.bnbchain.org \ +// --startNum 40000001 --num 100 \ +// --gasUsedThreshold 5000000 +async function getLargeTxs() { + const startTime = Date.now(); + const gasUsedThreshold = program.gasUsedThreshold; + const startBlock = parseInt(program.startNum); + const size = parseInt(program.num) || 100; + + let actualStartBlock = startBlock; + if (isNaN(startBlock) || startBlock === 0) { + actualStartBlock = await provider.getBlockNumber() - size; + } + const endBlock = actualStartBlock + size; + + console.log(`Finding transactions with gas usage >= ${gasUsedThreshold} between blocks ${actualStartBlock} and ${endBlock-1}`); + + // Cache for validator monikers to avoid redundant RPC calls + const validatorCache = new Map(); + + // Process blocks in batches to avoid memory issues with large ranges + const BATCH_SIZE = 50; + let largeTxCount = 0; + + for (let batchStart = actualStartBlock; batchStart < endBlock; batchStart += BATCH_SIZE) { + const batchEnd = Math.min(batchStart + BATCH_SIZE, endBlock); + + // Create promises for all blocks in the current batch + const blockPromises = []; + for (let i = batchStart; i < batchEnd; i++) { + blockPromises.push(provider.getBlock(i, true)); + } + + // Process all blocks in parallel + const blocks = await Promise.all(blockPromises); + + // Process each block + const results = await Promise.all(blocks.map(async (blockData) => { + if (!blockData || blockData.transactions.length === 0) { + return []; + } + + const blockResults = []; + const potentialTxs = []; + + // First-pass filter: check gas limit from the block data + for (let txIndex = 0; txIndex < blockData.transactions.length; txIndex++) { + const txData = await blockData.getTransaction(txIndex); + if (txData && txData.gasLimit >= gasUsedThreshold) { + potentialTxs.push(txData); + } + } + if (potentialTxs.length === 0) { + return []; + } + + // Fetch all transaction receipts in parallel + const receiptPromises = potentialTxs.map(tx => provider.getTransactionReceipt(tx.hash)); + const receipts = await Promise.all(receiptPromises); + + // Filter transactions by actual gas used + const largeTxs = potentialTxs.filter((tx, index) => + receipts[index] && receipts[index].gasUsed >= gasUsedThreshold + ); + if (largeTxs.length === 0) { + return []; + } + + // Get validator moniker (use cache if available) + let moniker; + if (validatorCache.has(blockData.miner)) { + moniker = validatorCache.get(blockData.miner); + } else { + moniker = await getValidatorMoniker(blockData.miner, blockData.number); + validatorCache.set(blockData.miner, moniker); + } + + // Add details for each large transaction + for (let i = 0; i < largeTxs.length; i++) { + const tx = largeTxs[i]; + const receipt = receipts[potentialTxs.findIndex(p => p.hash === tx.hash)]; + + blockResults.push({ + blockNumber: blockData.number, + difficulty: Number(blockData.difficulty), + txHash: tx.hash, + gasUsed: Number(receipt.gasUsed), + miner: moniker + }); + } + + return blockResults; + })); + + // Flatten results and log + const flatResults = results.flat(); + largeTxCount += flatResults.length; + + flatResults.forEach(result => { + console.log( + "block:", result.blockNumber, + "difficulty:", result.difficulty, + "txHash:", result.txHash, + "gasUsed:", result.gasUsed, + "miner:", result.miner + ); + }); + + // Show progress + console.log(`Progress: ${Math.min(batchEnd, endBlock) - actualStartBlock}/${endBlock - actualStartBlock} blocks processed (${Math.round((batchEnd - actualStartBlock) * 100 / (endBlock - actualStartBlock))}%)`); + } + + const endTime = Date.now(); + const duration = (endTime - startTime) / 1000; + console.log(`Found ${largeTxCount} large transactions in ${duration.toFixed(2)} seconds`); +} + const main = async () => { if (process.argv.length <= 2) { console.error("invalid process.argv.length", process.argv.length); @@ -840,6 +970,8 @@ const main = async () => { await getEip7623(); } else if (cmd === "GetMevStatus") { await getMevStatus(); + } else if (cmd === "GetLargeTxs") { + await getLargeTxs(); } else { console.log("unsupported cmd", cmd); printUsage(); diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 2bf32ab5c1..3acb6758d6 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -641,7 +641,7 @@ var ( MinerRecommitIntervalFlag = &cli.DurationFlag{ Name: "miner.recommit", Usage: "Time interval to recreate the block being mined", - Value: ethconfig.Defaults.Miner.Recommit, + Value: *ethconfig.Defaults.Miner.Recommit, Category: flags.MinerCategory, } MinerDelayLeftoverFlag = &cli.DurationFlag{ @@ -1125,6 +1125,52 @@ Please note that --` + MetricsHTTPFlag.Name + ` must be set to start the server. Usage: "the p2p port of the nodes in the network", Value: 30311, } + InitSentryNodeSize = &cli.IntFlag{ + Name: "init.sentrynode-size", + Usage: "the size of the sentry node", + Value: 0, + } + InitSentryNodeIPs = &cli.StringFlag{ + Name: "init.sentrynode-ips", + Usage: "the ips of each sentry node in the network, example '192.168.0.1,192.168.0.2'", + Value: "", + } + InitSentryNodePorts = &cli.StringFlag{ + Name: "init.sentrynode-ports", + Usage: "the ports of each sentry node in the network, example '30311,30312'", + Value: "", + } + InitFullNodeSize = &cli.IntFlag{ + Name: "init.fullnode-size", + Usage: "the size of the full node", + Value: 0, + } + InitFullNodeIPs = &cli.StringFlag{ + Name: "init.fullnode-ips", + Usage: "the ips of each full node in the network, example '192.168.0.1,192.168.0.2'", + Value: "", + } + InitFullNodePorts = &cli.StringFlag{ + Name: "init.fullnode-ports", + Usage: "the ports of each full node in the network, example '30311,30312'", + Value: "", + } + InitEVNSentryWhitelist = &cli.BoolFlag{ + Name: "init.evn-sentry-whitelist", + Usage: "whether to add evn sentry NodeIDs in Node.P2P.EVNNodeIDsWhitelist", + } + InitEVNValidatorWhitelist = &cli.BoolFlag{ + Name: "init.evn-validator-whitelist", + Usage: "whether to add evn validator NodeIDs in Node.P2P.EVNNodeIDsWhitelist", + } + InitEVNSentryRegister = &cli.BoolFlag{ + Name: "init.evn-sentry-register", + Usage: "whether to add evn sentry NodeIDs in ETH.EVNNodeIDsToAdd", + } + InitEVNValidatorRegister = &cli.BoolFlag{ + Name: "init.evn-validator-register", + Usage: "whether to add evn validator NodeIDs in ETH.EVNNodeIDsToAdd", + } MetricsInfluxDBOrganizationFlag = &cli.StringFlag{ Name: "metrics.influxdb.organization", Usage: "InfluxDB organization name (v2 only)", @@ -1862,7 +1908,8 @@ func setMiner(ctx *cli.Context, cfg *minerconfig.Config) { cfg.GasPrice = flags.GlobalBig(ctx, MinerGasPriceFlag.Name) } if ctx.IsSet(MinerRecommitIntervalFlag.Name) { - cfg.Recommit = ctx.Duration(MinerRecommitIntervalFlag.Name) + recommitIntervalFlag := ctx.Duration(MinerRecommitIntervalFlag.Name) + cfg.Recommit = &recommitIntervalFlag } if ctx.IsSet(MinerDelayLeftoverFlag.Name) { minerDelayLeftover := ctx.Duration(MinerDelayLeftoverFlag.Name) @@ -1873,7 +1920,8 @@ func setMiner(ctx *cli.Context, cfg *minerconfig.Config) { } if ctx.IsSet(MinerNewPayloadTimeoutFlag.Name) { log.Warn("The flag --miner.newpayload-timeout is deprecated and will be removed, please use --miner.recommit") - cfg.Recommit = ctx.Duration(MinerNewPayloadTimeoutFlag.Name) + recommitIntervalFlag := ctx.Duration(MinerRecommitIntervalFlag.Name) + cfg.Recommit = &recommitIntervalFlag } if ctx.Bool(DisableVoteAttestationFlag.Name) { cfg.DisableVoteAttestation = true diff --git a/cmd/utils/flags_legacy.go b/cmd/utils/flags_legacy.go index f1a91515b7..4e46b058c8 100644 --- a/cmd/utils/flags_legacy.go +++ b/cmd/utils/flags_legacy.go @@ -133,7 +133,7 @@ var ( MinerNewPayloadTimeoutFlag = &cli.DurationFlag{ Name: "miner.newpayload-timeout", Usage: "Specify the maximum time allowance for creating a new payload (deprecated)", - Value: ethconfig.Defaults.Miner.Recommit, + Value: *ethconfig.Defaults.Miner.Recommit, Category: flags.DeprecatedCategory, } MetricsEnabledExpensiveFlag = &cli.BoolFlag{ diff --git a/consensus/parlia/abi.go b/consensus/parlia/abi.go index 7b08edaa0d..4eed88bc33 100644 --- a/consensus/parlia/abi.go +++ b/consensus/parlia/abi.go @@ -4042,1817 +4042,2037 @@ const slashABI = ` ] ` -const stakeABI = ` -[ - { - "type": "receive", - "stateMutability": "payable" - }, - { - "type": "function", - "name": "BC_FUSION_CHANNELID", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint8", - "internalType": "uint8" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "BREATHE_BLOCK_INTERVAL", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "DEAD_ADDRESS", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "address", - "internalType": "address" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "LOCK_AMOUNT", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "REDELEGATE_FEE_RATE_BASE", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "STAKING_CHANNELID", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint8", - "internalType": "uint8" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "addToBlackList", - "inputs": [ - { - "name": "account", - "type": "address", - "internalType": "address" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "blackList", - "inputs": [ - { - "name": "", - "type": "address", - "internalType": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "bool", - "internalType": "bool" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "claim", - "inputs": [ - { - "name": "operatorAddress", - "type": "address", - "internalType": "address" - }, - { - "name": "requestNumber", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "claimBatch", - "inputs": [ - { - "name": "operatorAddresses", - "type": "address[]", - "internalType": "address[]" - }, - { - "name": "requestNumbers", - "type": "uint256[]", - "internalType": "uint256[]" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "consensusExpiration", - "inputs": [ - { - "name": "", - "type": "address", - "internalType": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "consensusToOperator", - "inputs": [ - { - "name": "", - "type": "address", - "internalType": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "address", - "internalType": "address" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "createValidator", - "inputs": [ - { - "name": "consensusAddress", - "type": "address", - "internalType": "address" - }, - { - "name": "voteAddress", - "type": "bytes", - "internalType": "bytes" - }, - { - "name": "blsProof", - "type": "bytes", - "internalType": "bytes" - }, - { - "name": "commission", - "type": "tuple", - "internalType": "struct StakeHub.Commission", - "components": [ - { - "name": "rate", - "type": "uint64", - "internalType": "uint64" - }, - { - "name": "maxRate", - "type": "uint64", - "internalType": "uint64" - }, - { - "name": "maxChangeRate", - "type": "uint64", - "internalType": "uint64" - } - ] - }, - { - "name": "description", - "type": "tuple", - "internalType": "struct StakeHub.Description", - "components": [ - { - "name": "moniker", - "type": "string", - "internalType": "string" - }, - { - "name": "identity", - "type": "string", - "internalType": "string" - }, - { - "name": "website", - "type": "string", - "internalType": "string" - }, - { - "name": "details", - "type": "string", - "internalType": "string" - } - ] - } - ], - "outputs": [], - "stateMutability": "payable" - }, - { - "type": "function", - "name": "delegate", - "inputs": [ - { - "name": "operatorAddress", - "type": "address", - "internalType": "address" - }, - { - "name": "delegateVotePower", - "type": "bool", - "internalType": "bool" - } - ], - "outputs": [], - "stateMutability": "payable" - }, - { - "type": "function", - "name": "distributeReward", - "inputs": [ - { - "name": "consensusAddress", - "type": "address", - "internalType": "address" - } - ], - "outputs": [], - "stateMutability": "payable" - }, - { - "type": "function", - "name": "doubleSignSlash", - "inputs": [ - { - "name": "consensusAddress", - "type": "address", - "internalType": "address" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "downtimeJailTime", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "downtimeSlash", - "inputs": [ - { - "name": "consensusAddress", - "type": "address", - "internalType": "address" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "downtimeSlashAmount", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "editCommissionRate", - "inputs": [ - { - "name": "commissionRate", - "type": "uint64", - "internalType": "uint64" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "editConsensusAddress", - "inputs": [ - { - "name": "newConsensusAddress", - "type": "address", - "internalType": "address" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "editDescription", - "inputs": [ - { - "name": "description", - "type": "tuple", - "internalType": "struct StakeHub.Description", - "components": [ - { - "name": "moniker", - "type": "string", - "internalType": "string" - }, - { - "name": "identity", - "type": "string", - "internalType": "string" - }, - { - "name": "website", - "type": "string", - "internalType": "string" - }, - { - "name": "details", - "type": "string", - "internalType": "string" - } - ] - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "editVoteAddress", - "inputs": [ - { - "name": "newVoteAddress", - "type": "bytes", - "internalType": "bytes" - }, - { - "name": "blsProof", - "type": "bytes", - "internalType": "bytes" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "felonyJailTime", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "felonySlashAmount", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getValidatorBasicInfo", - "inputs": [ - { - "name": "operatorAddress", - "type": "address", - "internalType": "address" - } - ], - "outputs": [ - { - "name": "createdTime", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "jailed", - "type": "bool", - "internalType": "bool" - }, - { - "name": "jailUntil", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getValidatorCommission", - "inputs": [ - { - "name": "operatorAddress", - "type": "address", - "internalType": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "tuple", - "internalType": "struct StakeHub.Commission", - "components": [ - { - "name": "rate", - "type": "uint64", - "internalType": "uint64" - }, - { - "name": "maxRate", - "type": "uint64", - "internalType": "uint64" - }, - { - "name": "maxChangeRate", - "type": "uint64", - "internalType": "uint64" - } - ] - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getValidatorConsensusAddress", - "inputs": [ - { - "name": "operatorAddress", - "type": "address", - "internalType": "address" - } - ], - "outputs": [ - { - "name": "consensusAddress", - "type": "address", - "internalType": "address" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getValidatorCreditContract", - "inputs": [ - { - "name": "operatorAddress", - "type": "address", - "internalType": "address" - } - ], - "outputs": [ - { - "name": "creditContract", - "type": "address", - "internalType": "address" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getValidatorDescription", - "inputs": [ - { - "name": "operatorAddress", - "type": "address", - "internalType": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "tuple", - "internalType": "struct StakeHub.Description", - "components": [ - { - "name": "moniker", - "type": "string", - "internalType": "string" - }, - { - "name": "identity", - "type": "string", - "internalType": "string" - }, - { - "name": "website", - "type": "string", - "internalType": "string" - }, - { - "name": "details", - "type": "string", - "internalType": "string" - } - ] - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getValidatorElectionInfo", - "inputs": [ - { - "name": "offset", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "limit", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [ - { - "name": "consensusAddrs", - "type": "address[]", - "internalType": "address[]" - }, - { - "name": "votingPowers", - "type": "uint256[]", - "internalType": "uint256[]" - }, - { - "name": "voteAddrs", - "type": "bytes[]", - "internalType": "bytes[]" - }, - { - "name": "totalLength", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getValidatorRewardRecord", - "inputs": [ - { - "name": "operatorAddress", - "type": "address", - "internalType": "address" - }, - { - "name": "index", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getValidatorTotalPooledBNBRecord", - "inputs": [ - { - "name": "operatorAddress", - "type": "address", - "internalType": "address" - }, - { - "name": "index", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getValidatorVoteAddress", - "inputs": [ - { - "name": "operatorAddress", - "type": "address", - "internalType": "address" - } - ], - "outputs": [ - { - "name": "voteAddress", - "type": "bytes", - "internalType": "bytes" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getValidators", - "inputs": [ - { - "name": "offset", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "limit", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [ - { - "name": "operatorAddrs", - "type": "address[]", - "internalType": "address[]" - }, - { - "name": "creditAddrs", - "type": "address[]", - "internalType": "address[]" - }, - { - "name": "totalLength", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "handleAckPackage", - "inputs": [ - { - "name": "channelId", - "type": "uint8", - "internalType": "uint8" - }, - { - "name": "msgBytes", - "type": "bytes", - "internalType": "bytes" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "handleFailAckPackage", - "inputs": [ - { - "name": "channelId", - "type": "uint8", - "internalType": "uint8" - }, - { - "name": "msgBytes", - "type": "bytes", - "internalType": "bytes" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "handleSynPackage", - "inputs": [ - { - "name": "", - "type": "uint8", - "internalType": "uint8" - }, - { - "name": "msgBytes", - "type": "bytes", - "internalType": "bytes" - } - ], - "outputs": [ - { - "name": "", - "type": "bytes", - "internalType": "bytes" - } - ], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "initialize", - "inputs": [], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "isPaused", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "bool", - "internalType": "bool" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "maliciousVoteSlash", - "inputs": [ - { - "name": "voteAddress", - "type": "bytes", - "internalType": "bytes" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "maxElectedValidators", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "maxFelonyBetweenBreatheBlock", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "minDelegationBNBChange", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "minSelfDelegationBNB", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "numOfJailed", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "pause", - "inputs": [], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "redelegate", - "inputs": [ - { - "name": "srcValidator", - "type": "address", - "internalType": "address" - }, - { - "name": "dstValidator", - "type": "address", - "internalType": "address" - }, - { - "name": "shares", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "delegateVotePower", - "type": "bool", - "internalType": "bool" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "redelegateFeeRate", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "removeFromBlackList", - "inputs": [ - { - "name": "account", - "type": "address", - "internalType": "address" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "resume", - "inputs": [], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "syncGovToken", - "inputs": [ - { - "name": "operatorAddresses", - "type": "address[]", - "internalType": "address[]" - }, - { - "name": "account", - "type": "address", - "internalType": "address" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "transferGasLimit", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "unbondPeriod", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "undelegate", - "inputs": [ - { - "name": "operatorAddress", - "type": "address", - "internalType": "address" - }, - { - "name": "shares", - "type": "uint256", - "internalType": "uint256" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "unjail", - "inputs": [ - { - "name": "operatorAddress", - "type": "address", - "internalType": "address" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "updateParam", - "inputs": [ - { - "name": "key", - "type": "string", - "internalType": "string" - }, - { - "name": "value", - "type": "bytes", - "internalType": "bytes" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "voteExpiration", - "inputs": [ - { - "name": "", - "type": "bytes", - "internalType": "bytes" - } - ], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "voteToOperator", - "inputs": [ - { - "name": "", - "type": "bytes", - "internalType": "bytes" - } - ], - "outputs": [ - { - "name": "", - "type": "address", - "internalType": "address" - } - ], - "stateMutability": "view" - }, - { - "type": "event", - "name": "BlackListed", - "inputs": [ - { - "name": "target", - "type": "address", - "indexed": true, - "internalType": "address" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "Claimed", - "inputs": [ - { - "name": "operatorAddress", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "delegator", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "bnbAmount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "CommissionRateEdited", - "inputs": [ - { - "name": "operatorAddress", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "newCommissionRate", - "type": "uint64", - "indexed": false, - "internalType": "uint64" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "ConsensusAddressEdited", - "inputs": [ - { - "name": "operatorAddress", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "newConsensusAddress", - "type": "address", - "indexed": true, - "internalType": "address" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "Delegated", - "inputs": [ - { - "name": "operatorAddress", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "delegator", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "shares", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - }, - { - "name": "bnbAmount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "DescriptionEdited", - "inputs": [ - { - "name": "operatorAddress", - "type": "address", - "indexed": true, - "internalType": "address" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "Initialized", - "inputs": [ - { - "name": "version", - "type": "uint8", - "indexed": false, - "internalType": "uint8" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "MigrateFailed", - "inputs": [ - { - "name": "operatorAddress", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "delegator", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "bnbAmount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - }, - { - "name": "respCode", - "type": "uint8", - "indexed": false, - "internalType": "enum StakeHub.StakeMigrationRespCode" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "MigrateSuccess", - "inputs": [ - { - "name": "operatorAddress", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "delegator", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "shares", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - }, - { - "name": "bnbAmount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "ParamChange", - "inputs": [ - { - "name": "key", - "type": "string", - "indexed": false, - "internalType": "string" - }, - { - "name": "value", - "type": "bytes", - "indexed": false, - "internalType": "bytes" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "Paused", - "inputs": [], - "anonymous": false - }, - { - "type": "event", - "name": "ProtectorChanged", - "inputs": [ - { - "name": "oldProtector", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "newProtector", - "type": "address", - "indexed": true, - "internalType": "address" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "Redelegated", - "inputs": [ - { - "name": "srcValidator", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "dstValidator", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "delegator", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "oldShares", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - }, - { - "name": "newShares", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - }, - { - "name": "bnbAmount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "Resumed", - "inputs": [], - "anonymous": false - }, - { - "type": "event", - "name": "RewardDistributeFailed", - "inputs": [ - { - "name": "operatorAddress", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "failReason", - "type": "bytes", - "indexed": false, - "internalType": "bytes" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "RewardDistributed", - "inputs": [ - { - "name": "operatorAddress", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "reward", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "StakeCreditInitialized", - "inputs": [ - { - "name": "operatorAddress", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "creditContract", - "type": "address", - "indexed": true, - "internalType": "address" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "UnBlackListed", - "inputs": [ - { - "name": "target", - "type": "address", - "indexed": true, - "internalType": "address" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "Undelegated", - "inputs": [ - { - "name": "operatorAddress", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "delegator", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "shares", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - }, - { - "name": "bnbAmount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "UnexpectedPackage", - "inputs": [ - { - "name": "channelId", - "type": "uint8", - "indexed": false, - "internalType": "uint8" - }, - { - "name": "msgBytes", - "type": "bytes", - "indexed": false, - "internalType": "bytes" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "ValidatorCreated", - "inputs": [ - { - "name": "consensusAddress", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "operatorAddress", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "creditContract", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "voteAddress", - "type": "bytes", - "indexed": false, - "internalType": "bytes" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "ValidatorEmptyJailed", - "inputs": [ - { - "name": "operatorAddress", - "type": "address", - "indexed": true, - "internalType": "address" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "ValidatorJailed", - "inputs": [ - { - "name": "operatorAddress", - "type": "address", - "indexed": true, - "internalType": "address" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "ValidatorSlashed", - "inputs": [ - { - "name": "operatorAddress", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "jailUntil", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - }, - { - "name": "slashAmount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - }, - { - "name": "slashType", - "type": "uint8", - "indexed": false, - "internalType": "enum StakeHub.SlashType" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "ValidatorUnjailed", - "inputs": [ - { - "name": "operatorAddress", - "type": "address", - "indexed": true, - "internalType": "address" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "VoteAddressEdited", - "inputs": [ - { - "name": "operatorAddress", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "newVoteAddress", - "type": "bytes", - "indexed": false, - "internalType": "bytes" - } - ], - "anonymous": false - }, - { - "type": "error", - "name": "AlreadyPaused", - "inputs": [] - }, - { - "type": "error", - "name": "AlreadySlashed", - "inputs": [] - }, - { - "type": "error", - "name": "ConsensusAddressExpired", - "inputs": [] - }, - { - "type": "error", - "name": "DelegationAmountTooSmall", - "inputs": [] - }, - { - "type": "error", - "name": "DuplicateConsensusAddress", - "inputs": [] - }, - { - "type": "error", - "name": "DuplicateMoniker", - "inputs": [] - }, - { - "type": "error", - "name": "DuplicateVoteAddress", - "inputs": [] - }, - { - "type": "error", - "name": "InBlackList", - "inputs": [] - }, - { - "type": "error", - "name": "InvalidCommission", - "inputs": [] - }, - { - "type": "error", - "name": "InvalidConsensusAddress", - "inputs": [] - }, - { - "type": "error", - "name": "InvalidMoniker", - "inputs": [] - }, - { - "type": "error", - "name": "InvalidRequest", - "inputs": [] - }, - { - "type": "error", - "name": "InvalidSynPackage", - "inputs": [] - }, - { - "type": "error", - "name": "InvalidValue", - "inputs": [ - { - "name": "key", - "type": "string", - "internalType": "string" - }, - { - "name": "value", - "type": "bytes", - "internalType": "bytes" - } - ] - }, - { - "type": "error", - "name": "InvalidVoteAddress", - "inputs": [] - }, - { - "type": "error", - "name": "JailTimeNotExpired", - "inputs": [] - }, - { - "type": "error", - "name": "NoMoreFelonyAllowed", - "inputs": [] - }, - { - "type": "error", - "name": "NotPaused", - "inputs": [] - }, - { - "type": "error", - "name": "OnlyCoinbase", - "inputs": [] - }, - { - "type": "error", - "name": "OnlyProtector", - "inputs": [] - }, - { - "type": "error", - "name": "OnlySelfDelegation", - "inputs": [] - }, - { - "type": "error", - "name": "OnlySystemContract", - "inputs": [ - { - "name": "systemContract", - "type": "address", - "internalType": "address" - } - ] - }, - { - "type": "error", - "name": "OnlyZeroGasPrice", - "inputs": [] - }, - { - "type": "error", - "name": "SameValidator", - "inputs": [] - }, - { - "type": "error", - "name": "SelfDelegationNotEnough", - "inputs": [] - }, - { - "type": "error", - "name": "TransferFailed", - "inputs": [] - }, - { - "type": "error", - "name": "UnknownParam", - "inputs": [ - { - "name": "key", - "type": "string", - "internalType": "string" - }, - { - "name": "value", - "type": "bytes", - "internalType": "bytes" - } - ] - }, - { - "type": "error", - "name": "UpdateTooFrequently", - "inputs": [] - }, - { - "type": "error", - "name": "ValidatorExisted", - "inputs": [] - }, - { - "type": "error", - "name": "ValidatorNotExisted", - "inputs": [] - }, - { - "type": "error", - "name": "ValidatorNotJailed", - "inputs": [] - }, - { - "type": "error", - "name": "VoteAddressExpired", - "inputs": [] - }, - { - "type": "error", - "name": "ZeroShares", - "inputs": [] - } +const stakeABI = `[ + { + "type": "receive", + "stateMutability": "payable" + }, + { + "type": "function", + "name": "BREATHE_BLOCK_INTERVAL", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "DEAD_ADDRESS", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "INIT_MAX_NUMBER_NODE_ID", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "LOCK_AMOUNT", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "REDELEGATE_FEE_RATE_BASE", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "addNodeIDs", + "inputs": [ + { + "name": "nodeIDs", + "type": "bytes32[]", + "internalType": "bytes32[]" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "addToBlackList", + "inputs": [ + { + "name": "account", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "agentToOperator", + "inputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "blackList", + "inputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "bool", + "internalType": "bool" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "claim", + "inputs": [ + { + "name": "operatorAddress", + "type": "address", + "internalType": "address" + }, + { + "name": "requestNumber", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "claimBatch", + "inputs": [ + { + "name": "operatorAddresses", + "type": "address[]", + "internalType": "address[]" + }, + { + "name": "requestNumbers", + "type": "uint256[]", + "internalType": "uint256[]" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "consensusExpiration", + "inputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "consensusToOperator", + "inputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "createValidator", + "inputs": [ + { + "name": "consensusAddress", + "type": "address", + "internalType": "address" + }, + { + "name": "voteAddress", + "type": "bytes", + "internalType": "bytes" + }, + { + "name": "blsProof", + "type": "bytes", + "internalType": "bytes" + }, + { + "name": "commission", + "type": "tuple", + "internalType": "struct StakeHub.Commission", + "components": [ + { + "name": "rate", + "type": "uint64", + "internalType": "uint64" + }, + { + "name": "maxRate", + "type": "uint64", + "internalType": "uint64" + }, + { + "name": "maxChangeRate", + "type": "uint64", + "internalType": "uint64" + } + ] + }, + { + "name": "description", + "type": "tuple", + "internalType": "struct StakeHub.Description", + "components": [ + { + "name": "moniker", + "type": "string", + "internalType": "string" + }, + { + "name": "identity", + "type": "string", + "internalType": "string" + }, + { + "name": "website", + "type": "string", + "internalType": "string" + }, + { + "name": "details", + "type": "string", + "internalType": "string" + } + ] + } + ], + "outputs": [], + "stateMutability": "payable" + }, + { + "type": "function", + "name": "delegate", + "inputs": [ + { + "name": "operatorAddress", + "type": "address", + "internalType": "address" + }, + { + "name": "delegateVotePower", + "type": "bool", + "internalType": "bool" + } + ], + "outputs": [], + "stateMutability": "payable" + }, + { + "type": "function", + "name": "distributeReward", + "inputs": [ + { + "name": "consensusAddress", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "payable" + }, + { + "type": "function", + "name": "doubleSignSlash", + "inputs": [ + { + "name": "consensusAddress", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "downtimeJailTime", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "downtimeSlash", + "inputs": [ + { + "name": "consensusAddress", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "downtimeSlashAmount", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "editCommissionRate", + "inputs": [ + { + "name": "commissionRate", + "type": "uint64", + "internalType": "uint64" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "editConsensusAddress", + "inputs": [ + { + "name": "newConsensusAddress", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "editDescription", + "inputs": [ + { + "name": "description", + "type": "tuple", + "internalType": "struct StakeHub.Description", + "components": [ + { + "name": "moniker", + "type": "string", + "internalType": "string" + }, + { + "name": "identity", + "type": "string", + "internalType": "string" + }, + { + "name": "website", + "type": "string", + "internalType": "string" + }, + { + "name": "details", + "type": "string", + "internalType": "string" + } + ] + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "editVoteAddress", + "inputs": [ + { + "name": "newVoteAddress", + "type": "bytes", + "internalType": "bytes" + }, + { + "name": "blsProof", + "type": "bytes", + "internalType": "bytes" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "felonyJailTime", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "felonySlashAmount", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getProtector", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getValidatorAgent", + "inputs": [ + { + "name": "operatorAddress", + "type": "address", + "internalType": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getValidatorBasicInfo", + "inputs": [ + { + "name": "operatorAddress", + "type": "address", + "internalType": "address" + } + ], + "outputs": [ + { + "name": "createdTime", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "jailed", + "type": "bool", + "internalType": "bool" + }, + { + "name": "jailUntil", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getValidatorCommission", + "inputs": [ + { + "name": "operatorAddress", + "type": "address", + "internalType": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "tuple", + "internalType": "struct StakeHub.Commission", + "components": [ + { + "name": "rate", + "type": "uint64", + "internalType": "uint64" + }, + { + "name": "maxRate", + "type": "uint64", + "internalType": "uint64" + }, + { + "name": "maxChangeRate", + "type": "uint64", + "internalType": "uint64" + } + ] + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getValidatorConsensusAddress", + "inputs": [ + { + "name": "operatorAddress", + "type": "address", + "internalType": "address" + } + ], + "outputs": [ + { + "name": "consensusAddress", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getValidatorCreditContract", + "inputs": [ + { + "name": "operatorAddress", + "type": "address", + "internalType": "address" + } + ], + "outputs": [ + { + "name": "creditContract", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getValidatorDescription", + "inputs": [ + { + "name": "operatorAddress", + "type": "address", + "internalType": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "tuple", + "internalType": "struct StakeHub.Description", + "components": [ + { + "name": "moniker", + "type": "string", + "internalType": "string" + }, + { + "name": "identity", + "type": "string", + "internalType": "string" + }, + { + "name": "website", + "type": "string", + "internalType": "string" + }, + { + "name": "details", + "type": "string", + "internalType": "string" + } + ] + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getValidatorElectionInfo", + "inputs": [ + { + "name": "offset", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "limit", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [ + { + "name": "consensusAddrs", + "type": "address[]", + "internalType": "address[]" + }, + { + "name": "votingPowers", + "type": "uint256[]", + "internalType": "uint256[]" + }, + { + "name": "voteAddrs", + "type": "bytes[]", + "internalType": "bytes[]" + }, + { + "name": "totalLength", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getValidatorRewardRecord", + "inputs": [ + { + "name": "operatorAddress", + "type": "address", + "internalType": "address" + }, + { + "name": "index", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getValidatorTotalPooledBNBRecord", + "inputs": [ + { + "name": "operatorAddress", + "type": "address", + "internalType": "address" + }, + { + "name": "index", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getValidatorUpdateTime", + "inputs": [ + { + "name": "operatorAddress", + "type": "address", + "internalType": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getValidatorVoteAddress", + "inputs": [ + { + "name": "operatorAddress", + "type": "address", + "internalType": "address" + } + ], + "outputs": [ + { + "name": "voteAddress", + "type": "bytes", + "internalType": "bytes" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getValidators", + "inputs": [ + { + "name": "offset", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "limit", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [ + { + "name": "operatorAddrs", + "type": "address[]", + "internalType": "address[]" + }, + { + "name": "creditAddrs", + "type": "address[]", + "internalType": "address[]" + }, + { + "name": "totalLength", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "handleAckPackage", + "inputs": [ + { + "name": "channelId", + "type": "uint8", + "internalType": "uint8" + }, + { + "name": "msgBytes", + "type": "bytes", + "internalType": "bytes" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "handleFailAckPackage", + "inputs": [ + { + "name": "channelId", + "type": "uint8", + "internalType": "uint8" + }, + { + "name": "msgBytes", + "type": "bytes", + "internalType": "bytes" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "handleSynPackage", + "inputs": [ + { + "name": "", + "type": "uint8", + "internalType": "uint8" + }, + { + "name": "msgBytes", + "type": "bytes", + "internalType": "bytes" + } + ], + "outputs": [ + { + "name": "", + "type": "bytes", + "internalType": "bytes" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "initialize", + "inputs": [], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "isPaused", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "bool", + "internalType": "bool" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getNodeIDs", + "inputs": [ + { + "name": "validatorsToQuery", + "type": "address[]", + "internalType": "address[]" + } + ], + "outputs": [ + { + "name": "consensusAddresses", + "type": "address[]", + "internalType": "address[]" + }, + { + "name": "nodeIDsList", + "type": "bytes32[][]", + "internalType": "bytes32[][]" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "maliciousVoteSlash", + "inputs": [ + { + "name": "voteAddress", + "type": "bytes", + "internalType": "bytes" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "maxElectedValidators", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "maxFelonyBetweenBreatheBlock", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "maxNodeIDs", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "minDelegationBNBChange", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "minSelfDelegationBNB", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "numOfJailed", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "pause", + "inputs": [], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "redelegate", + "inputs": [ + { + "name": "srcValidator", + "type": "address", + "internalType": "address" + }, + { + "name": "dstValidator", + "type": "address", + "internalType": "address" + }, + { + "name": "shares", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "delegateVotePower", + "type": "bool", + "internalType": "bool" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "redelegateFeeRate", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "removeFromBlackList", + "inputs": [ + { + "name": "account", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "removeNodeIDs", + "inputs": [ + { + "name": "targetNodeIDs", + "type": "bytes32[]", + "internalType": "bytes32[]" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "resume", + "inputs": [], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "syncGovToken", + "inputs": [ + { + "name": "operatorAddresses", + "type": "address[]", + "internalType": "address[]" + }, + { + "name": "account", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "transferGasLimit", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "unbondPeriod", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "undelegate", + "inputs": [ + { + "name": "operatorAddress", + "type": "address", + "internalType": "address" + }, + { + "name": "shares", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "unjail", + "inputs": [ + { + "name": "operatorAddress", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "updateAgent", + "inputs": [ + { + "name": "newAgent", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "updateParam", + "inputs": [ + { + "name": "key", + "type": "string", + "internalType": "string" + }, + { + "name": "value", + "type": "bytes", + "internalType": "bytes" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "voteExpiration", + "inputs": [ + { + "name": "", + "type": "bytes", + "internalType": "bytes" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "voteToOperator", + "inputs": [ + { + "name": "", + "type": "bytes", + "internalType": "bytes" + } + ], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, + { + "type": "event", + "name": "AgentChanged", + "inputs": [ + { + "name": "operatorAddress", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "oldAgent", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "newAgent", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "BlackListed", + "inputs": [ + { + "name": "target", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "Claimed", + "inputs": [ + { + "name": "operatorAddress", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "delegator", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "bnbAmount", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "CommissionRateEdited", + "inputs": [ + { + "name": "operatorAddress", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "newCommissionRate", + "type": "uint64", + "indexed": false, + "internalType": "uint64" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "ConsensusAddressEdited", + "inputs": [ + { + "name": "operatorAddress", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "newConsensusAddress", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "Delegated", + "inputs": [ + { + "name": "operatorAddress", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "delegator", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "shares", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + }, + { + "name": "bnbAmount", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "DescriptionEdited", + "inputs": [ + { + "name": "operatorAddress", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "Initialized", + "inputs": [ + { + "name": "version", + "type": "uint8", + "indexed": false, + "internalType": "uint8" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "MigrateFailed", + "inputs": [ + { + "name": "operatorAddress", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "delegator", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "bnbAmount", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + }, + { + "name": "respCode", + "type": "uint8", + "indexed": false, + "internalType": "enum StakeHub.StakeMigrationRespCode" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "MigrateSuccess", + "inputs": [ + { + "name": "operatorAddress", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "delegator", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "shares", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + }, + { + "name": "bnbAmount", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "NodeIDAdded", + "inputs": [ + { + "name": "validator", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "nodeID", + "type": "bytes32", + "indexed": false, + "internalType": "bytes32" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "NodeIDRemoved", + "inputs": [ + { + "name": "validator", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "nodeID", + "type": "bytes32", + "indexed": false, + "internalType": "bytes32" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "ParamChange", + "inputs": [ + { + "name": "key", + "type": "string", + "indexed": false, + "internalType": "string" + }, + { + "name": "value", + "type": "bytes", + "indexed": false, + "internalType": "bytes" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "Paused", + "inputs": [], + "anonymous": false + }, + { + "type": "event", + "name": "ProtectorChanged", + "inputs": [ + { + "name": "oldProtector", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "newProtector", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "Redelegated", + "inputs": [ + { + "name": "srcValidator", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "dstValidator", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "delegator", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "oldShares", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + }, + { + "name": "newShares", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + }, + { + "name": "bnbAmount", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "Resumed", + "inputs": [], + "anonymous": false + }, + { + "type": "event", + "name": "RewardDistributeFailed", + "inputs": [ + { + "name": "operatorAddress", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "failReason", + "type": "bytes", + "indexed": false, + "internalType": "bytes" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "RewardDistributed", + "inputs": [ + { + "name": "operatorAddress", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "reward", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "StakeCreditInitialized", + "inputs": [ + { + "name": "operatorAddress", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "creditContract", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "UnBlackListed", + "inputs": [ + { + "name": "target", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "Undelegated", + "inputs": [ + { + "name": "operatorAddress", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "delegator", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "shares", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + }, + { + "name": "bnbAmount", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "UnexpectedPackage", + "inputs": [ + { + "name": "channelId", + "type": "uint8", + "indexed": false, + "internalType": "uint8" + }, + { + "name": "msgBytes", + "type": "bytes", + "indexed": false, + "internalType": "bytes" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "ValidatorCreated", + "inputs": [ + { + "name": "consensusAddress", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "operatorAddress", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "creditContract", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "voteAddress", + "type": "bytes", + "indexed": false, + "internalType": "bytes" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "ValidatorEmptyJailed", + "inputs": [ + { + "name": "operatorAddress", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "ValidatorJailed", + "inputs": [ + { + "name": "operatorAddress", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "ValidatorSlashed", + "inputs": [ + { + "name": "operatorAddress", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "jailUntil", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + }, + { + "name": "slashAmount", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + }, + { + "name": "slashType", + "type": "uint8", + "indexed": false, + "internalType": "enum StakeHub.SlashType" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "ValidatorUnjailed", + "inputs": [ + { + "name": "operatorAddress", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "VoteAddressEdited", + "inputs": [ + { + "name": "operatorAddress", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "newVoteAddress", + "type": "bytes", + "indexed": false, + "internalType": "bytes" + } + ], + "anonymous": false + }, + { + "type": "error", + "name": "AlreadyPaused", + "inputs": [] + }, + { + "type": "error", + "name": "AlreadySlashed", + "inputs": [] + }, + { + "type": "error", + "name": "ConsensusAddressExpired", + "inputs": [] + }, + { + "type": "error", + "name": "DelegationAmountTooSmall", + "inputs": [] + }, + { + "type": "error", + "name": "DuplicateConsensusAddress", + "inputs": [] + }, + { + "type": "error", + "name": "DuplicateMoniker", + "inputs": [] + }, + { + "type": "error", + "name": "DuplicateNodeID", + "inputs": [] + }, + { + "type": "error", + "name": "DuplicateVoteAddress", + "inputs": [] + }, + { + "type": "error", + "name": "ExceedsMaxNodeIDs", + "inputs": [] + }, + { + "type": "error", + "name": "InBlackList", + "inputs": [] + }, + { + "type": "error", + "name": "InvalidAgent", + "inputs": [] + }, + { + "type": "error", + "name": "InvalidCommission", + "inputs": [] + }, + { + "type": "error", + "name": "InvalidConsensusAddress", + "inputs": [] + }, + { + "type": "error", + "name": "InvalidMoniker", + "inputs": [] + }, + { + "type": "error", + "name": "InvalidNodeID", + "inputs": [] + }, + { + "type": "error", + "name": "InvalidRequest", + "inputs": [] + }, + { + "type": "error", + "name": "InvalidSynPackage", + "inputs": [] + }, + { + "type": "error", + "name": "InvalidValidator", + "inputs": [] + }, + { + "type": "error", + "name": "InvalidValue", + "inputs": [ + { + "name": "key", + "type": "string", + "internalType": "string" + }, + { + "name": "value", + "type": "bytes", + "internalType": "bytes" + } + ] + }, + { + "type": "error", + "name": "InvalidVoteAddress", + "inputs": [] + }, + { + "type": "error", + "name": "JailTimeNotExpired", + "inputs": [] + }, + { + "type": "error", + "name": "NoMoreFelonyAllowed", + "inputs": [] + }, + { + "type": "error", + "name": "NotPaused", + "inputs": [] + }, + { + "type": "error", + "name": "OnlyCoinbase", + "inputs": [] + }, + { + "type": "error", + "name": "OnlyProtector", + "inputs": [] + }, + { + "type": "error", + "name": "OnlySelfDelegation", + "inputs": [] + }, + { + "type": "error", + "name": "OnlySystemContract", + "inputs": [ + { + "name": "systemContract", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "OnlyZeroGasPrice", + "inputs": [] + }, + { + "type": "error", + "name": "SameValidator", + "inputs": [] + }, + { + "type": "error", + "name": "SelfDelegationNotEnough", + "inputs": [] + }, + { + "type": "error", + "name": "TransferFailed", + "inputs": [] + }, + { + "type": "error", + "name": "UnknownParam", + "inputs": [ + { + "name": "key", + "type": "string", + "internalType": "string" + }, + { + "name": "value", + "type": "bytes", + "internalType": "bytes" + } + ] + }, + { + "type": "error", + "name": "UpdateTooFrequently", + "inputs": [] + }, + { + "type": "error", + "name": "ValidatorExisted", + "inputs": [] + }, + { + "type": "error", + "name": "ValidatorNotExisted", + "inputs": [] + }, + { + "type": "error", + "name": "ValidatorNotJailed", + "inputs": [] + }, + { + "type": "error", + "name": "VoteAddressExpired", + "inputs": [] + }, + { + "type": "error", + "name": "ZeroShares", + "inputs": [] + } ] ` diff --git a/consensus/parlia/parlia.go b/consensus/parlia/parlia.go index 21d7761b00..e6b84a15f9 100644 --- a/consensus/parlia/parlia.go +++ b/consensus/parlia/parlia.go @@ -60,6 +60,7 @@ const ( maxwellEpochLength uint64 = 1000 // Epoch length starting from the Maxwell hard fork defaultBlockInterval uint64 = 3000 // Default block interval in milliseconds lorentzBlockInterval uint64 = 1500 // Block interval starting from the Lorentz hard fork + maxwellBlockInterval uint64 = 750 // Block interval starting from the Maxwell hard fork defaultTurnLength uint8 = 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 @@ -349,6 +350,11 @@ func (p *Parlia) Author(header *types.Header) (common.Address, error) { return header.Coinbase, nil } +// ConsensusAddress returns the consensus address of the validator +func (p *Parlia) ConsensusAddress() common.Address { + return p.val +} + // VerifyHeader checks whether a header conforms to the consensus rules. func (p *Parlia) VerifyHeader(chain consensus.ChainHeaderReader, header *types.Header) error { return p.verifyHeader(chain, header, nil) @@ -795,14 +801,18 @@ func (p *Parlia) snapshot(chain consensus.ChainHeaderReader, number uint64, hash blockHeader := chain.GetHeaderByNumber(number) if blockHeader != nil { blockHash = blockHeader.Hash() - if p.chainConfig.IsLorentz(blockHeader.Number, blockHeader.Time) { + if p.chainConfig.IsMaxwell(blockHeader.Number, blockHeader.Time) { + blockInterval = maxwellBlockInterval + } else if p.chainConfig.IsLorentz(blockHeader.Number, blockHeader.Time) { blockInterval = lorentzBlockInterval } } if number > offset { // exclude `number == 200` blockBeforeCheckpoint := chain.GetHeaderByNumber(number - offset - 1) if blockBeforeCheckpoint != nil { - if p.chainConfig.IsLorentz(blockBeforeCheckpoint.Number, blockBeforeCheckpoint.Time) { + if p.chainConfig.IsMaxwell(blockBeforeCheckpoint.Number, blockBeforeCheckpoint.Time) { + epochLength = maxwellEpochLength + } else if p.chainConfig.IsLorentz(blockBeforeCheckpoint.Number, blockBeforeCheckpoint.Time) { epochLength = lorentzEpochLength } } diff --git a/consensus/parlia/ramanujanfork.go b/consensus/parlia/ramanujanfork.go index 64d149bf28..e26cebc9d8 100644 --- a/consensus/parlia/ramanujanfork.go +++ b/consensus/parlia/ramanujanfork.go @@ -12,7 +12,7 @@ import ( const ( wiggleTimeBeforeFork = 500 * time.Millisecond // Random delay (per signer) to allow concurrent signers fixedBackOffTimeBeforeFork = 200 * time.Millisecond - millisecondsUnit = 500 // Set to 250 if block interval is 750ms; not enforced at the consensus level + millisecondsUnit = 250 // not enforced at the consensus level ) func (p *Parlia) delayForRamanujanFork(snap *Snapshot, header *types.Header) time.Duration { diff --git a/consensus/parlia/snapshot.go b/consensus/parlia/snapshot.go index ebdbcbe1ed..d5df7abd43 100644 --- a/consensus/parlia/snapshot.go +++ b/consensus/parlia/snapshot.go @@ -196,13 +196,13 @@ func (s *Snapshot) isMajorityFork(forkHash string) bool { return ally > len(s.RecentForkHashes)/2 } -func (s *Snapshot) updateAttestation(header *types.Header, chainConfig *params.ChainConfig, epochLength uint64) { +func (s *Snapshot) updateAttestation(header *types.Header, chainConfig *params.ChainConfig) { if !chainConfig.IsLuban(header.Number) { return } // The attestation should have been checked in verify header, update directly - attestation, _ := getVoteAttestationFromHeader(header, chainConfig, epochLength) + attestation, _ := getVoteAttestationFromHeader(header, chainConfig, s.EpochLength) if attestation == nil { return } @@ -269,6 +269,13 @@ func (s *Snapshot) SignRecently(validator common.Address) bool { return s.signRecentlyByCounts(validator, s.countRecents()) } +func (s *Snapshot) getFinalizedNumber() uint64 { + if s.Attestation != nil { + return s.Attestation.SourceNumber + } + return 0 +} + 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 { @@ -320,16 +327,40 @@ func (s *Snapshot) apply(headers []*types.Header, chain consensus.ChainHeaderRea } } } + + snap.updateAttestation(header, chainConfig) + snap.Recents[number] = validator + if chainConfig.IsMaxwell(header.Number, header.Time) { + latestFinalizedBlockNumber := snap.getFinalizedNumber() + // BEP-524: Clear entries up to the latest finalized block + for blockNumber := range snap.Recents { + if blockNumber <= latestFinalizedBlockNumber { + delete(snap.Recents, blockNumber) + } + } + } + snap.RecentForkHashes[number] = hex.EncodeToString(header.Extra[extraVanity-nextForkHashSize : extraVanity]) + + if chainConfig.IsMaxwell(header.Number, header.Time) { + snap.BlockInterval = maxwellBlockInterval + } else if chainConfig.IsLorentz(header.Number, header.Time) { + snap.BlockInterval = lorentzBlockInterval + } + epochLength := snap.EpochLength - snap.updateAttestation(header, chainConfig, epochLength) - if chainConfig.IsLorentz(header.Number, header.Time) { + nextBlockNumber := header.Number.Uint64() + 1 + if snap.EpochLength == defaultEpochLength && + chainConfig.IsLorentz(header.Number, header.Time) && // Without this condition, an incorrect block might be used to parse validators for certain blocks after the Lorentz hard fork. - if (header.Number.Uint64()+1)%lorentzEpochLength == 0 { - snap.EpochLength = lorentzEpochLength - } - snap.BlockInterval = lorentzBlockInterval + nextBlockNumber%lorentzEpochLength == 0 { + snap.EpochLength = lorentzEpochLength + } + if snap.EpochLength == lorentzEpochLength && + chainConfig.IsMaxwell(header.Number, header.Time) && + nextBlockNumber%maxwellEpochLength == 0 { + snap.EpochLength = maxwellEpochLength } // change validator set if number > 0 && number%epochLength == snap.minerHistoryCheckLen() { diff --git a/consensus/parlia/stakehub.go b/consensus/parlia/stakehub.go new file mode 100644 index 0000000000..a6e7ac4ac6 --- /dev/null +++ b/consensus/parlia/stakehub.go @@ -0,0 +1,273 @@ +package parlia + +import ( + "context" + "fmt" + "math" + "math/big" + + "github.com/ethereum/go-ethereum/accounts" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "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/p2p/enode" + "github.com/ethereum/go-ethereum/rpc" +) + +// GetValidators retrieves validators from the StakeHubContract +// It returns operator addresses, credit addresses, and total length of validators +func (p *Parlia) GetValidators(offset, limit *big.Int) ([]common.Address, []common.Address, *big.Int, error) { + log.Debug("Getting validators from latest block", "offset", offset, "limit", limit) + + // Create the call data for getValidators + data, err := p.stakeHubABI.Pack("getValidators", offset, limit) + if err != nil { + log.Error("Failed to pack stakehub getValidators", "error", err) + return nil, nil, nil, fmt.Errorf("failed to pack getValidators: %v", err) + } + + // Make the call + blockNr := rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber) + msgData := (hexutil.Bytes)(data) + toAddress := common.HexToAddress(systemcontracts.StakeHubContract) + gas := (hexutil.Uint64)(uint64(math.MaxUint64 / 2)) + + log.Debug("Calling getValidators from latest block", "to", toAddress) + result, err := p.ethAPI.Call(context.Background(), ethapi.TransactionArgs{ + Gas: &gas, + To: &toAddress, + Data: &msgData, + }, &blockNr, nil, nil) + if err != nil { + log.Error("Failed to call stakehub getValidators", "error", err) + return nil, nil, nil, fmt.Errorf("failed to call stakehub getValidators: %v", err) + } + + // Unpack the result + var operatorAddrs []common.Address + var creditAddrs []common.Address + var totalLength *big.Int + if err := p.stakeHubABI.UnpackIntoInterface(&[]interface{}{&operatorAddrs, &creditAddrs, &totalLength}, "getValidators", result); err != nil { + log.Error("Failed to unpack stakehub getValidators result", "error", err) + return nil, nil, nil, fmt.Errorf("failed to unpack getValidators result: %v", err) + } + + log.Debug("Successfully retrieved stakehub validators", "operators", len(operatorAddrs), "credits", len(creditAddrs), "total", totalLength) + return operatorAddrs, creditAddrs, totalLength, nil +} + +// getNodeIDsForValidators retrieves node IDs for the given validators +// It returns a map of consensus addresses to their node IDs +func (p *Parlia) getNodeIDsForValidators(validatorsToQuery []common.Address) (map[common.Address][]enode.ID, error) { + log.Debug("Listing node IDs for validators from latest block", "validators", len(validatorsToQuery)) + + // Create the call data for getNodeIDs + data, err := p.stakeHubABI.Pack("getNodeIDs", validatorsToQuery) + if err != nil { + log.Error("Failed to pack getNodeIDs", "error", err) + return nil, fmt.Errorf("failed to pack getNodeIDs: %v", err) + } + + // Make the call + blockNr := rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber) + msgData := (hexutil.Bytes)(data) + toAddress := common.HexToAddress(systemcontracts.StakeHubContract) + gas := (hexutil.Uint64)(uint64(math.MaxUint64 / 2)) + + log.Debug("Calling getNodeIDs from latest block", "to", toAddress) + result, err := p.ethAPI.Call(context.Background(), ethapi.TransactionArgs{ + Gas: &gas, + To: &toAddress, + Data: &msgData, + }, &blockNr, nil, nil) + if err != nil { + log.Error("Failed to call getNodeIDs", "error", err) + return nil, fmt.Errorf("failed to call getNodeIDs: %v", err) + } + + // Unpack the result + var consensusAddresses []common.Address + var nodeIDsList [][]enode.ID + if err := p.stakeHubABI.UnpackIntoInterface(&[]interface{}{&consensusAddresses, &nodeIDsList}, "getNodeIDs", result); err != nil { + log.Error("Failed to unpack getNodeIDs result", "error", err) + return nil, fmt.Errorf("failed to unpack getNodeIDs result: %v", err) + } + + // Create a map of addresses to node IDs + addressToNodeIDs := make(map[common.Address][]enode.ID) + for i, addr := range consensusAddresses { + if i < len(nodeIDsList) { + addressToNodeIDs[addr] = nodeIDsList[i] + } + } + + log.Debug("Successfully retrieved node IDs", "addresses", len(addressToNodeIDs)) + return addressToNodeIDs, nil +} + +// GetNodeIDs returns a flattened array of all node IDs for current validators +func (p *Parlia) GetNodeIDs() ([]enode.ID, error) { + // Call GetValidators with latest block number + operatorAddrs, _, _, err := p.GetValidators(big.NewInt(0), big.NewInt(1000)) + if err != nil { + log.Error("Failed to get validators", "error", err) + return nil, fmt.Errorf("failed to get validators: %v", err) + } + log.Debug("Retrieved validators", "count", len(operatorAddrs)) + + // Get node IDs for validators + nodeIDs, err := p.getNodeIDsForValidators(operatorAddrs) + if err != nil { + log.Error("Failed to get node IDs", "error", err) + return nil, fmt.Errorf("failed to get node IDs: %v", err) + } + log.Debug("Retrieved node IDs map", "addresses", len(nodeIDs)) + + // Flatten the array of arrays into a single array + flatNodeIDs := make([]enode.ID, 0) + for addr, nodeIDArray := range nodeIDs { + flatNodeIDs = append(flatNodeIDs, nodeIDArray...) + log.Debug("Processing node IDs", "address", addr, "count", len(nodeIDArray)) + } + + log.Debug("Successfully flattened node IDs", "total", len(flatNodeIDs)) + return flatNodeIDs, nil +} + +// AddNodeIDs creates a signed transaction to add node IDs to the StakeHub contract +func (p *Parlia) AddNodeIDs(nodeIDs []enode.ID, nonce uint64) (*types.Transaction, error) { + log.Debug("Adding node IDs", "count", len(nodeIDs), "nonce", nonce) + + p.lock.RLock() + signTxFn := p.signTxFn + val := p.val + p.lock.RUnlock() + + if signTxFn == nil { + log.Error("Signing function not set") + return nil, fmt.Errorf("signing function not set, call Authorize first") + } + + // Create the call data for addNodeIDs + data, err := p.stakeHubABI.Pack("addNodeIDs", nodeIDs) + if err != nil { + log.Error("Failed to pack addNodeIDs", "error", err) + return nil, fmt.Errorf("failed to pack addNodeIDs: %v", err) + } + + to := common.HexToAddress(systemcontracts.StakeHubContract) + hexData := hexutil.Bytes(data) + hexNonce := hexutil.Uint64(nonce) + gas, err := p.ethAPI.EstimateGas(context.Background(), ethapi.TransactionArgs{ + From: &val, + To: &to, + Nonce: &hexNonce, + Data: &hexData, + }, nil, nil, nil) + if err != nil { + log.Error("Failed to estimate gas", "error", err) + return nil, fmt.Errorf("failed to estimate gas: %v", err) + } + + // Create the transaction + tx := types.NewTransaction( + nonce, + common.HexToAddress(systemcontracts.StakeHubContract), + common.Big0, + uint64(gas), + big.NewInt(1000000000), + data, + ) + + // Sign the transaction with the node's private key + log.Debug("Signing transaction", "validator", val) + signedTx, err := signTxFn(accounts.Account{Address: val}, tx, p.chainConfig.ChainID) + if err != nil { + log.Error("Failed to sign transaction", "error", err) + return nil, fmt.Errorf("failed to sign transaction: %v", err) + } + + log.Debug("Successfully created signed transaction", "hash", signedTx.Hash()) + return signedTx, nil +} + +// GetNodeIDsMap returns a map of consensus addresses to their node IDs for all current validators +func (p *Parlia) GetNodeIDsMap() (map[common.Address][]enode.ID, error) { + // Call GetValidators with latest block number + operatorAddrs, _, _, err := p.GetValidators(big.NewInt(0), big.NewInt(1000)) + if err != nil { + log.Error("Failed to get validators", "error", err) + return nil, fmt.Errorf("failed to get validators: %v", err) + } + log.Debug("Retrieved validators", "count", len(operatorAddrs)) + + // Get node IDs for validators + nodeIDsMap, err := p.getNodeIDsForValidators(operatorAddrs) + if err != nil { + log.Error("Failed to get node IDs", "error", err) + return nil, fmt.Errorf("failed to get node IDs: %v", err) + } + log.Debug("Retrieved node IDs map", "addresses", len(nodeIDsMap)) + + return nodeIDsMap, nil +} + +// RemoveNodeIDs creates a signed transaction to remove node IDs from the StakeHub contract +func (p *Parlia) RemoveNodeIDs(nodeIDs []enode.ID, nonce uint64) (*types.Transaction, error) { + log.Debug("Removing node IDs", "count", len(nodeIDs), "nonce", nonce) + + p.lock.RLock() + signTxFn := p.signTxFn + val := p.val + p.lock.RUnlock() + + if signTxFn == nil { + log.Error("Signing function not set") + return nil, fmt.Errorf("signing function not set, call Authorize first") + } + + // Create the call data for removeNodeIDs + data, err := p.stakeHubABI.Pack("removeNodeIDs", nodeIDs) + if err != nil { + log.Error("Failed to pack removeNodeIDs", "error", err) + return nil, fmt.Errorf("failed to pack removeNodeIDs: %v", err) + } + + to := common.HexToAddress(systemcontracts.StakeHubContract) + hexData := hexutil.Bytes(data) + hexNonce := hexutil.Uint64(nonce) + gas, err := p.ethAPI.EstimateGas(context.Background(), ethapi.TransactionArgs{ + From: &val, + To: &to, + Nonce: &hexNonce, + Data: &hexData, + }, nil, nil, nil) + if err != nil { + log.Error("Failed to estimate gas", "error", err) + return nil, fmt.Errorf("failed to estimate gas: %v", err) + } + + // Create the transaction + tx := types.NewTransaction( + nonce, + common.HexToAddress(systemcontracts.StakeHubContract), + common.Big0, + uint64(gas), + big.NewInt(1000000000), + data, + ) + + // Sign the transaction with the node's private key + log.Debug("Signing transaction", "validator", val) + signedTx, err := signTxFn(accounts.Account{Address: val}, tx, p.chainConfig.ChainID) + if err != nil { + log.Error("Failed to sign transaction", "error", err) + return nil, fmt.Errorf("failed to sign transaction: %v", err) + } + + log.Debug("Successfully created signed transaction", "hash", signedTx.Hash()) + return signedTx, nil +} diff --git a/core/bench_test.go b/core/bench_test.go index 9f7c525f09..7f7d3e33e5 100644 --- a/core/bench_test.go +++ b/core/bench_test.go @@ -183,7 +183,7 @@ func benchInsertChain(b *testing.B, disk bool, gen func(int, *BlockGen)) { if !disk { db = rawdb.NewMemoryDatabase() } else { - pdb, err := pebble.New(b.TempDir(), 128, 128, "", false) + pdb, err := pebble.New(b.TempDir(), 128, 128, "", false, true) if err != nil { b.Fatalf("cannot create temporary database: %v", err) } @@ -304,7 +304,7 @@ func makeChainForBench(db ethdb.Database, genesis *Genesis, full bool, count uin func benchWriteChain(b *testing.B, full bool, count uint64) { genesis := &Genesis{Config: params.AllEthashProtocolChanges} for i := 0; i < b.N; i++ { - pdb, err := pebble.New(b.TempDir(), 1024, 128, "", false) + pdb, err := pebble.New(b.TempDir(), 1024, 128, "", false, true) if err != nil { b.Fatalf("error opening database: %v", err) } @@ -317,7 +317,7 @@ func benchWriteChain(b *testing.B, full bool, count uint64) { func benchReadChain(b *testing.B, full bool, count uint64) { dir := b.TempDir() - pdb, err := pebble.New(dir, 1024, 128, "", false) + pdb, err := pebble.New(dir, 1024, 128, "", false, true) if err != nil { b.Fatalf("error opening database: %v", err) } @@ -333,7 +333,7 @@ func benchReadChain(b *testing.B, full bool, count uint64) { b.ResetTimer() for i := 0; i < b.N; i++ { - pdb, err = pebble.New(dir, 1024, 128, "", false) + pdb, err = pebble.New(dir, 1024, 128, "", false, true) if err != nil { b.Fatalf("error opening database: %v", err) } diff --git a/core/blockchain.go b/core/blockchain.go index 6f68a261e4..fde19bbe78 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -715,7 +715,7 @@ func (bc *BlockChain) GetJustifiedNumber(header *types.Header) uint64 { } // getFinalizedNumber returns the highest finalized number before the specific block. -func (bc *BlockChain) getFinalizedNumber(header *types.Header) uint64 { +func (bc *BlockChain) GetFinalizedNumber(header *types.Header) uint64 { if p, ok := bc.engine.(consensus.PoSA); ok { if finalizedHeader := p.GetFinalizedHeader(bc, header); finalizedHeader != nil { return finalizedHeader.Number.Uint64() @@ -747,7 +747,7 @@ func (bc *BlockChain) loadLastState() error { bc.currentBlock.Store(headBlock.Header()) headBlockGauge.Update(int64(headBlock.NumberU64())) justifiedBlockGauge.Update(int64(bc.GetJustifiedNumber(headBlock.Header()))) - finalizedBlockGauge.Update(int64(bc.getFinalizedNumber(headBlock.Header()))) + finalizedBlockGauge.Update(int64(bc.GetFinalizedNumber(headBlock.Header()))) // Restore the last known head header headHeader := headBlock.Header() @@ -1196,7 +1196,7 @@ func (bc *BlockChain) SnapSyncCommitHead(hash common.Hash) error { bc.currentBlock.Store(block.Header()) headBlockGauge.Update(int64(block.NumberU64())) justifiedBlockGauge.Update(int64(bc.GetJustifiedNumber(block.Header()))) - finalizedBlockGauge.Update(int64(bc.getFinalizedNumber(block.Header()))) + finalizedBlockGauge.Update(int64(bc.GetFinalizedNumber(block.Header()))) bc.chainmu.Unlock() // Destroy any existing state snapshot and regenerate it in the background, @@ -1337,7 +1337,7 @@ func (bc *BlockChain) writeHeadBlock(block *types.Block) { bc.currentBlock.Store(block.Header()) headBlockGauge.Update(int64(block.NumberU64())) justifiedBlockGauge.Update(int64(bc.GetJustifiedNumber(block.Header()))) - finalizedBlockGauge.Update(int64(bc.getFinalizedNumber(block.Header()))) + finalizedBlockGauge.Update(int64(bc.GetFinalizedNumber(block.Header()))) } // stopWithoutSaving stops the blockchain service. If any imports are currently in progress @@ -2617,9 +2617,6 @@ func (bc *BlockChain) insertSideChain(block *types.Block, it *insertIterator, ma if block == nil { log.Crit("Importing heavy sidechain block is nil", "hash", hashes[i], "number", numbers[i]) } - if bc.chainConfig.IsCancun(block.Number(), block.Time()) { - block = block.WithSidecars(bc.GetSidecarsByHash(hashes[i])) - } blocks = append(blocks, block) memory += block.Size() @@ -2691,9 +2688,6 @@ func (bc *BlockChain) recoverAncestors(block *types.Block, makeWitness bool) (co } else { b = bc.GetBlock(hashes[i], numbers[i]) } - if bc.chainConfig.IsCancun(b.Number(), b.Time()) { - b = b.WithSidecars(bc.GetSidecarsByHash(b.Hash())) - } if _, _, err := bc.insertChain(types.Blocks{b}, false, makeWitness && i == 0); err != nil { return b.ParentHash(), err } diff --git a/core/blockchain_reader.go b/core/blockchain_reader.go index eb0832509d..b0df521fa7 100644 --- a/core/blockchain_reader.go +++ b/core/blockchain_reader.go @@ -183,7 +183,7 @@ func (bc *BlockChain) HasFastBlock(hash common.Hash, number uint64) bool { return rawdb.HasReceipts(bc.db, hash, number) } -// GetBlock retrieves a block from the database by hash and number, +// GetBlock retrieves a block & sidecars from the database by hash and number, // caching it if found. func (bc *BlockChain) GetBlock(hash common.Hash, number uint64) *types.Block { // Short circuit if the block's already in the cache, retrieve otherwise @@ -194,12 +194,14 @@ func (bc *BlockChain) GetBlock(hash common.Hash, number uint64) *types.Block { if block == nil { return nil } + sidecars := rawdb.ReadBlobSidecars(bc.db, hash, number) + block = block.WithSidecars(sidecars) // Cache the found block for next time and return bc.blockCache.Add(block.Hash(), block) return block } -// GetBlockByHash retrieves a block from the database by hash, caching it if found. +// GetBlockByHash retrieves a block & sidecars from the database by hash, caching it if found. func (bc *BlockChain) GetBlockByHash(hash common.Hash) *types.Block { number := bc.hc.GetBlockNumber(hash) if number == nil { diff --git a/core/blockchain_repair_test.go b/core/blockchain_repair_test.go index 383e454ffb..e9d6694cf3 100644 --- a/core/blockchain_repair_test.go +++ b/core/blockchain_repair_test.go @@ -1767,7 +1767,7 @@ func testRepairWithScheme(t *testing.T, tt *rewindTest, snapshots bool, scheme s datadir := t.TempDir() ancient := filepath.Join(datadir, "ancient") - pdb, err := pebble.New(datadir, 0, 0, "", false) + pdb, err := pebble.New(datadir, 0, 0, "", false, true) if err != nil { t.Fatalf("Failed to create persistent key-value database: %v", err) } @@ -1861,7 +1861,7 @@ func testRepairWithScheme(t *testing.T, tt *rewindTest, snapshots bool, scheme s chain.stopWithoutSaving() // Start a new blockchain back up and see where the repair leads us - pdb, err = pebble.New(datadir, 0, 0, "", false) + pdb, err = pebble.New(datadir, 0, 0, "", false, true) if err != nil { t.Fatalf("Failed to reopen persistent key-value database: %v", err) } @@ -1926,7 +1926,7 @@ func testIssue23496(t *testing.T, scheme string) { datadir := t.TempDir() ancient := filepath.Join(datadir, "ancient") - pdb, err := pebble.New(datadir, 0, 0, "", false) + pdb, err := pebble.New(datadir, 0, 0, "", false, true) if err != nil { t.Fatalf("Failed to create persistent key-value database: %v", err) } @@ -1984,7 +1984,7 @@ func testIssue23496(t *testing.T, scheme string) { chain.stopWithoutSaving() // Start a new blockchain back up and see where the repair leads us - pdb, err = pebble.New(datadir, 0, 0, "", false) + pdb, err = pebble.New(datadir, 0, 0, "", false, true) if err != nil { t.Fatalf("Failed to reopen persistent key-value database: %v", err) } diff --git a/core/blockchain_sethead_test.go b/core/blockchain_sethead_test.go index 1b8f18fae6..5ed9a34292 100644 --- a/core/blockchain_sethead_test.go +++ b/core/blockchain_sethead_test.go @@ -1971,7 +1971,7 @@ func testSetHeadWithScheme(t *testing.T, tt *rewindTest, snapshots bool, scheme datadir := t.TempDir() ancient := filepath.Join(datadir, "ancient") - pdb, err := pebble.New(datadir, 0, 0, "", false) + pdb, err := pebble.New(datadir, 0, 0, "", false, true) if err != nil { t.Fatalf("Failed to create persistent key-value database: %v", err) } diff --git a/core/blockchain_snapshot_test.go b/core/blockchain_snapshot_test.go index 667a06f806..cfb158255e 100644 --- a/core/blockchain_snapshot_test.go +++ b/core/blockchain_snapshot_test.go @@ -66,7 +66,7 @@ func (basic *snapshotTestBasic) prepare(t *testing.T) (*BlockChain, []*types.Blo datadir := t.TempDir() ancient := filepath.Join(datadir, "ancient") - pdb, err := pebble.New(datadir, 0, 0, "", false) + pdb, err := pebble.New(datadir, 0, 0, "", false, true) if err != nil { t.Fatalf("Failed to create persistent key-value database: %v", err) } @@ -257,7 +257,7 @@ func (snaptest *crashSnapshotTest) test(t *testing.T) { chain.triedb.Close() // Start a new blockchain back up and see where the repair leads us - pdb, err := pebble.New(snaptest.datadir, 0, 0, "", false) + pdb, err := pebble.New(snaptest.datadir, 0, 0, "", false, true) if err != nil { t.Fatalf("Failed to create persistent key-value database: %v", err) } diff --git a/core/blockchain_test.go b/core/blockchain_test.go index 24c0505a7b..0cf7ac6ba5 100644 --- a/core/blockchain_test.go +++ b/core/blockchain_test.go @@ -2670,7 +2670,7 @@ func testSideImportPrunedBlocks(t *testing.T, scheme string) { datadir := t.TempDir() ancient := path.Join(datadir, "ancient") - pdb, err := pebble.New(datadir, 0, 0, "", false) + pdb, err := pebble.New(datadir, 0, 0, "", false, true) if err != nil { t.Fatalf("Failed to create persistent key-value database: %v", err) } @@ -4431,7 +4431,7 @@ func TestEIP7702(t *testing.T) { // The way the auths are combined, it becomes // 1. tx -> addr1 which is delegated to 0xaaaa // 2. addr1:0xaaaa calls into addr2:0xbbbb - // 3. addr2:0xbbbb writes to storage + // 3. addr2:0xbbbb writes to storage auth1, _ := types.SignSetCode(key1, types.SetCodeAuthorization{ ChainID: *uint256.MustFromBig(gspec.Config.ChainID), Address: aa, diff --git a/core/headerchain.go b/core/headerchain.go index 310dc57501..bf88e770cd 100644 --- a/core/headerchain.go +++ b/core/headerchain.go @@ -97,7 +97,7 @@ func NewHeaderChain(chainDb ethdb.Database, config *params.ChainConfig, engine c hc.currentHeaderHash = hc.CurrentHeader().Hash() headHeaderGauge.Update(hc.CurrentHeader().Number.Int64()) justifiedBlockGauge.Update(int64(hc.GetJustifiedNumber(hc.CurrentHeader()))) - finalizedBlockGauge.Update(int64(hc.getFinalizedNumber(hc.CurrentHeader()))) + finalizedBlockGauge.Update(int64(hc.GetFinalizedNumber(hc.CurrentHeader()))) return hc, nil } @@ -116,7 +116,7 @@ func (hc *HeaderChain) GetJustifiedNumber(header *types.Header) uint64 { } // getFinalizedNumber returns the highest finalized number before the specific block. -func (hc *HeaderChain) getFinalizedNumber(header *types.Header) uint64 { +func (hc *HeaderChain) GetFinalizedNumber(header *types.Header) uint64 { if p, ok := hc.engine.(consensus.PoSA); ok { if finalizedHeader := p.GetFinalizedHeader(hc, header); finalizedHeader != nil { return finalizedHeader.Number.Uint64() @@ -585,7 +585,7 @@ func (hc *HeaderChain) SetCurrentHeader(head *types.Header) { hc.currentHeaderHash = head.Hash() headHeaderGauge.Update(head.Number.Int64()) justifiedBlockGauge.Update(int64(hc.GetJustifiedNumber(head))) - finalizedBlockGauge.Update(int64(hc.getFinalizedNumber(head))) + finalizedBlockGauge.Update(int64(hc.GetFinalizedNumber(head))) } type ( @@ -673,7 +673,7 @@ func (hc *HeaderChain) setHead(headBlock uint64, headTime uint64, updateFn Updat hc.currentHeaderHash = parentHash headHeaderGauge.Update(parent.Number.Int64()) justifiedBlockGauge.Update(int64(hc.GetJustifiedNumber(parent))) - finalizedBlockGauge.Update(int64(hc.getFinalizedNumber(parent))) + finalizedBlockGauge.Update(int64(hc.GetFinalizedNumber(parent))) // If this is the first iteration, wipe any leftover data upwards too so // we don't end up with dangling daps in the database diff --git a/core/state_processor.go b/core/state_processor.go index 849055a16c..54f72dd5e2 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -20,6 +20,7 @@ import ( "errors" "fmt" "math/big" + "time" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/consensus" @@ -30,9 +31,12 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" ) +const largeTxGasLimit = 10000000 // 10M Gas, to measure the execution time of large tx + // StateProcessor is a basic Processor, which takes care of transitioning // state from one point to another. // @@ -77,7 +81,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg if lastBlock == nil { return nil, errors.New("could not get parent block") } - // Handle upgrade build-in system contract code + // Handle upgrade built-in system contract code systemcontracts.TryUpdateBuildInSystemContract(p.config, blockNumber, lastBlock.Time, block.Time(), statedb, true) var ( @@ -187,6 +191,18 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg // and uses the input parameters for its environment similar to ApplyTransaction. However, // this method takes an already created EVM instance as input. func ApplyTransactionWithEVM(msg *Message, gp *GasPool, statedb *state.StateDB, blockNumber *big.Int, blockHash common.Hash, tx *types.Transaction, usedGas *uint64, evm *vm.EVM, receiptProcessors ...ReceiptProcessor) (receipt *types.Receipt, err error) { + // Add timing measurement + var result *ExecutionResult + if tx.Gas() > largeTxGasLimit { + start := time.Now() + defer func() { + if result != nil && result.UsedGas > largeTxGasLimit { + elapsed := time.Since(start) + log.Info("LargeTX execution time", "block", blockNumber, "tx", tx.Hash(), "gasUsed", result.UsedGas, "elapsed", elapsed) + } + }() + } + if hooks := evm.Config.Tracer; hooks != nil { if hooks.OnTxStart != nil { hooks.OnTxStart(evm.GetVMContext(), tx, msg.From) @@ -196,7 +212,7 @@ func ApplyTransactionWithEVM(msg *Message, gp *GasPool, statedb *state.StateDB, } } // Apply the transaction to the current state (included in the env). - result, err := ApplyMessage(evm, msg, gp) + result, err = ApplyMessage(evm, msg, gp) if err != nil { return nil, err } @@ -210,7 +226,6 @@ func ApplyTransactionWithEVM(msg *Message, gp *GasPool, statedb *state.StateDB, *usedGas += result.UsedGas // Merge the tx-local access event into the "block-local" one, in order to collect - // all values, so that the witness can be built. if statedb.GetTrie().IsVerkle() { statedb.AccessEvents().Merge(evm.AccessEvents) diff --git a/core/state_processor_test.go b/core/state_processor_test.go index c9e8dca0e2..4b67892e7f 100644 --- a/core/state_processor_test.go +++ b/core/state_processor_test.go @@ -256,7 +256,8 @@ func TestStateProcessorErrors(t *testing.T) { }, want: "could not apply tx 0 [0xc18d10f4c809dbdfa1a074c3300de9bc4b7f16a20f0ec667f6f67312b71b956a]: EIP-7702 transaction with empty auth list (sender 0x71562b71999873DB5b286dF957af199Ec94617F7)", }, - // ErrSetCodeTxCreate cannot be tested: it is impossible to create a SetCode-tx with nil `to`. + // ErrSetCodeTxCreate cannot be tested here: it is impossible to create a SetCode-tx with nil `to`. + // The EstimateGas API tests test this case. } { block := GenerateBadBlock(gspec.ToBlock(), beacon.New(ethash.NewFaker()), tt.txs, gspec.Config, false) _, err := blockchain.InsertChain(types.Blocks{block}) diff --git a/core/systemcontracts/lorentz/rialto/ValidatorContract b/core/systemcontracts/lorentz/rialto/ValidatorContract deleted file mode 100644 index 0705dd92a0..0000000000 --- a/core/systemcontracts/lorentz/rialto/ValidatorContract +++ /dev/null @@ -1 +0,0 @@ -6080604052600436106104405760003560e01c80638b5ad0c911610234578063c81b16621161012e578063e1c7392a116100b6578063f92eb86b1161007a578063f92eb86b14610b3f578063f9a2bbc714610b54578063fccc281314610b69578063fd4ad81f14610b7e578063fd6a687914610bad57610447565b8063e1c7392a14610ac2578063e40716a114610ad7578063ea321e4914610aec578063eb57e20214610b0c578063f340fa0114610b2c57610447565b8063d58918ae116100fd578063d58918ae14610a59578063d68fb56a14610a6e578063daacdb6614610a83578063dc927faf14610a98578063df8079e914610aad57610447565b8063c81b166214610a0f578063c8509d81146107e6578063cb75a59214610a24578063ce910b0c14610a3957610447565b8063aa82dce1116101bc578063aef198a911610180578063aef198a914610999578063b7ab4db5146109ae578063b8cf4ef1146109d0578063c466689d146109e5578063c6d33945146109fa57610447565b8063aa82dce11461090d578063aad5606314610922578063ab51bb9614610937578063ac43175114610959578063ad3c9da61461097957610447565b80639dc09262116102035780639dc09262146108a45780639fe0f816146108b9578063a1a11bf5146108ce578063a5422d5c146108e3578063a78abc16146108f857610447565b80638b5ad0c9146108455780638c5d749d1461085a5780638d19a4101461086f5780639369d7de1461088f57610447565b80634df6e0c3116103455780636e47b482116102cd578063820dcaa811610291578063820dcaa8146107d1578063831d65d1146107e6578063862498821461080657806388b32f111461081b5780638a7beb011461083057610447565b80636e47b4821461076857806375d47a0a1461077d57806378dfed4a146107925780637a84ca2a146107a75780637e434d54146107bc57610447565b806355614fcc1161031457806355614fcc146106c1578063565c56b3146106e157806360eba4fe1461070157806362b72cf5146107215780636969a25c1461073657610447565b80634df6e0c31461066d5780635192c82c1461068257806351b4dce31461069757806351e80672146106ac57610447565b80632a0ffb6e116103c857806335409f7f1161039757806335409f7f146105de5780633b071dcc146105fe57806343756e5c1461062157806345cf9daf14610636578063493279b11461064b57610447565b80632a0ffb6e1461055e578063300c35671461057e578063321d398a1461059e5780633365af3a146105be57610447565b8063152ad3b81161040f578063152ad3b8146104dd5780631bd14ed8146104ff5780631e4c1524146105145780631ff1806914610534578063280870281461054957610447565b806304c4fec61461044c57806307a56847146104635780630e2374a51461048e5780631182b875146104b057610447565b3661044757005b600080fd5b34801561045857600080fd5b50610461610bc2565b005b34801561046f57600080fd5b50610478610c36565b6040516104859190616e48565b60405180910390f35b34801561049a57600080fd5b506104a3610c3c565b60405161048591906161fd565b3480156104bc57600080fd5b506104d06104cb3660046160e3565b610c42565b604051610485919061631d565b3480156104e957600080fd5b506104f2610d3d565b6040516104859190616312565b34801561050b57600080fd5b50610478610d46565b34801561052057600080fd5b5061046161052f366004615f11565b610d4c565b34801561054057600080fd5b50610478611080565b34801561055557600080fd5b506104a3611086565b34801561056a57600080fd5b50610461610579366004615e71565b61108c565b34801561058a57600080fd5b50610461610599366004615ea9565b6110ad565b3480156105aa57600080fd5b506104f26105b9366004616090565b6113f6565b3480156105ca57600080fd5b506104f26105d9366004616090565b6114c5565b3480156105ea57600080fd5b506104616105f9366004615e71565b611576565b34801561060a57600080fd5b506106136116db565b6040516104859291906162a2565b34801561062d57600080fd5b506104a36119b7565b34801561064257600080fd5b506104786119bd565b34801561065757600080fd5b506106606119c3565b6040516104859190616e39565b34801561067957600080fd5b506106136119c9565b34801561068e57600080fd5b50610478611b63565b3480156106a357600080fd5b506104a3611b69565b3480156106b857600080fd5b506104a3611b6f565b3480156106cd57600080fd5b506104f26106dc366004615e71565b611b75565b3480156106ed57600080fd5b506104786106fc366004615e71565b611bb1565b34801561070d57600080fd5b506104d061071c366004616090565b611c02565b34801561072d57600080fd5b50610478611ca8565b34801561074257600080fd5b50610756610751366004616090565b611cae565b6040516104859695949392919061622a565b34801561077457600080fd5b506104a3611d12565b34801561078957600080fd5b506104a3611d18565b34801561079e57600080fd5b50610478611d1e565b3480156107b357600080fd5b50610478611d24565b3480156107c857600080fd5b506104a3611d2a565b3480156107dd57600080fd5b50610478611d30565b3480156107f257600080fd5b506104616108013660046160e3565b611d36565b34801561081257600080fd5b50610478611d57565b34801561082757600080fd5b50610478611d5d565b34801561083c57600080fd5b506104f2611d63565b34801561085157600080fd5b50610478611d6c565b34801561086657600080fd5b50610478611d72565b34801561087b57600080fd5b5061047861088a366004615e71565b611d8f565b34801561089b57600080fd5b50610461611dcf565b3480156108b057600080fd5b506104a3611ee3565b3480156108c557600080fd5b50610478611ee9565b3480156108da57600080fd5b506104a3611eee565b3480156108ef57600080fd5b506104d0611ef4565b34801561090457600080fd5b506104f2611f10565b34801561091957600080fd5b506104a3611f19565b34801561092e57600080fd5b506104a3611f1f565b34801561094357600080fd5b5061094c611f25565b6040516104859190616e7b565b34801561096557600080fd5b50610461610974366004616034565b611f2a565b34801561098557600080fd5b50610478610994366004615e71565b612993565b3480156109a557600080fd5b506104786129a5565b3480156109ba57600080fd5b506109c36129b2565b604051610485919061628f565b3480156109dc57600080fd5b50610478612a9d565b3480156109f157600080fd5b50610478612aa2565b348015610a0657600080fd5b50610478612aa8565b348015610a1b57600080fd5b506104a3612aad565b348015610a3057600080fd5b50610478612ab3565b348015610a4557600080fd5b506104d0610a54366004616090565b612ab9565b348015610a6557600080fd5b50610478612ac6565b348015610a7a57600080fd5b50610478612acc565b348015610a8f57600080fd5b50610478612b0b565b348015610aa457600080fd5b506104a3612b11565b348015610ab957600080fd5b506104a3612b17565b348015610ace57600080fd5b50610461612b1d565b348015610ae357600080fd5b50610478612da8565b348015610af857600080fd5b506104f2610b07366004615ff5565b612dae565b348015610b1857600080fd5b50610461610b27366004615e71565b612f34565b610461610b3a366004615e71565b61303c565b348015610b4b57600080fd5b506104786133f2565b348015610b6057600080fd5b506104a36133f8565b348015610b7557600080fd5b506104a36133fe565b348015610b8a57600080fd5b50610b9e610b99366004616090565b613404565b60405161048593929190616e51565b348015610bb957600080fd5b506104a36134c6565b6000610bcd33611d8f565b9050600b8181548110610bdc57fe5b600091825260209091206001601690920201015460ff16610c185760405162461bcd60e51b8152600401610c0f90616aef565b60405180910390fd5b6000610c22612acc565b9050610c3133838360016134cc565b505050565b60095481565b61200181565b60005460609060ff16610c675760405162461bcd60e51b8152600401610c0f90616502565b600b54610d2557610c76615a1d565b60015460005b81811015610d2157600b80546001810182556000919091528351600080516020616f138339815191526016909202918201908155602080860151600080516020616f538339815191528401805460ff1916911515919091179055604086015180518794610cfd93600080516020616f33833981519152909101920190615a4c565b506060820151610d139060038301906013615ac6565b505050806001019050610c7c565b5050505b60405162461bcd60e51b8152600401610c0f90616754565b60075460ff1681565b600f5481565b334114610d6b5760405162461bcd60e51b8152600401610c0f90616c50565b3a15610d895760405162461bcd60e51b8152600401610c0f90616a2e565b8251604080518281526020808402820101909152606090828015610dc757816020015b610db4615af3565b815260200190600190039081610dac5790505b50905060005b82811015610e71576040518060c00160405280878381518110610dec57fe5b60200260200101516001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b03168152602001868381518110610e2e57fe5b60200260200101516001600160401b031681526020016000151581526020016000815250828281518110610e5e57fe5b6020908102919091010152600101610dcd565b50606080610e7f83866136be565b9150915060005b600154811015610f7557600060018281548110610e9f57fe5b906000526020600020906004020160030154905080600014610f6c57600060018381548110610eca57fe5b9060005260206000209060040201600301819055506120026001600160a01b031663092193ab8260018581548110610efe57fe5b60009182526020909120600491820201546040516001600160e01b031960e086901b168152610f39926001600160a01b0390921691016161fd565b6000604051808303818588803b158015610f5257600080fd5b505af1158015610f66573d6000803e3d6000fd5b50505050505b50600101610e86565b504715610fe3577f6ecc855f9440a9282c90913bbc91619fd44f5ec0b462af28d127b116f130aa4d47604051610fab9190616e48565b60405180910390a1604051611002904780156108fc02916000818181858888f19350505050158015610fe1573d6000803e3d6000fd5b505b6000600355815115610ff957610ff98282613ba8565b6110016001600160a01b031663fc4333cd6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561103657600080fd5b505af115801561104a573d6000803e3d6000fd5b50506040517fedd8d7296956dd970ab4de3f2fc03be2b0ffc615d20cd4c72c6e44f928630ebf925060009150a150505050505050565b60035481565b61200581565b3361200214610d255760405162461bcd60e51b8152600401610c0f90616e02565b3341146110cc5760405162461bcd60e51b8152600401610c0f90616c50565b60105443116110ed5760405162461bcd60e51b8152600401610c0f9061667e565b3a1561110b5760405162461bcd60e51b8152600401610c0f90616a2e565b60005460ff1661112d5760405162461bcd60e51b8152600401610c0f90616502565b60006110023168056bc75e2d631000008111156111645761115d8168056bc75e2d6310000063ffffffff61439716565b915061116b565b50506113ec565b6040516309a99b4f60e41b815261100290639a99b4f0906111929030908690600401616211565b602060405180830381600087803b1580156111ac57600080fd5b505af11580156111c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111e491906160a8565b9150816111f25750506113ec565b6000805b848110156112205785858281811061120a57fe5b90506020020135820191508060010190506111f6565b508061122e575050506113ec565b6000806000805b898110156113e4578489898381811061124a57fe5b9050602002013588028161125a57fe5b0493508a8a8281811061126957fe5b905060200201602081019061127e9190615e71565b6001600160a01b0381166000908152600460205260409020549093509150811561139a5760006001808403815481106112b357fe5b9060005260206000209060040201905080600201601c9054906101000a900460ff161561132057836001600160a01b03167fb9c75cbbfde137c4281689580799ef5f52144e78858f776a5979b2b212137d85866040516113139190616e48565b60405180910390a2611394565b600354611333908663ffffffff6143d916565b600390815581015461134b908663ffffffff6143d916565b60038201556040516001600160a01b038516907fcb0aad6cf9cd03bdf6137e359f541c42f38b39f007cae8e89e88aa7d8c6617b29061138b908890616e48565b60405180910390a25b506113dc565b826001600160a01b03167fb9c75cbbfde137c4281689580799ef5f52144e78858f776a5979b2b212137d85856040516113d39190616e48565b60405180910390a25b600101611235565b505050505050505b5050436010555050565b600154600090821061140a575060006114c0565b60006001600160a01b03166001838154811061142257fe5b60009182526020909120600490910201546001600160a01b03161480611452575060085415806114525750600a54155b80611461575060085460095410155b806114725750611470826114c5565b155b8061149b57506000600b838154811061148757fe5b906000526020600020906016020160000154115b806114af575060016114ab6129b2565b5111155b156114bc575060006114c0565b5060015b919050565b60015460009082106114d9575060006114c0565b600b54821061151657600182815481106114ef57fe5b9060005260206000209060040201600201601c9054906101000a900460ff161590506114c0565b6001828154811061152357fe5b9060005260206000209060040201600201601c9054906101000a900460ff161580156115705750600b828154811061155757fe5b600091825260209091206001601690920201015460ff16155b92915050565b600b5461163457611585615a1d565b60015460005b8181101561163057600b80546001810182556000919091528351600080516020616f138339815191526016909202918201908155602080860151600080516020616f538339815191528401805460ff191691151591909117905560408601518051879461160c93600080516020616f33833981519152909101920190615a4c565b5060608201516116229060038301906013615ac6565b50505080600101905061158b565b5050505b336110011480611645575033612002145b6116615760405162461bcd60e51b8152600401610c0f90616539565b6001600160a01b0381166000908152600460205260409020548061168557506116d8565b6001810390506000600b828154811061169a57fe5b600091825260209091206001601690920201015460ff1690506116bd83836143fe565b80156116c65750805b15610c31576009805460001901905550505b50565b60015460609081906000805b8281101561172e57600181815481106116fc57fe5b9060005260206000209060040201600201601c9054906101000a900460ff16611726576001909101905b6001016116e7565b5060608160405190808252806020026020018201604052801561175b578160200160208202803683370190505b50905060608260405190808252806020026020018201604052801561179457816020015b606081526020019060019003908161177f5790505b50600b546000945090915084141561190f5760005b8481101561190957600181815481106117be57fe5b9060005260206000209060040201600201601c9054906101000a900460ff1661190157600181815481106117ee57fe5b600091825260209091206004909102015483516001600160a01b039091169084908690811061181957fe5b60200260200101906001600160a01b031690816001600160a01b031681525050600b818154811061184657fe5b600091825260209182902060026016909202018101805460408051601f6000196101006001861615020190931694909404918201859004850284018501905280835291929091908301828280156118de5780601f106118b3576101008083540402835291602001916118de565b820191906000526020600020905b8154815290600101906020018083116118c157829003601f168201915b50505050508285815181106118ef57fe5b60209081029190910101526001909301925b6001016117a9565b506119ab565b60005b848110156119a9576001818154811061192757fe5b9060005260206000209060040201600201601c9054906101000a900460ff166119a1576001818154811061195757fe5b600091825260209091206004909102015483516001600160a01b039091169084908690811061198257fe5b6001600160a01b03909216602092830291909101909101526001909301925b600101611912565b505b909450925050505b9091565b61100181565b60085481565b6102ca81565b6060806000600e549050600080600c54116119e55760156119e9565b600c545b905060c860606119f76129b2565b90506060611a04826147c1565b905083825111611a1c5790955093506119b392505050565b84848351031015611a2e578382510394505b8415611a6e576000834381611a3f57fe5b049050611a5483838389890360008b8b61492f565b611a6c8383838989038a8a038b8c8c8b51030161492f565b505b606084604051908082528060200260200182016040528015611a9a578160200160208202803683370190505b509050606085604051908082528060200260200182016040528015611ad357816020015b6060815260200190600190039081611abe5790505b50905060005b86811015611b5457848181518110611aed57fe5b6020026020010151838281518110611b0157fe5b60200260200101906001600160a01b031690816001600160a01b031681525050838181518110611b2d57fe5b6020026020010151828281518110611b4157fe5b6020908102919091010152600101611ad9565b50909750955050505050509091565b60065481565b61200681565b61200081565b6001600160a01b03811660009081526004602052604081205480611b9d5760009150506114c0565b60001901611baa816114c5565b9392505050565b6001600160a01b03811660009081526004602052604081205480611bd95760009150506114c0565b600180820381548110611be857fe5b906000526020600020906004020160030154915050919050565b60128181548110611c0f57fe5b600091825260209182902001805460408051601f6002600019610100600187161502019094169390930492830185900485028101850190915281815293509091830182828015611ca05780601f10611c7557610100808354040283529160200191611ca0565b820191906000526020600020905b815481529060010190602001808311611c8357829003601f168201915b505050505081565b60105481565b60018181548110611cbb57fe5b600091825260209091206004909102018054600182015460028301546003909301546001600160a01b0392831694509082169291821691600160a01b81046001600160401b031691600160e01b90910460ff169086565b61100581565b61100881565b6103e881565b600c5481565b61200381565b61271081565b3361200014610d255760405162461bcd60e51b8152600401610c0f90616c01565b60025481565b60115481565b60145460ff1681565b600a5481565b600060175460001415611d8757506001611d8c565b506017545b90565b6001600160a01b03811660009081526004602052604081205480611dc55760405162461bcd60e51b8152600401610c0f90616b89565b6000190192915050565b600b54611e8d57611dde615a1d565b60015460005b81811015611e8957600b80546001810182556000919091528351600080516020616f138339815191526016909202918201908155602080860151600080516020616f538339815191528401805460ff1916911515919091179055604086015180518794611e6593600080516020616f33833981519152909101920190615a4c565b506060820151611e7b9060038301906013615ac6565b505050806001019050611de4565b5050505b600854611e9a5760036008555b600a54611ea7576002600a555b6000611eb233611d8f565b9050611ebd816113f6565b611ed95760405162461bcd60e51b8152600401610c0f906169aa565b6116d83382614a86565b61100781565b600381565b61100681565b6040518060a0016040528060788152602001616f736078913981565b60005460ff1681565b61200281565b61300081565b600081565b60005460ff16611f4c5760405162461bcd60e51b8152600401610c0f90616502565b3361100714611f6d5760405162461bcd60e51b8152600401610c0f90616a5c565b611fcd84848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260098152686275726e526174696f60b81b60208201529150614b1e9050565b156120825760208114611ff25760405162461bcd60e51b8152600401610c0f90616362565b604080516020601f840181900481028201810190925282815260009161203091858580838501838280828437600092019190915250614b7792505050565b905061271061205c601854612050600f54856143d990919063ffffffff16565b9063ffffffff6143d916565b111561207a5760405162461bcd60e51b8152600401610c0f90616778565b600655612950565b6120ec84848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260138152726d61784e756d4f664d61696e7461696e696e6760681b60208201529150614b1e9050565b1561218657602081146121115760405162461bcd60e51b8152600401610c0f90616399565b604080516020601f840181900481028201810190925282815260009161214f91858580838501838280828437600092019190915250614b7792505050565b600c549091508061215e575060155b80821061217d5760405162461bcd60e51b8152600401610c0f906166c0565b50600855612950565b6121ef84848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260128152716d61696e7461696e536c6173685363616c6560701b60208201529150614b1e9050565b1561228857602081146122145760405162461bcd60e51b8152600401610c0f90616488565b604080516020601f840181900481028201810190925282815260009161225291858580838501838280828437600092019190915250614b7792505050565b90506000811180156122645750600a81105b6122805760405162461bcd60e51b8152600401610c0f90616ce5565b600a55612950565b6122fc84848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152601981527f6d61784e756d4f66576f726b696e6743616e646964617465730000000000000060208201529150614b1e9050565b1561238b57602081146123215760405162461bcd60e51b8152600401610c0f9061643c565b604080516020601f840181900481028201810190925282815260009161235f91858580838501838280828437600092019190915250614b7792505050565b9050600d548111156123835760405162461bcd60e51b8152600401610c0f90616881565b600e55612950565b6123f484848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260128152716d61784e756d4f6643616e6469646174657360701b60208201529150614b1e9050565b1561247657602081146124195760405162461bcd60e51b8152600401610c0f90616aaa565b604080516020601f840181900481028201810190925282815260009161245791858580838501838280828437600092019190915250614b7792505050565b600d819055600e5490915081101561247057600d54600e555b50612950565b6124da84848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152600d81526c6e756d4f66436162696e65747360981b60208201529150614b1e9050565b156125ff57602081146124ff5760405162461bcd60e51b8152600401610c0f906164cd565b604080516020601f840181900481028201810190925282815260009161253d91858580838501838280828437600092019190915250614b7792505050565b90506000811161255f5760405162461bcd60e51b8152600401610c0f90616636565b60006120026001600160a01b031663c473318f6040518163ffffffff1660e01b815260040160206040518083038186803b15801561259c57600080fd5b505afa1580156125b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125d491906160a8565b9050808211156125f65760405162461bcd60e51b8152600401610c0f906163df565b50600c55612950565b61266b84848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152601581527473797374656d52657761726442617365526174696f60581b60208201529150614b1e9050565b1561271457602081146126905760405162461bcd60e51b8152600401610c0f90616c9d565b604080516020601f84018190048102820181019092528281526000916126ce91858580838501838280828437600092019190915250614b7792505050565b90506127106126ee601854612050600654856143d990919063ffffffff16565b111561270c5760405162461bcd60e51b8152600401610c0f906165a7565b600f55612950565b61278884848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152601881527f73797374656d526577617264416e74694d4556526174696f000000000000000060208201529150614b1e9050565b1561283157602081146127ad5760405162461bcd60e51b8152600401610c0f90616807565b604080516020601f84018190048102820181019092528281526000916127eb91858580838501838280828437600092019190915250614b7792505050565b905061271061280b600f54612050600654856143d990919063ffffffff16565b11156128295760405162461bcd60e51b8152600401610c0f9061691b565b601855612950565b61289284848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152600a8152690e8eae4dc98cadccee8d60b31b60208201529150614b1e9050565b1561293857602081146128b75760405162461bcd60e51b8152600401610c0f9061671d565b604080516020601f84018190048102820181019092528281526000916128f591858580838501838280828437600092019190915250614b7792505050565b905060038110158015612909575060408111155b806129145750806001145b6129305760405162461bcd60e51b8152600401610c0f90616d42565b601755612950565b60405162461bcd60e51b8152600401610c0f90616d92565b7f6cdb0ac70ab7f2e2d035cca5be60d89906f2dede7648ddbd7402189c1eeed17a848484846040516129859493929190616330565b60405180910390a150505050565b60046020526000908152604090205481565b68056bc75e2d6310000081565b6001546060906000805b828110156129e1576129cd816114c5565b156129d9578160010191505b6001016129bc565b50606081604051908082528060200260200182016040528015612a0e578160200160208202803683370190505b5090506000915060005b83811015612a9557612a29816114c5565b15612a8d5760018181548110612a3b57fe5b600091825260209091206004909102015482516001600160a01b0390911690839085908110612a6657fe5b60200260200101906001600160a01b031690816001600160a01b0316815250508260010192505b600101612a18565b509250505090565b601581565b61027181565b600281565b61100281565b60175481565b60138181548110611c0f57fe5b60185481565b6000612ad66129b2565b519050600080600c5411612aeb576015612aef565b600c545b905080821115612afd578091505b81612b0757600191505b5090565b60055481565b61100381565b61200481565b60005460ff1615612b405760405162461bcd60e51b8152600401610c0f90616b1b565b612b48615b28565b6000612b6b6040518060a0016040528060788152602001616f7360789139614b7c565b9150915080612b8c5760405162461bcd60e51b8152600401610c0f90616bc0565b612b94615a1d565b60005b836020015151811015612d9557600b80546001810182556000919091528251600080516020616f138339815191526016909202918201908155602080850151600080516020616f538339815191528401805460ff1916911515919091179055604085015180518694612c1d93600080516020616f33833981519152909101920190615a4c565b506060820151612c339060038301906013615ac6565b50505083604001518181518110612c4657fe5b6020026020010151600b8281548110612c5b57fe5b90600052602060002090601602016002019080519060200190612c7f929190615a4c565b50600184602001518281518110612c9257fe5b60209081029190910181015182546001818101855560009485528385208351600493840290910180546001600160a01b039283166001600160a01b03199182161782558587015182850180549185169183169190911790556040860151600283018054606089015160808a01511515600160e01b0260ff60e01b196001600160401b03909216600160a01b0267ffffffffffffffff60a01b199590981692909516919091179290921694909417161790915560a090930151600390930192909255918701518051918501939185908110612d6857fe5b602090810291909101810151516001600160a01b0316825281019190915260400160002055600101612b97565b50506000805460ff191660011790555050565b600d5481565b601354600090815b81811015612eb757612e9f85858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050601380549092508591508110612e0757fe5b600091825260209182902001805460408051601f6002600019610100600187161502019094169390930492830185900485028101850190915281815292830182828015612e955780601f10612e6a57610100808354040283529160200191612e95565b820191906000526020600020905b815481529060010190602001808311612e7857829003601f168201915b5050505050614d38565b15612eaf57600192505050611570565b600101612db6565b5060125460005b81811015612f2857612f0f86868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050601280549092508591508110612e0757fe5b15612f205760019350505050611570565b600101612ebe565b50600095945050505050565b3361100114612f555760405162461bcd60e51b8152600401610c0f90616db9565b600b5461301357612f64615a1d565b60015460005b8181101561300f57600b80546001810182556000919091528351600080516020616f138339815191526016909202918201908155602080860151600080516020616f538339815191528401805460ff1916911515919091179055604086015180518794612feb93600080516020616f33833981519152909101920190615a4c565b5060608201516130019060038301906013615ac6565b505050806001019050612f6a565b5050505b600061301e82614d9c565b9050613029816113f6565b15613038576130388282614a86565b5050565b33411461305b5760405162461bcd60e51b8152600401610c0f90616c50565b60005460ff1661307d5760405162461bcd60e51b8152600401610c0f90616502565b6000341161309d5760405162461bcd60e51b8152600401610c0f90616852565b3a156130bb5760405162461bcd60e51b8152600401610c0f90616a2e565b6001600160a01b03811660009081526004602052604090205460145434919060ff166130fb57610271600f556103e86006556014805460ff191660011790555b600f54601754600110801561311257506000601854115b1561313757600160175403601754438161312857fe5b06601854028161313457fe5b04015b6000831180156131475750600081115b156131f4576000613170612710613164348563ffffffff614f1f16565b9063ffffffff614f5916565b905080156131f2576040516110029082156108fc029083906000818181858888f193505050501580156131a7573d6000803e3d6000fd5b507f6ecc855f9440a9282c90913bbc91619fd44f5ec0b462af28d127b116f130aa4d816040516131d79190616e48565b60405180910390a16131ef848263ffffffff61439716565b93505b505b60008311801561320657506000600654115b156132ac57600061322861271061316460065434614f1f90919063ffffffff16565b905080156132aa5760405161dead9082156108fc029083906000818181858888f1935050505015801561325f573d6000803e3d6000fd5b507f627059660ea01c4733a328effb2294d2f86905bf806da763a89cee254de8bee58160405161328f9190616e48565b60405180910390a16132a7848263ffffffff61439716565b93505b505b81156133aa5760006001808403815481106132c357fe5b9060005260206000209060040201905080600201601c9054906101000a900460ff161561333057846001600160a01b03167ff177e5d6c5764d79c32883ed824111d9b13f5668cf6ab1cc12dd36791dd955b4856040516133239190616e48565b60405180910390a26133a4565b600354613343908563ffffffff6143d916565b600390815581015461335b908563ffffffff6143d916565b60038201556040516001600160a01b038616907f93a090ecc682c002995fad3c85b30c5651d7fd29b0be5da9d784a3302aedc0559061339b908790616e48565b60405180910390a25b506133ec565b836001600160a01b03167ff177e5d6c5764d79c32883ed824111d9b13f5668cf6ab1cc12dd36791dd955b4846040516133e39190616e48565b60405180910390a25b50505050565b600e5481565b61100081565b61dead81565b600b818154811061341157fe5b6000918252602091829020601691909102018054600180830154600280850180546040805161010096831615969096026000190190911692909204601f810188900488028501880190925281845293965060ff909116949192918301828280156134bc5780601f10613491576101008083540402835291602001916134bc565b820191906000526020600020905b81548152906001019060200180831161349f57829003601f168201915b5050505050905083565b61100481565b6000600a54600014806134dd575082155b806134e85750600954155b156134f5575060006136b6565b60096000815460019003919050819055506000613540600a5461316486613164600b8a8154811061352257fe5b6000918252602090912060169091020154439063ffffffff61439716565b90506000600b868154811061355157fe5b906000526020600020906016020160010160006101000a81548160ff0219169083151502179055506000806110016001600160a01b0316638256ace66040518163ffffffff1660e01b8152600401604080518083038186803b1580156135b657600080fd5b505afa1580156135ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135ee91906160c0565b915091506000935080831061366c5761360788886143fe565b506040516328aa02b160e01b8152611001906328aa02b190613631908b9087908a9060040161626c565b600060405180830381600087803b15801561364b57600080fd5b505af115801561365f573d6000803e3d6000fd5b505050506001935061367e565b81831061367e5761367c88614d9c565b505b6040516001600160a01b038916907fb9d38178dc641ff1817967a63c9078cbcd955a9f1fcd75e0e3636de615d44d3b90600090a25050505b949350505050565b6060806000808080806136cf612acc565b6001549091505b801561390157600181039250600b83815481106136ef57fe5b600091825260209091206001601690920201015460ff1661370f576138f8565b6001838154811061371c57fe5b600091825260208220600490910201546001600160a01b03169550613746908690859085906134cc565b935083613752576138f8565b60405163436aa28360e11b81526000908190612002906386d545069061377c908a906004016161fd565b60206040518083038186803b15801561379457600080fd5b505afa1580156137a8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137cc9190615e8d565b90506001600160a01b03811615613855576040516302ceee9160e11b81526120029063059ddd22906138029084906004016161fd565b60206040518083038186803b15801561381a57600080fd5b505afa15801561382e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138529190615e8d565b91505b60005b8c518110156138f457876001600160a01b03168d828151811061387757fe5b6020026020010151600001516001600160a01b031614806138c05750826001600160a01b03168d82815181106138a957fe5b6020026020010151600001516001600160a01b0316145b156138ec5760018d82815181106138d357fe5b60209081029190910101519015156080909101526138f4565b600101613858565b5050505b600019016136d6565b5060005b895181101561396e5789818151811061391a57fe5b6020026020010151608001518061395a575060006001600160a01b03168a828151811061394357fe5b6020026020010151600001516001600160a01b0316145b15613966578560010195505b600101613905565b5088518510613a565760408051600180825281830190925290816020015b613994615af3565b81526020019060019003908161398c575050604080516001808252818301909252919850602082015b60608152602001906001900390816139bd579050509550886000815181106139e157fe5b6020026020010151876000815181106139f657fe5b602002602001018190525087600081518110613a0e57fe5b602002602001015186600081518110613a2357fe5b6020026020010181905250600087600081518110613a3d57fe5b6020908102919091010151901515608090910152613b9b565b84895103604051908082528060200260200182016040528015613a9357816020015b613a80615af3565b815260200190600190039081613a785790505b50965084895103604051908082528060200260200182016040528015613acd57816020015b6060815260200190600190039081613ab85790505b5095506000915060005b8951811015613b9957898181518110613aec57fe5b602002602001015160800151158015613b2f575060006001600160a01b03168a8281518110613b1757fe5b6020026020010151600001516001600160a01b031614155b15613b9157898181518110613b4057fe5b6020026020010151888481518110613b5457fe5b6020026020010181905250888181518110613b6b57fe5b6020026020010151878481518110613b7f57fe5b60200260200101819052508260010192505b600101613ad7565b505b50505050505b9250929050565b600154825160005b82811015613cc5576001613bc2615af3565b60018381548110613bcf57fe5b600091825260208083206040805160c08101825260049490940290910180546001600160a01b0390811685526001820154811693850193909352600281015492831691840191909152600160a01b82046001600160401b03166060840152600160e01b90910460ff16151560808301526003015460a082015291505b84811015613c9957878181518110613c5f57fe5b6020026020010151600001516001600160a01b031682600001516001600160a01b03161415613c915760009250613c99565b600101613c4b565b508115613cbb5780516001600160a01b03166000908152600460205260408120555b5050600101613bb0565b5080821115613d8457805b82811015613d82576001805480613ce357fe5b60008281526020812060046000199093019283020180546001600160a01b0319908116825560018201805490911690556002810180546001600160e81b0319169055600301559055600b805480613d3657fe5b60008281526020812060166000199093019283020181815560018101805460ff1916905590613d686002830182615b4c565b613d76600383016000615b90565b50509055600101613cd0565b505b6000818310613d935781613d95565b825b905060005b8181101561413957613e47868281518110613db157fe5b602002602001015160018381548110613dc657fe5b60009182526020918290206040805160c08101825260049390930290910180546001600160a01b0390811684526001820154811694840194909452600281015493841691830191909152600160a01b83046001600160401b03166060830152600160e01b90920460ff161515608082015260039091015460a0820152614f9b565b613ffb578060010160046000888481518110613e5f57fe5b6020026020010151600001516001600160a01b03166001600160a01b0316815260200190815260200160002081905550858181518110613e9b57fe5b602002602001015160018281548110613eb057fe5b6000918252602091829020835160049092020180546001600160a01b039283166001600160a01b0319918216178255928401516001820180549184169185169190911790556040840151600282018054606087015160808801511515600160e01b0260ff60e01b196001600160401b03909216600160a01b0267ffffffffffffffff60a01b1995909716929097169190911792909216939093171692909217905560a0909101516003909101558451859082908110613f6b57fe5b6020026020010151600b8281548110613f8057fe5b90600052602060002090601602016002019080519060200190613fa4929190615a4c565b506000600b8281548110613fb457fe5b60009182526020822060169190910201600101805460ff191692151592909217909155600b805483908110613fe557fe5b6000918252602090912060169091020155614131565b85818151811061400757fe5b6020026020010151606001516001828154811061402057fe5b906000526020600020906004020160020160146101000a8154816001600160401b0302191690836001600160401b031602179055506140e685828151811061406457fe5b6020026020010151600b838154811061407957fe5b600091825260209182902060026016909202018101805460408051601f600019610100600186161502019093169490940491820185900485028401850190528083529192909190830182828015612e955780601f10612e6a57610100808354040283529160200191612e95565b614131578481815181106140f657fe5b6020026020010151600b828154811061410b57fe5b9060005260206000209060160201600201908051906020019061412f929190615a4c565b505b600101613d9a565b50828211156143115761414a615a1d565b835b8381101561430e5785818151811061416057fe5b60200260200101518260400181905250600187828151811061417e57fe5b6020908102919091018101518254600181810185556000948552838520835160049093020180546001600160a01b039384166001600160a01b0319918216178255848601518284018054918616918316919091179055604080860151600284018054606089015160808a01511515600160e01b0260ff60e01b196001600160401b03909216600160a01b0267ffffffffffffffff60a01b1995909a1692909616919091179290921696909617169190911790935560a090930151600390930192909255600b8054928301815590935284516016909102600080516020616f13833981519152810191825585830151600080516020616f538339815191528201805491151560ff19909216919091179055928501518051869492936142b493600080516020616f3383398151915201920190615a4c565b5060608201516142ca9060038301906013615ac6565b50505080600101600460008984815181106142e157fe5b602090810291909101810151516001600160a01b031682528101919091526040016000205560010161414c565b50505b614319614ff7565b6143216151d9565b6000600981905560015493505b8381101561438f576000600b828154811061434557fe5b60009182526020822060169190910201600101805460ff191692151592909217909155600b80548390811061437657fe5b600091825260209091206016909102015560010161432e565b505050505050565b6000611baa83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506153c7565b600082820183811015611baa5760405162461bcd60e51b8152600401610c0f90616570565b6000806001838154811061440e57fe5b906000526020600020906004020160030154905060006001808054905003905060016144386129b2565b511161446d5760006001858154811061444d57fe5b906000526020600020906004020160030181905550600092505050611570565b846001600160a01b03167f3b6f9ef90462b512a1293ecec018670bf7b7f1876fb727590a8a6d7643130a70836040516144a69190616e48565b60405180910390a26001600160a01b038516600090815260046020526040812055835b6001546000190181101561469357600181600101815481106144e757fe5b90600052602060002090600402016001828154811061450257fe5b60009182526020909120825460049092020180546001600160a01b03199081166001600160a01b0393841617825560018085015481840180548416918616919091179055600280860180549185018054909416919095161780835584546001600160401b03600160a01b91829004160267ffffffffffffffff60a01b1990911617808355935460ff600160e01b918290041615150260ff60e01b19909416939093179055600392830154920191909155600b8054909183019081106145c357fe5b9060005260206000209060160201600b82815481106145de57fe5b600091825260209091208254601690920201908155600180830154818301805460ff909216151560ff1990921691909117905560028084018054614635938386019390821615610100026000190190911604615b9f565b5061464860038281019084016013615c14565b5090505080600101600460006001848154811061466157fe5b600091825260208083206004909202909101546001600160a01b031683528201929092526040019020556001016144c9565b50600180548061469f57fe5b60008281526020812060046000199093019283020180546001600160a01b0319908116825560018201805490911690556002810180546001600160e81b0319169055600301559055600b8054806146f257fe5b60008281526020812060166000199093019283020181815560018101805460ff19169055906147246002830182615b4c565b614732600383016000615b90565b50509055600081838161474157fe5b04905080156147b55760015460005b818110156147b257614789836001838154811061476957fe5b9060005260206000209060040201600301546143d990919063ffffffff16565b6001828154811061479657fe5b6000918252602090912060036004909202010155600101614750565b50505b50600195945050505050565b60015481516040805182815260208084028201019091526060929190839082801561480057816020015b60608152602001906001900390816147eb5790505b50600b5490915083146148175792506114c0915050565b60005b8281101561492657600b60016004600089858151811061483657fe5b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054038154811061486a57fe5b600091825260209182902060026016909202018101805460408051601f6000196101006001861615020190931694909404918201859004850284018501905280835291929091908301828280156149025780601f106148d757610100808354040283529160200191614902565b820191906000526020600020905b8154815290600101906020018083116148e557829003601f168201915b505050505082828151811061491357fe5b602090810291909101015260010161481a565b50949350505050565b60005b82811015614a7c57600082878388016040516020016149529291906161ef565b6040516020818303038152906040528051906020012060001c8161497257fe5b06905080850182870114614a73576000898388018151811061499057fe5b60200260200101519050606089848901815181106149aa57fe5b602002602001015190508a838801815181106149c257fe5b60200260200101518b858a01815181106149d857fe5b60200260200101906001600160a01b031690816001600160a01b031681525050818b84890181518110614a0757fe5b60200260200101906001600160a01b031690816001600160a01b0316815250508983880181518110614a3557fe5b60200260200101518a858a0181518110614a4b57fe5b6020026020010181905250808a84890181518110614a6557fe5b602002602001018190525050505b50600101614932565b5050505050505050565b600980546001908101909155600b805483908110614aa057fe5b906000526020600020906016020160010160006101000a81548160ff02191690831515021790555043600b8281548110614ad657fe5b600091825260208220601690910201919091556040516001600160a01b038416917ff62981a567ec3cec866c6fa93c55bcdf841d6292d18b8d522ececa769375d82d91a25050565b600081604051602001614b3191906161d3565b6040516020818303038152906040528051906020012083604051602001614b5891906161d3565b6040516020818303038152906040528051906020012014905092915050565b015190565b614b84615b28565b6000614b8e615b28565b614b96615c3e565b614ba7614ba2866153f3565b615418565b90506000805b614bb683615462565b15614d2a5780614bdb57614bd1614bcc84615483565b6154d1565b60ff168452614d22565b8060011415614d1d576060614bf7614bf285615483565b615551565b90508051604051908082528060200260200182016040528015614c3457816020015b614c21615af3565b815260200190600190039081614c195790505b5085602001819052508051604051908082528060200260200182016040528015614c7257816020015b6060815260200190600190039081614c5d5790505b50604086015260005b8151811015614d1257614c8c615af3565b60606000614cac858581518110614c9f57fe5b6020026020010151615622565b92509250925080614ccc578860009a509a50505050505050505050614d33565b8289602001518581518110614cdd57fe5b60200260200101819052508189604001518581518110614cf957fe5b6020026020010181905250505050806001019050614c7b565b506001925050614d22565b614d2a565b600101614bad565b50919350909150505b915091565b815181516000916001918114808314614d545760009250614d92565b600160208701838101602088015b600284838510011415614d8d578051835114614d815760009650600093505b60209283019201614d62565b505050505b5090949350505050565b6001600160a01b03811660009081526004602052604081205480614dc5575060001990506114c0565b600181039050600060018281548110614dda57fe5b9060005260206000209060040201600301549050600060018381548110614dfd57fe5b6000918252602090912060036004909202010155600154604051600019909101906001600160a01b038616907f8cd4e147d8af98a9e3b6724021b8bf6aed2e5dac71c38f2dce8161b82585b25d90614e56908590616e48565b60405180910390a280614e6e578293505050506114c0565b6000818381614e7957fe5b0490508015614f155760005b84811015614ec757614e9e826001838154811061476957fe5b60018281548110614eab57fe5b6000918252602090912060036004909202010155600101614e85565b50600180549085015b81811015614f1257614ee9836001838154811061476957fe5b60018281548110614ef657fe5b6000918252602090912060036004909202010155600101614ed0565b50505b5091949350505050565b600082614f2e57506000611570565b82820282848281614f3b57fe5b0414611baa5760405162461bcd60e51b8152600401610c0f906169ed565b6000611baa83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f00000000000081525061573c565b805182516000916001600160a01b039182169116148015614fd5575081602001516001600160a01b031683602001516001600160a01b0316145b8015611baa5750506040908101519101516001600160a01b0390811691161490565b6012546013548082111561504257805b8281101561504057601280548061501a57fe5b6001900381819060005260206000200160006150369190615b4c565b9055600101615007565b505b60008183106150515781615053565b825b905060005b8181101561516b576151106012828154811061507057fe5b600091825260209182902001805460408051601f60026000196101006001871615020190941693909304928301859004850281018501909152818152928301828280156150fe5780601f106150d3576101008083540402835291602001916150fe565b820191906000526020600020905b8154815290600101906020018083116150e157829003601f168201915b505050505060138381548110612e0757fe5b615163576013818154811061512157fe5b906000526020600020016012828154811061513857fe5b906000526020600020019080546001816001161561010002031660029004615161929190615b9f565b505b600101615058565b5082821115610c3157825b828110156133ec5760126013828154811061518d57fe5b60009182526020808320845460018181018755958552919093209290910180546151d0949390920192909160026101009282161592909202600019011604615b9f565b50600101615176565b601354600b548082111561522457805b828110156152225760138054806151fc57fe5b6001900381819060005260206000200160006152189190615b4c565b90556001016151e9565b505b60008183106152335781615235565b825b905060005b81811015615354576152f26013828154811061525257fe5b600091825260209182902001805460408051601f60026000196101006001871615020190941693909304928301859004850281018501909152818152928301828280156152e05780601f106152b5576101008083540402835291602001916152e0565b820191906000526020600020905b8154815290600101906020018083116152c357829003601f168201915b5050505050600b838154811061407957fe5b61534c57600b818154811061530357fe5b90600052602060002090601602016002016013828154811061532157fe5b90600052602060002001908054600181600116156101000203166002900461534a929190615b9f565b505b60010161523a565b5082821115610c3157825b828110156133ec576013600b828154811061537657fe5b6000918252602080832084546001808201875595855291909320601692909202909201600290810180546153be95939094019390926000199082161561010002011604615b9f565b5060010161535f565b600081848411156153eb5760405162461bcd60e51b8152600401610c0f919061631d565b505050900390565b6153fb615c5e565b506040805180820190915281518152602082810190820152919050565b615420615c3e565b61542982615773565b61543257600080fd5b600061544183602001516157ad565b60208085015160408051808201909152868152920190820152915050919050565b600061546c615c5e565b505080518051602091820151919092015191011190565b61548b615c5e565b61549482615462565b61549d57600080fd5b602082015160006154ad82615810565b80830160209586015260408051808201909152908152938401919091525090919050565b8051600090158015906154e657508151602110155b6154ef57600080fd5b60006154fe83602001516157ad565b905080836000015110156155245760405162461bcd60e51b8152600401610c0f90616b52565b82516020808501518301805192849003929183101561492657506020919091036101000a90049392505050565b606061555c82615773565b61556557600080fd5b6000615570836158f1565b90506060816040519080825280602002602001820160405280156155ae57816020015b61559b615c5e565b8152602001906001900390816155935790505b50905060006155c085602001516157ad565b60208601510190506000805b84811015615617576155dd83615810565b915060405180604001604052808381526020018481525084828151811061560057fe5b6020908102919091010152918101916001016155cc565b509195945050505050565b61562a615af3565b60606000615636615af3565b6060615640615c3e565b61564987615418565b90506000805b61565883615462565b1561572d57806156835761567361566e84615483565b61594d565b6001600160a01b03168552615725565b80600114156156ab5761569861566e84615483565b6001600160a01b03166020860152615725565b80600214156156d3576156c061566e84615483565b6001600160a01b03166040860152615725565b80600314156156ff576156e8614bcc84615483565b6001600160401b0316606086015260019150615725565b80600414156157205761571961571484615483565b615967565b9350615725565b61572d565b60010161564f565b50929791965091945092505050565b6000818361575d5760405162461bcd60e51b8152600401610c0f919061631d565b50600083858161576957fe5b0495945050505050565b8051600090615784575060006114c0565b6020820151805160001a9060c08210156157a3576000925050506114c0565b5060019392505050565b8051600090811a60808110156157c75760009150506114c0565b60b88110806157e2575060c081108015906157e2575060f881105b156157f15760019150506114c0565b60c08110156158055760b5190190506114c0565b60f5190190506114c0565b80516000908190811a608081101561582b57600191506158ea565b60b881101561584057607e19810191506158ea565b60c081101561589157600060b78203600186019550806020036101000a86510491506001810182019350508083101561588b5760405162461bcd60e51b8152600401610c0f906168f0565b506158ea565b60f88110156158a65760be19810191506158ea565b600060f78203600186019550806020036101000a8651049150600181018201935050808310156158e85760405162461bcd60e51b8152600401610c0f906168f0565b505b5092915050565b8051600090615902575060006114c0565b6000809050600061591684602001516157ad565b602085015185519181019250015b808210156159445761593582615810565b82019150826001019250615924565b50909392505050565b805160009060151461595e57600080fd5b611570826154d1565b805160609061597557600080fd5b600061598483602001516157ad565b83516040805191839003808352601f19601f82011683016020019091529192506060908280156159bb576020820181803683370190505b5090506000816020019050614926848760200151018285806159dc57610c31565b5b602081106159fc578251825260209283019290910190601f19016159dd565b915181516020939093036101000a6000190180199091169216919091179052565b60405180608001604052806000815260200160001515815260200160608152602001615a47615c78565b905290565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10615a8d57805160ff1916838001178555615aba565b82800160010185558215615aba579182015b82811115615aba578251825591602001919060010190615a9f565b50612b07929150615c97565b8260138101928215615aba5791602002820182811115615aba578251825591602001919060010190615a9f565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a081019190915290565b6040518060600160405280600060ff16815260200160608152602001606081525090565b50805460018160011615610100020316600290046000825580601f10615b7257506116d8565b601f0160209004906000526020600020908101906116d89190615c97565b506116d8906013810190615c97565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10615bd85780548555615aba565b82800160010185558215615aba57600052602060002091601f016020900482015b82811115615aba578254825591600101919060010190615bf9565b8260138101928215615aba5791820182811115615aba578254825591600101919060010190615bf9565b6040518060400160405280615c51615c5e565b8152602001600081525090565b604051806040016040528060008152602001600081525090565b6040518061026001604052806013906020820280368337509192915050565b611d8c91905b80821115612b075760008155600101615c9d565b803561157081616efd565b60008083601f840112615ccd578182fd5b5081356001600160401b03811115615ce3578182fd5b6020830191508360208083028501011115613ba157600080fd5b6000601f8381840112615d0e578182fd5b8235615d21615d1c82616eb2565b616e8c565b818152925060208084019085810160005b84811015615db3578135880189603f820112615d4d57600080fd5b838101356001600160401b03811115615d6557600080fd5b615d76818901601f19168601616e8c565b81815260408c81848601011115615d8c57600080fd5b82818501888401375060009181018601919091528552509282019290820190600101615d32565b50505050505092915050565b600082601f830112615dcf578081fd5b8135615ddd615d1c82616eb2565b818152915060208083019084810181840286018201871015615dfe57600080fd5b6000805b85811015615db35782356001600160401b0381168114615e20578283fd5b85529383019391830191600101615e02565b60008083601f840112615e43578182fd5b5081356001600160401b03811115615e59578182fd5b602083019150836020828501011115613ba157600080fd5b600060208284031215615e82578081fd5b8135611baa81616efd565b600060208284031215615e9e578081fd5b8151611baa81616efd565b60008060008060408587031215615ebe578283fd5b84356001600160401b0380821115615ed4578485fd5b615ee088838901615cbc565b90965094506020870135915080821115615ef8578384fd5b50615f0587828801615cbc565b95989497509550505050565b600080600060608486031215615f25578283fd5b83356001600160401b0380821115615f3b578485fd5b81860187601f820112615f4c578586fd5b80359250615f5c615d1c84616eb2565b80848252602080830192508084018b828389028701011115615f7c57898afd5b8994505b86851015615fa657615f928c82615cb1565b845260019490940193928101928101615f80565b509097508801359350505080821115615fbd578384fd5b615fc987838801615dbf565b93506040860135915080821115615fde578283fd5b50615feb86828701615cfd565b9150509250925092565b60008060208385031215616007578182fd5b82356001600160401b0381111561601c578283fd5b61602885828601615e32565b90969095509350505050565b60008060008060408587031215616049578384fd5b84356001600160401b038082111561605f578586fd5b61606b88838901615e32565b90965094506020870135915080821115616083578384fd5b50615f0587828801615e32565b6000602082840312156160a1578081fd5b5035919050565b6000602082840312156160b9578081fd5b5051919050565b600080604083850312156160d2578182fd5b505080516020909101519092909150565b6000806000604084860312156160f7578081fd5b833560ff81168114616107578182fd5b925060208401356001600160401b03811115616121578182fd5b61612d86828701615e32565b9497909650939450505050565b6000815180845260208085019450808401835b838110156161725781516001600160a01b03168752958201959082019060010161614d565b509495945050505050565b60008284528282602086013780602084860101526020601f19601f85011685010190509392505050565b600081518084526161bf816020860160208601616ed1565b601f01601f19169290920160200192915050565b600082516161e5818460208701616ed1565b9190910192915050565b918252602082015260400190565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b03968716815294861660208601529290941660408401526001600160401b03166060830152911515608082015260a081019190915260c00190565b6001600160a01b0393909316835260208301919091521515604082015260600190565b600060208252611baa602083018461613a565b6000604082526162b5604083018561613a565b602083820381850152818551808452828401915082838202850101838801865b8381101561630357601f198784030185526162f18383516161a7565b948601949250908501906001016162d5565b50909998505050505050505050565b901515815260200190565b600060208252611baa60208301846161a7565b60006040825261634460408301868861617d565b828103602084015261635781858761617d565b979650505050505050565b6020808252601c908201527f6c656e677468206f66206275726e526174696f206d69736d6174636800000000604082015260600190565b60208082526026908201527f6c656e677468206f66206d61784e756d4f664d61696e7461696e696e67206d696040820152650e6dac2e8c6d60d31b606082015260800190565b60208082526038908201527f746865206e756d4f66436162696e657473206d757374206265206c657373207460408201527f68616e206d6178456c656374656456616c696461746f72730000000000000000606082015260800190565b6020808252602c908201527f6c656e677468206f66206d61784e756d4f66576f726b696e6743616e6469646160408201526b0e8cae640dad2e6dac2e8c6d60a31b606082015260800190565b60208082526025908201527f6c656e677468206f66206d61696e7461696e536c6173685363616c65206d69736040820152640dac2e8c6d60db1b606082015260800190565b6020808252818101527f6c656e677468206f66206e756d4f66436162696e657473206d69736d61746368604082015260600190565b60208082526019908201527f74686520636f6e7472616374206e6f7420696e69742079657400000000000000604082015260600190565b6020808252601f908201527f6f6e6c7920736c617368206f72207374616b6548756220636f6e747261637400604082015260600190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b60208082526063908201527f7468652073797374656d52657761726442617365526174696f20706c7573206260408201527f75726e526174696f20616e642073797374656d526577617264416e74694d455660608201527f526174696f206d757374206265206e6f2067726561746572207468616e20313060808201526203030360ec1b60a082015260c00190565b60208082526028908201527f746865206e756d4f66436162696e657473206d75737420626520677265617465604082015267072207468616e20360c41b606082015260800190565b60208082526022908201527f63616e206e6f7420646f207468697320747769636520696e206f6e6520626c6f604082015261636b60f01b606082015260800190565b60208082526037908201527f746865206d61784e756d4f664d61696e7461696e696e67206d7573742062652060408201527f6c657373207468616e206e756d4f66436162696e657473000000000000000000606082015260800190565b6020808252601d908201527f6c656e677468206f66207475726e4c656e677468206d69736d61746368000000604082015260600190565b6020808252600a908201526919195c1c9958d85d195960b21b604082015260600190565b60208082526063908201527f746865206275726e526174696f20706c75732073797374656d5265776172644260408201527f617365526174696f20616e642073797374656d526577617264416e74694d455660608201527f526174696f206d757374206265206e6f2067726561746572207468616e20313060808201526203030360ec1b60a082015260c00190565b6020808252602b908201527f6c656e677468206f662073797374656d526577617264416e74694d455652617460408201526a0d2de40dad2e6dac2e8c6d60ab1b606082015260800190565b6020808252601590820152746465706f7369742076616c7565206973207a65726f60581b604082015260600190565b60208082526049908201527f746865206d61784e756d4f66576f726b696e6743616e64696461746573206d7560408201527f7374206265206e6f742067726561746572207468616e206d61784e756d4f6643606082015268616e6469646174657360b81b608082015260a00190565b6020808252601190820152706164646974696f6e206f766572666c6f7760781b604082015260600190565b60208082526063908201527f7468652073797374656d526577617264416e74694d4556526174696f20706c7560408201527f73206275726e526174696f20616e642073797374656d5265776172644261736560608201527f526174696f206d757374206265206e6f2067726561746572207468616e20313060808201526203030360ec1b60a082015260c00190565b60208082526023908201527f63616e206e6f7420656e7465722054656d706f72617279204d61696e74656e616040820152626e636560e81b606082015260800190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b6020808252601490820152736761737072696365206973206e6f74207a65726f60601b604082015260600190565b6020808252602e908201527f746865206d6573736167652073656e646572206d75737420626520676f76657260408201526d1b985b98d94818dbdb9d1c9858dd60921b606082015260800190565b60208082526025908201527f6c656e677468206f66206d61784e756d4f6643616e64696461746573206d69736040820152640dac2e8c6d60db1b606082015260800190565b6020808252601290820152716e6f7420696e206d61696e74656e616e636560701b604082015260600190565b60208082526019908201527f74686520636f6e747261637420616c726561647920696e697400000000000000604082015260600190565b6020808252601a908201527f6c656e677468206973206c657373207468616e206f6666736574000000000000604082015260600190565b60208082526017908201527f6f6e6c792063757272656e742076616c696461746f7273000000000000000000604082015260600190565b60208082526021908201527f6661696c656420746f20706172736520696e69742076616c696461746f7253656040820152601d60fa1b606082015260800190565b6020808252602f908201527f746865206d6573736167652073656e646572206d7573742062652063726f737360408201526e0818da185a5b8818dbdb9d1c9858dd608a1b606082015260800190565b6020808252602d908201527f746865206d6573736167652073656e646572206d75737420626520746865206260408201526c3637b1b590383937b23ab1b2b960991b606082015260800190565b60208082526028908201527f6c656e677468206f662073797374656d52657761726442617365526174696f206040820152670dad2e6dac2e8c6d60c31b606082015260800190565b6020808252603e908201527f746865206d61696e7461696e536c6173685363616c65206d757374206265206760408201527f726561746572207468616e203020616e64206c657373207468616e2031300000606082015260800190565b60208082526030908201527f746865207475726e4c656e6774682073686f756c6420626520696e205b332c3660408201526f345d206f7220657175616c20746f203160801b606082015260800190565b6020808252600d908201526c756e6b6e6f776e20706172616d60981b604082015260600190565b60208082526029908201527f746865206d6573736167652073656e646572206d75737420626520736c6173686040820152680818dbdb9d1c9858dd60ba1b606082015260800190565b6020808252601f908201527f746865206d73672073656e646572206d757374206265207374616b6548756200604082015260600190565b61ffff91909116815260200190565b90815260200190565b6000848252831515602083015260606040830152616e7260608301846161a7565b95945050505050565b63ffffffff91909116815260200190565b6040518181016001600160401b0381118282101715616eaa57600080fd5b604052919050565b60006001600160401b03821115616ec7578081fd5b5060209081020190565b60005b83811015616eec578181015183820152602001616ed4565b838111156133ec5750506000910152565b6001600160a01b03811681146116d857600080fdfe0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db90175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01dbb0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01dbaf87680f873f871949fb29aac15b9a4b7f17c3385939b007540f4d791949fb29aac15b9a4b7f17c3385939b007540f4d791949fb29aac15b9a4b7f17c3385939b007540f4d79164b085e6972fc98cd3c81d64d40e325acfed44365b97a7567a27939c14dbc7512ddcf54cb1284eb637cfa308ae4e00cb5588a164736f6c6343000604000a \ No newline at end of file diff --git a/core/systemcontracts/lorentz/types.go b/core/systemcontracts/lorentz/types.go index 4ae56835e7..f9b3ddc8cf 100644 --- a/core/systemcontracts/lorentz/types.go +++ b/core/systemcontracts/lorentz/types.go @@ -13,9 +13,3 @@ var ( //go:embed chapel/ValidatorContract ChapelValidatorContract string ) - -// contract codes for Rialto upgrade -var ( - //go:embed rialto/ValidatorContract - RialtoValidatorContract string -) diff --git a/core/systemcontracts/maxwell/chapel/StakeHubContract b/core/systemcontracts/maxwell/chapel/StakeHubContract new file mode 100644 index 0000000000..219e5cb476 --- /dev/null +++ b/core/systemcontracts/maxwell/chapel/StakeHubContract @@ -0,0 +1 @@ +6080604052600436106200043b5760003560e01c806386d545061162000233578063ca47908f116200012f578063dd42a1dd11620000b9578063f1f74d841162000084578063f1f74d841462000d75578063f80a34021462000d8d578063fb50b31f1462000db2578063fc0c5ff11462000dd7578063ff69ab611462000def57600080fd5b8063dd42a1dd1462000ce2578063e8f67c3b1462000d09578063e992aaf51462000d21578063efdbf0e11462000d3957600080fd5b8063d7c2dfc811620000fa578063d7c2dfc81462000c68578063d8ca511f1462000c8d578063daacdb661462000ca5578063dbda7fb31462000cbd57600080fd5b8063ca47908f1462000bd1578063cbb04d9d1462000be9578063d115a2061462000c2a578063d6ca429d1462000c4357600080fd5b8063b187bd2611620001bd578063bfff04751162000188578063bfff04751462000b58578063c166f58a1462000b7d578063c38fbec81462000b94578063c473318f1462000bb9578063c8509d81146200095157600080fd5b8063b187bd261462000ac5578063baa7199e1462000ae5578063bdceadf31462000b0a578063bff02e201462000b2257600080fd5b8063a1832e6411620001fe578063a1832e641462000a22578063a43569b31462000a47578063aad3ec961462000a7b578063ac4317511462000aa057600080fd5b806386d54506146200098e5780638a4d3fa814620009c85780638cd22b2214620009e6578063982ef0a71462000a0b57600080fd5b80634838d165116200034357806364028fbd11620002cd57806375cc7d89116200029857806375cc7d8914620008fc57806376e7d6d614620009215780638129fc1c1462000939578063831d65d114620009515780638456cb59146200097657600080fd5b806364028fbd1462000837578063663706d3146200084e5780636ec01b27146200087f5780636f8e2fa414620008d757600080fd5b80634e6fd6c4116200030e5780634e6fd6c4146200079e5780635949187114620007b65780635e7cc1c914620007db57806363a036b5146200080057600080fd5b80634838d16514620006ea57806349f41a42146200072f5780634a49ac4c14620007545780634d99dd16146200077957600080fd5b80631fab701511620003c5578063384099881162000390578063384099881462000663578063417c73a7146200067b578063449ecfe614620006a057806345211bfd14620006c557600080fd5b80631fab701514620005aa5780632b727c8614620005cf5780632e8e8c7114620005f4578063367dad49146200062e57600080fd5b80630e9fbf5111620004065780630e9fbf5114620004f35780631182b875146200051857806317b4f353146200054c5780631fa8882b146200059157600080fd5b8063046f7da2146200045b578063059ddd2214620004735780630661806e14620004b5578063092193ab14620004dc57600080fd5b36620004565760345460ff166001146200045457600080fd5b005b600080fd5b3480156200046857600080fd5b506200045462000e07565b3480156200048057600080fd5b506200049862000492366004620096f0565b62000e99565b6040516001600160a01b0390911681526020015b60405180910390f35b348015620004c257600080fd5b50620004cd60365481565b604051908152602001620004ac565b62000454620004ed366004620096f0565b620012c1565b3480156200050057600080fd5b50620004546200051236600462009752565b62001912565b3480156200052557600080fd5b506200053d6200053736600462009797565b62001c3e565b604051620004ac91906200984a565b3480156200055957600080fd5b50620004986200056b3660046200991c565b80516020818301810180516045825292820191909301209152546001600160a01b031681565b3480156200059e57600080fd5b50620004cd6201518081565b348015620005b757600080fd5b5062000454620005c9366004620099b8565b62001cd6565b348015620005dc57600080fd5b5062000498620005ee366004620096f0565b6200202d565b3480156200060157600080fd5b506200049862000613366004620096f0565b604d602052600090815260409020546001600160a01b031681565b3480156200063b57600080fd5b50620006536200064d366004620099b8565b62002082565b604051620004ac92919062009a37565b3480156200067057600080fd5b50620004cd60375481565b3480156200068857600080fd5b50620004546200069a366004620096f0565b62002651565b348015620006ad57600080fd5b5062000454620006bf366004620096f0565b620026d3565b348015620006d257600080fd5b5062000454620006e4366004620096f0565b620028b8565b348015620006f757600080fd5b506200071e62000709366004620096f0565b60016020526000908152604090205460ff1681565b6040519015158152602001620004ac565b3480156200073c57600080fd5b50620004546200074e366004620096f0565b62002a91565b3480156200076157600080fd5b506200045462000773366004620096f0565b62002cad565b3480156200078657600080fd5b50620004546200079836600462009ad6565b62002d29565b348015620007ab57600080fd5b506200049861dead81565b348015620007c357600080fd5b5062000454620007d536600462009b14565b62003359565b348015620007e857600080fd5b5062000454620007fa36600462009b7e565b62004152565b3480156200080d57600080fd5b50620008256200081f36600462009ba5565b6200437c565b604051620004ac949392919062009bc8565b620004546200084836600462009c84565b62004a21565b3480156200085b57600080fd5b50620004cd6200086d366004620096f0565b60446020526000908152604090205481565b3480156200088c57600080fd5b50620008a46200089e366004620096f0565b62005070565b6040805182516001600160401b0390811682526020808501518216908301529282015190921690820152606001620004ac565b348015620008e457600080fd5b506200053d620008f6366004620096f0565b62005115565b3480156200090957600080fd5b50620004546200091b366004620096f0565b62005541565b3480156200092e57600080fd5b50620004cd603d5481565b3480156200094657600080fd5b506200045462005713565b3480156200095e57600080fd5b50620004546200097036600462009797565b620058de565b3480156200098357600080fd5b50620004546200593c565b3480156200099b57600080fd5b5062000498620009ad366004620096f0565b6043602052600090815260409020546001600160a01b031681565b348015620009d557600080fd5b50620004cd670de0b6b3a764000081565b348015620009f357600080fd5b50620004cd62000a0536600462009ad6565b620059d4565b6200045462000a1c36600462009d5a565b62005a8d565b34801562000a2f57600080fd5b506200045462000a41366004620099b8565b6200613b565b34801562000a5457600080fd5b5062000a6c62000a66366004620096f0565b62006441565b604051620004ac919062009d92565b34801562000a8857600080fd5b506200045462000a9a36600462009ad6565b6200672e565b34801562000aad57600080fd5b506200045462000abf36600462009e0f565b6200679b565b34801562000ad257600080fd5b5060005462010000900460ff166200071e565b34801562000af257600080fd5b506200045462000b0436600462009e81565b6200774d565b34801562000b1757600080fd5b50620004cd603c5481565b34801562000b2f57600080fd5b5062000b4762000b4136600462009ba5565b6200791a565b604051620004ac9392919062009eda565b34801562000b6557600080fd5b50620004cd62000b77366004620096f0565b62007af6565b34801562000b8a57600080fd5b50620004cd600581565b34801562000ba157600080fd5b506200045462000bb3366004620096f0565b62007b44565b34801562000bc657600080fd5b50620004cd60385481565b34801562000bde57600080fd5b50620004cd604e5481565b34801562000bf657600080fd5b5062000c0e62000c08366004620096f0565b62007e06565b60408051938452911515602084015290820152606001620004ac565b34801562000c3757600080fd5b50620004cd620186a081565b34801562000c5057600080fd5b506200045462000c6236600462009f37565b62008249565b34801562000c7557600080fd5b506200045462000c873660046200a020565b6200846f565b34801562000c9a57600080fd5b50620004cd603b5481565b34801562000cb257600080fd5b50620004cd60495481565b34801562000cca57600080fd5b506200049862000cdc366004620096f0565b62008565565b34801562000cef57600080fd5b50600054630100000090046001600160a01b031662000498565b34801562000d1657600080fd5b50620004cd60355481565b34801562000d2e57600080fd5b50620004cd603a5481565b34801562000d4657600080fd5b50620004cd62000d583660046200991c565b805160208183018101805160468252928201919093012091525481565b34801562000d8257600080fd5b50620004cd603e5481565b34801562000d9a57600080fd5b50620004cd62000dac36600462009ad6565b6200898f565b34801562000dbf57600080fd5b506200045462000dd136600462009e0f565b62008a00565b34801562000de457600080fd5b50620004cd60395481565b34801562000dfc57600080fd5b50620004cd604a5481565b600054630100000090046001600160a01b0316331462000e3a576040516306fbb1e360e01b815260040160405180910390fd5b60005462010000900460ff1662000e6457604051636cd6020160e01b815260040160405180910390fd5b6000805462ff0000191681556040517f62451d457bc659158be6e6247f56ec1df424a5c7597f71c20c2bc44e0965c8f99190a1565b6001600160a01b038082166000908152604160209081526040808320815161018081018352815486168152600182015486169381019390935260028101549094169082015260038301546060820152600483018054929384939091608084019162000f04906200a086565b80601f016020809104026020016040519081016040528092919081815260200182805462000f32906200a086565b801562000f835780601f1062000f575761010080835404028352916020019162000f83565b820191906000526020600020905b81548152906001019060200180831162000f6557829003601f168201915b505050505081526020016005820160405180608001604052908160008201805462000fae906200a086565b80601f016020809104026020016040519081016040528092919081815260200182805462000fdc906200a086565b80156200102d5780601f1062001001576101008083540402835291602001916200102d565b820191906000526020600020905b8154815290600101906020018083116200100f57829003601f168201915b5050505050815260200160018201805462001048906200a086565b80601f016020809104026020016040519081016040528092919081815260200182805462001076906200a086565b8015620010c75780601f106200109b57610100808354040283529160200191620010c7565b820191906000526020600020905b815481529060010190602001808311620010a957829003601f168201915b50505050508152602001600282018054620010e2906200a086565b80601f016020809104026020016040519081016040528092919081815260200182805462001110906200a086565b8015620011615780601f10620011355761010080835404028352916020019162001161565b820191906000526020600020905b8154815290600101906020018083116200114357829003601f168201915b505050505081526020016003820180546200117c906200a086565b80601f0160208091040260200160405190810160405280929190818152602001828054620011aa906200a086565b8015620011fb5780601f10620011cf57610100808354040283529160200191620011fb565b820191906000526020600020905b815481529060010190602001808311620011dd57829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152600d8301546001600160a01b031660a0830152805161026081019182905260c09092019190600e84019060139082845b8154815260200190600101908083116200129a575050509190925250509051949350505050565b3361100014620012ed57604051630f22c43960e41b815261100060048201526024015b60405180910390fd5b6001600160a01b0380821660009081526043602090815260408083205484168084526041835281842082516101808101845281548716815260018201548716948101949094526002810154909516918301919091526003840154606083015260048401805491949160808401919062001366906200a086565b80601f016020809104026020016040519081016040528092919081815260200182805462001394906200a086565b8015620013e55780601f10620013b957610100808354040283529160200191620013e5565b820191906000526020600020905b815481529060010190602001808311620013c757829003601f168201915b505050505081526020016005820160405180608001604052908160008201805462001410906200a086565b80601f01602080910402602001604051908101604052809291908181526020018280546200143e906200a086565b80156200148f5780601f1062001463576101008083540402835291602001916200148f565b820191906000526020600020905b8154815290600101906020018083116200147157829003601f168201915b50505050508152602001600182018054620014aa906200a086565b80601f0160208091040260200160405190810160405280929190818152602001828054620014d8906200a086565b8015620015295780601f10620014fd5761010080835404028352916020019162001529565b820191906000526020600020905b8154815290600101906020018083116200150b57829003601f168201915b5050505050815260200160028201805462001544906200a086565b80601f016020809104026020016040519081016040528092919081815260200182805462001572906200a086565b8015620015c35780601f106200159757610100808354040283529160200191620015c3565b820191906000526020600020905b815481529060010190602001808311620015a557829003601f168201915b50505050508152602001600382018054620015de906200a086565b80601f01602080910402602001604051908101604052809291908181526020018280546200160c906200a086565b80156200165d5780601f1062001631576101008083540402835291602001916200165d565b820191906000526020600020905b8154815290600101906020018083116200163f57829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152600d8301546001600160a01b031660a0830152805161026081019182905260c09092019190600e84019060139082845b815481526020019060010190808311620016fc575050509190925250505060408101519091506001600160a01b031615806200173957508060e001515b15620017f657604051611002903490600081818185875af1925050503d806000811462001783576040519150601f19603f3d011682016040523d82523d6000602084013e62001788565b606091505b505050816001600160a01b03167ffc8bff675087dd2da069cc3fb517b9ed001e19750c0865241a5542dba1ba170d604051620017e99060208082526011908201527024a72b20a624a22fab20a624a220aa27a960791b604082015260600190565b60405180910390a2505050565b60408181015160c0830151519151632f303ebb60e11b81526001600160401b0390921660048301526001600160a01b031690635e607d769034906024016000604051808303818588803b1580156200184d57600080fd5b505af115801562001862573d6000803e3d6000fd5b5050505050816001600160a01b03167fe34918ff1c7084970068b53fd71ad6d8b04e9f15d3886cbf006443e6cdc52ea634604051620018a391815260200190565b60405180910390a26040808201519051633041949b60e01b815261200591633041949b91620018d8919086906004016200a0bc565b600060405180830381600087803b158015620018f357600080fd5b505af115801562001908573d6000803e3d6000fd5b5050505050505b50565b33611001146200193a57604051630f22c43960e41b81526110016004820152602401620012e4565b60005462010000900460ff16156200196557604051631785c68160e01b815260040160405180910390fd5b6000604583836040516200197b9291906200a0d6565b908152604051908190036020019020546001600160a01b03169050620019a3603f8262008c39565b620019c15760405163056e881160e01b815260040160405180910390fd5b6001600160a01b038116600090815260416020526040812090620019e962015180426200a0fc565b604a546000828152604b60205260409020549192501162001a1d5760405163bd52fcdb60e01b815260040160405180910390fd5b6000818152604b6020526040812080546001929062001a3e9084906200a11f565b909155505060405160469062001a5890879087906200a0d6565b90815260200160405180910390205460001415801562001aa9575042620151806046878760405162001a8c9291906200a0d6565b90815260200160405180910390205462001aa791906200a11f565b105b1562001ac857604051631898eb6b60e01b815260040160405180910390fd5b60008062001ad885600262008c5c565b915091508162001afb57604051631b919bb160e11b815260040160405180910390fd5b6002840154603c5460405163045bc4d160e41b815260048101919091526000916001600160a01b0316906345bc4d10906024016020604051808303816000875af115801562001b4e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001b7491906200a135565b905062001b82858362008ce4565b856001600160a01b03167f6e9a2ee7aee95665e3a774a212eb11441b217e3e4656ab9563793094689aabb28383600260405162001bc2939291906200a14f565b60405180910390a26002850154604051633041949b60e01b815261200591633041949b9162001c00916001600160a01b0316908a906004016200a0bc565b600060405180830381600087803b15801562001c1b57600080fd5b505af115801562001c30573d6000803e3d6000fd5b505050505050505050505050565b6060336120001462001c6857604051630f22c43960e41b81526120006004820152602401620012e4565b60005462010000900460ff161562001c9357604051631785c68160e01b815260040160405180910390fd5b6034805460ff1916600117905560405162461bcd60e51b815260206004820152600a60248201526919195c1c9958d85d195960b21b6044820152606401620012e4565b60005462010000900460ff161562001d0157604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff161562001d335760405163b1d02c3d60e01b815260040160405180910390fd5b62001d3d62008dd8565b62001d4a603f8262008c39565b62001d685760405163056e881160e01b815260040160405180910390fd5b62001d7262008e23565b600082900362001d9557604051636490ffd360e01b815260040160405180910390fd5b600062001da162008dd8565b6001600160a01b0381166000908152604f602052604090208054604e54929350909162001dcf86836200a11f565b111562001def5760405163091af98560e21b815260040160405180910390fd5b60005b8581101562001ed557600087878381811062001e125762001e126200a18a565b905060200201350362001e3857604051636490ffd360e01b815260040160405180910390fd5b600062001e478260016200a11f565b90505b8681101562001ebf5787878281811062001e685762001e686200a18a565b9050602002013588888481811062001e845762001e846200a18a565b905060200201350362001eaa57604051632205e3c760e11b815260040160405180910390fd5b8062001eb6816200a1a0565b91505062001e4a565b508062001ecc816200a1a0565b91505062001df2565b5060005b8581101562001f745760005b8281101562001f5e5783818154811062001f035762001f036200a18a565b906000526020600020015488888481811062001f235762001f236200a18a565b905060200201350362001f4957604051632205e3c760e11b815260040160405180910390fd5b8062001f55816200a1a0565b91505062001ee5565b508062001f6b816200a1a0565b91505062001ed9565b5060005b8581101562001908578287878381811062001f975762001f976200a18a565b835460018101855560009485526020948590209190940292909201359190920155506001600160a01b0384167f7c4ff4c9a343a2daef608f3b5a91016e994a15fc0ef8611109e4f45823249f2988888481811062001ff95762001ff96200a18a565b905060200201356040516200201091815260200190565b60405180910390a28062002024816200a1a0565b91505062001f78565b6000816200203d603f8262008c39565b6200205b5760405163056e881160e01b815260040160405180910390fd5b6001600160a01b038084166000908152604160205260409020600d01541691505b50919050565b60608082806001600160401b03811115620020a157620020a16200985f565b604051908082528060200260200182016040528015620020cb578160200160208202803683370190505b509250806001600160401b03811115620020e957620020e96200985f565b6040519080825280602002602001820160405280156200211e57816020015b6060815260200190600190039081620021085790505b50915060005b81811015620026475760008686838181106200214457620021446200a18a565b90506020020160208101906200215b9190620096f0565b6001600160a01b03808216600090815260416020908152604080832081516101808101835281548616815260018201548616938101939093526002810154909416908201526003830154606082015260048301805494955091939092916080840191620021c8906200a086565b80601f0160208091040260200160405190810160405280929190818152602001828054620021f6906200a086565b8015620022475780601f106200221b5761010080835404028352916020019162002247565b820191906000526020600020905b8154815290600101906020018083116200222957829003601f168201915b505050505081526020016005820160405180608001604052908160008201805462002272906200a086565b80601f0160208091040260200160405190810160405280929190818152602001828054620022a0906200a086565b8015620022f15780601f10620022c557610100808354040283529160200191620022f1565b820191906000526020600020905b815481529060010190602001808311620022d357829003601f168201915b505050505081526020016001820180546200230c906200a086565b80601f01602080910402602001604051908101604052809291908181526020018280546200233a906200a086565b80156200238b5780601f106200235f576101008083540402835291602001916200238b565b820191906000526020600020905b8154815290600101906020018083116200236d57829003601f168201915b50505050508152602001600282018054620023a6906200a086565b80601f0160208091040260200160405190810160405280929190818152602001828054620023d4906200a086565b8015620024255780601f10620023f95761010080835404028352916020019162002425565b820191906000526020600020905b8154815290600101906020018083116200240757829003601f168201915b5050505050815260200160038201805462002440906200a086565b80601f01602080910402602001604051908101604052809291908181526020018280546200246e906200a086565b8015620024bf5780601f106200249357610100808354040283529160200191620024bf565b820191906000526020600020905b815481529060010190602001808311620024a157829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152600d8301546001600160a01b031660a0830152805161026081019182905260c09092019190600e84019060139082845b8154815260200190600101908083116200255e57505050505081525050905080600001518684815181106200259757620025976200a18a565b6001600160a01b039283166020918202929092018101919091529083166000908152604f8252604090819020805482518185028101850190935280835291929091908301828280156200260a57602002820191906000526020600020905b815481526020019060010190808311620025f5575b50505050508584815181106200262457620026246200a18a565b6020026020010181905250505080806200263e906200a1a0565b91505062002124565b50505b9250929050565b600054630100000090046001600160a01b0316331462002684576040516306fbb1e360e01b815260040160405180910390fd5b6001600160a01b0381166000818152600160208190526040808320805460ff1916909217909155517f7fd26be6fc92aff63f1f4409b2b2ddeb272a888031d7f55ec830485ec61941869190a250565b60005462010000900460ff1615620026fe57604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff1615620027305760405163b1d02c3d60e01b815260040160405180910390fd5b806200273e603f8262008c39565b6200275c5760405163056e881160e01b815260040160405180910390fd5b6001600160a01b0382166000908152604160205260409020600a81015460ff166200279a57604051634b6b857d60e01b815260040160405180910390fd5b6036546002820154604051630913db4760e01b81526001600160a01b03868116600483015290911690630913db4790602401602060405180830381865afa158015620027ea573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200281091906200a135565b101562002830576040516317b204bf60e11b815260040160405180910390fd5b4281600b01541115620028565760405163170cb76760e21b815260040160405180910390fd5b600a8101805460ff1916905560498054600191906000906200287a9084906200a1bc565b90915550506040516001600160a01b038416907f9390b453426557da5ebdc31f19a37753ca04addf656d32f35232211bb2af3f1990600090a2505050565b60005462010000900460ff1615620028e357604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff1615620029155760405163b1d02c3d60e01b815260040160405180910390fd5b6200291f62008e36565b6200292c603f8262008c39565b6200294a5760405163056e881160e01b815260040160405180910390fd5b6001600160a01b0382166200297257604051636520611b60e11b815260040160405180910390fd5b6001600160a01b038281166000908152604360205260409020541615620029ac57604051631e6f587560e11b815260040160405180910390fd5b6000620029b862008e36565b6001600160a01b0381166000908152604160205260409020600c810154919250904290620029eb9062015180906200a11f565b111562002a0b57604051631f92cdbd60e11b815260040160405180910390fd5b80546001600160a01b039081166000908152604460209081526040808320429081905585548986166001600160a01b031991821681178855600c88019290925581855260439093528184208054958816959093168517909255519092917f6e4e747ca35203f16401c69805c7dd52fff67ef60b0ebc5c7fe16890530f223591a350505050565b3362002a9f603f8262008c39565b62002abd5760405163056e881160e01b815260040160405180910390fd5b60005462010000900460ff161562002ae857604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff161562002b1a5760405163b1d02c3d60e01b815260040160405180910390fd5b6001600160a01b038281166000908152604d6020526040902054161562002b545760405163bebdc75760e01b815260040160405180910390fd5b62002b61603f8362008c39565b1562002b805760405163bebdc75760e01b815260040160405180910390fd5b336000818152604160205260409020600d01546001600160a01b03908116908416810362002bc15760405163bebdc75760e01b815260040160405180910390fd5b6001600160a01b0381161562002bf8576001600160a01b0381166000908152604d6020526040902080546001600160a01b03191690555b6001600160a01b038281166000908152604160205260409020600d0180546001600160a01b03191691861691821790551562002c5d576001600160a01b038481166000908152604d6020526040902080546001600160a01b0319169184169190911790555b836001600160a01b0316816001600160a01b0316836001600160a01b03167fcbb728765de145e99c00e8ae32a325231e850359b7b8a6da3b84d672ab3f1d0a60405160405180910390a450505050565b600054630100000090046001600160a01b0316331462002ce0576040516306fbb1e360e01b815260040160405180910390fd5b6001600160a01b038116600081815260016020526040808220805460ff19169055517fe0db3499b7fdc3da4cddff5f45d694549c19835e7f719fb5606d3ad1a5de40119190a250565b60005462010000900460ff161562002d5457604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff161562002d865760405163b1d02c3d60e01b815260040160405180910390fd5b8162002d94603f8262008c39565b62002db25760405163056e881160e01b815260040160405180910390fd5b8160000362002dd457604051639811e0c760e01b815260040160405180910390fd5b6001600160a01b038084166000908152604160209081526040808320815161018081018352815486168152600182015486169381019390935260028101549094169082015260038301546060820152600483018054339491608084019162002e3c906200a086565b80601f016020809104026020016040519081016040528092919081815260200182805462002e6a906200a086565b801562002ebb5780601f1062002e8f5761010080835404028352916020019162002ebb565b820191906000526020600020905b81548152906001019060200180831162002e9d57829003601f168201915b505050505081526020016005820160405180608001604052908160008201805462002ee6906200a086565b80601f016020809104026020016040519081016040528092919081815260200182805462002f14906200a086565b801562002f655780601f1062002f395761010080835404028352916020019162002f65565b820191906000526020600020905b81548152906001019060200180831162002f4757829003601f168201915b5050505050815260200160018201805462002f80906200a086565b80601f016020809104026020016040519081016040528092919081815260200182805462002fae906200a086565b801562002fff5780601f1062002fd35761010080835404028352916020019162002fff565b820191906000526020600020905b81548152906001019060200180831162002fe157829003601f168201915b505050505081526020016002820180546200301a906200a086565b80601f016020809104026020016040519081016040528092919081815260200182805462003048906200a086565b8015620030995780601f106200306d5761010080835404028352916020019162003099565b820191906000526020600020905b8154815290600101906020018083116200307b57829003601f168201915b50505050508152602001600382018054620030b4906200a086565b80601f0160208091040260200160405190810160405280929190818152602001828054620030e2906200a086565b8015620031335780601f10620031075761010080835404028352916020019162003133565b820191906000526020600020905b8154815290600101906020018083116200311557829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152600d8301546001600160a01b031660a0830152805161026081019182905260c09092019190600e84019060139082845b815481526020019060010190808311620031d2575050509190925250505060408082015190516326ccee8b60e11b81526001600160a01b0385811660048301526024820188905292935060009290911690634d99dd16906044016020604051808303816000875af11580156200324c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200327291906200a135565b9050826001600160a01b0316866001600160a01b03167f3aace7340547de7b9156593a7652dc07ee900cea3fd8f82cb6c9d38b408298028784604051620032c3929190918252602082015260400190565b60405180910390a3856001600160a01b0316836001600160a01b031603620032f057620032f08662008e77565b6040808301519051633041949b60e01b815261200591633041949b916200331d919087906004016200a0bc565b600060405180830381600087803b1580156200333857600080fd5b505af11580156200334d573d6000803e3d6000fd5b50505050505050505050565b60005462010000900460ff16156200338457604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff1615620033b65760405163b1d02c3d60e01b815260040160405180910390fd5b83620033c4603f8262008c39565b620033e25760405163056e881160e01b815260040160405180910390fd5b83620033f0603f8262008c39565b6200340e5760405163056e881160e01b815260040160405180910390fd5b6034805460ff1916600117905560008490036200343e57604051639811e0c760e01b815260040160405180910390fd5b846001600160a01b0316866001600160a01b031603620034715760405163f0e3e62960e01b815260040160405180910390fd5b6001600160a01b0380871660009081526041602090815260408083208151610180810183528154861681526001820154861693810193909352600281015490941690820152600383015460608201526004830180543394916080840191620034d9906200a086565b80601f016020809104026020016040519081016040528092919081815260200182805462003507906200a086565b8015620035585780601f106200352c5761010080835404028352916020019162003558565b820191906000526020600020905b8154815290600101906020018083116200353a57829003601f168201915b505050505081526020016005820160405180608001604052908160008201805462003583906200a086565b80601f0160208091040260200160405190810160405280929190818152602001828054620035b1906200a086565b8015620036025780601f10620035d65761010080835404028352916020019162003602565b820191906000526020600020905b815481529060010190602001808311620035e457829003601f168201915b505050505081526020016001820180546200361d906200a086565b80601f01602080910402602001604051908101604052809291908181526020018280546200364b906200a086565b80156200369c5780601f1062003670576101008083540402835291602001916200369c565b820191906000526020600020905b8154815290600101906020018083116200367e57829003601f168201915b50505050508152602001600282018054620036b7906200a086565b80601f0160208091040260200160405190810160405280929190818152602001828054620036e5906200a086565b8015620037365780601f106200370a5761010080835404028352916020019162003736565b820191906000526020600020905b8154815290600101906020018083116200371857829003601f168201915b5050505050815260200160038201805462003751906200a086565b80601f01602080910402602001604051908101604052809291908181526020018280546200377f906200a086565b8015620037d05780601f10620037a457610100808354040283529160200191620037d0565b820191906000526020600020905b815481529060010190602001808311620037b257829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152600d8301546001600160a01b031660a0830152805161026081019182905260c09092019190600e84019060139082845b8154815260200190600101908083116200386f57505050919092525050506001600160a01b03808916600090815260416020908152604080832081516101808101835281548616815260018201548616938101939093526002810154909416908201526003830154606082015260048301805494955091939092916080840191620038fa906200a086565b80601f016020809104026020016040519081016040528092919081815260200182805462003928906200a086565b8015620039795780601f106200394d5761010080835404028352916020019162003979565b820191906000526020600020905b8154815290600101906020018083116200395b57829003601f168201915b5050505050815260200160058201604051806080016040529081600082018054620039a4906200a086565b80601f0160208091040260200160405190810160405280929190818152602001828054620039d2906200a086565b801562003a235780601f10620039f75761010080835404028352916020019162003a23565b820191906000526020600020905b81548152906001019060200180831162003a0557829003601f168201915b5050505050815260200160018201805462003a3e906200a086565b80601f016020809104026020016040519081016040528092919081815260200182805462003a6c906200a086565b801562003abd5780601f1062003a915761010080835404028352916020019162003abd565b820191906000526020600020905b81548152906001019060200180831162003a9f57829003601f168201915b5050505050815260200160028201805462003ad8906200a086565b80601f016020809104026020016040519081016040528092919081815260200182805462003b06906200a086565b801562003b575780601f1062003b2b5761010080835404028352916020019162003b57565b820191906000526020600020905b81548152906001019060200180831162003b3957829003601f168201915b5050505050815260200160038201805462003b72906200a086565b80601f016020809104026020016040519081016040528092919081815260200182805462003ba0906200a086565b801562003bf15780601f1062003bc55761010080835404028352916020019162003bf1565b820191906000526020600020905b81548152906001019060200180831162003bd357829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152600d8301546001600160a01b031660a0830152805161026081019182905260c09092019190600e84019060139082845b81548152602001906001019080831162003c905750505050508152505090508060e00151801562003cd35750876001600160a01b0316836001600160a01b031614155b1562003cf257604051636468920360e01b815260040160405180910390fd5b60408083015190516352e82ce560e11b81526001600160a01b038581166004830152602482018a9052600092169063a5d059ca906044016020604051808303816000875af115801562003d49573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062003d6f91906200a135565b905060375481101562003d955760405163dc6f0bdd60e01b815260040160405180910390fd5b896001600160a01b0316846001600160a01b031614801562003e2a57506036546040808501519051630913db4760e01b81526001600160a01b038d8116600483015290911690630913db4790602401602060405180830381865afa15801562003e02573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062003e2891906200a135565b105b1562003e49576040516317b204bf60e11b815260040160405180910390fd5b6000620186a0603a548362003e5f91906200a1d2565b62003e6b91906200a0fc565b9050600083604001516001600160a01b03168260405160006040518083038185875af1925050503d806000811462003ec0576040519150601f19603f3d011682016040523d82523d6000602084013e62003ec5565b606091505b505090508062003ee8576040516312171d8360e31b815260040160405180910390fd5b62003ef482846200a1bc565b60408086015190516317066a5760e21b81526001600160a01b03898116600483015292955060009290911690635c19a95c90869060240160206040518083038185885af115801562003f4a573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019062003f7191906200a135565b9050866001600160a01b03168c6001600160a01b03168e6001600160a01b03167ffdac6e81913996d95abcc289e90f2d8bd235487ce6fe6f821e7d21002a1915b48e858960405162003fd6939291909283526020830191909152604082015260600190565b60405180910390a46040805160028082526060820183526000926020830190803683370190505090508660400151816000815181106200401a576200401a6200a18a565b60200260200101906001600160a01b031690816001600160a01b0316815250508560400151816001815181106200405557620040556200a18a565b6001600160a01b0390921660209283029190910190910152604051634484077560e01b815261200590634484077590620040969084908c906004016200a1ec565b600060405180830381600087803b158015620040b157600080fd5b505af1158015620040c6573d6000803e3d6000fd5b505050508a1562004138576120056001600160a01b031663e5ed5b1e898f6040518363ffffffff1660e01b8152600401620041039291906200a0bc565b600060405180830381600087803b1580156200411e57600080fd5b505af115801562004133573d6000803e3d6000fd5b505050505b50506034805460ff19169055505050505050505050505050565b60005462010000900460ff16156200417d57604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff1615620041af5760405163b1d02c3d60e01b815260040160405180910390fd5b620041b962008e36565b620041c6603f8262008c39565b620041e45760405163056e881160e01b815260040160405180910390fd5b6000620041f062008e36565b6001600160a01b0381166000908152604160205260409020600c810154919250904290620042239062015180906200a11f565b11156200424357604051631f92cdbd60e11b815260040160405180910390fd5b60098101546001600160401b03600160401b909104811690851611156200427d5760405163dc81db8560e01b815260040160405180910390fd5b60098101546000906001600160401b039081169086161015620042bb576009820154620042b59086906001600160401b03166200a218565b620042d5565b6009820154620042d5906001600160401b0316866200a218565b60098301546001600160401b039182169250600160801b900416811115620043105760405163dc81db8560e01b815260040160405180910390fd5b60098201805467ffffffffffffffff19166001600160401b03871690811790915542600c8401556040519081526001600160a01b038416907f78cdd96edf59e09cfd4d26ef6ef6c92d166effe6a40970c54821206d541932cb9060200160405180910390a25050505050565b606080606060006200438f603f62008f95565b90508086101562004a18578415620043a85784620043aa565b805b9450600085620043bb88846200a1bc565b11620043d357620043cd87836200a1bc565b620043d5565b855b9050806001600160401b03811115620043f257620043f26200985f565b6040519080825280602002602001820160405280156200441c578160200160208202803683370190505b509450806001600160401b038111156200443a576200443a6200985f565b60405190808252806020026020018201604052801562004464578160200160208202803683370190505b509350806001600160401b038111156200448257620044826200985f565b604051908082528060200260200182016040528015620044b757816020015b6060815260200190600190039081620044a15790505b50925060005b8181101562004a15576000620044e1620044d8838b6200a11f565b603f9062008fa0565b6001600160a01b038082166000908152604160209081526040808320815161018081018352815486168152600182015486169381019390935260028101549094169082015260038301546060820152600483018054949550919390929160808401916200454e906200a086565b80601f01602080910402602001604051908101604052809291908181526020018280546200457c906200a086565b8015620045cd5780601f10620045a157610100808354040283529160200191620045cd565b820191906000526020600020905b815481529060010190602001808311620045af57829003601f168201915b5050505050815260200160058201604051806080016040529081600082018054620045f8906200a086565b80601f016020809104026020016040519081016040528092919081815260200182805462004626906200a086565b8015620046775780601f106200464b5761010080835404028352916020019162004677565b820191906000526020600020905b8154815290600101906020018083116200465957829003601f168201915b5050505050815260200160018201805462004692906200a086565b80601f0160208091040260200160405190810160405280929190818152602001828054620046c0906200a086565b8015620047115780601f10620046e55761010080835404028352916020019162004711565b820191906000526020600020905b815481529060010190602001808311620046f357829003601f168201915b505050505081526020016002820180546200472c906200a086565b80601f01602080910402602001604051908101604052809291908181526020018280546200475a906200a086565b8015620047ab5780601f106200477f57610100808354040283529160200191620047ab565b820191906000526020600020905b8154815290600101906020018083116200478d57829003601f168201915b50505050508152602001600382018054620047c6906200a086565b80601f0160208091040260200160405190810160405280929190818152602001828054620047f4906200a086565b8015620048455780601f10620048195761010080835404028352916020019162004845565b820191906000526020600020905b8154815290600101906020018083116200482757829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152600d8301546001600160a01b031660a0830152805161026081019182905260c09092019190600e84019060139082845b815481526020019060010190808311620048e457505050505081525050905080600001518884815181106200491d576200491d6200a18a565b60200260200101906001600160a01b031690816001600160a01b0316815250508060e00151620049b65780604001516001600160a01b03166315d1f8986040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200498a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620049b091906200a135565b620049b9565b60005b878481518110620049ce57620049ce6200a18a565b6020026020010181815250508060800151868481518110620049f457620049f46200a18a565b602002602001018190525050508062004a0d906200a1a0565b9050620044bd565b50505b92959194509250565b60005462010000900460ff161562004a4c57604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff161562004a7e5760405163b1d02c3d60e01b815260040160405180910390fd5b3362004a8c603f8262008c39565b1562004aab57604051635f28f62b60e01b815260040160405180910390fd5b6001600160a01b038181166000908152604d6020526040902054161562004ae557604051631a0a9b9f60e21b815260040160405180910390fd5b6001600160a01b03888116600090815260436020526040902054161562004b1f57604051631e6f587560e11b815260040160405180910390fd5b60006001600160a01b03166045888860405162004b3e9291906200a0d6565b908152604051908190036020019020546001600160a01b03161462004b76576040516311fdb94760e01b815260040160405180910390fd5b600062004b8483806200a242565b60405160200162004b979291906200a0d6565b60408051601f1981840301815291815281516020928301206000818152604290935291205490915060ff161562004be15760405163c0bf414360e01b815260040160405180910390fd5b600062004bf7670de0b6b3a7640000346200a1bc565b905060365481101562004c1d576040516317b204bf60e11b815260040160405180910390fd5b6001600160a01b038a1662004c4557604051636520611b60e11b815260040160405180910390fd5b61138862004c5a604087016020880162009b7e565b6001600160401b0316118062004ca0575062004c7d604086016020870162009b7e565b6001600160401b031662004c95602087018762009b7e565b6001600160401b0316115b8062004cdf575062004cb9604086016020870162009b7e565b6001600160401b031662004cd4606087016040880162009b7e565b6001600160401b0316115b1562004cfe5760405163dc81db8560e01b815260040160405180910390fd5b62004d4962004d0e85806200a242565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525062008fae92505050565b62004d6757604051635dba5ad760e01b815260040160405180910390fd5b62004d76838a8a8a8a62009150565b62004d9457604051631647e3cb60e11b815260040160405180910390fd5b600062004de28462004da787806200a242565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506200928092505050565b905062004df1603f8562009381565b506000838152604260209081526040808320805460ff191660019081179091556001600160a01b0380891680865260419094529190932080548f83166001600160a01b03199182161782559381018054851690931790925560028201805491851691909316179091554260038201556004810162004e718b8d836200a2ea565b50856005820162004e8382826200a3b2565b508790506009820162004e9782826200a4eb565b505042600c8201556001600160a01b038c81166000908152604360205260409081902080546001600160a01b0319169288169290921790915551859060459062004ee5908e908e906200a0d6565b908152602001604051809103902060006101000a8154816001600160a01b0302191690836001600160a01b03160217905550816001600160a01b0316856001600160a01b03168d6001600160a01b03167faecd9fb95e79c75a3a1de93362c6be5fe6ab65770d8614be583884161cd8228d8e8e60405162004f689291906200a5bb565b60405180910390a460408051848152602081018590526001600160a01b0387169182917f24d7bda8602b916d64417f0dbfe2e2e88ec9b1157bd9f596dfdb91ba26624e04910160405180910390a360408051670de0b6b3a7640000808252602082015261dead916001600160a01b038816917f24d7bda8602b916d64417f0dbfe2e2e88ec9b1157bd9f596dfdb91ba26624e04910160405180910390a3604051633041949b60e01b815261200590633041949b906200502e90859089906004016200a0bc565b600060405180830381600087803b1580156200504957600080fd5b505af11580156200505e573d6000803e3d6000fd5b50505050505050505050505050505050565b6040805160608101825260008082526020820181905291810191909152816200509b603f8262008c39565b620050b95760405163056e881160e01b815260040160405180910390fd5b50506001600160a01b031660009081526041602090815260409182902082516060810184526009909101546001600160401b038082168352600160401b8204811693830193909352600160801b90049091169181019190915290565b6001600160a01b0380821660009081526041602090815260408083208151610180810183528154861681526001820154861693810193909352600281015490941690820152600383015460608281019190915260048401805491949160808401919062005182906200a086565b80601f0160208091040260200160405190810160405280929190818152602001828054620051b0906200a086565b8015620052015780601f10620051d55761010080835404028352916020019162005201565b820191906000526020600020905b815481529060010190602001808311620051e357829003601f168201915b50505050508152602001600582016040518060800160405290816000820180546200522c906200a086565b80601f01602080910402602001604051908101604052809291908181526020018280546200525a906200a086565b8015620052ab5780601f106200527f57610100808354040283529160200191620052ab565b820191906000526020600020905b8154815290600101906020018083116200528d57829003601f168201915b50505050508152602001600182018054620052c6906200a086565b80601f0160208091040260200160405190810160405280929190818152602001828054620052f4906200a086565b8015620053455780601f10620053195761010080835404028352916020019162005345565b820191906000526020600020905b8154815290600101906020018083116200532757829003601f168201915b5050505050815260200160028201805462005360906200a086565b80601f01602080910402602001604051908101604052809291908181526020018280546200538e906200a086565b8015620053df5780601f10620053b357610100808354040283529160200191620053df565b820191906000526020600020905b815481529060010190602001808311620053c157829003601f168201915b50505050508152602001600382018054620053fa906200a086565b80601f016020809104026020016040519081016040528092919081815260200182805462005428906200a086565b8015620054795780601f106200544d5761010080835404028352916020019162005479565b820191906000526020600020905b8154815290600101906020018083116200545b57829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152600d8301546001600160a01b031660a0830152805161026081019182905260c09092019190600e84019060139082845b815481526020019060010190808311620055185750505091909252505050608001519392505050565b33611001146200556957604051630f22c43960e41b81526110016004820152602401620012e4565b6001600160a01b038082166000908152604360205260409020541662005591603f8262008c39565b620055af5760405163056e881160e01b815260040160405180910390fd5b6001600160a01b038181166000908152604160205260408082206002810154603b54925163045bc4d160e41b81526004810193909352909316906345bc4d10906024016020604051808303816000875af115801562005612573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200563891906200a135565b90506000603d54426200564c91906200a11f565b90506200565a838262008ce4565b836001600160a01b03167f6e9a2ee7aee95665e3a774a212eb11441b217e3e4656ab9563793094689aabb2828460016040516200569a939291906200a14f565b60405180910390a26002830154604051633041949b60e01b815261200591633041949b91620056d8916001600160a01b03169088906004016200a0bc565b600060405180830381600087803b158015620056f357600080fd5b505af115801562005708573d6000803e3d6000fd5b505050505050505050565b600054610100900460ff1615808015620057345750600054600160ff909116105b80620057505750303b15801562005750575060005460ff166001145b620057b55760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401620012e4565b6000805460ff191660011790558015620057d9576000805461ff0019166101001790555b334114620057fa5760405163022d8c9560e31b815260040160405180910390fd5b3a156200581a576040516383f1b1d360e01b815260040160405180910390fd5b611388603555686c6b935b8bbd400000603655670de0b6b3a7640000603755600960385562093a806039556002603a819055678ac7230489e80000603b55680ad78ebc5ac6200000603c556202a300603d5562069780603e55604a55620058957330151da466ec8ab345bef3d6983023e050fb067362009398565b80156200190f576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150565b33612000146200590657604051630f22c43960e41b81526120006004820152602401620012e4565b60405162461bcd60e51b815260206004820152600a60248201526919195c1c9958d85d195960b21b6044820152606401620012e4565b600054630100000090046001600160a01b031633146200596f576040516306fbb1e360e01b815260040160405180910390fd5b60005462010000900460ff16156200599a57604051631785c68160e01b815260040160405180910390fd5b6000805462ff00001916620100001781556040517f9e87fac88ff661f02d44f95383c817fece4bce600a3dab7a54406878b965e7529190a1565b6000620059e3603f8462008c39565b62005a015760405163056e881160e01b815260040160405180910390fd5b6001600160a01b0383811660009081526041602052604090819020600201549051636bbf224960e01b815260048101859052911690636bbf2249906024015b602060405180830381865afa15801562005a5e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062005a8491906200a135565b90505b92915050565b60005462010000900460ff161562005ab857604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff161562005aea5760405163b1d02c3d60e01b815260040160405180910390fd5b8162005af8603f8262008c39565b62005b165760405163056e881160e01b815260040160405180910390fd5b603754349081101562005b3c5760405163dc6f0bdd60e01b815260040160405180910390fd5b6001600160a01b038085166000908152604160209081526040808320815161018081018352815486168152600182015486169381019390935260028101549094169082015260038301546060820152600483018054339491608084019162005ba4906200a086565b80601f016020809104026020016040519081016040528092919081815260200182805462005bd2906200a086565b801562005c235780601f1062005bf75761010080835404028352916020019162005c23565b820191906000526020600020905b81548152906001019060200180831162005c0557829003601f168201915b505050505081526020016005820160405180608001604052908160008201805462005c4e906200a086565b80601f016020809104026020016040519081016040528092919081815260200182805462005c7c906200a086565b801562005ccd5780601f1062005ca15761010080835404028352916020019162005ccd565b820191906000526020600020905b81548152906001019060200180831162005caf57829003601f168201915b5050505050815260200160018201805462005ce8906200a086565b80601f016020809104026020016040519081016040528092919081815260200182805462005d16906200a086565b801562005d675780601f1062005d3b5761010080835404028352916020019162005d67565b820191906000526020600020905b81548152906001019060200180831162005d4957829003601f168201915b5050505050815260200160028201805462005d82906200a086565b80601f016020809104026020016040519081016040528092919081815260200182805462005db0906200a086565b801562005e015780601f1062005dd55761010080835404028352916020019162005e01565b820191906000526020600020905b81548152906001019060200180831162005de357829003601f168201915b5050505050815260200160038201805462005e1c906200a086565b80601f016020809104026020016040519081016040528092919081815260200182805462005e4a906200a086565b801562005e9b5780601f1062005e6f5761010080835404028352916020019162005e9b565b820191906000526020600020905b81548152906001019060200180831162005e7d57829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152600d8301546001600160a01b031660a0830152805161026081019182905260c09092019190600e84019060139082845b81548152602001906001019080831162005f3a5750505050508152505090508060e00151801562005f7d5750856001600160a01b0316826001600160a01b031614155b1562005f9c57604051636468920360e01b815260040160405180910390fd5b60408082015190516317066a5760e21b81526001600160a01b0384811660048301526000921690635c19a95c90869060240160206040518083038185885af115801562005fed573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906200601491906200a135565b9050826001600160a01b0316876001600160a01b03167f24d7bda8602b916d64417f0dbfe2e2e88ec9b1157bd9f596dfdb91ba26624e04838760405162006065929190918252602082015260400190565b60405180910390a36040808301519051633041949b60e01b815261200591633041949b916200609a919087906004016200a0bc565b600060405180830381600087803b158015620060b557600080fd5b505af1158015620060ca573d6000803e3d6000fd5b50505050851562001908576040516372f6ad8f60e11b81526120059063e5ed5b1e90620060fe9086908b906004016200a0bc565b600060405180830381600087803b1580156200611957600080fd5b505af11580156200612e573d6000803e3d6000fd5b5050505050505050505050565b60005462010000900460ff16156200616657604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff1615620061985760405163b1d02c3d60e01b815260040160405180910390fd5b620061a262008dd8565b620061af603f8262008c39565b620061cd5760405163056e881160e01b815260040160405180910390fd5b6000620061d962008dd8565b6001600160a01b0381166000908152604f6020526040812080549293509190859003620062b05760005b818110156200628457836001600160a01b03167f08e60c1b84aab23d99a7262015e647d5ffd6c6e08f78205e1df6774c48e1427a8483815481106200624c576200624c6200a18a565b90600052602060002001546040516200626791815260200190565b60405180910390a2806200627b816200a1a0565b91505062006203565b506001600160a01b0383166000908152604f60205260408120620062a8916200968a565b505050505050565b60005b858110156200640e576000878783818110620062d357620062d36200a18a565b90506020020135905060005b83811015620063f65781858281548110620062fe57620062fe6200a18a565b906000526020600020015403620063e157846200631d6001866200a1bc565b815481106200633057620063306200a18a565b90600052602060002001548582815481106200635057620063506200a18a565b9060005260206000200181905550848054806200637157620063716200a5d1565b60019003818190600052602060002001600090559055838062006394906200a5e7565b945050856001600160a01b03167f08e60c1b84aab23d99a7262015e647d5ffd6c6e08f78205e1df6774c48e1427a83604051620063d391815260200190565b60405180910390a2620063f6565b80620063ed816200a1a0565b915050620062df565b5050808062006405906200a1a0565b915050620062b3565b508154600003620062a8576001600160a01b0383166000908152604f60205260408120620062a8916200968a565b505050565b6200646d6040518060800160405280606081526020016060815260200160608152602001606081525090565b816200647b603f8262008c39565b620064995760405163056e881160e01b815260040160405180910390fd5b6001600160a01b03831660009081526041602052604090819020815160808101909252600501805482908290620064d0906200a086565b80601f0160208091040260200160405190810160405280929190818152602001828054620064fe906200a086565b80156200654f5780601f1062006523576101008083540402835291602001916200654f565b820191906000526020600020905b8154815290600101906020018083116200653157829003601f168201915b505050505081526020016001820180546200656a906200a086565b80601f016020809104026020016040519081016040528092919081815260200182805462006598906200a086565b8015620065e95780601f10620065bd57610100808354040283529160200191620065e9565b820191906000526020600020905b815481529060010190602001808311620065cb57829003601f168201915b5050505050815260200160028201805462006604906200a086565b80601f016020809104026020016040519081016040528092919081815260200182805462006632906200a086565b8015620066835780601f10620066575761010080835404028352916020019162006683565b820191906000526020600020905b8154815290600101906020018083116200666557829003601f168201915b505050505081526020016003820180546200669e906200a086565b80601f0160208091040260200160405190810160405280929190818152602001828054620066cc906200a086565b80156200671d5780601f10620066f1576101008083540402835291602001916200671d565b820191906000526020600020905b815481529060010190602001808311620066ff57829003601f168201915b505050505081525050915050919050565b60005462010000900460ff16156200675957604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff16156200678b5760405163b1d02c3d60e01b815260040160405180910390fd5b62006797828262009431565b5050565b3361100714620067c357604051630f22c43960e41b81526110076004820152602401620012e4565b620068306040518060400160405280601081526020016f1d1c985b9cd9995c91d85cd31a5b5a5d60821b81525085858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092939250506200953d9050565b15620068eb5760208114620068625783838383604051630a5a604160e01b8152600401620012e494939291906200a601565b604080516020601f8401819004810282018101909252828152600091620068a59185858083850183828082843760009201919091525092939250506200959a9050565b90506108fc811080620068b9575061271081115b15620068e25784848484604051630a5a604160e01b8152600401620012e494939291906200a601565b60355562007708565b6200695c6040518060400160405280601481526020017336b4b729b2b6332232b632b3b0ba34b7b721272160611b81525085858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092939250506200953d9050565b1562006a2657602081146200698e5783838383604051630a5a604160e01b8152600401620012e494939291906200a601565b604080516020601f8401819004810282018101909252828152600091620069d19185858083850183828082843760009201919091525092939250506200959a9050565b9050683635c9adc5dea00000811080620069f4575069152d02c7e14af680000081115b1562006a1d5784848484604051630a5a604160e01b8152600401620012e494939291906200a601565b60365562007708565b62006a99604051806040016040528060168152602001756d696e44656c65676174696f6e424e424368616e676560501b81525085858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092939250506200953d9050565b1562006b60576020811462006acb5783838383604051630a5a604160e01b8152600401620012e494939291906200a601565b604080516020601f840181900481028201810190925282815260009162006b0e9185858083850183828082843760009201919091525092939250506200959a9050565b905067016345785d8a000081108062006b2e5750678ac7230489e8000081115b1562006b575784848484604051630a5a604160e01b8152600401620012e494939291906200a601565b60375562007708565b62006bd1604051806040016040528060148152602001736d6178456c656374656456616c696461746f727360601b81525085858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092939250506200953d9050565b1562006c89576020811462006c035783838383604051630a5a604160e01b8152600401620012e494939291906200a601565b604080516020601f840181900481028201810190925282815260009162006c469185858083850183828082843760009201919091525092939250506200959a9050565b905080158062006c5757506101f481115b1562006c805784848484604051630a5a604160e01b8152600401620012e494939291906200a601565b60385562007708565b62006cf26040518060400160405280600c81526020016b1d5b989bdb9914195c9a5bd960a21b81525085858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092939250506200953d9050565b1562006daf576020811462006d245783838383604051630a5a604160e01b8152600401620012e494939291906200a601565b604080516020601f840181900481028201810190925282815260009162006d679185858083850183828082843760009201919091525092939250506200959a9050565b90506203f48081108062006d7d575062278d0081115b1562006da65784848484604051630a5a604160e01b8152600401620012e494939291906200a601565b60395562007708565b62006e1d60405180604001604052806011815260200170726564656c65676174654665655261746560781b81525085858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092939250506200953d9050565b1562006eca576020811462006e4f5783838383604051630a5a604160e01b8152600401620012e494939291906200a601565b604080516020601f840181900481028201810190925282815260009162006e929185858083850183828082843760009201919091525092939250506200959a9050565b9050606481111562006ec15784848484604051630a5a604160e01b8152600401620012e494939291906200a601565b603a5562007708565b62006f3a60405180604001604052806013815260200172191bdddb9d1a5b5954db185cda105b5bdd5b9d606a1b81525085858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092939250506200953d9050565b1562006ffb576020811462006f6c5783838383604051630a5a604160e01b8152600401620012e494939291906200a601565b604080516020601f840181900481028201810190925282815260009162006faf9185858083850183828082843760009201919091525092939250506200959a9050565b9050674563918244f4000081108062006fc95750603c5481115b1562006ff25784848484604051630a5a604160e01b8152600401620012e494939291906200a601565b603b5562007708565b620070696040518060400160405280601181526020017019995b1bdb9e54db185cda105b5bdd5b9d607a1b81525085858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092939250506200953d9050565b156200712c57602081146200709b5783838383604051630a5a604160e01b8152600401620012e494939291906200a601565b604080516020601f8401819004810282018101909252828152600091620070de9185858083850183828082843760009201919091525092939250506200959a9050565b905068056bc75e2d63100000811080620070fa5750603b548111155b15620071235784848484604051630a5a604160e01b8152600401620012e494939291906200a601565b603c5562007708565b620071996040518060400160405280601081526020016f646f776e74696d654a61696c54696d6560801b81525085858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092939250506200953d9050565b15620072565760208114620071cb5783838383604051630a5a604160e01b8152600401620012e494939291906200a601565b604080516020601f84018190048102820181019092528281526000916200720e9185858083850183828082843760009201919091525092939250506200959a9050565b90506202a300811080620072245750603e548110155b156200724d5784848484604051630a5a604160e01b8152600401620012e494939291906200a601565b603d5562007708565b620072c16040518060400160405280600e81526020016d66656c6f6e794a61696c54696d6560901b81525085858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092939250506200953d9050565b156200737e5760208114620072f35783838383604051630a5a604160e01b8152600401620012e494939291906200a601565b604080516020601f8401819004810282018101909252828152600091620073369185858083850183828082843760009201919091525092939250506200959a9050565b9050620d2f008110806200734c5750603d548111155b15620073755784848484604051630a5a604160e01b8152600401620012e494939291906200a601565b603e5562007708565b620073f86040518060400160405280601c81526020017f6d617846656c6f6e794265747765656e42726561746865426c6f636b0000000081525085858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092939250506200953d9050565b15620074a457602081146200742a5783838383604051630a5a604160e01b8152600401620012e494939291906200a601565b604080516020601f84018190048102820181019092528281526000916200746d9185858083850183828082843760009201919091525092939250506200959a9050565b9050806000036200749b5784848484604051630a5a604160e01b8152600401620012e494939291906200a601565b604a5562007708565b620075126040518060400160405280601181526020017039ba30b5b2a43ab1283937ba32b1ba37b960791b81525085858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092939250506200953d9050565b15620075d25760148114620075445783838383604051630a5a604160e01b8152600401620012e494939291906200a601565b60006200758c601484848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092939250506200959a9050565b90506001600160a01b038116620075c05784848484604051630a5a604160e01b8152600401620012e494939291906200a601565b620075cb816200959f565b5062007708565b620076396040518060400160405280600a8152602001696d61784e6f646549447360b01b81525085858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092939250506200953d9050565b15620076e557602081146200766b5783838383604051630a5a604160e01b8152600401620012e494939291906200a601565b604080516020601f8401819004810282018101909252828152600091620076ae9185858083850183828082843760009201919091525092939250506200959a9050565b905080600003620076dc5784848484604051630a5a604160e01b8152600401620012e494939291906200a601565b604e5562007708565b838383836040516325ee20d560e21b8152600401620012e494939291906200a601565b7ff1ce9b2cbf50eeb05769a29e2543fd350cab46894a7dd9978a12d534bb20e633848484846040516200773f94939291906200a601565b60405180910390a150505050565b60005462010000900460ff16156200777857604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff1615620077aa5760405163b1d02c3d60e01b815260040160405180910390fd5b816000816001600160401b03811115620077c857620077c86200985f565b604051908082528060200260200182016040528015620077f2578160200160208202803683370190505b5090506000805b83811015620078f0576200783b8787838181106200781b576200781b6200a18a565b9050602002016020810190620078329190620096f0565b603f9062008c39565b620078595760405163056e881160e01b815260040160405180910390fd5b604160008888848181106200787257620078726200a18a565b9050602002016020810190620078899190620096f0565b6001600160a01b0390811682526020820192909252604001600020600201548451911692508290849083908110620078c557620078c56200a18a565b6001600160a01b0390921660209283029190910190910152620078e8816200a1a0565b9050620077f9565b50604051634484077560e01b8152612005906344840775906200331d90859088906004016200a1ec565b60608060006200792b603f62008f95565b90508085101562007aef57831562007944578362007946565b805b93506000846200795787846200a1bc565b116200796f576200796986836200a1bc565b62007971565b845b9050806001600160401b038111156200798e576200798e6200985f565b604051908082528060200260200182016040528015620079b8578160200160208202803683370190505b509350806001600160401b03811115620079d657620079d66200985f565b60405190808252806020026020018201604052801562007a00578160200160208202803683370190505b50925060005b8181101562007aec5762007a1f620044d882896200a11f565b85828151811062007a345762007a346200a18a565b60200260200101906001600160a01b031690816001600160a01b0316815250506041600086838151811062007a6d5762007a6d6200a18a565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060020160009054906101000a90046001600160a01b031684828151811062007ac15762007ac16200a18a565b6001600160a01b039092166020928302919091019091015262007ae4816200a1a0565b905062007a06565b50505b9250925092565b60008162007b06603f8262008c39565b62007b245760405163056e881160e01b815260040160405180910390fd5b50506001600160a01b03166000908152604160205260409020600c015490565b336110011462007b6c57604051630f22c43960e41b81526110016004820152602401620012e4565b60005462010000900460ff161562007b9757604051631785c68160e01b815260040160405180910390fd5b6001600160a01b038082166000908152604360205260409020541662007bbf603f8262008c39565b62007bdd5760405163056e881160e01b815260040160405180910390fd5b6001600160a01b03811660009081526041602052604081209062007c0562015180426200a0fc565b604a546000828152604b60205260409020549192501162007c395760405163bd52fcdb60e01b815260040160405180910390fd5b6000818152604b6020526040812080546001929062007c5a9084906200a11f565b90915550506001600160a01b0384166000908152604460205260409020541580159062007caf57506001600160a01b038416600090815260446020526040902054429062007cad9062015180906200a11f565b105b1562007cce576040516330abb81d60e21b815260040160405180910390fd5b60008062007cde85600062008c5c565b915091508162007d0157604051631b919bb160e11b815260040160405180910390fd5b6002840154603c5460405163045bc4d160e41b815260048101919091526000916001600160a01b0316906345bc4d10906024016020604051808303816000875af115801562007d54573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062007d7a91906200a135565b905062007d88858362008ce4565b856001600160a01b03167f6e9a2ee7aee95665e3a774a212eb11441b217e3e4656ab9563793094689aabb28383600060405162007dc8939291906200a14f565b60405180910390a26002850154604051633041949b60e01b815261200591633041949b91620060fe916001600160a01b0316908a906004016200a0bc565b6001600160a01b038082166000908152604160209081526040808320815161018081018352815486168152600182015486169381019390935260028101549094169082015260038301546060820152600483018054929384938493849390929160808401919062007e77906200a086565b80601f016020809104026020016040519081016040528092919081815260200182805462007ea5906200a086565b801562007ef65780601f1062007eca5761010080835404028352916020019162007ef6565b820191906000526020600020905b81548152906001019060200180831162007ed857829003601f168201915b505050505081526020016005820160405180608001604052908160008201805462007f21906200a086565b80601f016020809104026020016040519081016040528092919081815260200182805462007f4f906200a086565b801562007fa05780601f1062007f745761010080835404028352916020019162007fa0565b820191906000526020600020905b81548152906001019060200180831162007f8257829003601f168201915b5050505050815260200160018201805462007fbb906200a086565b80601f016020809104026020016040519081016040528092919081815260200182805462007fe9906200a086565b80156200803a5780601f106200800e576101008083540402835291602001916200803a565b820191906000526020600020905b8154815290600101906020018083116200801c57829003601f168201915b5050505050815260200160028201805462008055906200a086565b80601f016020809104026020016040519081016040528092919081815260200182805462008083906200a086565b8015620080d45780601f10620080a857610100808354040283529160200191620080d4565b820191906000526020600020905b815481529060010190602001808311620080b657829003601f168201915b50505050508152602001600382018054620080ef906200a086565b80601f01602080910402602001604051908101604052809291908181526020018280546200811d906200a086565b80156200816e5780601f1062008142576101008083540402835291602001916200816e565b820191906000526020600020905b8154815290600101906020018083116200815057829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152600d8301546001600160a01b031660a0830152805161026081019182905260c09092019190600e84019060139082845b8154815260200190600101908083116200820d5750505091909252505050606081015160e0820151610100909201519097919650945092505050565b60005462010000900460ff16156200827457604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff1615620082a65760405163b1d02c3d60e01b815260040160405180910390fd5b620082b062008e36565b620082bd603f8262008c39565b620082db5760405163056e881160e01b815260040160405180910390fd5b6000620082e762008e36565b6001600160a01b0381166000908152604160205260409020600c8101549192509042906200831a9062015180906200a11f565b11156200833a57604051631f92cdbd60e11b815260040160405180910390fd5b6005810180546200834b906200a086565b80601f016020809104026020016040519081016040528092919081815260200182805462008379906200a086565b8015620083ca5780601f106200839e57610100808354040283529160200191620083ca565b820191906000526020600020905b815481529060010190602001808311620083ac57829003601f168201915b5050508287525085916005840191508190620083e790826200a637565b5060208201516001820190620083fe90826200a637565b50604082015160028201906200841590826200a637565b50606082015160038201906200842c90826200a637565b505042600c830155506040516001600160a01b038316907f85d6366b336ade7f106987ec7a8eac1e8799e508aeab045a39d2f63e0dc969d990600090a250505050565b60005462010000900460ff16156200849a57604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff1615620084cc5760405163b1d02c3d60e01b815260040160405180910390fd5b828114620084ed576040516341abc80160e01b815260040160405180910390fd5b60005b838110156200855e576200854b8585838181106200851257620085126200a18a565b9050602002016020810190620085299190620096f0565b8484848181106200853e576200853e6200a18a565b9050602002013562009431565b62008556816200a1a0565b9050620084f0565b5050505050565b6001600160a01b0380821660009081526041602090815260408083208151610180810183528154861681526001820154861693810193909352600281015490941690820152600383015460608201526004830180549293849390916080840191620085d0906200a086565b80601f0160208091040260200160405190810160405280929190818152602001828054620085fe906200a086565b80156200864f5780601f1062008623576101008083540402835291602001916200864f565b820191906000526020600020905b8154815290600101906020018083116200863157829003601f168201915b50505050508152602001600582016040518060800160405290816000820180546200867a906200a086565b80601f0160208091040260200160405190810160405280929190818152602001828054620086a8906200a086565b8015620086f95780601f10620086cd57610100808354040283529160200191620086f9565b820191906000526020600020905b815481529060010190602001808311620086db57829003601f168201915b5050505050815260200160018201805462008714906200a086565b80601f016020809104026020016040519081016040528092919081815260200182805462008742906200a086565b8015620087935780601f10620087675761010080835404028352916020019162008793565b820191906000526020600020905b8154815290600101906020018083116200877557829003601f168201915b50505050508152602001600282018054620087ae906200a086565b80601f0160208091040260200160405190810160405280929190818152602001828054620087dc906200a086565b80156200882d5780601f1062008801576101008083540402835291602001916200882d565b820191906000526020600020905b8154815290600101906020018083116200880f57829003601f168201915b5050505050815260200160038201805462008848906200a086565b80601f016020809104026020016040519081016040528092919081815260200182805462008876906200a086565b8015620088c75780601f106200889b57610100808354040283529160200191620088c7565b820191906000526020600020905b815481529060010190602001808311620088a957829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152600d8301546001600160a01b031660a0830152805161026081019182905260c09092019190600e84019060139082845b815481526020019060010190808311620089665750505091909252505050604001519392505050565b60006200899e603f8462008c39565b620089bc5760405163056e881160e01b815260040160405180910390fd5b6001600160a01b038381166000908152604160205260409081902060020154905163aa1966cd60e01b81526004810185905291169063aa1966cd9060240162005a40565b60005462010000900460ff161562008a2b57604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff161562008a5d5760405163b1d02c3d60e01b815260040160405180910390fd5b62008a6762008e36565b62008a74603f8262008c39565b62008a925760405163056e881160e01b815260040160405180910390fd5b600062008a9e62008e36565b905062008aaf818787878762009150565b62008acd57604051631647e3cb60e11b815260040160405180910390fd5b60006001600160a01b03166045878760405162008aec9291906200a0d6565b908152604051908190036020019020546001600160a01b03161462008b24576040516311fdb94760e01b815260040160405180910390fd5b6001600160a01b0381166000908152604160205260409020600c810154429062008b539062015180906200a11f565b111562008b7357604051631f92cdbd60e11b815260040160405180910390fd5b4260468260040160405162008b8991906200a6ff565b908152604051908190036020019020556004810162008baa8789836200a2ea565b5042600c820155604051829060459062008bc8908a908a906200a0d6565b90815260405190819003602001812080546001600160a01b039384166001600160a01b0319909116179055908316907f783156582145bd0ff7924fae6953ba054cf1233eb60739a200ddb10de068ff0d9062008c28908a908a906200a5bb565b60405180910390a250505050505050565b6001600160a01b0381166000908152600183016020526040812054151562005a84565b6000806000848460405160200162008c769291906200a77d565b60408051601f1981840301815291815281516020928301206000818152604c9093529120549091504281111562008cb6576000809350935050506200264a565b603e5462008cc590426200a11f565b6000928352604c60205260409092208290555060019590945092505050565b6000600162008cf4603f62008f95565b62008d0091906200a1bc565b604954108015915062008d4c5760018301546040516001600160a01b03909116907f2afdc18061ac21cff7d9f11527ab9c8dec6fabd4edf6f894ed634bebd6a20d4590600090a2505050565b82600b015482111562008d6157600b83018290555b600a83015460ff166200643c57600a8301805460ff191660019081179091556049805460009062008d949084906200a11f565b909155505060018301546040516001600160a01b03909116907f4905ac32602da3fb8b4b7b00c285e5fc4c6c2308cc908b4a1e4e9625a29c90a390600090a2505050565b336000908152604360205260408120546001600160a01b03161562008e145750336000908152604360205260409020546001600160a01b031690565b62008e1e62008e36565b905090565b604e5460000362008e34576005604e555b565b336000908152604d60205260408120546001600160a01b03161562008e725750336000908152604d60205260409020546001600160a01b031690565b503390565b6001600160a01b0381166000908152604160205260409020600a81015460ff161562008ea1575050565b6036546002820154604051630913db4760e01b81526001600160a01b03858116600483015290911690630913db4790602401602060405180830381865afa15801562008ef1573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062008f1791906200a135565b1015620067975762008f3981603d544262008f3391906200a11f565b62008ce4565b80546040516335409f7f60e01b81526001600160a01b039091166004820152611000906335409f7f90602401600060405180830381600087803b15801562008f8057600080fd5b505af1158015620062a8573d6000803e3d6000fd5b600062005a87825490565b600062005a8483836200960b565b60008082905060038151108062008fc6575060098151115b1562008fd55750600092915050565b60418160008151811062008fed5762008fed6200a18a565b016020015160f81c10806200901f5750605a816000815181106200901557620090156200a18a565b016020015160f81c115b156200902e5750600092915050565b60015b8151811015620091465760308282815181106200905257620090526200a18a565b016020015160f81c108062009083575060398282815181106200907957620090796200a18a565b016020015160f81c115b8015620090d357506041828281518110620090a257620090a26200a18a565b016020015160f81c1080620090d35750605a828281518110620090c957620090c96200a18a565b016020015160f81c115b80156200912357506061828281518110620090f257620090f26200a18a565b016020015160f81c1080620091235750607a8282815181106200911957620091196200a18a565b016020015160f81c115b1562009133575060009392505050565b6200913e816200a1a0565b905062009031565b5060019392505050565b600060308414158062009164575060608214155b15620091735750600062009277565b6000868686466040516020016200918e94939291906200a7c7565b60408051808303601f1901815282825280516020918201208184528383019092529092506000919060208201818036833701905050905081602082015260008186868a8a604051602001620091e89594939291906200a7f4565b60408051808303601f190181526001808452838301909252925060009190602082018180368337019050509050815160016020830182602086016066600019fa6200923257600080fd5b506000816000815181106200924b576200924b6200a18a565b016020015160f81c9050600181146200926d5760009550505050505062009277565b6001955050505050505b95945050505050565b60008061200361dead6040516200929790620096aa565b6001600160a01b03928316815291166020820152606060408201819052600090820152608001604051809103906000f080158015620092da573d6000803e3d6000fd5b509050806001600160a01b031663f399e22e3486866040518463ffffffff1660e01b81526004016200930e9291906200a82c565b6000604051808303818588803b1580156200932857600080fd5b505af11580156200933d573d6000803e3d6000fd5b50506040516001600160a01b038086169450881692507fd481492e4e93bb36b4c12a5af93f03be3bf04b454dfbc35dd2663fa26f44d5b09150600090a39392505050565b600062005a84836001600160a01b03841662009638565b600054610100900460ff16620094055760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401620012e4565b600080546001600160a01b039092166301000000026301000000600160b81b0319909216919091179055565b816200943f603f8262008c39565b6200945d5760405163056e881160e01b815260040160405180910390fd5b6001600160a01b03838116600090815260416020526040808220600201549051635569f64b60e11b8152336004820152602481018690529192169063aad3ec96906044016020604051808303816000875af1158015620094c1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620094e791906200a135565b9050336001600160a01b0316846001600160a01b03167ff7a40077ff7a04c7e61f6f26fb13774259ddf1b6bce9ecf26a8276cdd3992683836040516200952f91815260200190565b60405180910390a350505050565b6000816040516020016200955291906200a852565b60405160208183030381529060405280519060200120836040516020016200957b91906200a852565b6040516020818303038152906040528051906020012014905092915050565b015190565b600080546040516001600160a01b0380851693630100000090930416917f44fc1b38a4abaa91ebd1b628a5b259a698f86238c8217d68f516e87769c60c0b91a3600080546001600160a01b039092166301000000026301000000600160b81b0319909216919091179055565b60008260000182815481106200962557620096256200a18a565b9060005260206000200154905092915050565b6000818152600183016020526040812054620096815750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562005a87565b50600062005a87565b50805460008255906000526020600020908101906200190f9190620096b8565b610e96806200a87183390190565b5b80821115620096cf5760008155600101620096b9565b5090565b80356001600160a01b0381168114620096eb57600080fd5b919050565b6000602082840312156200970357600080fd5b62005a8482620096d3565b60008083601f8401126200972157600080fd5b5081356001600160401b038111156200973957600080fd5b6020830191508360208285010111156200264a57600080fd5b600080602083850312156200976657600080fd5b82356001600160401b038111156200977d57600080fd5b6200978b858286016200970e565b90969095509350505050565b600080600060408486031215620097ad57600080fd5b833560ff81168114620097bf57600080fd5b925060208401356001600160401b03811115620097db57600080fd5b620097e9868287016200970e565b9497909650939450505050565b60005b8381101562009813578181015183820152602001620097f9565b50506000910152565b6000815180845262009836816020860160208601620097f6565b601f01601f19169290920160200192915050565b60208152600062005a8460208301846200981c565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b03811182821017156200989a576200989a6200985f565b60405290565b60006001600160401b0380841115620098bd57620098bd6200985f565b604051601f8501601f19908116603f01168101908282118183101715620098e857620098e86200985f565b816040528093508581528686860111156200990257600080fd5b858560208301376000602087830101525050509392505050565b6000602082840312156200992f57600080fd5b81356001600160401b038111156200994657600080fd5b8201601f810184136200995857600080fd5b6200996984823560208401620098a0565b949350505050565b60008083601f8401126200998457600080fd5b5081356001600160401b038111156200999c57600080fd5b6020830191508360208260051b85010111156200264a57600080fd5b60008060208385031215620099cc57600080fd5b82356001600160401b03811115620099e357600080fd5b6200978b8582860162009971565b600081518084526020808501945080840160005b8381101562009a2c5781516001600160a01b03168752958201959082019060010162009a05565b509495945050505050565b60408152600062009a4c6040830185620099f1565b6020838203818501528185518084528284019150828160051b8501018388016000805b8481101562009ac657878403601f19018652825180518086529088019088860190845b8181101562009ab05783518352928a0192918a019160010162009a92565b5050968801969450509186019160010162009a6f565b50919a9950505050505050505050565b6000806040838503121562009aea57600080fd5b62009af583620096d3565b946020939093013593505050565b80358015158114620096eb57600080fd5b6000806000806080858703121562009b2b57600080fd5b62009b3685620096d3565b935062009b4660208601620096d3565b92506040850135915062009b5d6060860162009b03565b905092959194509250565b6001600160401b03811681146200190f57600080fd5b60006020828403121562009b9157600080fd5b813562009b9e8162009b68565b9392505050565b6000806040838503121562009bb957600080fd5b50508035926020909101359150565b60808152600062009bdd6080830187620099f1565b82810360208481019190915286518083528782019282019060005b8181101562009c165784518352938301939183019160010162009bf8565b5050848103604086015286518082528282019350600581901b8201830183890160005b8381101562009c6b57601f1985840301875262009c588383516200981c565b9686019692509085019060010162009c39565b5050809550505050505082606083015295945050505050565b600080600080600080600087890360e081121562009ca157600080fd5b62009cac89620096d3565b975060208901356001600160401b038082111562009cc957600080fd5b62009cd78c838d016200970e565b909950975060408b013591508082111562009cf157600080fd5b62009cff8c838d016200970e565b90975095508591506060605f198401121562009d1a57600080fd5b60608b01945060c08b013592508083111562009d3557600080fd5b505088016080818b03121562009d4a57600080fd5b8091505092959891949750929550565b6000806040838503121562009d6e57600080fd5b62009d7983620096d3565b915062009d896020840162009b03565b90509250929050565b60208152600082516080602084015262009db060a08401826200981c565b90506020840151601f198085840301604086015262009dd083836200981c565b9250604086015191508085840301606086015262009def83836200981c565b92506060860151915080858403016080860152506200927782826200981c565b6000806000806040858703121562009e2657600080fd5b84356001600160401b038082111562009e3e57600080fd5b62009e4c888389016200970e565b9096509450602087013591508082111562009e6657600080fd5b5062009e75878288016200970e565b95989497509550505050565b60008060006040848603121562009e9757600080fd5b83356001600160401b0381111562009eae57600080fd5b62009ebc8682870162009971565b909450925062009ed1905060208501620096d3565b90509250925092565b60608152600062009eef6060830186620099f1565b828103602084015262009f038186620099f1565b915050826040830152949350505050565b600082601f83011262009f2657600080fd5b62005a8483833560208501620098a0565b60006020828403121562009f4a57600080fd5b81356001600160401b038082111562009f6257600080fd5b908301906080828603121562009f7757600080fd5b62009f8162009875565b82358281111562009f9157600080fd5b62009f9f8782860162009f14565b82525060208301358281111562009fb557600080fd5b62009fc38782860162009f14565b60208301525060408301358281111562009fdc57600080fd5b62009fea8782860162009f14565b6040830152506060830135828111156200a00357600080fd5b6200a0118782860162009f14565b60608301525095945050505050565b600080600080604085870312156200a03757600080fd5b84356001600160401b03808211156200a04f57600080fd5b6200a05d8883890162009971565b909650945060208701359150808211156200a07757600080fd5b5062009e758782880162009971565b600181811c908216806200a09b57607f821691505b6020821081036200207c57634e487b7160e01b600052602260045260246000fd5b6001600160a01b0392831681529116602082015260400190565b8183823760009101908152919050565b634e487b7160e01b600052601160045260246000fd5b6000826200a11a57634e487b7160e01b600052601260045260246000fd5b500490565b8082018082111562005a875762005a876200a0e6565b6000602082840312156200a14857600080fd5b5051919050565b8381526020810183905260608101600383106200a17c57634e487b7160e01b600052602160045260246000fd5b826040830152949350505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200a1b5576200a1b56200a0e6565b5060010190565b8181038181111562005a875762005a876200a0e6565b808202811582820484141762005a875762005a876200a0e6565b6040815260006200a2016040830185620099f1565b905060018060a01b03831660208301529392505050565b6001600160401b038281168282160390808211156200a23b576200a23b6200a0e6565b5092915050565b6000808335601e198436030181126200a25a57600080fd5b8301803591506001600160401b038211156200a27557600080fd5b6020019150368190038213156200264a57600080fd5b601f8211156200643c57600081815260208120601f850160051c810160208610156200a2b45750805b601f850160051c820191505b81811015620062a8578281556001016200a2c0565b600019600383901b1c191660019190911b1790565b6001600160401b038311156200a304576200a3046200985f565b6200a31c836200a31583546200a086565b836200a28b565b6000601f8411600181146200a34f57600085156200a33a5750838201355b6200a34686826200a2d5565b8455506200855e565b600083815260209020601f19861690835b828110156200a38257868501358255602094850194600190920191016200a360565b50868210156200a3a05760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b6200a3be82836200a242565b6001600160401b038111156200a3d8576200a3d86200985f565b6200a3f0816200a3e985546200a086565b856200a28b565b6000601f8211600181146200a42357600083156200a40e5750838201355b6200a41a84826200a2d5565b8655506200a480565b600085815260209020601f19841690835b828110156200a45657868501358255602094850194600190920191016200a434565b50848210156200a4745760001960f88660031b161c19848701351681555b505060018360011b0185555b505050506200a49360208301836200a242565b6200a4a38183600186016200a2ea565b50506200a4b460408301836200a242565b6200a4c48183600286016200a2ea565b50506200a4d560608301836200a242565b6200a4e58183600386016200a2ea565b50505050565b81356200a4f88162009b68565b6001600160401b03811690508154816001600160401b0319821617835560208401356200a5258162009b68565b6fffffffffffffffff0000000000000000604091821b166fffffffffffffffffffffffffffffffff198316841781178555908501356200a5658162009b68565b6001600160c01b0319929092169092179190911760809190911b67ffffffffffffffff60801b1617905550565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b602081526000620099696020830184866200a592565b634e487b7160e01b600052603160045260246000fd5b6000816200a5f9576200a5f96200a0e6565b506000190190565b6040815260006200a6176040830186886200a592565b82810360208401526200a62c8185876200a592565b979650505050505050565b81516001600160401b038111156200a653576200a6536200985f565b6200a66b816200a66484546200a086565b846200a28b565b602080601f8311600181146200a69f57600084156200a68a5750858301515b6200a69685826200a2d5565b865550620062a8565b600085815260208120601f198616915b828110156200a6d0578886015182559484019460019091019084016200a6af565b50858210156200a6ef5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60008083546200a70f816200a086565b600182811680156200a72a57600181146200a740576200a771565b60ff19841687528215158302870194506200a771565b8760005260208060002060005b858110156200a7685781548a8201529084019082016200a74d565b50505082870194505b50929695505050505050565b6bffffffffffffffffffffffff198360601b1681526000600383106200a7b357634e487b7160e01b600052602160045260246000fd5b5060f89190911b6014820152601501919050565b6bffffffffffffffffffffffff198560601b16815282846014830137601492019182015260340192915050565b600086516200a808818460208b01620097f6565b82018587823760009086019081528385823760009301928352509095945050505050565b6001600160a01b038316815260406020820181905260009062009969908301846200981c565b600082516200a866818460208701620097f6565b919091019291505056fe608060405260405162000e9638038062000e96833981016040819052620000269162000497565b828162000036828260006200004d565b50620000449050826200008a565b505050620005ca565b6200005883620000e5565b600082511180620000665750805b1562000085576200008383836200012760201b620001691760201c565b505b505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f620000b562000156565b604080516001600160a01b03928316815291841660208301520160405180910390a1620000e2816200018f565b50565b620000f08162000244565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606200014f838360405180606001604052806027815260200162000e6f60279139620002f8565b9392505050565b60006200018060008051602062000e4f83398151915260001b6200037760201b620001951760201c565b546001600160a01b0316919050565b6001600160a01b038116620001fa5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b806200022360008051602062000e4f83398151915260001b6200037760201b620001951760201c565b80546001600160a01b0319166001600160a01b039290921691909117905550565b6200025a816200037a60201b620001981760201c565b620002be5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401620001f1565b80620002237f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc60001b6200037760201b620001951760201c565b6060600080856001600160a01b03168560405162000317919062000577565b600060405180830381855af49150503d806000811462000354576040519150601f19603f3d011682016040523d82523d6000602084013e62000359565b606091505b5090925090506200036d8683838762000389565b9695505050505050565b90565b6001600160a01b03163b151590565b60608315620003fd578251600003620003f5576001600160a01b0385163b620003f55760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401620001f1565b508162000409565b62000409838362000411565b949350505050565b815115620004225781518083602001fd5b8060405162461bcd60e51b8152600401620001f1919062000595565b80516001600160a01b03811681146200045657600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b838110156200048e57818101518382015260200162000474565b50506000910152565b600080600060608486031215620004ad57600080fd5b620004b8846200043e565b9250620004c8602085016200043e565b60408501519092506001600160401b0380821115620004e657600080fd5b818601915086601f830112620004fb57600080fd5b8151818111156200051057620005106200045b565b604051601f8201601f19908116603f011681019083821181831017156200053b576200053b6200045b565b816040528281528960208487010111156200055557600080fd5b6200056883602083016020880162000471565b80955050505050509250925092565b600082516200058b81846020870162000471565b9190910192915050565b6020815260008251806020840152620005b681604085016020870162000471565b601f01601f19169190910160400192915050565b61087580620005da6000396000f3fe60806040523661001357610011610017565b005b6100115b61001f6101a7565b6001600160a01b0316330361015f5760606001600160e01b0319600035166364d3180d60e11b810161005a576100536101da565b9150610157565b63587086bd60e11b6001600160e01b031982160161007a57610053610231565b63070d7c6960e41b6001600160e01b031982160161009a57610053610277565b621eb96f60e61b6001600160e01b03198216016100b9576100536102a8565b63a39f25e560e01b6001600160e01b03198216016100d9576100536102e8565b60405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b815160208301f35b6101676102fc565b565b606061018e83836040518060600160405280602781526020016108426027913961030c565b9392505050565b90565b6001600160a01b03163b151590565b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b60606101e4610384565b60006101f33660048184610695565b81019061020091906106db565b905061021d8160405180602001604052806000815250600061038f565b505060408051602081019091526000815290565b60606000806102433660048184610695565b810190610250919061070c565b915091506102608282600161038f565b604051806020016040528060008152509250505090565b6060610281610384565b60006102903660048184610695565b81019061029d91906106db565b905061021d816103bb565b60606102b2610384565b60006102bc6101a7565b604080516001600160a01b03831660208201529192500160405160208183030381529060405291505090565b60606102f2610384565b60006102bc610412565b610167610307610412565b610421565b6060600080856001600160a01b03168560405161032991906107f2565b600060405180830381855af49150503d8060008114610364576040519150601f19603f3d011682016040523d82523d6000602084013e610369565b606091505b509150915061037a86838387610445565b9695505050505050565b341561016757600080fd5b610398836104c6565b6000825111806103a55750805b156103b6576103b48383610169565b505b505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6103e46101a7565b604080516001600160a01b03928316815291841660208301520160405180910390a161040f81610506565b50565b600061041c6105af565b905090565b3660008037600080366000845af43d6000803e808015610440573d6000f35b3d6000fd5b606083156104b45782516000036104ad576001600160a01b0385163b6104ad5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161014e565b50816104be565b6104be83836105d7565b949350505050565b6104cf81610601565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6001600160a01b03811661056b5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b606482015260840161014e565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6101cb565b8151156105e75781518083602001fd5b8060405162461bcd60e51b815260040161014e919061080e565b6001600160a01b0381163b61066e5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b606482015260840161014e565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc61058e565b600080858511156106a557600080fd5b838611156106b257600080fd5b5050820193919092039150565b80356001600160a01b03811681146106d657600080fd5b919050565b6000602082840312156106ed57600080fd5b61018e826106bf565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561071f57600080fd5b610728836106bf565b9150602083013567ffffffffffffffff8082111561074557600080fd5b818501915085601f83011261075957600080fd5b81358181111561076b5761076b6106f6565b604051601f8201601f19908116603f01168101908382118183101715610793576107936106f6565b816040528281528860208487010111156107ac57600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b60005b838110156107e95781810151838201526020016107d1565b50506000910152565b600082516108048184602087016107ce565b9190910192915050565b602081526000825180602084015261082d8160408501602087016107ce565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a164736f6c6343000811000ab53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a164736f6c6343000811000a \ No newline at end of file diff --git a/core/systemcontracts/maxwell/mainnet/StakeHubContract b/core/systemcontracts/maxwell/mainnet/StakeHubContract new file mode 100644 index 0000000000..1b8f19e435 --- /dev/null +++ b/core/systemcontracts/maxwell/mainnet/StakeHubContract @@ -0,0 +1 @@ +6080604052600436106200043b5760003560e01c806386d545061162000233578063ca47908f116200012f578063dd42a1dd11620000b9578063f1f74d841162000084578063f1f74d841462000d75578063f80a34021462000d8d578063fb50b31f1462000db2578063fc0c5ff11462000dd7578063ff69ab611462000def57600080fd5b8063dd42a1dd1462000ce2578063e8f67c3b1462000d09578063e992aaf51462000d21578063efdbf0e11462000d3957600080fd5b8063d7c2dfc811620000fa578063d7c2dfc81462000c68578063d8ca511f1462000c8d578063daacdb661462000ca5578063dbda7fb31462000cbd57600080fd5b8063ca47908f1462000bd1578063cbb04d9d1462000be9578063d115a2061462000c2a578063d6ca429d1462000c4357600080fd5b8063b187bd2611620001bd578063bfff04751162000188578063bfff04751462000b58578063c166f58a1462000b7d578063c38fbec81462000b94578063c473318f1462000bb9578063c8509d81146200095157600080fd5b8063b187bd261462000ac5578063baa7199e1462000ae5578063bdceadf31462000b0a578063bff02e201462000b2257600080fd5b8063a1832e6411620001fe578063a1832e641462000a22578063a43569b31462000a47578063aad3ec961462000a7b578063ac4317511462000aa057600080fd5b806386d54506146200098e5780638a4d3fa814620009c85780638cd22b2214620009e6578063982ef0a71462000a0b57600080fd5b80634838d165116200034357806364028fbd11620002cd57806375cc7d89116200029857806375cc7d8914620008fc57806376e7d6d614620009215780638129fc1c1462000939578063831d65d114620009515780638456cb59146200097657600080fd5b806364028fbd1462000837578063663706d3146200084e5780636ec01b27146200087f5780636f8e2fa414620008d757600080fd5b80634e6fd6c4116200030e5780634e6fd6c4146200079e5780635949187114620007b65780635e7cc1c914620007db57806363a036b5146200080057600080fd5b80634838d16514620006ea57806349f41a42146200072f5780634a49ac4c14620007545780634d99dd16146200077957600080fd5b80631fab701511620003c5578063384099881162000390578063384099881462000663578063417c73a7146200067b578063449ecfe614620006a057806345211bfd14620006c557600080fd5b80631fab701514620005aa5780632b727c8614620005cf5780632e8e8c7114620005f4578063367dad49146200062e57600080fd5b80630e9fbf5111620004065780630e9fbf5114620004f35780631182b875146200051857806317b4f353146200054c5780631fa8882b146200059157600080fd5b8063046f7da2146200045b578063059ddd2214620004735780630661806e14620004b5578063092193ab14620004dc57600080fd5b36620004565760345460ff166001146200045457600080fd5b005b600080fd5b3480156200046857600080fd5b506200045462000e07565b3480156200048057600080fd5b506200049862000492366004620096f0565b62000e99565b6040516001600160a01b0390911681526020015b60405180910390f35b348015620004c257600080fd5b50620004cd60365481565b604051908152602001620004ac565b62000454620004ed366004620096f0565b620012c1565b3480156200050057600080fd5b50620004546200051236600462009752565b62001912565b3480156200052557600080fd5b506200053d6200053736600462009797565b62001c3e565b604051620004ac91906200984a565b3480156200055957600080fd5b50620004986200056b3660046200991c565b80516020818301810180516045825292820191909301209152546001600160a01b031681565b3480156200059e57600080fd5b50620004cd6201518081565b348015620005b757600080fd5b5062000454620005c9366004620099b8565b62001cd6565b348015620005dc57600080fd5b5062000498620005ee366004620096f0565b6200202d565b3480156200060157600080fd5b506200049862000613366004620096f0565b604d602052600090815260409020546001600160a01b031681565b3480156200063b57600080fd5b50620006536200064d366004620099b8565b62002082565b604051620004ac92919062009a37565b3480156200067057600080fd5b50620004cd60375481565b3480156200068857600080fd5b50620004546200069a366004620096f0565b62002651565b348015620006ad57600080fd5b5062000454620006bf366004620096f0565b620026d3565b348015620006d257600080fd5b5062000454620006e4366004620096f0565b620028b8565b348015620006f757600080fd5b506200071e62000709366004620096f0565b60016020526000908152604090205460ff1681565b6040519015158152602001620004ac565b3480156200073c57600080fd5b50620004546200074e366004620096f0565b62002a91565b3480156200076157600080fd5b506200045462000773366004620096f0565b62002cad565b3480156200078657600080fd5b50620004546200079836600462009ad6565b62002d29565b348015620007ab57600080fd5b506200049861dead81565b348015620007c357600080fd5b5062000454620007d536600462009b14565b62003359565b348015620007e857600080fd5b5062000454620007fa36600462009b7e565b62004152565b3480156200080d57600080fd5b50620008256200081f36600462009ba5565b6200437c565b604051620004ac949392919062009bc8565b620004546200084836600462009c84565b62004a21565b3480156200085b57600080fd5b50620004cd6200086d366004620096f0565b60446020526000908152604090205481565b3480156200088c57600080fd5b50620008a46200089e366004620096f0565b62005070565b6040805182516001600160401b0390811682526020808501518216908301529282015190921690820152606001620004ac565b348015620008e457600080fd5b506200053d620008f6366004620096f0565b62005115565b3480156200090957600080fd5b50620004546200091b366004620096f0565b62005541565b3480156200092e57600080fd5b50620004cd603d5481565b3480156200094657600080fd5b506200045462005713565b3480156200095e57600080fd5b50620004546200097036600462009797565b620058de565b3480156200098357600080fd5b50620004546200593c565b3480156200099b57600080fd5b5062000498620009ad366004620096f0565b6043602052600090815260409020546001600160a01b031681565b348015620009d557600080fd5b50620004cd670de0b6b3a764000081565b348015620009f357600080fd5b50620004cd62000a0536600462009ad6565b620059d4565b6200045462000a1c36600462009d5a565b62005a8d565b34801562000a2f57600080fd5b506200045462000a41366004620099b8565b6200613b565b34801562000a5457600080fd5b5062000a6c62000a66366004620096f0565b62006441565b604051620004ac919062009d92565b34801562000a8857600080fd5b506200045462000a9a36600462009ad6565b6200672e565b34801562000aad57600080fd5b506200045462000abf36600462009e0f565b6200679b565b34801562000ad257600080fd5b5060005462010000900460ff166200071e565b34801562000af257600080fd5b506200045462000b0436600462009e81565b6200774d565b34801562000b1757600080fd5b50620004cd603c5481565b34801562000b2f57600080fd5b5062000b4762000b4136600462009ba5565b6200791a565b604051620004ac9392919062009eda565b34801562000b6557600080fd5b50620004cd62000b77366004620096f0565b62007af6565b34801562000b8a57600080fd5b50620004cd600581565b34801562000ba157600080fd5b506200045462000bb3366004620096f0565b62007b44565b34801562000bc657600080fd5b50620004cd60385481565b34801562000bde57600080fd5b50620004cd604e5481565b34801562000bf657600080fd5b5062000c0e62000c08366004620096f0565b62007e06565b60408051938452911515602084015290820152606001620004ac565b34801562000c3757600080fd5b50620004cd620186a081565b34801562000c5057600080fd5b506200045462000c6236600462009f37565b62008249565b34801562000c7557600080fd5b506200045462000c873660046200a020565b6200846f565b34801562000c9a57600080fd5b50620004cd603b5481565b34801562000cb257600080fd5b50620004cd60495481565b34801562000cca57600080fd5b506200049862000cdc366004620096f0565b62008565565b34801562000cef57600080fd5b50600054630100000090046001600160a01b031662000498565b34801562000d1657600080fd5b50620004cd60355481565b34801562000d2e57600080fd5b50620004cd603a5481565b34801562000d4657600080fd5b50620004cd62000d583660046200991c565b805160208183018101805160468252928201919093012091525481565b34801562000d8257600080fd5b50620004cd603e5481565b34801562000d9a57600080fd5b50620004cd62000dac36600462009ad6565b6200898f565b34801562000dbf57600080fd5b506200045462000dd136600462009e0f565b62008a00565b34801562000de457600080fd5b50620004cd60395481565b34801562000dfc57600080fd5b50620004cd604a5481565b600054630100000090046001600160a01b0316331462000e3a576040516306fbb1e360e01b815260040160405180910390fd5b60005462010000900460ff1662000e6457604051636cd6020160e01b815260040160405180910390fd5b6000805462ff0000191681556040517f62451d457bc659158be6e6247f56ec1df424a5c7597f71c20c2bc44e0965c8f99190a1565b6001600160a01b038082166000908152604160209081526040808320815161018081018352815486168152600182015486169381019390935260028101549094169082015260038301546060820152600483018054929384939091608084019162000f04906200a086565b80601f016020809104026020016040519081016040528092919081815260200182805462000f32906200a086565b801562000f835780601f1062000f575761010080835404028352916020019162000f83565b820191906000526020600020905b81548152906001019060200180831162000f6557829003601f168201915b505050505081526020016005820160405180608001604052908160008201805462000fae906200a086565b80601f016020809104026020016040519081016040528092919081815260200182805462000fdc906200a086565b80156200102d5780601f1062001001576101008083540402835291602001916200102d565b820191906000526020600020905b8154815290600101906020018083116200100f57829003601f168201915b5050505050815260200160018201805462001048906200a086565b80601f016020809104026020016040519081016040528092919081815260200182805462001076906200a086565b8015620010c75780601f106200109b57610100808354040283529160200191620010c7565b820191906000526020600020905b815481529060010190602001808311620010a957829003601f168201915b50505050508152602001600282018054620010e2906200a086565b80601f016020809104026020016040519081016040528092919081815260200182805462001110906200a086565b8015620011615780601f10620011355761010080835404028352916020019162001161565b820191906000526020600020905b8154815290600101906020018083116200114357829003601f168201915b505050505081526020016003820180546200117c906200a086565b80601f0160208091040260200160405190810160405280929190818152602001828054620011aa906200a086565b8015620011fb5780601f10620011cf57610100808354040283529160200191620011fb565b820191906000526020600020905b815481529060010190602001808311620011dd57829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152600d8301546001600160a01b031660a0830152805161026081019182905260c09092019190600e84019060139082845b8154815260200190600101908083116200129a575050509190925250509051949350505050565b3361100014620012ed57604051630f22c43960e41b815261100060048201526024015b60405180910390fd5b6001600160a01b0380821660009081526043602090815260408083205484168084526041835281842082516101808101845281548716815260018201548716948101949094526002810154909516918301919091526003840154606083015260048401805491949160808401919062001366906200a086565b80601f016020809104026020016040519081016040528092919081815260200182805462001394906200a086565b8015620013e55780601f10620013b957610100808354040283529160200191620013e5565b820191906000526020600020905b815481529060010190602001808311620013c757829003601f168201915b505050505081526020016005820160405180608001604052908160008201805462001410906200a086565b80601f01602080910402602001604051908101604052809291908181526020018280546200143e906200a086565b80156200148f5780601f1062001463576101008083540402835291602001916200148f565b820191906000526020600020905b8154815290600101906020018083116200147157829003601f168201915b50505050508152602001600182018054620014aa906200a086565b80601f0160208091040260200160405190810160405280929190818152602001828054620014d8906200a086565b8015620015295780601f10620014fd5761010080835404028352916020019162001529565b820191906000526020600020905b8154815290600101906020018083116200150b57829003601f168201915b5050505050815260200160028201805462001544906200a086565b80601f016020809104026020016040519081016040528092919081815260200182805462001572906200a086565b8015620015c35780601f106200159757610100808354040283529160200191620015c3565b820191906000526020600020905b815481529060010190602001808311620015a557829003601f168201915b50505050508152602001600382018054620015de906200a086565b80601f01602080910402602001604051908101604052809291908181526020018280546200160c906200a086565b80156200165d5780601f1062001631576101008083540402835291602001916200165d565b820191906000526020600020905b8154815290600101906020018083116200163f57829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152600d8301546001600160a01b031660a0830152805161026081019182905260c09092019190600e84019060139082845b815481526020019060010190808311620016fc575050509190925250505060408101519091506001600160a01b031615806200173957508060e001515b15620017f657604051611002903490600081818185875af1925050503d806000811462001783576040519150601f19603f3d011682016040523d82523d6000602084013e62001788565b606091505b505050816001600160a01b03167ffc8bff675087dd2da069cc3fb517b9ed001e19750c0865241a5542dba1ba170d604051620017e99060208082526011908201527024a72b20a624a22fab20a624a220aa27a960791b604082015260600190565b60405180910390a2505050565b60408181015160c0830151519151632f303ebb60e11b81526001600160401b0390921660048301526001600160a01b031690635e607d769034906024016000604051808303818588803b1580156200184d57600080fd5b505af115801562001862573d6000803e3d6000fd5b5050505050816001600160a01b03167fe34918ff1c7084970068b53fd71ad6d8b04e9f15d3886cbf006443e6cdc52ea634604051620018a391815260200190565b60405180910390a26040808201519051633041949b60e01b815261200591633041949b91620018d8919086906004016200a0bc565b600060405180830381600087803b158015620018f357600080fd5b505af115801562001908573d6000803e3d6000fd5b5050505050505b50565b33611001146200193a57604051630f22c43960e41b81526110016004820152602401620012e4565b60005462010000900460ff16156200196557604051631785c68160e01b815260040160405180910390fd5b6000604583836040516200197b9291906200a0d6565b908152604051908190036020019020546001600160a01b03169050620019a3603f8262008c39565b620019c15760405163056e881160e01b815260040160405180910390fd5b6001600160a01b038116600090815260416020526040812090620019e962015180426200a0fc565b604a546000828152604b60205260409020549192501162001a1d5760405163bd52fcdb60e01b815260040160405180910390fd5b6000818152604b6020526040812080546001929062001a3e9084906200a11f565b909155505060405160469062001a5890879087906200a0d6565b90815260200160405180910390205460001415801562001aa9575042620151806046878760405162001a8c9291906200a0d6565b90815260200160405180910390205462001aa791906200a11f565b105b1562001ac857604051631898eb6b60e01b815260040160405180910390fd5b60008062001ad885600262008c5c565b915091508162001afb57604051631b919bb160e11b815260040160405180910390fd5b6002840154603c5460405163045bc4d160e41b815260048101919091526000916001600160a01b0316906345bc4d10906024016020604051808303816000875af115801562001b4e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001b7491906200a135565b905062001b82858362008ce4565b856001600160a01b03167f6e9a2ee7aee95665e3a774a212eb11441b217e3e4656ab9563793094689aabb28383600260405162001bc2939291906200a14f565b60405180910390a26002850154604051633041949b60e01b815261200591633041949b9162001c00916001600160a01b0316908a906004016200a0bc565b600060405180830381600087803b15801562001c1b57600080fd5b505af115801562001c30573d6000803e3d6000fd5b505050505050505050505050565b6060336120001462001c6857604051630f22c43960e41b81526120006004820152602401620012e4565b60005462010000900460ff161562001c9357604051631785c68160e01b815260040160405180910390fd5b6034805460ff1916600117905560405162461bcd60e51b815260206004820152600a60248201526919195c1c9958d85d195960b21b6044820152606401620012e4565b60005462010000900460ff161562001d0157604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff161562001d335760405163b1d02c3d60e01b815260040160405180910390fd5b62001d3d62008dd8565b62001d4a603f8262008c39565b62001d685760405163056e881160e01b815260040160405180910390fd5b62001d7262008e23565b600082900362001d9557604051636490ffd360e01b815260040160405180910390fd5b600062001da162008dd8565b6001600160a01b0381166000908152604f602052604090208054604e54929350909162001dcf86836200a11f565b111562001def5760405163091af98560e21b815260040160405180910390fd5b60005b8581101562001ed557600087878381811062001e125762001e126200a18a565b905060200201350362001e3857604051636490ffd360e01b815260040160405180910390fd5b600062001e478260016200a11f565b90505b8681101562001ebf5787878281811062001e685762001e686200a18a565b9050602002013588888481811062001e845762001e846200a18a565b905060200201350362001eaa57604051632205e3c760e11b815260040160405180910390fd5b8062001eb6816200a1a0565b91505062001e4a565b508062001ecc816200a1a0565b91505062001df2565b5060005b8581101562001f745760005b8281101562001f5e5783818154811062001f035762001f036200a18a565b906000526020600020015488888481811062001f235762001f236200a18a565b905060200201350362001f4957604051632205e3c760e11b815260040160405180910390fd5b8062001f55816200a1a0565b91505062001ee5565b508062001f6b816200a1a0565b91505062001ed9565b5060005b8581101562001908578287878381811062001f975762001f976200a18a565b835460018101855560009485526020948590209190940292909201359190920155506001600160a01b0384167f7c4ff4c9a343a2daef608f3b5a91016e994a15fc0ef8611109e4f45823249f2988888481811062001ff95762001ff96200a18a565b905060200201356040516200201091815260200190565b60405180910390a28062002024816200a1a0565b91505062001f78565b6000816200203d603f8262008c39565b6200205b5760405163056e881160e01b815260040160405180910390fd5b6001600160a01b038084166000908152604160205260409020600d01541691505b50919050565b60608082806001600160401b03811115620020a157620020a16200985f565b604051908082528060200260200182016040528015620020cb578160200160208202803683370190505b509250806001600160401b03811115620020e957620020e96200985f565b6040519080825280602002602001820160405280156200211e57816020015b6060815260200190600190039081620021085790505b50915060005b81811015620026475760008686838181106200214457620021446200a18a565b90506020020160208101906200215b9190620096f0565b6001600160a01b03808216600090815260416020908152604080832081516101808101835281548616815260018201548616938101939093526002810154909416908201526003830154606082015260048301805494955091939092916080840191620021c8906200a086565b80601f0160208091040260200160405190810160405280929190818152602001828054620021f6906200a086565b8015620022475780601f106200221b5761010080835404028352916020019162002247565b820191906000526020600020905b8154815290600101906020018083116200222957829003601f168201915b505050505081526020016005820160405180608001604052908160008201805462002272906200a086565b80601f0160208091040260200160405190810160405280929190818152602001828054620022a0906200a086565b8015620022f15780601f10620022c557610100808354040283529160200191620022f1565b820191906000526020600020905b815481529060010190602001808311620022d357829003601f168201915b505050505081526020016001820180546200230c906200a086565b80601f01602080910402602001604051908101604052809291908181526020018280546200233a906200a086565b80156200238b5780601f106200235f576101008083540402835291602001916200238b565b820191906000526020600020905b8154815290600101906020018083116200236d57829003601f168201915b50505050508152602001600282018054620023a6906200a086565b80601f0160208091040260200160405190810160405280929190818152602001828054620023d4906200a086565b8015620024255780601f10620023f95761010080835404028352916020019162002425565b820191906000526020600020905b8154815290600101906020018083116200240757829003601f168201915b5050505050815260200160038201805462002440906200a086565b80601f01602080910402602001604051908101604052809291908181526020018280546200246e906200a086565b8015620024bf5780601f106200249357610100808354040283529160200191620024bf565b820191906000526020600020905b815481529060010190602001808311620024a157829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152600d8301546001600160a01b031660a0830152805161026081019182905260c09092019190600e84019060139082845b8154815260200190600101908083116200255e57505050505081525050905080600001518684815181106200259757620025976200a18a565b6001600160a01b039283166020918202929092018101919091529083166000908152604f8252604090819020805482518185028101850190935280835291929091908301828280156200260a57602002820191906000526020600020905b815481526020019060010190808311620025f5575b50505050508584815181106200262457620026246200a18a565b6020026020010181905250505080806200263e906200a1a0565b91505062002124565b50505b9250929050565b600054630100000090046001600160a01b0316331462002684576040516306fbb1e360e01b815260040160405180910390fd5b6001600160a01b0381166000818152600160208190526040808320805460ff1916909217909155517f7fd26be6fc92aff63f1f4409b2b2ddeb272a888031d7f55ec830485ec61941869190a250565b60005462010000900460ff1615620026fe57604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff1615620027305760405163b1d02c3d60e01b815260040160405180910390fd5b806200273e603f8262008c39565b6200275c5760405163056e881160e01b815260040160405180910390fd5b6001600160a01b0382166000908152604160205260409020600a81015460ff166200279a57604051634b6b857d60e01b815260040160405180910390fd5b6036546002820154604051630913db4760e01b81526001600160a01b03868116600483015290911690630913db4790602401602060405180830381865afa158015620027ea573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200281091906200a135565b101562002830576040516317b204bf60e11b815260040160405180910390fd5b4281600b01541115620028565760405163170cb76760e21b815260040160405180910390fd5b600a8101805460ff1916905560498054600191906000906200287a9084906200a1bc565b90915550506040516001600160a01b038416907f9390b453426557da5ebdc31f19a37753ca04addf656d32f35232211bb2af3f1990600090a2505050565b60005462010000900460ff1615620028e357604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff1615620029155760405163b1d02c3d60e01b815260040160405180910390fd5b6200291f62008e36565b6200292c603f8262008c39565b6200294a5760405163056e881160e01b815260040160405180910390fd5b6001600160a01b0382166200297257604051636520611b60e11b815260040160405180910390fd5b6001600160a01b038281166000908152604360205260409020541615620029ac57604051631e6f587560e11b815260040160405180910390fd5b6000620029b862008e36565b6001600160a01b0381166000908152604160205260409020600c810154919250904290620029eb9062015180906200a11f565b111562002a0b57604051631f92cdbd60e11b815260040160405180910390fd5b80546001600160a01b039081166000908152604460209081526040808320429081905585548986166001600160a01b031991821681178855600c88019290925581855260439093528184208054958816959093168517909255519092917f6e4e747ca35203f16401c69805c7dd52fff67ef60b0ebc5c7fe16890530f223591a350505050565b3362002a9f603f8262008c39565b62002abd5760405163056e881160e01b815260040160405180910390fd5b60005462010000900460ff161562002ae857604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff161562002b1a5760405163b1d02c3d60e01b815260040160405180910390fd5b6001600160a01b038281166000908152604d6020526040902054161562002b545760405163bebdc75760e01b815260040160405180910390fd5b62002b61603f8362008c39565b1562002b805760405163bebdc75760e01b815260040160405180910390fd5b336000818152604160205260409020600d01546001600160a01b03908116908416810362002bc15760405163bebdc75760e01b815260040160405180910390fd5b6001600160a01b0381161562002bf8576001600160a01b0381166000908152604d6020526040902080546001600160a01b03191690555b6001600160a01b038281166000908152604160205260409020600d0180546001600160a01b03191691861691821790551562002c5d576001600160a01b038481166000908152604d6020526040902080546001600160a01b0319169184169190911790555b836001600160a01b0316816001600160a01b0316836001600160a01b03167fcbb728765de145e99c00e8ae32a325231e850359b7b8a6da3b84d672ab3f1d0a60405160405180910390a450505050565b600054630100000090046001600160a01b0316331462002ce0576040516306fbb1e360e01b815260040160405180910390fd5b6001600160a01b038116600081815260016020526040808220805460ff19169055517fe0db3499b7fdc3da4cddff5f45d694549c19835e7f719fb5606d3ad1a5de40119190a250565b60005462010000900460ff161562002d5457604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff161562002d865760405163b1d02c3d60e01b815260040160405180910390fd5b8162002d94603f8262008c39565b62002db25760405163056e881160e01b815260040160405180910390fd5b8160000362002dd457604051639811e0c760e01b815260040160405180910390fd5b6001600160a01b038084166000908152604160209081526040808320815161018081018352815486168152600182015486169381019390935260028101549094169082015260038301546060820152600483018054339491608084019162002e3c906200a086565b80601f016020809104026020016040519081016040528092919081815260200182805462002e6a906200a086565b801562002ebb5780601f1062002e8f5761010080835404028352916020019162002ebb565b820191906000526020600020905b81548152906001019060200180831162002e9d57829003601f168201915b505050505081526020016005820160405180608001604052908160008201805462002ee6906200a086565b80601f016020809104026020016040519081016040528092919081815260200182805462002f14906200a086565b801562002f655780601f1062002f395761010080835404028352916020019162002f65565b820191906000526020600020905b81548152906001019060200180831162002f4757829003601f168201915b5050505050815260200160018201805462002f80906200a086565b80601f016020809104026020016040519081016040528092919081815260200182805462002fae906200a086565b801562002fff5780601f1062002fd35761010080835404028352916020019162002fff565b820191906000526020600020905b81548152906001019060200180831162002fe157829003601f168201915b505050505081526020016002820180546200301a906200a086565b80601f016020809104026020016040519081016040528092919081815260200182805462003048906200a086565b8015620030995780601f106200306d5761010080835404028352916020019162003099565b820191906000526020600020905b8154815290600101906020018083116200307b57829003601f168201915b50505050508152602001600382018054620030b4906200a086565b80601f0160208091040260200160405190810160405280929190818152602001828054620030e2906200a086565b8015620031335780601f10620031075761010080835404028352916020019162003133565b820191906000526020600020905b8154815290600101906020018083116200311557829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152600d8301546001600160a01b031660a0830152805161026081019182905260c09092019190600e84019060139082845b815481526020019060010190808311620031d2575050509190925250505060408082015190516326ccee8b60e11b81526001600160a01b0385811660048301526024820188905292935060009290911690634d99dd16906044016020604051808303816000875af11580156200324c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200327291906200a135565b9050826001600160a01b0316866001600160a01b03167f3aace7340547de7b9156593a7652dc07ee900cea3fd8f82cb6c9d38b408298028784604051620032c3929190918252602082015260400190565b60405180910390a3856001600160a01b0316836001600160a01b031603620032f057620032f08662008e77565b6040808301519051633041949b60e01b815261200591633041949b916200331d919087906004016200a0bc565b600060405180830381600087803b1580156200333857600080fd5b505af11580156200334d573d6000803e3d6000fd5b50505050505050505050565b60005462010000900460ff16156200338457604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff1615620033b65760405163b1d02c3d60e01b815260040160405180910390fd5b83620033c4603f8262008c39565b620033e25760405163056e881160e01b815260040160405180910390fd5b83620033f0603f8262008c39565b6200340e5760405163056e881160e01b815260040160405180910390fd5b6034805460ff1916600117905560008490036200343e57604051639811e0c760e01b815260040160405180910390fd5b846001600160a01b0316866001600160a01b031603620034715760405163f0e3e62960e01b815260040160405180910390fd5b6001600160a01b0380871660009081526041602090815260408083208151610180810183528154861681526001820154861693810193909352600281015490941690820152600383015460608201526004830180543394916080840191620034d9906200a086565b80601f016020809104026020016040519081016040528092919081815260200182805462003507906200a086565b8015620035585780601f106200352c5761010080835404028352916020019162003558565b820191906000526020600020905b8154815290600101906020018083116200353a57829003601f168201915b505050505081526020016005820160405180608001604052908160008201805462003583906200a086565b80601f0160208091040260200160405190810160405280929190818152602001828054620035b1906200a086565b8015620036025780601f10620035d65761010080835404028352916020019162003602565b820191906000526020600020905b815481529060010190602001808311620035e457829003601f168201915b505050505081526020016001820180546200361d906200a086565b80601f01602080910402602001604051908101604052809291908181526020018280546200364b906200a086565b80156200369c5780601f1062003670576101008083540402835291602001916200369c565b820191906000526020600020905b8154815290600101906020018083116200367e57829003601f168201915b50505050508152602001600282018054620036b7906200a086565b80601f0160208091040260200160405190810160405280929190818152602001828054620036e5906200a086565b8015620037365780601f106200370a5761010080835404028352916020019162003736565b820191906000526020600020905b8154815290600101906020018083116200371857829003601f168201915b5050505050815260200160038201805462003751906200a086565b80601f01602080910402602001604051908101604052809291908181526020018280546200377f906200a086565b8015620037d05780601f10620037a457610100808354040283529160200191620037d0565b820191906000526020600020905b815481529060010190602001808311620037b257829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152600d8301546001600160a01b031660a0830152805161026081019182905260c09092019190600e84019060139082845b8154815260200190600101908083116200386f57505050919092525050506001600160a01b03808916600090815260416020908152604080832081516101808101835281548616815260018201548616938101939093526002810154909416908201526003830154606082015260048301805494955091939092916080840191620038fa906200a086565b80601f016020809104026020016040519081016040528092919081815260200182805462003928906200a086565b8015620039795780601f106200394d5761010080835404028352916020019162003979565b820191906000526020600020905b8154815290600101906020018083116200395b57829003601f168201915b5050505050815260200160058201604051806080016040529081600082018054620039a4906200a086565b80601f0160208091040260200160405190810160405280929190818152602001828054620039d2906200a086565b801562003a235780601f10620039f75761010080835404028352916020019162003a23565b820191906000526020600020905b81548152906001019060200180831162003a0557829003601f168201915b5050505050815260200160018201805462003a3e906200a086565b80601f016020809104026020016040519081016040528092919081815260200182805462003a6c906200a086565b801562003abd5780601f1062003a915761010080835404028352916020019162003abd565b820191906000526020600020905b81548152906001019060200180831162003a9f57829003601f168201915b5050505050815260200160028201805462003ad8906200a086565b80601f016020809104026020016040519081016040528092919081815260200182805462003b06906200a086565b801562003b575780601f1062003b2b5761010080835404028352916020019162003b57565b820191906000526020600020905b81548152906001019060200180831162003b3957829003601f168201915b5050505050815260200160038201805462003b72906200a086565b80601f016020809104026020016040519081016040528092919081815260200182805462003ba0906200a086565b801562003bf15780601f1062003bc55761010080835404028352916020019162003bf1565b820191906000526020600020905b81548152906001019060200180831162003bd357829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152600d8301546001600160a01b031660a0830152805161026081019182905260c09092019190600e84019060139082845b81548152602001906001019080831162003c905750505050508152505090508060e00151801562003cd35750876001600160a01b0316836001600160a01b031614155b1562003cf257604051636468920360e01b815260040160405180910390fd5b60408083015190516352e82ce560e11b81526001600160a01b038581166004830152602482018a9052600092169063a5d059ca906044016020604051808303816000875af115801562003d49573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062003d6f91906200a135565b905060375481101562003d955760405163dc6f0bdd60e01b815260040160405180910390fd5b896001600160a01b0316846001600160a01b031614801562003e2a57506036546040808501519051630913db4760e01b81526001600160a01b038d8116600483015290911690630913db4790602401602060405180830381865afa15801562003e02573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062003e2891906200a135565b105b1562003e49576040516317b204bf60e11b815260040160405180910390fd5b6000620186a0603a548362003e5f91906200a1d2565b62003e6b91906200a0fc565b9050600083604001516001600160a01b03168260405160006040518083038185875af1925050503d806000811462003ec0576040519150601f19603f3d011682016040523d82523d6000602084013e62003ec5565b606091505b505090508062003ee8576040516312171d8360e31b815260040160405180910390fd5b62003ef482846200a1bc565b60408086015190516317066a5760e21b81526001600160a01b03898116600483015292955060009290911690635c19a95c90869060240160206040518083038185885af115801562003f4a573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019062003f7191906200a135565b9050866001600160a01b03168c6001600160a01b03168e6001600160a01b03167ffdac6e81913996d95abcc289e90f2d8bd235487ce6fe6f821e7d21002a1915b48e858960405162003fd6939291909283526020830191909152604082015260600190565b60405180910390a46040805160028082526060820183526000926020830190803683370190505090508660400151816000815181106200401a576200401a6200a18a565b60200260200101906001600160a01b031690816001600160a01b0316815250508560400151816001815181106200405557620040556200a18a565b6001600160a01b0390921660209283029190910190910152604051634484077560e01b815261200590634484077590620040969084908c906004016200a1ec565b600060405180830381600087803b158015620040b157600080fd5b505af1158015620040c6573d6000803e3d6000fd5b505050508a1562004138576120056001600160a01b031663e5ed5b1e898f6040518363ffffffff1660e01b8152600401620041039291906200a0bc565b600060405180830381600087803b1580156200411e57600080fd5b505af115801562004133573d6000803e3d6000fd5b505050505b50506034805460ff19169055505050505050505050505050565b60005462010000900460ff16156200417d57604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff1615620041af5760405163b1d02c3d60e01b815260040160405180910390fd5b620041b962008e36565b620041c6603f8262008c39565b620041e45760405163056e881160e01b815260040160405180910390fd5b6000620041f062008e36565b6001600160a01b0381166000908152604160205260409020600c810154919250904290620042239062015180906200a11f565b11156200424357604051631f92cdbd60e11b815260040160405180910390fd5b60098101546001600160401b03600160401b909104811690851611156200427d5760405163dc81db8560e01b815260040160405180910390fd5b60098101546000906001600160401b039081169086161015620042bb576009820154620042b59086906001600160401b03166200a218565b620042d5565b6009820154620042d5906001600160401b0316866200a218565b60098301546001600160401b039182169250600160801b900416811115620043105760405163dc81db8560e01b815260040160405180910390fd5b60098201805467ffffffffffffffff19166001600160401b03871690811790915542600c8401556040519081526001600160a01b038416907f78cdd96edf59e09cfd4d26ef6ef6c92d166effe6a40970c54821206d541932cb9060200160405180910390a25050505050565b606080606060006200438f603f62008f95565b90508086101562004a18578415620043a85784620043aa565b805b9450600085620043bb88846200a1bc565b11620043d357620043cd87836200a1bc565b620043d5565b855b9050806001600160401b03811115620043f257620043f26200985f565b6040519080825280602002602001820160405280156200441c578160200160208202803683370190505b509450806001600160401b038111156200443a576200443a6200985f565b60405190808252806020026020018201604052801562004464578160200160208202803683370190505b509350806001600160401b038111156200448257620044826200985f565b604051908082528060200260200182016040528015620044b757816020015b6060815260200190600190039081620044a15790505b50925060005b8181101562004a15576000620044e1620044d8838b6200a11f565b603f9062008fa0565b6001600160a01b038082166000908152604160209081526040808320815161018081018352815486168152600182015486169381019390935260028101549094169082015260038301546060820152600483018054949550919390929160808401916200454e906200a086565b80601f01602080910402602001604051908101604052809291908181526020018280546200457c906200a086565b8015620045cd5780601f10620045a157610100808354040283529160200191620045cd565b820191906000526020600020905b815481529060010190602001808311620045af57829003601f168201915b5050505050815260200160058201604051806080016040529081600082018054620045f8906200a086565b80601f016020809104026020016040519081016040528092919081815260200182805462004626906200a086565b8015620046775780601f106200464b5761010080835404028352916020019162004677565b820191906000526020600020905b8154815290600101906020018083116200465957829003601f168201915b5050505050815260200160018201805462004692906200a086565b80601f0160208091040260200160405190810160405280929190818152602001828054620046c0906200a086565b8015620047115780601f10620046e55761010080835404028352916020019162004711565b820191906000526020600020905b815481529060010190602001808311620046f357829003601f168201915b505050505081526020016002820180546200472c906200a086565b80601f01602080910402602001604051908101604052809291908181526020018280546200475a906200a086565b8015620047ab5780601f106200477f57610100808354040283529160200191620047ab565b820191906000526020600020905b8154815290600101906020018083116200478d57829003601f168201915b50505050508152602001600382018054620047c6906200a086565b80601f0160208091040260200160405190810160405280929190818152602001828054620047f4906200a086565b8015620048455780601f10620048195761010080835404028352916020019162004845565b820191906000526020600020905b8154815290600101906020018083116200482757829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152600d8301546001600160a01b031660a0830152805161026081019182905260c09092019190600e84019060139082845b815481526020019060010190808311620048e457505050505081525050905080600001518884815181106200491d576200491d6200a18a565b60200260200101906001600160a01b031690816001600160a01b0316815250508060e00151620049b65780604001516001600160a01b03166315d1f8986040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200498a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620049b091906200a135565b620049b9565b60005b878481518110620049ce57620049ce6200a18a565b6020026020010181815250508060800151868481518110620049f457620049f46200a18a565b602002602001018190525050508062004a0d906200a1a0565b9050620044bd565b50505b92959194509250565b60005462010000900460ff161562004a4c57604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff161562004a7e5760405163b1d02c3d60e01b815260040160405180910390fd5b3362004a8c603f8262008c39565b1562004aab57604051635f28f62b60e01b815260040160405180910390fd5b6001600160a01b038181166000908152604d6020526040902054161562004ae557604051631a0a9b9f60e21b815260040160405180910390fd5b6001600160a01b03888116600090815260436020526040902054161562004b1f57604051631e6f587560e11b815260040160405180910390fd5b60006001600160a01b03166045888860405162004b3e9291906200a0d6565b908152604051908190036020019020546001600160a01b03161462004b76576040516311fdb94760e01b815260040160405180910390fd5b600062004b8483806200a242565b60405160200162004b979291906200a0d6565b60408051601f1981840301815291815281516020928301206000818152604290935291205490915060ff161562004be15760405163c0bf414360e01b815260040160405180910390fd5b600062004bf7670de0b6b3a7640000346200a1bc565b905060365481101562004c1d576040516317b204bf60e11b815260040160405180910390fd5b6001600160a01b038a1662004c4557604051636520611b60e11b815260040160405180910390fd5b61138862004c5a604087016020880162009b7e565b6001600160401b0316118062004ca0575062004c7d604086016020870162009b7e565b6001600160401b031662004c95602087018762009b7e565b6001600160401b0316115b8062004cdf575062004cb9604086016020870162009b7e565b6001600160401b031662004cd4606087016040880162009b7e565b6001600160401b0316115b1562004cfe5760405163dc81db8560e01b815260040160405180910390fd5b62004d4962004d0e85806200a242565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525062008fae92505050565b62004d6757604051635dba5ad760e01b815260040160405180910390fd5b62004d76838a8a8a8a62009150565b62004d9457604051631647e3cb60e11b815260040160405180910390fd5b600062004de28462004da787806200a242565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506200928092505050565b905062004df1603f8562009381565b506000838152604260209081526040808320805460ff191660019081179091556001600160a01b0380891680865260419094529190932080548f83166001600160a01b03199182161782559381018054851690931790925560028201805491851691909316179091554260038201556004810162004e718b8d836200a2ea565b50856005820162004e8382826200a3b2565b508790506009820162004e9782826200a4eb565b505042600c8201556001600160a01b038c81166000908152604360205260409081902080546001600160a01b0319169288169290921790915551859060459062004ee5908e908e906200a0d6565b908152602001604051809103902060006101000a8154816001600160a01b0302191690836001600160a01b03160217905550816001600160a01b0316856001600160a01b03168d6001600160a01b03167faecd9fb95e79c75a3a1de93362c6be5fe6ab65770d8614be583884161cd8228d8e8e60405162004f689291906200a5bb565b60405180910390a460408051848152602081018590526001600160a01b0387169182917f24d7bda8602b916d64417f0dbfe2e2e88ec9b1157bd9f596dfdb91ba26624e04910160405180910390a360408051670de0b6b3a7640000808252602082015261dead916001600160a01b038816917f24d7bda8602b916d64417f0dbfe2e2e88ec9b1157bd9f596dfdb91ba26624e04910160405180910390a3604051633041949b60e01b815261200590633041949b906200502e90859089906004016200a0bc565b600060405180830381600087803b1580156200504957600080fd5b505af11580156200505e573d6000803e3d6000fd5b50505050505050505050505050505050565b6040805160608101825260008082526020820181905291810191909152816200509b603f8262008c39565b620050b95760405163056e881160e01b815260040160405180910390fd5b50506001600160a01b031660009081526041602090815260409182902082516060810184526009909101546001600160401b038082168352600160401b8204811693830193909352600160801b90049091169181019190915290565b6001600160a01b0380821660009081526041602090815260408083208151610180810183528154861681526001820154861693810193909352600281015490941690820152600383015460608281019190915260048401805491949160808401919062005182906200a086565b80601f0160208091040260200160405190810160405280929190818152602001828054620051b0906200a086565b8015620052015780601f10620051d55761010080835404028352916020019162005201565b820191906000526020600020905b815481529060010190602001808311620051e357829003601f168201915b50505050508152602001600582016040518060800160405290816000820180546200522c906200a086565b80601f01602080910402602001604051908101604052809291908181526020018280546200525a906200a086565b8015620052ab5780601f106200527f57610100808354040283529160200191620052ab565b820191906000526020600020905b8154815290600101906020018083116200528d57829003601f168201915b50505050508152602001600182018054620052c6906200a086565b80601f0160208091040260200160405190810160405280929190818152602001828054620052f4906200a086565b8015620053455780601f10620053195761010080835404028352916020019162005345565b820191906000526020600020905b8154815290600101906020018083116200532757829003601f168201915b5050505050815260200160028201805462005360906200a086565b80601f01602080910402602001604051908101604052809291908181526020018280546200538e906200a086565b8015620053df5780601f10620053b357610100808354040283529160200191620053df565b820191906000526020600020905b815481529060010190602001808311620053c157829003601f168201915b50505050508152602001600382018054620053fa906200a086565b80601f016020809104026020016040519081016040528092919081815260200182805462005428906200a086565b8015620054795780601f106200544d5761010080835404028352916020019162005479565b820191906000526020600020905b8154815290600101906020018083116200545b57829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152600d8301546001600160a01b031660a0830152805161026081019182905260c09092019190600e84019060139082845b815481526020019060010190808311620055185750505091909252505050608001519392505050565b33611001146200556957604051630f22c43960e41b81526110016004820152602401620012e4565b6001600160a01b038082166000908152604360205260409020541662005591603f8262008c39565b620055af5760405163056e881160e01b815260040160405180910390fd5b6001600160a01b038181166000908152604160205260408082206002810154603b54925163045bc4d160e41b81526004810193909352909316906345bc4d10906024016020604051808303816000875af115801562005612573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200563891906200a135565b90506000603d54426200564c91906200a11f565b90506200565a838262008ce4565b836001600160a01b03167f6e9a2ee7aee95665e3a774a212eb11441b217e3e4656ab9563793094689aabb2828460016040516200569a939291906200a14f565b60405180910390a26002830154604051633041949b60e01b815261200591633041949b91620056d8916001600160a01b03169088906004016200a0bc565b600060405180830381600087803b158015620056f357600080fd5b505af115801562005708573d6000803e3d6000fd5b505050505050505050565b600054610100900460ff1615808015620057345750600054600160ff909116105b80620057505750303b15801562005750575060005460ff166001145b620057b55760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401620012e4565b6000805460ff191660011790558015620057d9576000805461ff0019166101001790555b334114620057fa5760405163022d8c9560e31b815260040160405180910390fd5b3a156200581a576040516383f1b1d360e01b815260040160405180910390fd5b611388603555686c6b935b8bbd400000603655670de0b6b3a7640000603755602d60385562093a806039556002603a819055678ac7230489e80000603b55680ad78ebc5ac6200000603c556202a300603d5562278d00603e55604a55620058957308e68ec70fa3b629784fdb28887e206ce8561e0862009398565b80156200190f576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150565b33612000146200590657604051630f22c43960e41b81526120006004820152602401620012e4565b60405162461bcd60e51b815260206004820152600a60248201526919195c1c9958d85d195960b21b6044820152606401620012e4565b600054630100000090046001600160a01b031633146200596f576040516306fbb1e360e01b815260040160405180910390fd5b60005462010000900460ff16156200599a57604051631785c68160e01b815260040160405180910390fd5b6000805462ff00001916620100001781556040517f9e87fac88ff661f02d44f95383c817fece4bce600a3dab7a54406878b965e7529190a1565b6000620059e3603f8462008c39565b62005a015760405163056e881160e01b815260040160405180910390fd5b6001600160a01b0383811660009081526041602052604090819020600201549051636bbf224960e01b815260048101859052911690636bbf2249906024015b602060405180830381865afa15801562005a5e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062005a8491906200a135565b90505b92915050565b60005462010000900460ff161562005ab857604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff161562005aea5760405163b1d02c3d60e01b815260040160405180910390fd5b8162005af8603f8262008c39565b62005b165760405163056e881160e01b815260040160405180910390fd5b603754349081101562005b3c5760405163dc6f0bdd60e01b815260040160405180910390fd5b6001600160a01b038085166000908152604160209081526040808320815161018081018352815486168152600182015486169381019390935260028101549094169082015260038301546060820152600483018054339491608084019162005ba4906200a086565b80601f016020809104026020016040519081016040528092919081815260200182805462005bd2906200a086565b801562005c235780601f1062005bf75761010080835404028352916020019162005c23565b820191906000526020600020905b81548152906001019060200180831162005c0557829003601f168201915b505050505081526020016005820160405180608001604052908160008201805462005c4e906200a086565b80601f016020809104026020016040519081016040528092919081815260200182805462005c7c906200a086565b801562005ccd5780601f1062005ca15761010080835404028352916020019162005ccd565b820191906000526020600020905b81548152906001019060200180831162005caf57829003601f168201915b5050505050815260200160018201805462005ce8906200a086565b80601f016020809104026020016040519081016040528092919081815260200182805462005d16906200a086565b801562005d675780601f1062005d3b5761010080835404028352916020019162005d67565b820191906000526020600020905b81548152906001019060200180831162005d4957829003601f168201915b5050505050815260200160028201805462005d82906200a086565b80601f016020809104026020016040519081016040528092919081815260200182805462005db0906200a086565b801562005e015780601f1062005dd55761010080835404028352916020019162005e01565b820191906000526020600020905b81548152906001019060200180831162005de357829003601f168201915b5050505050815260200160038201805462005e1c906200a086565b80601f016020809104026020016040519081016040528092919081815260200182805462005e4a906200a086565b801562005e9b5780601f1062005e6f5761010080835404028352916020019162005e9b565b820191906000526020600020905b81548152906001019060200180831162005e7d57829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152600d8301546001600160a01b031660a0830152805161026081019182905260c09092019190600e84019060139082845b81548152602001906001019080831162005f3a5750505050508152505090508060e00151801562005f7d5750856001600160a01b0316826001600160a01b031614155b1562005f9c57604051636468920360e01b815260040160405180910390fd5b60408082015190516317066a5760e21b81526001600160a01b0384811660048301526000921690635c19a95c90869060240160206040518083038185885af115801562005fed573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906200601491906200a135565b9050826001600160a01b0316876001600160a01b03167f24d7bda8602b916d64417f0dbfe2e2e88ec9b1157bd9f596dfdb91ba26624e04838760405162006065929190918252602082015260400190565b60405180910390a36040808301519051633041949b60e01b815261200591633041949b916200609a919087906004016200a0bc565b600060405180830381600087803b158015620060b557600080fd5b505af1158015620060ca573d6000803e3d6000fd5b50505050851562001908576040516372f6ad8f60e11b81526120059063e5ed5b1e90620060fe9086908b906004016200a0bc565b600060405180830381600087803b1580156200611957600080fd5b505af11580156200612e573d6000803e3d6000fd5b5050505050505050505050565b60005462010000900460ff16156200616657604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff1615620061985760405163b1d02c3d60e01b815260040160405180910390fd5b620061a262008dd8565b620061af603f8262008c39565b620061cd5760405163056e881160e01b815260040160405180910390fd5b6000620061d962008dd8565b6001600160a01b0381166000908152604f6020526040812080549293509190859003620062b05760005b818110156200628457836001600160a01b03167f08e60c1b84aab23d99a7262015e647d5ffd6c6e08f78205e1df6774c48e1427a8483815481106200624c576200624c6200a18a565b90600052602060002001546040516200626791815260200190565b60405180910390a2806200627b816200a1a0565b91505062006203565b506001600160a01b0383166000908152604f60205260408120620062a8916200968a565b505050505050565b60005b858110156200640e576000878783818110620062d357620062d36200a18a565b90506020020135905060005b83811015620063f65781858281548110620062fe57620062fe6200a18a565b906000526020600020015403620063e157846200631d6001866200a1bc565b815481106200633057620063306200a18a565b90600052602060002001548582815481106200635057620063506200a18a565b9060005260206000200181905550848054806200637157620063716200a5d1565b60019003818190600052602060002001600090559055838062006394906200a5e7565b945050856001600160a01b03167f08e60c1b84aab23d99a7262015e647d5ffd6c6e08f78205e1df6774c48e1427a83604051620063d391815260200190565b60405180910390a2620063f6565b80620063ed816200a1a0565b915050620062df565b5050808062006405906200a1a0565b915050620062b3565b508154600003620062a8576001600160a01b0383166000908152604f60205260408120620062a8916200968a565b505050565b6200646d6040518060800160405280606081526020016060815260200160608152602001606081525090565b816200647b603f8262008c39565b620064995760405163056e881160e01b815260040160405180910390fd5b6001600160a01b03831660009081526041602052604090819020815160808101909252600501805482908290620064d0906200a086565b80601f0160208091040260200160405190810160405280929190818152602001828054620064fe906200a086565b80156200654f5780601f1062006523576101008083540402835291602001916200654f565b820191906000526020600020905b8154815290600101906020018083116200653157829003601f168201915b505050505081526020016001820180546200656a906200a086565b80601f016020809104026020016040519081016040528092919081815260200182805462006598906200a086565b8015620065e95780601f10620065bd57610100808354040283529160200191620065e9565b820191906000526020600020905b815481529060010190602001808311620065cb57829003601f168201915b5050505050815260200160028201805462006604906200a086565b80601f016020809104026020016040519081016040528092919081815260200182805462006632906200a086565b8015620066835780601f10620066575761010080835404028352916020019162006683565b820191906000526020600020905b8154815290600101906020018083116200666557829003601f168201915b505050505081526020016003820180546200669e906200a086565b80601f0160208091040260200160405190810160405280929190818152602001828054620066cc906200a086565b80156200671d5780601f10620066f1576101008083540402835291602001916200671d565b820191906000526020600020905b815481529060010190602001808311620066ff57829003601f168201915b505050505081525050915050919050565b60005462010000900460ff16156200675957604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff16156200678b5760405163b1d02c3d60e01b815260040160405180910390fd5b62006797828262009431565b5050565b3361100714620067c357604051630f22c43960e41b81526110076004820152602401620012e4565b620068306040518060400160405280601081526020016f1d1c985b9cd9995c91d85cd31a5b5a5d60821b81525085858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092939250506200953d9050565b15620068eb5760208114620068625783838383604051630a5a604160e01b8152600401620012e494939291906200a601565b604080516020601f8401819004810282018101909252828152600091620068a59185858083850183828082843760009201919091525092939250506200959a9050565b90506108fc811080620068b9575061271081115b15620068e25784848484604051630a5a604160e01b8152600401620012e494939291906200a601565b60355562007708565b6200695c6040518060400160405280601481526020017336b4b729b2b6332232b632b3b0ba34b7b721272160611b81525085858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092939250506200953d9050565b1562006a2657602081146200698e5783838383604051630a5a604160e01b8152600401620012e494939291906200a601565b604080516020601f8401819004810282018101909252828152600091620069d19185858083850183828082843760009201919091525092939250506200959a9050565b9050683635c9adc5dea00000811080620069f4575069152d02c7e14af680000081115b1562006a1d5784848484604051630a5a604160e01b8152600401620012e494939291906200a601565b60365562007708565b62006a99604051806040016040528060168152602001756d696e44656c65676174696f6e424e424368616e676560501b81525085858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092939250506200953d9050565b1562006b60576020811462006acb5783838383604051630a5a604160e01b8152600401620012e494939291906200a601565b604080516020601f840181900481028201810190925282815260009162006b0e9185858083850183828082843760009201919091525092939250506200959a9050565b905067016345785d8a000081108062006b2e5750678ac7230489e8000081115b1562006b575784848484604051630a5a604160e01b8152600401620012e494939291906200a601565b60375562007708565b62006bd1604051806040016040528060148152602001736d6178456c656374656456616c696461746f727360601b81525085858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092939250506200953d9050565b1562006c89576020811462006c035783838383604051630a5a604160e01b8152600401620012e494939291906200a601565b604080516020601f840181900481028201810190925282815260009162006c469185858083850183828082843760009201919091525092939250506200959a9050565b905080158062006c5757506101f481115b1562006c805784848484604051630a5a604160e01b8152600401620012e494939291906200a601565b60385562007708565b62006cf26040518060400160405280600c81526020016b1d5b989bdb9914195c9a5bd960a21b81525085858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092939250506200953d9050565b1562006daf576020811462006d245783838383604051630a5a604160e01b8152600401620012e494939291906200a601565b604080516020601f840181900481028201810190925282815260009162006d679185858083850183828082843760009201919091525092939250506200959a9050565b90506203f48081108062006d7d575062278d0081115b1562006da65784848484604051630a5a604160e01b8152600401620012e494939291906200a601565b60395562007708565b62006e1d60405180604001604052806011815260200170726564656c65676174654665655261746560781b81525085858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092939250506200953d9050565b1562006eca576020811462006e4f5783838383604051630a5a604160e01b8152600401620012e494939291906200a601565b604080516020601f840181900481028201810190925282815260009162006e929185858083850183828082843760009201919091525092939250506200959a9050565b9050606481111562006ec15784848484604051630a5a604160e01b8152600401620012e494939291906200a601565b603a5562007708565b62006f3a60405180604001604052806013815260200172191bdddb9d1a5b5954db185cda105b5bdd5b9d606a1b81525085858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092939250506200953d9050565b1562006ffb576020811462006f6c5783838383604051630a5a604160e01b8152600401620012e494939291906200a601565b604080516020601f840181900481028201810190925282815260009162006faf9185858083850183828082843760009201919091525092939250506200959a9050565b9050674563918244f4000081108062006fc95750603c5481115b1562006ff25784848484604051630a5a604160e01b8152600401620012e494939291906200a601565b603b5562007708565b620070696040518060400160405280601181526020017019995b1bdb9e54db185cda105b5bdd5b9d607a1b81525085858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092939250506200953d9050565b156200712c57602081146200709b5783838383604051630a5a604160e01b8152600401620012e494939291906200a601565b604080516020601f8401819004810282018101909252828152600091620070de9185858083850183828082843760009201919091525092939250506200959a9050565b905068056bc75e2d63100000811080620070fa5750603b548111155b15620071235784848484604051630a5a604160e01b8152600401620012e494939291906200a601565b603c5562007708565b620071996040518060400160405280601081526020016f646f776e74696d654a61696c54696d6560801b81525085858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092939250506200953d9050565b15620072565760208114620071cb5783838383604051630a5a604160e01b8152600401620012e494939291906200a601565b604080516020601f84018190048102820181019092528281526000916200720e9185858083850183828082843760009201919091525092939250506200959a9050565b90506202a300811080620072245750603e548110155b156200724d5784848484604051630a5a604160e01b8152600401620012e494939291906200a601565b603d5562007708565b620072c16040518060400160405280600e81526020016d66656c6f6e794a61696c54696d6560901b81525085858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092939250506200953d9050565b156200737e5760208114620072f35783838383604051630a5a604160e01b8152600401620012e494939291906200a601565b604080516020601f8401819004810282018101909252828152600091620073369185858083850183828082843760009201919091525092939250506200959a9050565b9050620d2f008110806200734c5750603d548111155b15620073755784848484604051630a5a604160e01b8152600401620012e494939291906200a601565b603e5562007708565b620073f86040518060400160405280601c81526020017f6d617846656c6f6e794265747765656e42726561746865426c6f636b0000000081525085858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092939250506200953d9050565b15620074a457602081146200742a5783838383604051630a5a604160e01b8152600401620012e494939291906200a601565b604080516020601f84018190048102820181019092528281526000916200746d9185858083850183828082843760009201919091525092939250506200959a9050565b9050806000036200749b5784848484604051630a5a604160e01b8152600401620012e494939291906200a601565b604a5562007708565b620075126040518060400160405280601181526020017039ba30b5b2a43ab1283937ba32b1ba37b960791b81525085858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092939250506200953d9050565b15620075d25760148114620075445783838383604051630a5a604160e01b8152600401620012e494939291906200a601565b60006200758c601484848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092939250506200959a9050565b90506001600160a01b038116620075c05784848484604051630a5a604160e01b8152600401620012e494939291906200a601565b620075cb816200959f565b5062007708565b620076396040518060400160405280600a8152602001696d61784e6f646549447360b01b81525085858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092939250506200953d9050565b15620076e557602081146200766b5783838383604051630a5a604160e01b8152600401620012e494939291906200a601565b604080516020601f8401819004810282018101909252828152600091620076ae9185858083850183828082843760009201919091525092939250506200959a9050565b905080600003620076dc5784848484604051630a5a604160e01b8152600401620012e494939291906200a601565b604e5562007708565b838383836040516325ee20d560e21b8152600401620012e494939291906200a601565b7ff1ce9b2cbf50eeb05769a29e2543fd350cab46894a7dd9978a12d534bb20e633848484846040516200773f94939291906200a601565b60405180910390a150505050565b60005462010000900460ff16156200777857604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff1615620077aa5760405163b1d02c3d60e01b815260040160405180910390fd5b816000816001600160401b03811115620077c857620077c86200985f565b604051908082528060200260200182016040528015620077f2578160200160208202803683370190505b5090506000805b83811015620078f0576200783b8787838181106200781b576200781b6200a18a565b9050602002016020810190620078329190620096f0565b603f9062008c39565b620078595760405163056e881160e01b815260040160405180910390fd5b604160008888848181106200787257620078726200a18a565b9050602002016020810190620078899190620096f0565b6001600160a01b0390811682526020820192909252604001600020600201548451911692508290849083908110620078c557620078c56200a18a565b6001600160a01b0390921660209283029190910190910152620078e8816200a1a0565b9050620077f9565b50604051634484077560e01b8152612005906344840775906200331d90859088906004016200a1ec565b60608060006200792b603f62008f95565b90508085101562007aef57831562007944578362007946565b805b93506000846200795787846200a1bc565b116200796f576200796986836200a1bc565b62007971565b845b9050806001600160401b038111156200798e576200798e6200985f565b604051908082528060200260200182016040528015620079b8578160200160208202803683370190505b509350806001600160401b03811115620079d657620079d66200985f565b60405190808252806020026020018201604052801562007a00578160200160208202803683370190505b50925060005b8181101562007aec5762007a1f620044d882896200a11f565b85828151811062007a345762007a346200a18a565b60200260200101906001600160a01b031690816001600160a01b0316815250506041600086838151811062007a6d5762007a6d6200a18a565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060020160009054906101000a90046001600160a01b031684828151811062007ac15762007ac16200a18a565b6001600160a01b039092166020928302919091019091015262007ae4816200a1a0565b905062007a06565b50505b9250925092565b60008162007b06603f8262008c39565b62007b245760405163056e881160e01b815260040160405180910390fd5b50506001600160a01b03166000908152604160205260409020600c015490565b336110011462007b6c57604051630f22c43960e41b81526110016004820152602401620012e4565b60005462010000900460ff161562007b9757604051631785c68160e01b815260040160405180910390fd5b6001600160a01b038082166000908152604360205260409020541662007bbf603f8262008c39565b62007bdd5760405163056e881160e01b815260040160405180910390fd5b6001600160a01b03811660009081526041602052604081209062007c0562015180426200a0fc565b604a546000828152604b60205260409020549192501162007c395760405163bd52fcdb60e01b815260040160405180910390fd5b6000818152604b6020526040812080546001929062007c5a9084906200a11f565b90915550506001600160a01b0384166000908152604460205260409020541580159062007caf57506001600160a01b038416600090815260446020526040902054429062007cad9062015180906200a11f565b105b1562007cce576040516330abb81d60e21b815260040160405180910390fd5b60008062007cde85600062008c5c565b915091508162007d0157604051631b919bb160e11b815260040160405180910390fd5b6002840154603c5460405163045bc4d160e41b815260048101919091526000916001600160a01b0316906345bc4d10906024016020604051808303816000875af115801562007d54573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062007d7a91906200a135565b905062007d88858362008ce4565b856001600160a01b03167f6e9a2ee7aee95665e3a774a212eb11441b217e3e4656ab9563793094689aabb28383600060405162007dc8939291906200a14f565b60405180910390a26002850154604051633041949b60e01b815261200591633041949b91620060fe916001600160a01b0316908a906004016200a0bc565b6001600160a01b038082166000908152604160209081526040808320815161018081018352815486168152600182015486169381019390935260028101549094169082015260038301546060820152600483018054929384938493849390929160808401919062007e77906200a086565b80601f016020809104026020016040519081016040528092919081815260200182805462007ea5906200a086565b801562007ef65780601f1062007eca5761010080835404028352916020019162007ef6565b820191906000526020600020905b81548152906001019060200180831162007ed857829003601f168201915b505050505081526020016005820160405180608001604052908160008201805462007f21906200a086565b80601f016020809104026020016040519081016040528092919081815260200182805462007f4f906200a086565b801562007fa05780601f1062007f745761010080835404028352916020019162007fa0565b820191906000526020600020905b81548152906001019060200180831162007f8257829003601f168201915b5050505050815260200160018201805462007fbb906200a086565b80601f016020809104026020016040519081016040528092919081815260200182805462007fe9906200a086565b80156200803a5780601f106200800e576101008083540402835291602001916200803a565b820191906000526020600020905b8154815290600101906020018083116200801c57829003601f168201915b5050505050815260200160028201805462008055906200a086565b80601f016020809104026020016040519081016040528092919081815260200182805462008083906200a086565b8015620080d45780601f10620080a857610100808354040283529160200191620080d4565b820191906000526020600020905b815481529060010190602001808311620080b657829003601f168201915b50505050508152602001600382018054620080ef906200a086565b80601f01602080910402602001604051908101604052809291908181526020018280546200811d906200a086565b80156200816e5780601f1062008142576101008083540402835291602001916200816e565b820191906000526020600020905b8154815290600101906020018083116200815057829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152600d8301546001600160a01b031660a0830152805161026081019182905260c09092019190600e84019060139082845b8154815260200190600101908083116200820d5750505091909252505050606081015160e0820151610100909201519097919650945092505050565b60005462010000900460ff16156200827457604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff1615620082a65760405163b1d02c3d60e01b815260040160405180910390fd5b620082b062008e36565b620082bd603f8262008c39565b620082db5760405163056e881160e01b815260040160405180910390fd5b6000620082e762008e36565b6001600160a01b0381166000908152604160205260409020600c8101549192509042906200831a9062015180906200a11f565b11156200833a57604051631f92cdbd60e11b815260040160405180910390fd5b6005810180546200834b906200a086565b80601f016020809104026020016040519081016040528092919081815260200182805462008379906200a086565b8015620083ca5780601f106200839e57610100808354040283529160200191620083ca565b820191906000526020600020905b815481529060010190602001808311620083ac57829003601f168201915b5050508287525085916005840191508190620083e790826200a637565b5060208201516001820190620083fe90826200a637565b50604082015160028201906200841590826200a637565b50606082015160038201906200842c90826200a637565b505042600c830155506040516001600160a01b038316907f85d6366b336ade7f106987ec7a8eac1e8799e508aeab045a39d2f63e0dc969d990600090a250505050565b60005462010000900460ff16156200849a57604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff1615620084cc5760405163b1d02c3d60e01b815260040160405180910390fd5b828114620084ed576040516341abc80160e01b815260040160405180910390fd5b60005b838110156200855e576200854b8585838181106200851257620085126200a18a565b9050602002016020810190620085299190620096f0565b8484848181106200853e576200853e6200a18a565b9050602002013562009431565b62008556816200a1a0565b9050620084f0565b5050505050565b6001600160a01b0380821660009081526041602090815260408083208151610180810183528154861681526001820154861693810193909352600281015490941690820152600383015460608201526004830180549293849390916080840191620085d0906200a086565b80601f0160208091040260200160405190810160405280929190818152602001828054620085fe906200a086565b80156200864f5780601f1062008623576101008083540402835291602001916200864f565b820191906000526020600020905b8154815290600101906020018083116200863157829003601f168201915b50505050508152602001600582016040518060800160405290816000820180546200867a906200a086565b80601f0160208091040260200160405190810160405280929190818152602001828054620086a8906200a086565b8015620086f95780601f10620086cd57610100808354040283529160200191620086f9565b820191906000526020600020905b815481529060010190602001808311620086db57829003601f168201915b5050505050815260200160018201805462008714906200a086565b80601f016020809104026020016040519081016040528092919081815260200182805462008742906200a086565b8015620087935780601f10620087675761010080835404028352916020019162008793565b820191906000526020600020905b8154815290600101906020018083116200877557829003601f168201915b50505050508152602001600282018054620087ae906200a086565b80601f0160208091040260200160405190810160405280929190818152602001828054620087dc906200a086565b80156200882d5780601f1062008801576101008083540402835291602001916200882d565b820191906000526020600020905b8154815290600101906020018083116200880f57829003601f168201915b5050505050815260200160038201805462008848906200a086565b80601f016020809104026020016040519081016040528092919081815260200182805462008876906200a086565b8015620088c75780601f106200889b57610100808354040283529160200191620088c7565b820191906000526020600020905b815481529060010190602001808311620088a957829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152600d8301546001600160a01b031660a0830152805161026081019182905260c09092019190600e84019060139082845b815481526020019060010190808311620089665750505091909252505050604001519392505050565b60006200899e603f8462008c39565b620089bc5760405163056e881160e01b815260040160405180910390fd5b6001600160a01b038381166000908152604160205260409081902060020154905163aa1966cd60e01b81526004810185905291169063aa1966cd9060240162005a40565b60005462010000900460ff161562008a2b57604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff161562008a5d5760405163b1d02c3d60e01b815260040160405180910390fd5b62008a6762008e36565b62008a74603f8262008c39565b62008a925760405163056e881160e01b815260040160405180910390fd5b600062008a9e62008e36565b905062008aaf818787878762009150565b62008acd57604051631647e3cb60e11b815260040160405180910390fd5b60006001600160a01b03166045878760405162008aec9291906200a0d6565b908152604051908190036020019020546001600160a01b03161462008b24576040516311fdb94760e01b815260040160405180910390fd5b6001600160a01b0381166000908152604160205260409020600c810154429062008b539062015180906200a11f565b111562008b7357604051631f92cdbd60e11b815260040160405180910390fd5b4260468260040160405162008b8991906200a6ff565b908152604051908190036020019020556004810162008baa8789836200a2ea565b5042600c820155604051829060459062008bc8908a908a906200a0d6565b90815260405190819003602001812080546001600160a01b039384166001600160a01b0319909116179055908316907f783156582145bd0ff7924fae6953ba054cf1233eb60739a200ddb10de068ff0d9062008c28908a908a906200a5bb565b60405180910390a250505050505050565b6001600160a01b0381166000908152600183016020526040812054151562005a84565b6000806000848460405160200162008c769291906200a77d565b60408051601f1981840301815291815281516020928301206000818152604c9093529120549091504281111562008cb6576000809350935050506200264a565b603e5462008cc590426200a11f565b6000928352604c60205260409092208290555060019590945092505050565b6000600162008cf4603f62008f95565b62008d0091906200a1bc565b604954108015915062008d4c5760018301546040516001600160a01b03909116907f2afdc18061ac21cff7d9f11527ab9c8dec6fabd4edf6f894ed634bebd6a20d4590600090a2505050565b82600b015482111562008d6157600b83018290555b600a83015460ff166200643c57600a8301805460ff191660019081179091556049805460009062008d949084906200a11f565b909155505060018301546040516001600160a01b03909116907f4905ac32602da3fb8b4b7b00c285e5fc4c6c2308cc908b4a1e4e9625a29c90a390600090a2505050565b336000908152604360205260408120546001600160a01b03161562008e145750336000908152604360205260409020546001600160a01b031690565b62008e1e62008e36565b905090565b604e5460000362008e34576005604e555b565b336000908152604d60205260408120546001600160a01b03161562008e725750336000908152604d60205260409020546001600160a01b031690565b503390565b6001600160a01b0381166000908152604160205260409020600a81015460ff161562008ea1575050565b6036546002820154604051630913db4760e01b81526001600160a01b03858116600483015290911690630913db4790602401602060405180830381865afa15801562008ef1573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062008f1791906200a135565b1015620067975762008f3981603d544262008f3391906200a11f565b62008ce4565b80546040516335409f7f60e01b81526001600160a01b039091166004820152611000906335409f7f90602401600060405180830381600087803b15801562008f8057600080fd5b505af1158015620062a8573d6000803e3d6000fd5b600062005a87825490565b600062005a8483836200960b565b60008082905060038151108062008fc6575060098151115b1562008fd55750600092915050565b60418160008151811062008fed5762008fed6200a18a565b016020015160f81c10806200901f5750605a816000815181106200901557620090156200a18a565b016020015160f81c115b156200902e5750600092915050565b60015b8151811015620091465760308282815181106200905257620090526200a18a565b016020015160f81c108062009083575060398282815181106200907957620090796200a18a565b016020015160f81c115b8015620090d357506041828281518110620090a257620090a26200a18a565b016020015160f81c1080620090d35750605a828281518110620090c957620090c96200a18a565b016020015160f81c115b80156200912357506061828281518110620090f257620090f26200a18a565b016020015160f81c1080620091235750607a8282815181106200911957620091196200a18a565b016020015160f81c115b1562009133575060009392505050565b6200913e816200a1a0565b905062009031565b5060019392505050565b600060308414158062009164575060608214155b15620091735750600062009277565b6000868686466040516020016200918e94939291906200a7c7565b60408051808303601f1901815282825280516020918201208184528383019092529092506000919060208201818036833701905050905081602082015260008186868a8a604051602001620091e89594939291906200a7f4565b60408051808303601f190181526001808452838301909252925060009190602082018180368337019050509050815160016020830182602086016066600019fa6200923257600080fd5b506000816000815181106200924b576200924b6200a18a565b016020015160f81c9050600181146200926d5760009550505050505062009277565b6001955050505050505b95945050505050565b60008061200361dead6040516200929790620096aa565b6001600160a01b03928316815291166020820152606060408201819052600090820152608001604051809103906000f080158015620092da573d6000803e3d6000fd5b509050806001600160a01b031663f399e22e3486866040518463ffffffff1660e01b81526004016200930e9291906200a82c565b6000604051808303818588803b1580156200932857600080fd5b505af11580156200933d573d6000803e3d6000fd5b50506040516001600160a01b038086169450881692507fd481492e4e93bb36b4c12a5af93f03be3bf04b454dfbc35dd2663fa26f44d5b09150600090a39392505050565b600062005a84836001600160a01b03841662009638565b600054610100900460ff16620094055760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401620012e4565b600080546001600160a01b039092166301000000026301000000600160b81b0319909216919091179055565b816200943f603f8262008c39565b6200945d5760405163056e881160e01b815260040160405180910390fd5b6001600160a01b03838116600090815260416020526040808220600201549051635569f64b60e11b8152336004820152602481018690529192169063aad3ec96906044016020604051808303816000875af1158015620094c1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620094e791906200a135565b9050336001600160a01b0316846001600160a01b03167ff7a40077ff7a04c7e61f6f26fb13774259ddf1b6bce9ecf26a8276cdd3992683836040516200952f91815260200190565b60405180910390a350505050565b6000816040516020016200955291906200a852565b60405160208183030381529060405280519060200120836040516020016200957b91906200a852565b6040516020818303038152906040528051906020012014905092915050565b015190565b600080546040516001600160a01b0380851693630100000090930416917f44fc1b38a4abaa91ebd1b628a5b259a698f86238c8217d68f516e87769c60c0b91a3600080546001600160a01b039092166301000000026301000000600160b81b0319909216919091179055565b60008260000182815481106200962557620096256200a18a565b9060005260206000200154905092915050565b6000818152600183016020526040812054620096815750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562005a87565b50600062005a87565b50805460008255906000526020600020908101906200190f9190620096b8565b610e96806200a87183390190565b5b80821115620096cf5760008155600101620096b9565b5090565b80356001600160a01b0381168114620096eb57600080fd5b919050565b6000602082840312156200970357600080fd5b62005a8482620096d3565b60008083601f8401126200972157600080fd5b5081356001600160401b038111156200973957600080fd5b6020830191508360208285010111156200264a57600080fd5b600080602083850312156200976657600080fd5b82356001600160401b038111156200977d57600080fd5b6200978b858286016200970e565b90969095509350505050565b600080600060408486031215620097ad57600080fd5b833560ff81168114620097bf57600080fd5b925060208401356001600160401b03811115620097db57600080fd5b620097e9868287016200970e565b9497909650939450505050565b60005b8381101562009813578181015183820152602001620097f9565b50506000910152565b6000815180845262009836816020860160208601620097f6565b601f01601f19169290920160200192915050565b60208152600062005a8460208301846200981c565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b03811182821017156200989a576200989a6200985f565b60405290565b60006001600160401b0380841115620098bd57620098bd6200985f565b604051601f8501601f19908116603f01168101908282118183101715620098e857620098e86200985f565b816040528093508581528686860111156200990257600080fd5b858560208301376000602087830101525050509392505050565b6000602082840312156200992f57600080fd5b81356001600160401b038111156200994657600080fd5b8201601f810184136200995857600080fd5b6200996984823560208401620098a0565b949350505050565b60008083601f8401126200998457600080fd5b5081356001600160401b038111156200999c57600080fd5b6020830191508360208260051b85010111156200264a57600080fd5b60008060208385031215620099cc57600080fd5b82356001600160401b03811115620099e357600080fd5b6200978b8582860162009971565b600081518084526020808501945080840160005b8381101562009a2c5781516001600160a01b03168752958201959082019060010162009a05565b509495945050505050565b60408152600062009a4c6040830185620099f1565b6020838203818501528185518084528284019150828160051b8501018388016000805b8481101562009ac657878403601f19018652825180518086529088019088860190845b8181101562009ab05783518352928a0192918a019160010162009a92565b5050968801969450509186019160010162009a6f565b50919a9950505050505050505050565b6000806040838503121562009aea57600080fd5b62009af583620096d3565b946020939093013593505050565b80358015158114620096eb57600080fd5b6000806000806080858703121562009b2b57600080fd5b62009b3685620096d3565b935062009b4660208601620096d3565b92506040850135915062009b5d6060860162009b03565b905092959194509250565b6001600160401b03811681146200190f57600080fd5b60006020828403121562009b9157600080fd5b813562009b9e8162009b68565b9392505050565b6000806040838503121562009bb957600080fd5b50508035926020909101359150565b60808152600062009bdd6080830187620099f1565b82810360208481019190915286518083528782019282019060005b8181101562009c165784518352938301939183019160010162009bf8565b5050848103604086015286518082528282019350600581901b8201830183890160005b8381101562009c6b57601f1985840301875262009c588383516200981c565b9686019692509085019060010162009c39565b5050809550505050505082606083015295945050505050565b600080600080600080600087890360e081121562009ca157600080fd5b62009cac89620096d3565b975060208901356001600160401b038082111562009cc957600080fd5b62009cd78c838d016200970e565b909950975060408b013591508082111562009cf157600080fd5b62009cff8c838d016200970e565b90975095508591506060605f198401121562009d1a57600080fd5b60608b01945060c08b013592508083111562009d3557600080fd5b505088016080818b03121562009d4a57600080fd5b8091505092959891949750929550565b6000806040838503121562009d6e57600080fd5b62009d7983620096d3565b915062009d896020840162009b03565b90509250929050565b60208152600082516080602084015262009db060a08401826200981c565b90506020840151601f198085840301604086015262009dd083836200981c565b9250604086015191508085840301606086015262009def83836200981c565b92506060860151915080858403016080860152506200927782826200981c565b6000806000806040858703121562009e2657600080fd5b84356001600160401b038082111562009e3e57600080fd5b62009e4c888389016200970e565b9096509450602087013591508082111562009e6657600080fd5b5062009e75878288016200970e565b95989497509550505050565b60008060006040848603121562009e9757600080fd5b83356001600160401b0381111562009eae57600080fd5b62009ebc8682870162009971565b909450925062009ed1905060208501620096d3565b90509250925092565b60608152600062009eef6060830186620099f1565b828103602084015262009f038186620099f1565b915050826040830152949350505050565b600082601f83011262009f2657600080fd5b62005a8483833560208501620098a0565b60006020828403121562009f4a57600080fd5b81356001600160401b038082111562009f6257600080fd5b908301906080828603121562009f7757600080fd5b62009f8162009875565b82358281111562009f9157600080fd5b62009f9f8782860162009f14565b82525060208301358281111562009fb557600080fd5b62009fc38782860162009f14565b60208301525060408301358281111562009fdc57600080fd5b62009fea8782860162009f14565b6040830152506060830135828111156200a00357600080fd5b6200a0118782860162009f14565b60608301525095945050505050565b600080600080604085870312156200a03757600080fd5b84356001600160401b03808211156200a04f57600080fd5b6200a05d8883890162009971565b909650945060208701359150808211156200a07757600080fd5b5062009e758782880162009971565b600181811c908216806200a09b57607f821691505b6020821081036200207c57634e487b7160e01b600052602260045260246000fd5b6001600160a01b0392831681529116602082015260400190565b8183823760009101908152919050565b634e487b7160e01b600052601160045260246000fd5b6000826200a11a57634e487b7160e01b600052601260045260246000fd5b500490565b8082018082111562005a875762005a876200a0e6565b6000602082840312156200a14857600080fd5b5051919050565b8381526020810183905260608101600383106200a17c57634e487b7160e01b600052602160045260246000fd5b826040830152949350505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200a1b5576200a1b56200a0e6565b5060010190565b8181038181111562005a875762005a876200a0e6565b808202811582820484141762005a875762005a876200a0e6565b6040815260006200a2016040830185620099f1565b905060018060a01b03831660208301529392505050565b6001600160401b038281168282160390808211156200a23b576200a23b6200a0e6565b5092915050565b6000808335601e198436030181126200a25a57600080fd5b8301803591506001600160401b038211156200a27557600080fd5b6020019150368190038213156200264a57600080fd5b601f8211156200643c57600081815260208120601f850160051c810160208610156200a2b45750805b601f850160051c820191505b81811015620062a8578281556001016200a2c0565b600019600383901b1c191660019190911b1790565b6001600160401b038311156200a304576200a3046200985f565b6200a31c836200a31583546200a086565b836200a28b565b6000601f8411600181146200a34f57600085156200a33a5750838201355b6200a34686826200a2d5565b8455506200855e565b600083815260209020601f19861690835b828110156200a38257868501358255602094850194600190920191016200a360565b50868210156200a3a05760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b6200a3be82836200a242565b6001600160401b038111156200a3d8576200a3d86200985f565b6200a3f0816200a3e985546200a086565b856200a28b565b6000601f8211600181146200a42357600083156200a40e5750838201355b6200a41a84826200a2d5565b8655506200a480565b600085815260209020601f19841690835b828110156200a45657868501358255602094850194600190920191016200a434565b50848210156200a4745760001960f88660031b161c19848701351681555b505060018360011b0185555b505050506200a49360208301836200a242565b6200a4a38183600186016200a2ea565b50506200a4b460408301836200a242565b6200a4c48183600286016200a2ea565b50506200a4d560608301836200a242565b6200a4e58183600386016200a2ea565b50505050565b81356200a4f88162009b68565b6001600160401b03811690508154816001600160401b0319821617835560208401356200a5258162009b68565b6fffffffffffffffff0000000000000000604091821b166fffffffffffffffffffffffffffffffff198316841781178555908501356200a5658162009b68565b6001600160c01b0319929092169092179190911760809190911b67ffffffffffffffff60801b1617905550565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b602081526000620099696020830184866200a592565b634e487b7160e01b600052603160045260246000fd5b6000816200a5f9576200a5f96200a0e6565b506000190190565b6040815260006200a6176040830186886200a592565b82810360208401526200a62c8185876200a592565b979650505050505050565b81516001600160401b038111156200a653576200a6536200985f565b6200a66b816200a66484546200a086565b846200a28b565b602080601f8311600181146200a69f57600084156200a68a5750858301515b6200a69685826200a2d5565b865550620062a8565b600085815260208120601f198616915b828110156200a6d0578886015182559484019460019091019084016200a6af565b50858210156200a6ef5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60008083546200a70f816200a086565b600182811680156200a72a57600181146200a740576200a771565b60ff19841687528215158302870194506200a771565b8760005260208060002060005b858110156200a7685781548a8201529084019082016200a74d565b50505082870194505b50929695505050505050565b6bffffffffffffffffffffffff198360601b1681526000600383106200a7b357634e487b7160e01b600052602160045260246000fd5b5060f89190911b6014820152601501919050565b6bffffffffffffffffffffffff198560601b16815282846014830137601492019182015260340192915050565b600086516200a808818460208b01620097f6565b82018587823760009086019081528385823760009301928352509095945050505050565b6001600160a01b038316815260406020820181905260009062009969908301846200981c565b600082516200a866818460208701620097f6565b919091019291505056fe608060405260405162000e9638038062000e96833981016040819052620000269162000497565b828162000036828260006200004d565b50620000449050826200008a565b505050620005ca565b6200005883620000e5565b600082511180620000665750805b1562000085576200008383836200012760201b620001691760201c565b505b505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f620000b562000156565b604080516001600160a01b03928316815291841660208301520160405180910390a1620000e2816200018f565b50565b620000f08162000244565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606200014f838360405180606001604052806027815260200162000e6f60279139620002f8565b9392505050565b60006200018060008051602062000e4f83398151915260001b6200037760201b620001951760201c565b546001600160a01b0316919050565b6001600160a01b038116620001fa5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b806200022360008051602062000e4f83398151915260001b6200037760201b620001951760201c565b80546001600160a01b0319166001600160a01b039290921691909117905550565b6200025a816200037a60201b620001981760201c565b620002be5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401620001f1565b80620002237f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc60001b6200037760201b620001951760201c565b6060600080856001600160a01b03168560405162000317919062000577565b600060405180830381855af49150503d806000811462000354576040519150601f19603f3d011682016040523d82523d6000602084013e62000359565b606091505b5090925090506200036d8683838762000389565b9695505050505050565b90565b6001600160a01b03163b151590565b60608315620003fd578251600003620003f5576001600160a01b0385163b620003f55760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401620001f1565b508162000409565b62000409838362000411565b949350505050565b815115620004225781518083602001fd5b8060405162461bcd60e51b8152600401620001f1919062000595565b80516001600160a01b03811681146200045657600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b838110156200048e57818101518382015260200162000474565b50506000910152565b600080600060608486031215620004ad57600080fd5b620004b8846200043e565b9250620004c8602085016200043e565b60408501519092506001600160401b0380821115620004e657600080fd5b818601915086601f830112620004fb57600080fd5b8151818111156200051057620005106200045b565b604051601f8201601f19908116603f011681019083821181831017156200053b576200053b6200045b565b816040528281528960208487010111156200055557600080fd5b6200056883602083016020880162000471565b80955050505050509250925092565b600082516200058b81846020870162000471565b9190910192915050565b6020815260008251806020840152620005b681604085016020870162000471565b601f01601f19169190910160400192915050565b61087580620005da6000396000f3fe60806040523661001357610011610017565b005b6100115b61001f6101a7565b6001600160a01b0316330361015f5760606001600160e01b0319600035166364d3180d60e11b810161005a576100536101da565b9150610157565b63587086bd60e11b6001600160e01b031982160161007a57610053610231565b63070d7c6960e41b6001600160e01b031982160161009a57610053610277565b621eb96f60e61b6001600160e01b03198216016100b9576100536102a8565b63a39f25e560e01b6001600160e01b03198216016100d9576100536102e8565b60405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b815160208301f35b6101676102fc565b565b606061018e83836040518060600160405280602781526020016108426027913961030c565b9392505050565b90565b6001600160a01b03163b151590565b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b60606101e4610384565b60006101f33660048184610695565b81019061020091906106db565b905061021d8160405180602001604052806000815250600061038f565b505060408051602081019091526000815290565b60606000806102433660048184610695565b810190610250919061070c565b915091506102608282600161038f565b604051806020016040528060008152509250505090565b6060610281610384565b60006102903660048184610695565b81019061029d91906106db565b905061021d816103bb565b60606102b2610384565b60006102bc6101a7565b604080516001600160a01b03831660208201529192500160405160208183030381529060405291505090565b60606102f2610384565b60006102bc610412565b610167610307610412565b610421565b6060600080856001600160a01b03168560405161032991906107f2565b600060405180830381855af49150503d8060008114610364576040519150601f19603f3d011682016040523d82523d6000602084013e610369565b606091505b509150915061037a86838387610445565b9695505050505050565b341561016757600080fd5b610398836104c6565b6000825111806103a55750805b156103b6576103b48383610169565b505b505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6103e46101a7565b604080516001600160a01b03928316815291841660208301520160405180910390a161040f81610506565b50565b600061041c6105af565b905090565b3660008037600080366000845af43d6000803e808015610440573d6000f35b3d6000fd5b606083156104b45782516000036104ad576001600160a01b0385163b6104ad5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161014e565b50816104be565b6104be83836105d7565b949350505050565b6104cf81610601565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6001600160a01b03811661056b5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b606482015260840161014e565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6101cb565b8151156105e75781518083602001fd5b8060405162461bcd60e51b815260040161014e919061080e565b6001600160a01b0381163b61066e5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b606482015260840161014e565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc61058e565b600080858511156106a557600080fd5b838611156106b257600080fd5b5050820193919092039150565b80356001600160a01b03811681146106d657600080fd5b919050565b6000602082840312156106ed57600080fd5b61018e826106bf565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561071f57600080fd5b610728836106bf565b9150602083013567ffffffffffffffff8082111561074557600080fd5b818501915085601f83011261075957600080fd5b81358181111561076b5761076b6106f6565b604051601f8201601f19908116603f01168101908382118183101715610793576107936106f6565b816040528281528860208487010111156107ac57600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b60005b838110156107e95781810151838201526020016107d1565b50506000910152565b600082516108048184602087016107ce565b9190910192915050565b602081526000825180602084015261082d8160408501602087016107ce565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a164736f6c6343000811000ab53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a164736f6c6343000811000a \ No newline at end of file diff --git a/core/systemcontracts/maxwell/rialto/StakeHubContract b/core/systemcontracts/maxwell/rialto/StakeHubContract new file mode 100644 index 0000000000..47f9e75338 --- /dev/null +++ b/core/systemcontracts/maxwell/rialto/StakeHubContract @@ -0,0 +1 @@ +6080604052600436106200043b5760003560e01c806386d545061162000233578063ca47908f116200012f578063dd42a1dd11620000b9578063f1f74d841162000084578063f1f74d841462000d74578063f80a34021462000d8c578063fb50b31f1462000db1578063fc0c5ff11462000dd6578063ff69ab611462000dee57600080fd5b8063dd42a1dd1462000ce1578063e8f67c3b1462000d08578063e992aaf51462000d20578063efdbf0e11462000d3857600080fd5b8063d7c2dfc811620000fa578063d7c2dfc81462000c67578063d8ca511f1462000c8c578063daacdb661462000ca4578063dbda7fb31462000cbc57600080fd5b8063ca47908f1462000bd0578063cbb04d9d1462000be8578063d115a2061462000c29578063d6ca429d1462000c4257600080fd5b8063b187bd2611620001bd578063bfff04751162000188578063bfff04751462000b57578063c166f58a1462000b7c578063c38fbec81462000b93578063c473318f1462000bb8578063c8509d81146200095057600080fd5b8063b187bd261462000ac4578063baa7199e1462000ae4578063bdceadf31462000b09578063bff02e201462000b2157600080fd5b8063a1832e6411620001fe578063a1832e641462000a21578063a43569b31462000a46578063aad3ec961462000a7a578063ac4317511462000a9f57600080fd5b806386d54506146200098d5780638a4d3fa814620009c75780638cd22b2214620009e5578063982ef0a71462000a0a57600080fd5b80634838d165116200034357806364028fbd11620002cd57806375cc7d89116200029857806375cc7d8914620008fb57806376e7d6d614620009205780638129fc1c1462000938578063831d65d114620009505780638456cb59146200097557600080fd5b806364028fbd1462000836578063663706d3146200084d5780636ec01b27146200087e5780636f8e2fa414620008d657600080fd5b80634e6fd6c4116200030e5780634e6fd6c4146200079d5780635949187114620007b55780635e7cc1c914620007da57806363a036b514620007ff57600080fd5b80634838d16514620006e957806349f41a42146200072e5780634a49ac4c14620007535780634d99dd16146200077857600080fd5b80631fab701511620003c5578063384099881162000390578063384099881462000662578063417c73a7146200067a578063449ecfe6146200069f57806345211bfd14620006c457600080fd5b80631fab701514620005a95780632b727c8614620005ce5780632e8e8c7114620005f3578063367dad49146200062d57600080fd5b80630e9fbf5111620004065780630e9fbf5114620004f35780631182b875146200051857806317b4f353146200054c5780631fa8882b146200059157600080fd5b8063046f7da2146200045b578063059ddd2214620004735780630661806e14620004b5578063092193ab14620004dc57600080fd5b36620004565760345460ff166001146200045457600080fd5b005b600080fd5b3480156200046857600080fd5b506200045462000e06565b3480156200048057600080fd5b506200049862000492366004620096e4565b62000e98565b6040516001600160a01b0390911681526020015b60405180910390f35b348015620004c257600080fd5b50620004cd60365481565b604051908152602001620004ac565b62000454620004ed366004620096e4565b620012c0565b3480156200050057600080fd5b50620004546200051236600462009746565b62001911565b3480156200052557600080fd5b506200053d620005373660046200978b565b62001c3b565b604051620004ac91906200983e565b3480156200055957600080fd5b50620004986200056b36600462009910565b80516020818301810180516045825292820191909301209152546001600160a01b031681565b3480156200059e57600080fd5b50620004cd61025881565b348015620005b657600080fd5b5062000454620005c8366004620099ac565b62001cd3565b348015620005db57600080fd5b5062000498620005ed366004620096e4565b6200202a565b3480156200060057600080fd5b506200049862000612366004620096e4565b604d602052600090815260409020546001600160a01b031681565b3480156200063a57600080fd5b50620006526200064c366004620099ac565b6200207f565b604051620004ac92919062009a2b565b3480156200066f57600080fd5b50620004cd60375481565b3480156200068757600080fd5b506200045462000699366004620096e4565b6200264e565b348015620006ac57600080fd5b5062000454620006be366004620096e4565b620026d0565b348015620006d157600080fd5b5062000454620006e3366004620096e4565b620028b5565b348015620006f657600080fd5b506200071d62000708366004620096e4565b60016020526000908152604090205460ff1681565b6040519015158152602001620004ac565b3480156200073b57600080fd5b50620004546200074d366004620096e4565b62002a8d565b3480156200076057600080fd5b506200045462000772366004620096e4565b62002ca9565b3480156200078557600080fd5b50620004546200079736600462009aca565b62002d25565b348015620007aa57600080fd5b506200049861dead81565b348015620007c257600080fd5b5062000454620007d436600462009b08565b62003355565b348015620007e757600080fd5b5062000454620007f936600462009b72565b6200414e565b3480156200080c57600080fd5b50620008246200081e36600462009b99565b62004377565b604051620004ac949392919062009bbc565b620004546200084736600462009c78565b62004a1c565b3480156200085a57600080fd5b50620004cd6200086c366004620096e4565b60446020526000908152604090205481565b3480156200088b57600080fd5b50620008a36200089d366004620096e4565b6200506b565b6040805182516001600160401b0390811682526020808501518216908301529282015190921690820152606001620004ac565b348015620008e357600080fd5b506200053d620008f5366004620096e4565b62005110565b3480156200090857600080fd5b50620004546200091a366004620096e4565b6200553c565b3480156200092d57600080fd5b50620004cd603d5481565b3480156200094557600080fd5b50620004546200570e565b3480156200095d57600080fd5b50620004546200096f3660046200978b565b620058d6565b3480156200098257600080fd5b506200045462005934565b3480156200099a57600080fd5b5062000498620009ac366004620096e4565b6043602052600090815260409020546001600160a01b031681565b348015620009d457600080fd5b50620004cd670de0b6b3a764000081565b348015620009f257600080fd5b50620004cd62000a0436600462009aca565b620059cc565b6200045462000a1b36600462009d4e565b62005a85565b34801562000a2e57600080fd5b506200045462000a40366004620099ac565b62006133565b34801562000a5357600080fd5b5062000a6b62000a65366004620096e4565b62006439565b604051620004ac919062009d86565b34801562000a8757600080fd5b506200045462000a9936600462009aca565b62006726565b34801562000aac57600080fd5b506200045462000abe36600462009e03565b62006793565b34801562000ad157600080fd5b5060005462010000900460ff166200071d565b34801562000af157600080fd5b506200045462000b0336600462009e75565b62007745565b34801562000b1657600080fd5b50620004cd603c5481565b34801562000b2e57600080fd5b5062000b4662000b4036600462009b99565b62007912565b604051620004ac9392919062009ece565b34801562000b6457600080fd5b50620004cd62000b76366004620096e4565b62007aee565b34801562000b8957600080fd5b50620004cd600581565b34801562000ba057600080fd5b506200045462000bb2366004620096e4565b62007b3c565b34801562000bc557600080fd5b50620004cd60385481565b34801562000bdd57600080fd5b50620004cd604e5481565b34801562000bf557600080fd5b5062000c0d62000c07366004620096e4565b62007dfc565b60408051938452911515602084015290820152606001620004ac565b34801562000c3657600080fd5b50620004cd620186a081565b34801562000c4f57600080fd5b506200045462000c6136600462009f2b565b6200823f565b34801562000c7457600080fd5b506200045462000c863660046200a014565b62008464565b34801562000c9957600080fd5b50620004cd603b5481565b34801562000cb157600080fd5b50620004cd60495481565b34801562000cc957600080fd5b506200049862000cdb366004620096e4565b6200855a565b34801562000cee57600080fd5b50600054630100000090046001600160a01b031662000498565b34801562000d1557600080fd5b50620004cd60355481565b34801562000d2d57600080fd5b50620004cd603a5481565b34801562000d4557600080fd5b50620004cd62000d5736600462009910565b805160208183018101805160468252928201919093012091525481565b34801562000d8157600080fd5b50620004cd603e5481565b34801562000d9957600080fd5b50620004cd62000dab36600462009aca565b62008984565b34801562000dbe57600080fd5b506200045462000dd036600462009e03565b620089f5565b34801562000de357600080fd5b50620004cd60395481565b34801562000dfb57600080fd5b50620004cd604a5481565b600054630100000090046001600160a01b0316331462000e39576040516306fbb1e360e01b815260040160405180910390fd5b60005462010000900460ff1662000e6357604051636cd6020160e01b815260040160405180910390fd5b6000805462ff0000191681556040517f62451d457bc659158be6e6247f56ec1df424a5c7597f71c20c2bc44e0965c8f99190a1565b6001600160a01b038082166000908152604160209081526040808320815161018081018352815486168152600182015486169381019390935260028101549094169082015260038301546060820152600483018054929384939091608084019162000f03906200a07a565b80601f016020809104026020016040519081016040528092919081815260200182805462000f31906200a07a565b801562000f825780601f1062000f565761010080835404028352916020019162000f82565b820191906000526020600020905b81548152906001019060200180831162000f6457829003601f168201915b505050505081526020016005820160405180608001604052908160008201805462000fad906200a07a565b80601f016020809104026020016040519081016040528092919081815260200182805462000fdb906200a07a565b80156200102c5780601f1062001000576101008083540402835291602001916200102c565b820191906000526020600020905b8154815290600101906020018083116200100e57829003601f168201915b5050505050815260200160018201805462001047906200a07a565b80601f016020809104026020016040519081016040528092919081815260200182805462001075906200a07a565b8015620010c65780601f106200109a57610100808354040283529160200191620010c6565b820191906000526020600020905b815481529060010190602001808311620010a857829003601f168201915b50505050508152602001600282018054620010e1906200a07a565b80601f01602080910402602001604051908101604052809291908181526020018280546200110f906200a07a565b8015620011605780601f10620011345761010080835404028352916020019162001160565b820191906000526020600020905b8154815290600101906020018083116200114257829003601f168201915b505050505081526020016003820180546200117b906200a07a565b80601f0160208091040260200160405190810160405280929190818152602001828054620011a9906200a07a565b8015620011fa5780601f10620011ce57610100808354040283529160200191620011fa565b820191906000526020600020905b815481529060010190602001808311620011dc57829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152600d8301546001600160a01b031660a0830152805161026081019182905260c09092019190600e84019060139082845b81548152602001906001019080831162001299575050509190925250509051949350505050565b3361100014620012ec57604051630f22c43960e41b815261100060048201526024015b60405180910390fd5b6001600160a01b0380821660009081526043602090815260408083205484168084526041835281842082516101808101845281548716815260018201548716948101949094526002810154909516918301919091526003840154606083015260048401805491949160808401919062001365906200a07a565b80601f016020809104026020016040519081016040528092919081815260200182805462001393906200a07a565b8015620013e45780601f10620013b857610100808354040283529160200191620013e4565b820191906000526020600020905b815481529060010190602001808311620013c657829003601f168201915b50505050508152602001600582016040518060800160405290816000820180546200140f906200a07a565b80601f01602080910402602001604051908101604052809291908181526020018280546200143d906200a07a565b80156200148e5780601f1062001462576101008083540402835291602001916200148e565b820191906000526020600020905b8154815290600101906020018083116200147057829003601f168201915b50505050508152602001600182018054620014a9906200a07a565b80601f0160208091040260200160405190810160405280929190818152602001828054620014d7906200a07a565b8015620015285780601f10620014fc5761010080835404028352916020019162001528565b820191906000526020600020905b8154815290600101906020018083116200150a57829003601f168201915b5050505050815260200160028201805462001543906200a07a565b80601f016020809104026020016040519081016040528092919081815260200182805462001571906200a07a565b8015620015c25780601f106200159657610100808354040283529160200191620015c2565b820191906000526020600020905b815481529060010190602001808311620015a457829003601f168201915b50505050508152602001600382018054620015dd906200a07a565b80601f01602080910402602001604051908101604052809291908181526020018280546200160b906200a07a565b80156200165c5780601f1062001630576101008083540402835291602001916200165c565b820191906000526020600020905b8154815290600101906020018083116200163e57829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152600d8301546001600160a01b031660a0830152805161026081019182905260c09092019190600e84019060139082845b815481526020019060010190808311620016fb575050509190925250505060408101519091506001600160a01b031615806200173857508060e001515b15620017f557604051611002903490600081818185875af1925050503d806000811462001782576040519150601f19603f3d011682016040523d82523d6000602084013e62001787565b606091505b505050816001600160a01b03167ffc8bff675087dd2da069cc3fb517b9ed001e19750c0865241a5542dba1ba170d604051620017e89060208082526011908201527024a72b20a624a22fab20a624a220aa27a960791b604082015260600190565b60405180910390a2505050565b60408181015160c0830151519151632f303ebb60e11b81526001600160401b0390921660048301526001600160a01b031690635e607d769034906024016000604051808303818588803b1580156200184c57600080fd5b505af115801562001861573d6000803e3d6000fd5b5050505050816001600160a01b03167fe34918ff1c7084970068b53fd71ad6d8b04e9f15d3886cbf006443e6cdc52ea634604051620018a291815260200190565b60405180910390a26040808201519051633041949b60e01b815261200591633041949b91620018d7919086906004016200a0b0565b600060405180830381600087803b158015620018f257600080fd5b505af115801562001907573d6000803e3d6000fd5b5050505050505b50565b33611001146200193957604051630f22c43960e41b81526110016004820152602401620012e3565b60005462010000900460ff16156200196457604051631785c68160e01b815260040160405180910390fd5b6000604583836040516200197a9291906200a0ca565b908152604051908190036020019020546001600160a01b03169050620019a2603f8262008c2d565b620019c05760405163056e881160e01b815260040160405180910390fd5b6001600160a01b038116600090815260416020526040812090620019e7610258426200a0f0565b604a546000828152604b60205260409020549192501162001a1b5760405163bd52fcdb60e01b815260040160405180910390fd5b6000818152604b6020526040812080546001929062001a3c9084906200a113565b909155505060405160469062001a5690879087906200a0ca565b90815260200160405180910390205460001415801562001aa65750426102586046878760405162001a899291906200a0ca565b90815260200160405180910390205462001aa491906200a113565b105b1562001ac557604051631898eb6b60e01b815260040160405180910390fd5b60008062001ad585600262008c50565b915091508162001af857604051631b919bb160e11b815260040160405180910390fd5b6002840154603c5460405163045bc4d160e41b815260048101919091526000916001600160a01b0316906345bc4d10906024016020604051808303816000875af115801562001b4b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001b7191906200a129565b905062001b7f858362008cd8565b856001600160a01b03167f6e9a2ee7aee95665e3a774a212eb11441b217e3e4656ab9563793094689aabb28383600260405162001bbf939291906200a143565b60405180910390a26002850154604051633041949b60e01b815261200591633041949b9162001bfd916001600160a01b0316908a906004016200a0b0565b600060405180830381600087803b15801562001c1857600080fd5b505af115801562001c2d573d6000803e3d6000fd5b505050505050505050505050565b6060336120001462001c6557604051630f22c43960e41b81526120006004820152602401620012e3565b60005462010000900460ff161562001c9057604051631785c68160e01b815260040160405180910390fd5b6034805460ff1916600117905560405162461bcd60e51b815260206004820152600a60248201526919195c1c9958d85d195960b21b6044820152606401620012e3565b60005462010000900460ff161562001cfe57604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff161562001d305760405163b1d02c3d60e01b815260040160405180910390fd5b62001d3a62008dcc565b62001d47603f8262008c2d565b62001d655760405163056e881160e01b815260040160405180910390fd5b62001d6f62008e17565b600082900362001d9257604051636490ffd360e01b815260040160405180910390fd5b600062001d9e62008dcc565b6001600160a01b0381166000908152604f602052604090208054604e54929350909162001dcc86836200a113565b111562001dec5760405163091af98560e21b815260040160405180910390fd5b60005b8581101562001ed257600087878381811062001e0f5762001e0f6200a17e565b905060200201350362001e3557604051636490ffd360e01b815260040160405180910390fd5b600062001e448260016200a113565b90505b8681101562001ebc5787878281811062001e655762001e656200a17e565b9050602002013588888481811062001e815762001e816200a17e565b905060200201350362001ea757604051632205e3c760e11b815260040160405180910390fd5b8062001eb3816200a194565b91505062001e47565b508062001ec9816200a194565b91505062001def565b5060005b8581101562001f715760005b8281101562001f5b5783818154811062001f005762001f006200a17e565b906000526020600020015488888481811062001f205762001f206200a17e565b905060200201350362001f4657604051632205e3c760e11b815260040160405180910390fd5b8062001f52816200a194565b91505062001ee2565b508062001f68816200a194565b91505062001ed6565b5060005b8581101562001907578287878381811062001f945762001f946200a17e565b835460018101855560009485526020948590209190940292909201359190920155506001600160a01b0384167f7c4ff4c9a343a2daef608f3b5a91016e994a15fc0ef8611109e4f45823249f2988888481811062001ff65762001ff66200a17e565b905060200201356040516200200d91815260200190565b60405180910390a28062002021816200a194565b91505062001f75565b6000816200203a603f8262008c2d565b620020585760405163056e881160e01b815260040160405180910390fd5b6001600160a01b038084166000908152604160205260409020600d01541691505b50919050565b60608082806001600160401b038111156200209e576200209e62009853565b604051908082528060200260200182016040528015620020c8578160200160208202803683370190505b509250806001600160401b03811115620020e657620020e662009853565b6040519080825280602002602001820160405280156200211b57816020015b6060815260200190600190039081620021055790505b50915060005b81811015620026445760008686838181106200214157620021416200a17e565b9050602002016020810190620021589190620096e4565b6001600160a01b03808216600090815260416020908152604080832081516101808101835281548616815260018201548616938101939093526002810154909416908201526003830154606082015260048301805494955091939092916080840191620021c5906200a07a565b80601f0160208091040260200160405190810160405280929190818152602001828054620021f3906200a07a565b8015620022445780601f10620022185761010080835404028352916020019162002244565b820191906000526020600020905b8154815290600101906020018083116200222657829003601f168201915b50505050508152602001600582016040518060800160405290816000820180546200226f906200a07a565b80601f01602080910402602001604051908101604052809291908181526020018280546200229d906200a07a565b8015620022ee5780601f10620022c257610100808354040283529160200191620022ee565b820191906000526020600020905b815481529060010190602001808311620022d057829003601f168201915b5050505050815260200160018201805462002309906200a07a565b80601f016020809104026020016040519081016040528092919081815260200182805462002337906200a07a565b8015620023885780601f106200235c5761010080835404028352916020019162002388565b820191906000526020600020905b8154815290600101906020018083116200236a57829003601f168201915b50505050508152602001600282018054620023a3906200a07a565b80601f0160208091040260200160405190810160405280929190818152602001828054620023d1906200a07a565b8015620024225780601f10620023f65761010080835404028352916020019162002422565b820191906000526020600020905b8154815290600101906020018083116200240457829003601f168201915b505050505081526020016003820180546200243d906200a07a565b80601f01602080910402602001604051908101604052809291908181526020018280546200246b906200a07a565b8015620024bc5780601f106200249057610100808354040283529160200191620024bc565b820191906000526020600020905b8154815290600101906020018083116200249e57829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152600d8301546001600160a01b031660a0830152805161026081019182905260c09092019190600e84019060139082845b8154815260200190600101908083116200255b57505050505081525050905080600001518684815181106200259457620025946200a17e565b6001600160a01b039283166020918202929092018101919091529083166000908152604f8252604090819020805482518185028101850190935280835291929091908301828280156200260757602002820191906000526020600020905b815481526020019060010190808311620025f2575b50505050508584815181106200262157620026216200a17e565b6020026020010181905250505080806200263b906200a194565b91505062002121565b50505b9250929050565b600054630100000090046001600160a01b0316331462002681576040516306fbb1e360e01b815260040160405180910390fd5b6001600160a01b0381166000818152600160208190526040808320805460ff1916909217909155517f7fd26be6fc92aff63f1f4409b2b2ddeb272a888031d7f55ec830485ec61941869190a250565b60005462010000900460ff1615620026fb57604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff16156200272d5760405163b1d02c3d60e01b815260040160405180910390fd5b806200273b603f8262008c2d565b620027595760405163056e881160e01b815260040160405180910390fd5b6001600160a01b0382166000908152604160205260409020600a81015460ff166200279757604051634b6b857d60e01b815260040160405180910390fd5b6036546002820154604051630913db4760e01b81526001600160a01b03868116600483015290911690630913db4790602401602060405180830381865afa158015620027e7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200280d91906200a129565b10156200282d576040516317b204bf60e11b815260040160405180910390fd5b4281600b01541115620028535760405163170cb76760e21b815260040160405180910390fd5b600a8101805460ff191690556049805460019190600090620028779084906200a1b0565b90915550506040516001600160a01b038416907f9390b453426557da5ebdc31f19a37753ca04addf656d32f35232211bb2af3f1990600090a2505050565b60005462010000900460ff1615620028e057604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff1615620029125760405163b1d02c3d60e01b815260040160405180910390fd5b6200291c62008e2a565b62002929603f8262008c2d565b620029475760405163056e881160e01b815260040160405180910390fd5b6001600160a01b0382166200296f57604051636520611b60e11b815260040160405180910390fd5b6001600160a01b038281166000908152604360205260409020541615620029a957604051631e6f587560e11b815260040160405180910390fd5b6000620029b562008e2a565b6001600160a01b0381166000908152604160205260409020600c810154919250904290620029e790610258906200a113565b111562002a0757604051631f92cdbd60e11b815260040160405180910390fd5b80546001600160a01b039081166000908152604460209081526040808320429081905585548986166001600160a01b031991821681178855600c88019290925581855260439093528184208054958816959093168517909255519092917f6e4e747ca35203f16401c69805c7dd52fff67ef60b0ebc5c7fe16890530f223591a350505050565b3362002a9b603f8262008c2d565b62002ab95760405163056e881160e01b815260040160405180910390fd5b60005462010000900460ff161562002ae457604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff161562002b165760405163b1d02c3d60e01b815260040160405180910390fd5b6001600160a01b038281166000908152604d6020526040902054161562002b505760405163bebdc75760e01b815260040160405180910390fd5b62002b5d603f8362008c2d565b1562002b7c5760405163bebdc75760e01b815260040160405180910390fd5b336000818152604160205260409020600d01546001600160a01b03908116908416810362002bbd5760405163bebdc75760e01b815260040160405180910390fd5b6001600160a01b0381161562002bf4576001600160a01b0381166000908152604d6020526040902080546001600160a01b03191690555b6001600160a01b038281166000908152604160205260409020600d0180546001600160a01b03191691861691821790551562002c59576001600160a01b038481166000908152604d6020526040902080546001600160a01b0319169184169190911790555b836001600160a01b0316816001600160a01b0316836001600160a01b03167fcbb728765de145e99c00e8ae32a325231e850359b7b8a6da3b84d672ab3f1d0a60405160405180910390a450505050565b600054630100000090046001600160a01b0316331462002cdc576040516306fbb1e360e01b815260040160405180910390fd5b6001600160a01b038116600081815260016020526040808220805460ff19169055517fe0db3499b7fdc3da4cddff5f45d694549c19835e7f719fb5606d3ad1a5de40119190a250565b60005462010000900460ff161562002d5057604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff161562002d825760405163b1d02c3d60e01b815260040160405180910390fd5b8162002d90603f8262008c2d565b62002dae5760405163056e881160e01b815260040160405180910390fd5b8160000362002dd057604051639811e0c760e01b815260040160405180910390fd5b6001600160a01b038084166000908152604160209081526040808320815161018081018352815486168152600182015486169381019390935260028101549094169082015260038301546060820152600483018054339491608084019162002e38906200a07a565b80601f016020809104026020016040519081016040528092919081815260200182805462002e66906200a07a565b801562002eb75780601f1062002e8b5761010080835404028352916020019162002eb7565b820191906000526020600020905b81548152906001019060200180831162002e9957829003601f168201915b505050505081526020016005820160405180608001604052908160008201805462002ee2906200a07a565b80601f016020809104026020016040519081016040528092919081815260200182805462002f10906200a07a565b801562002f615780601f1062002f355761010080835404028352916020019162002f61565b820191906000526020600020905b81548152906001019060200180831162002f4357829003601f168201915b5050505050815260200160018201805462002f7c906200a07a565b80601f016020809104026020016040519081016040528092919081815260200182805462002faa906200a07a565b801562002ffb5780601f1062002fcf5761010080835404028352916020019162002ffb565b820191906000526020600020905b81548152906001019060200180831162002fdd57829003601f168201915b5050505050815260200160028201805462003016906200a07a565b80601f016020809104026020016040519081016040528092919081815260200182805462003044906200a07a565b8015620030955780601f10620030695761010080835404028352916020019162003095565b820191906000526020600020905b8154815290600101906020018083116200307757829003601f168201915b50505050508152602001600382018054620030b0906200a07a565b80601f0160208091040260200160405190810160405280929190818152602001828054620030de906200a07a565b80156200312f5780601f1062003103576101008083540402835291602001916200312f565b820191906000526020600020905b8154815290600101906020018083116200311157829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152600d8301546001600160a01b031660a0830152805161026081019182905260c09092019190600e84019060139082845b815481526020019060010190808311620031ce575050509190925250505060408082015190516326ccee8b60e11b81526001600160a01b0385811660048301526024820188905292935060009290911690634d99dd16906044016020604051808303816000875af115801562003248573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200326e91906200a129565b9050826001600160a01b0316866001600160a01b03167f3aace7340547de7b9156593a7652dc07ee900cea3fd8f82cb6c9d38b408298028784604051620032bf929190918252602082015260400190565b60405180910390a3856001600160a01b0316836001600160a01b031603620032ec57620032ec8662008e6b565b6040808301519051633041949b60e01b815261200591633041949b9162003319919087906004016200a0b0565b600060405180830381600087803b1580156200333457600080fd5b505af115801562003349573d6000803e3d6000fd5b50505050505050505050565b60005462010000900460ff16156200338057604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff1615620033b25760405163b1d02c3d60e01b815260040160405180910390fd5b83620033c0603f8262008c2d565b620033de5760405163056e881160e01b815260040160405180910390fd5b83620033ec603f8262008c2d565b6200340a5760405163056e881160e01b815260040160405180910390fd5b6034805460ff1916600117905560008490036200343a57604051639811e0c760e01b815260040160405180910390fd5b846001600160a01b0316866001600160a01b0316036200346d5760405163f0e3e62960e01b815260040160405180910390fd5b6001600160a01b0380871660009081526041602090815260408083208151610180810183528154861681526001820154861693810193909352600281015490941690820152600383015460608201526004830180543394916080840191620034d5906200a07a565b80601f016020809104026020016040519081016040528092919081815260200182805462003503906200a07a565b8015620035545780601f10620035285761010080835404028352916020019162003554565b820191906000526020600020905b8154815290600101906020018083116200353657829003601f168201915b50505050508152602001600582016040518060800160405290816000820180546200357f906200a07a565b80601f0160208091040260200160405190810160405280929190818152602001828054620035ad906200a07a565b8015620035fe5780601f10620035d257610100808354040283529160200191620035fe565b820191906000526020600020905b815481529060010190602001808311620035e057829003601f168201915b5050505050815260200160018201805462003619906200a07a565b80601f016020809104026020016040519081016040528092919081815260200182805462003647906200a07a565b8015620036985780601f106200366c5761010080835404028352916020019162003698565b820191906000526020600020905b8154815290600101906020018083116200367a57829003601f168201915b50505050508152602001600282018054620036b3906200a07a565b80601f0160208091040260200160405190810160405280929190818152602001828054620036e1906200a07a565b8015620037325780601f10620037065761010080835404028352916020019162003732565b820191906000526020600020905b8154815290600101906020018083116200371457829003601f168201915b505050505081526020016003820180546200374d906200a07a565b80601f01602080910402602001604051908101604052809291908181526020018280546200377b906200a07a565b8015620037cc5780601f10620037a057610100808354040283529160200191620037cc565b820191906000526020600020905b815481529060010190602001808311620037ae57829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152600d8301546001600160a01b031660a0830152805161026081019182905260c09092019190600e84019060139082845b8154815260200190600101908083116200386b57505050919092525050506001600160a01b03808916600090815260416020908152604080832081516101808101835281548616815260018201548616938101939093526002810154909416908201526003830154606082015260048301805494955091939092916080840191620038f6906200a07a565b80601f016020809104026020016040519081016040528092919081815260200182805462003924906200a07a565b8015620039755780601f10620039495761010080835404028352916020019162003975565b820191906000526020600020905b8154815290600101906020018083116200395757829003601f168201915b5050505050815260200160058201604051806080016040529081600082018054620039a0906200a07a565b80601f0160208091040260200160405190810160405280929190818152602001828054620039ce906200a07a565b801562003a1f5780601f10620039f35761010080835404028352916020019162003a1f565b820191906000526020600020905b81548152906001019060200180831162003a0157829003601f168201915b5050505050815260200160018201805462003a3a906200a07a565b80601f016020809104026020016040519081016040528092919081815260200182805462003a68906200a07a565b801562003ab95780601f1062003a8d5761010080835404028352916020019162003ab9565b820191906000526020600020905b81548152906001019060200180831162003a9b57829003601f168201915b5050505050815260200160028201805462003ad4906200a07a565b80601f016020809104026020016040519081016040528092919081815260200182805462003b02906200a07a565b801562003b535780601f1062003b275761010080835404028352916020019162003b53565b820191906000526020600020905b81548152906001019060200180831162003b3557829003601f168201915b5050505050815260200160038201805462003b6e906200a07a565b80601f016020809104026020016040519081016040528092919081815260200182805462003b9c906200a07a565b801562003bed5780601f1062003bc15761010080835404028352916020019162003bed565b820191906000526020600020905b81548152906001019060200180831162003bcf57829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152600d8301546001600160a01b031660a0830152805161026081019182905260c09092019190600e84019060139082845b81548152602001906001019080831162003c8c5750505050508152505090508060e00151801562003ccf5750876001600160a01b0316836001600160a01b031614155b1562003cee57604051636468920360e01b815260040160405180910390fd5b60408083015190516352e82ce560e11b81526001600160a01b038581166004830152602482018a9052600092169063a5d059ca906044016020604051808303816000875af115801562003d45573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062003d6b91906200a129565b905060375481101562003d915760405163dc6f0bdd60e01b815260040160405180910390fd5b896001600160a01b0316846001600160a01b031614801562003e2657506036546040808501519051630913db4760e01b81526001600160a01b038d8116600483015290911690630913db4790602401602060405180830381865afa15801562003dfe573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062003e2491906200a129565b105b1562003e45576040516317b204bf60e11b815260040160405180910390fd5b6000620186a0603a548362003e5b91906200a1c6565b62003e6791906200a0f0565b9050600083604001516001600160a01b03168260405160006040518083038185875af1925050503d806000811462003ebc576040519150601f19603f3d011682016040523d82523d6000602084013e62003ec1565b606091505b505090508062003ee4576040516312171d8360e31b815260040160405180910390fd5b62003ef082846200a1b0565b60408086015190516317066a5760e21b81526001600160a01b03898116600483015292955060009290911690635c19a95c90869060240160206040518083038185885af115801562003f46573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019062003f6d91906200a129565b9050866001600160a01b03168c6001600160a01b03168e6001600160a01b03167ffdac6e81913996d95abcc289e90f2d8bd235487ce6fe6f821e7d21002a1915b48e858960405162003fd2939291909283526020830191909152604082015260600190565b60405180910390a46040805160028082526060820183526000926020830190803683370190505090508660400151816000815181106200401657620040166200a17e565b60200260200101906001600160a01b031690816001600160a01b0316815250508560400151816001815181106200405157620040516200a17e565b6001600160a01b0390921660209283029190910190910152604051634484077560e01b815261200590634484077590620040929084908c906004016200a1e0565b600060405180830381600087803b158015620040ad57600080fd5b505af1158015620040c2573d6000803e3d6000fd5b505050508a1562004134576120056001600160a01b031663e5ed5b1e898f6040518363ffffffff1660e01b8152600401620040ff9291906200a0b0565b600060405180830381600087803b1580156200411a57600080fd5b505af11580156200412f573d6000803e3d6000fd5b505050505b50506034805460ff19169055505050505050505050505050565b60005462010000900460ff16156200417957604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff1615620041ab5760405163b1d02c3d60e01b815260040160405180910390fd5b620041b562008e2a565b620041c2603f8262008c2d565b620041e05760405163056e881160e01b815260040160405180910390fd5b6000620041ec62008e2a565b6001600160a01b0381166000908152604160205260409020600c8101549192509042906200421e90610258906200a113565b11156200423e57604051631f92cdbd60e11b815260040160405180910390fd5b60098101546001600160401b03600160401b90910481169085161115620042785760405163dc81db8560e01b815260040160405180910390fd5b60098101546000906001600160401b039081169086161015620042b6576009820154620042b09086906001600160401b03166200a20c565b620042d0565b6009820154620042d0906001600160401b0316866200a20c565b60098301546001600160401b039182169250600160801b9004168111156200430b5760405163dc81db8560e01b815260040160405180910390fd5b60098201805467ffffffffffffffff19166001600160401b03871690811790915542600c8401556040519081526001600160a01b038416907f78cdd96edf59e09cfd4d26ef6ef6c92d166effe6a40970c54821206d541932cb9060200160405180910390a25050505050565b606080606060006200438a603f62008f89565b90508086101562004a13578415620043a35784620043a5565b805b9450600085620043b688846200a1b0565b11620043ce57620043c887836200a1b0565b620043d0565b855b9050806001600160401b03811115620043ed57620043ed62009853565b60405190808252806020026020018201604052801562004417578160200160208202803683370190505b509450806001600160401b0381111562004435576200443562009853565b6040519080825280602002602001820160405280156200445f578160200160208202803683370190505b509350806001600160401b038111156200447d576200447d62009853565b604051908082528060200260200182016040528015620044b257816020015b60608152602001906001900390816200449c5790505b50925060005b8181101562004a10576000620044dc620044d3838b6200a113565b603f9062008f94565b6001600160a01b0380821660009081526041602090815260408083208151610180810183528154861681526001820154861693810193909352600281015490941690820152600383015460608201526004830180549495509193909291608084019162004549906200a07a565b80601f016020809104026020016040519081016040528092919081815260200182805462004577906200a07a565b8015620045c85780601f106200459c57610100808354040283529160200191620045c8565b820191906000526020600020905b815481529060010190602001808311620045aa57829003601f168201915b5050505050815260200160058201604051806080016040529081600082018054620045f3906200a07a565b80601f016020809104026020016040519081016040528092919081815260200182805462004621906200a07a565b8015620046725780601f10620046465761010080835404028352916020019162004672565b820191906000526020600020905b8154815290600101906020018083116200465457829003601f168201915b505050505081526020016001820180546200468d906200a07a565b80601f0160208091040260200160405190810160405280929190818152602001828054620046bb906200a07a565b80156200470c5780601f10620046e0576101008083540402835291602001916200470c565b820191906000526020600020905b815481529060010190602001808311620046ee57829003601f168201915b5050505050815260200160028201805462004727906200a07a565b80601f016020809104026020016040519081016040528092919081815260200182805462004755906200a07a565b8015620047a65780601f106200477a57610100808354040283529160200191620047a6565b820191906000526020600020905b8154815290600101906020018083116200478857829003601f168201915b50505050508152602001600382018054620047c1906200a07a565b80601f0160208091040260200160405190810160405280929190818152602001828054620047ef906200a07a565b8015620048405780601f10620048145761010080835404028352916020019162004840565b820191906000526020600020905b8154815290600101906020018083116200482257829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152600d8301546001600160a01b031660a0830152805161026081019182905260c09092019190600e84019060139082845b815481526020019060010190808311620048df57505050505081525050905080600001518884815181106200491857620049186200a17e565b60200260200101906001600160a01b031690816001600160a01b0316815250508060e00151620049b15780604001516001600160a01b03166315d1f8986040518163ffffffff1660e01b8152600401602060405180830381865afa15801562004985573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620049ab91906200a129565b620049b4565b60005b878481518110620049c957620049c96200a17e565b6020026020010181815250508060800151868481518110620049ef57620049ef6200a17e565b602002602001018190525050508062004a08906200a194565b9050620044b8565b50505b92959194509250565b60005462010000900460ff161562004a4757604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff161562004a795760405163b1d02c3d60e01b815260040160405180910390fd5b3362004a87603f8262008c2d565b1562004aa657604051635f28f62b60e01b815260040160405180910390fd5b6001600160a01b038181166000908152604d6020526040902054161562004ae057604051631a0a9b9f60e21b815260040160405180910390fd5b6001600160a01b03888116600090815260436020526040902054161562004b1a57604051631e6f587560e11b815260040160405180910390fd5b60006001600160a01b03166045888860405162004b399291906200a0ca565b908152604051908190036020019020546001600160a01b03161462004b71576040516311fdb94760e01b815260040160405180910390fd5b600062004b7f83806200a236565b60405160200162004b929291906200a0ca565b60408051601f1981840301815291815281516020928301206000818152604290935291205490915060ff161562004bdc5760405163c0bf414360e01b815260040160405180910390fd5b600062004bf2670de0b6b3a7640000346200a1b0565b905060365481101562004c18576040516317b204bf60e11b815260040160405180910390fd5b6001600160a01b038a1662004c4057604051636520611b60e11b815260040160405180910390fd5b61138862004c55604087016020880162009b72565b6001600160401b0316118062004c9b575062004c78604086016020870162009b72565b6001600160401b031662004c90602087018762009b72565b6001600160401b0316115b8062004cda575062004cb4604086016020870162009b72565b6001600160401b031662004ccf606087016040880162009b72565b6001600160401b0316115b1562004cf95760405163dc81db8560e01b815260040160405180910390fd5b62004d4462004d0985806200a236565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525062008fa292505050565b62004d6257604051635dba5ad760e01b815260040160405180910390fd5b62004d71838a8a8a8a62009144565b62004d8f57604051631647e3cb60e11b815260040160405180910390fd5b600062004ddd8462004da287806200a236565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506200927492505050565b905062004dec603f8562009375565b506000838152604260209081526040808320805460ff191660019081179091556001600160a01b0380891680865260419094529190932080548f83166001600160a01b03199182161782559381018054851690931790925560028201805491851691909316179091554260038201556004810162004e6c8b8d836200a2de565b50856005820162004e7e82826200a3a6565b508790506009820162004e9282826200a4df565b505042600c8201556001600160a01b038c81166000908152604360205260409081902080546001600160a01b0319169288169290921790915551859060459062004ee0908e908e906200a0ca565b908152602001604051809103902060006101000a8154816001600160a01b0302191690836001600160a01b03160217905550816001600160a01b0316856001600160a01b03168d6001600160a01b03167faecd9fb95e79c75a3a1de93362c6be5fe6ab65770d8614be583884161cd8228d8e8e60405162004f639291906200a5af565b60405180910390a460408051848152602081018590526001600160a01b0387169182917f24d7bda8602b916d64417f0dbfe2e2e88ec9b1157bd9f596dfdb91ba26624e04910160405180910390a360408051670de0b6b3a7640000808252602082015261dead916001600160a01b038816917f24d7bda8602b916d64417f0dbfe2e2e88ec9b1157bd9f596dfdb91ba26624e04910160405180910390a3604051633041949b60e01b815261200590633041949b906200502990859089906004016200a0b0565b600060405180830381600087803b1580156200504457600080fd5b505af115801562005059573d6000803e3d6000fd5b50505050505050505050505050505050565b60408051606081018252600080825260208201819052918101919091528162005096603f8262008c2d565b620050b45760405163056e881160e01b815260040160405180910390fd5b50506001600160a01b031660009081526041602090815260409182902082516060810184526009909101546001600160401b038082168352600160401b8204811693830193909352600160801b90049091169181019190915290565b6001600160a01b038082166000908152604160209081526040808320815161018081018352815486168152600182015486169381019390935260028101549094169082015260038301546060828101919091526004840180549194916080840191906200517d906200a07a565b80601f0160208091040260200160405190810160405280929190818152602001828054620051ab906200a07a565b8015620051fc5780601f10620051d057610100808354040283529160200191620051fc565b820191906000526020600020905b815481529060010190602001808311620051de57829003601f168201915b505050505081526020016005820160405180608001604052908160008201805462005227906200a07a565b80601f016020809104026020016040519081016040528092919081815260200182805462005255906200a07a565b8015620052a65780601f106200527a57610100808354040283529160200191620052a6565b820191906000526020600020905b8154815290600101906020018083116200528857829003601f168201915b50505050508152602001600182018054620052c1906200a07a565b80601f0160208091040260200160405190810160405280929190818152602001828054620052ef906200a07a565b8015620053405780601f10620053145761010080835404028352916020019162005340565b820191906000526020600020905b8154815290600101906020018083116200532257829003601f168201915b505050505081526020016002820180546200535b906200a07a565b80601f016020809104026020016040519081016040528092919081815260200182805462005389906200a07a565b8015620053da5780601f10620053ae57610100808354040283529160200191620053da565b820191906000526020600020905b815481529060010190602001808311620053bc57829003601f168201915b50505050508152602001600382018054620053f5906200a07a565b80601f016020809104026020016040519081016040528092919081815260200182805462005423906200a07a565b8015620054745780601f10620054485761010080835404028352916020019162005474565b820191906000526020600020905b8154815290600101906020018083116200545657829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152600d8301546001600160a01b031660a0830152805161026081019182905260c09092019190600e84019060139082845b815481526020019060010190808311620055135750505091909252505050608001519392505050565b33611001146200556457604051630f22c43960e41b81526110016004820152602401620012e3565b6001600160a01b03808216600090815260436020526040902054166200558c603f8262008c2d565b620055aa5760405163056e881160e01b815260040160405180910390fd5b6001600160a01b038181166000908152604160205260408082206002810154603b54925163045bc4d160e41b81526004810193909352909316906345bc4d10906024016020604051808303816000875af11580156200560d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200563391906200a129565b90506000603d54426200564791906200a113565b905062005655838262008cd8565b836001600160a01b03167f6e9a2ee7aee95665e3a774a212eb11441b217e3e4656ab9563793094689aabb28284600160405162005695939291906200a143565b60405180910390a26002830154604051633041949b60e01b815261200591633041949b91620056d3916001600160a01b03169088906004016200a0b0565b600060405180830381600087803b158015620056ee57600080fd5b505af115801562005703573d6000803e3d6000fd5b505050505050505050565b600054610100900460ff16158080156200572f5750600054600160ff909116105b806200574b5750303b1580156200574b575060005460ff166001145b620057b05760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401620012e3565b6000805460ff191660011790558015620057d4576000805461ff0019166101001790555b334114620057f55760405163022d8c9560e31b815260040160405180910390fd5b3a1562005815576040516383f1b1d360e01b815260040160405180910390fd5b611388603555686c6b935b8bbd400000603655670de0b6b3a7640000603755602d603855607860398190556002603a819055678ac7230489e80000603b55680ad78ebc5ac6200000603c55603d9190915560b4603e55604a556200588d7304d63abcd2b9b1baa327f2dda0f873f197ccd1866200938c565b80156200190e576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150565b3361200014620058fe57604051630f22c43960e41b81526120006004820152602401620012e3565b60405162461bcd60e51b815260206004820152600a60248201526919195c1c9958d85d195960b21b6044820152606401620012e3565b600054630100000090046001600160a01b0316331462005967576040516306fbb1e360e01b815260040160405180910390fd5b60005462010000900460ff16156200599257604051631785c68160e01b815260040160405180910390fd5b6000805462ff00001916620100001781556040517f9e87fac88ff661f02d44f95383c817fece4bce600a3dab7a54406878b965e7529190a1565b6000620059db603f8462008c2d565b620059f95760405163056e881160e01b815260040160405180910390fd5b6001600160a01b0383811660009081526041602052604090819020600201549051636bbf224960e01b815260048101859052911690636bbf2249906024015b602060405180830381865afa15801562005a56573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062005a7c91906200a129565b90505b92915050565b60005462010000900460ff161562005ab057604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff161562005ae25760405163b1d02c3d60e01b815260040160405180910390fd5b8162005af0603f8262008c2d565b62005b0e5760405163056e881160e01b815260040160405180910390fd5b603754349081101562005b345760405163dc6f0bdd60e01b815260040160405180910390fd5b6001600160a01b038085166000908152604160209081526040808320815161018081018352815486168152600182015486169381019390935260028101549094169082015260038301546060820152600483018054339491608084019162005b9c906200a07a565b80601f016020809104026020016040519081016040528092919081815260200182805462005bca906200a07a565b801562005c1b5780601f1062005bef5761010080835404028352916020019162005c1b565b820191906000526020600020905b81548152906001019060200180831162005bfd57829003601f168201915b505050505081526020016005820160405180608001604052908160008201805462005c46906200a07a565b80601f016020809104026020016040519081016040528092919081815260200182805462005c74906200a07a565b801562005cc55780601f1062005c995761010080835404028352916020019162005cc5565b820191906000526020600020905b81548152906001019060200180831162005ca757829003601f168201915b5050505050815260200160018201805462005ce0906200a07a565b80601f016020809104026020016040519081016040528092919081815260200182805462005d0e906200a07a565b801562005d5f5780601f1062005d335761010080835404028352916020019162005d5f565b820191906000526020600020905b81548152906001019060200180831162005d4157829003601f168201915b5050505050815260200160028201805462005d7a906200a07a565b80601f016020809104026020016040519081016040528092919081815260200182805462005da8906200a07a565b801562005df95780601f1062005dcd5761010080835404028352916020019162005df9565b820191906000526020600020905b81548152906001019060200180831162005ddb57829003601f168201915b5050505050815260200160038201805462005e14906200a07a565b80601f016020809104026020016040519081016040528092919081815260200182805462005e42906200a07a565b801562005e935780601f1062005e675761010080835404028352916020019162005e93565b820191906000526020600020905b81548152906001019060200180831162005e7557829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152600d8301546001600160a01b031660a0830152805161026081019182905260c09092019190600e84019060139082845b81548152602001906001019080831162005f325750505050508152505090508060e00151801562005f755750856001600160a01b0316826001600160a01b031614155b1562005f9457604051636468920360e01b815260040160405180910390fd5b60408082015190516317066a5760e21b81526001600160a01b0384811660048301526000921690635c19a95c90869060240160206040518083038185885af115801562005fe5573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906200600c91906200a129565b9050826001600160a01b0316876001600160a01b03167f24d7bda8602b916d64417f0dbfe2e2e88ec9b1157bd9f596dfdb91ba26624e0483876040516200605d929190918252602082015260400190565b60405180910390a36040808301519051633041949b60e01b815261200591633041949b9162006092919087906004016200a0b0565b600060405180830381600087803b158015620060ad57600080fd5b505af1158015620060c2573d6000803e3d6000fd5b50505050851562001907576040516372f6ad8f60e11b81526120059063e5ed5b1e90620060f69086908b906004016200a0b0565b600060405180830381600087803b1580156200611157600080fd5b505af115801562006126573d6000803e3d6000fd5b5050505050505050505050565b60005462010000900460ff16156200615e57604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff1615620061905760405163b1d02c3d60e01b815260040160405180910390fd5b6200619a62008dcc565b620061a7603f8262008c2d565b620061c55760405163056e881160e01b815260040160405180910390fd5b6000620061d162008dcc565b6001600160a01b0381166000908152604f6020526040812080549293509190859003620062a85760005b818110156200627c57836001600160a01b03167f08e60c1b84aab23d99a7262015e647d5ffd6c6e08f78205e1df6774c48e1427a8483815481106200624457620062446200a17e565b90600052602060002001546040516200625f91815260200190565b60405180910390a28062006273816200a194565b915050620061fb565b506001600160a01b0383166000908152604f60205260408120620062a0916200967e565b505050505050565b60005b8581101562006406576000878783818110620062cb57620062cb6200a17e565b90506020020135905060005b83811015620063ee5781858281548110620062f657620062f66200a17e565b906000526020600020015403620063d95784620063156001866200a1b0565b815481106200632857620063286200a17e565b90600052602060002001548582815481106200634857620063486200a17e565b9060005260206000200181905550848054806200636957620063696200a5c5565b6001900381819060005260206000200160009055905583806200638c906200a5db565b945050856001600160a01b03167f08e60c1b84aab23d99a7262015e647d5ffd6c6e08f78205e1df6774c48e1427a83604051620063cb91815260200190565b60405180910390a2620063ee565b80620063e5816200a194565b915050620062d7565b50508080620063fd906200a194565b915050620062ab565b508154600003620062a0576001600160a01b0383166000908152604f60205260408120620062a0916200967e565b505050565b620064656040518060800160405280606081526020016060815260200160608152602001606081525090565b8162006473603f8262008c2d565b620064915760405163056e881160e01b815260040160405180910390fd5b6001600160a01b03831660009081526041602052604090819020815160808101909252600501805482908290620064c8906200a07a565b80601f0160208091040260200160405190810160405280929190818152602001828054620064f6906200a07a565b8015620065475780601f106200651b5761010080835404028352916020019162006547565b820191906000526020600020905b8154815290600101906020018083116200652957829003601f168201915b5050505050815260200160018201805462006562906200a07a565b80601f016020809104026020016040519081016040528092919081815260200182805462006590906200a07a565b8015620065e15780601f10620065b557610100808354040283529160200191620065e1565b820191906000526020600020905b815481529060010190602001808311620065c357829003601f168201915b50505050508152602001600282018054620065fc906200a07a565b80601f01602080910402602001604051908101604052809291908181526020018280546200662a906200a07a565b80156200667b5780601f106200664f576101008083540402835291602001916200667b565b820191906000526020600020905b8154815290600101906020018083116200665d57829003601f168201915b5050505050815260200160038201805462006696906200a07a565b80601f0160208091040260200160405190810160405280929190818152602001828054620066c4906200a07a565b8015620067155780601f10620066e95761010080835404028352916020019162006715565b820191906000526020600020905b815481529060010190602001808311620066f757829003601f168201915b505050505081525050915050919050565b60005462010000900460ff16156200675157604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff1615620067835760405163b1d02c3d60e01b815260040160405180910390fd5b6200678f828262009425565b5050565b3361100714620067bb57604051630f22c43960e41b81526110076004820152602401620012e3565b620068286040518060400160405280601081526020016f1d1c985b9cd9995c91d85cd31a5b5a5d60821b81525085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050620095319050565b15620068e357602081146200685a5783838383604051630a5a604160e01b8152600401620012e394939291906200a5f5565b604080516020601f84018190048102820181019092528281526000916200689d9185858083850183828082843760009201919091525092939250506200958e9050565b90506108fc811080620068b1575061271081115b15620068da5784848484604051630a5a604160e01b8152600401620012e394939291906200a5f5565b60355562007700565b620069546040518060400160405280601481526020017336b4b729b2b6332232b632b3b0ba34b7b721272160611b81525085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050620095319050565b1562006a1e5760208114620069865783838383604051630a5a604160e01b8152600401620012e394939291906200a5f5565b604080516020601f8401819004810282018101909252828152600091620069c99185858083850183828082843760009201919091525092939250506200958e9050565b9050683635c9adc5dea00000811080620069ec575069152d02c7e14af680000081115b1562006a155784848484604051630a5a604160e01b8152600401620012e394939291906200a5f5565b60365562007700565b62006a91604051806040016040528060168152602001756d696e44656c65676174696f6e424e424368616e676560501b81525085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050620095319050565b1562006b58576020811462006ac35783838383604051630a5a604160e01b8152600401620012e394939291906200a5f5565b604080516020601f840181900481028201810190925282815260009162006b069185858083850183828082843760009201919091525092939250506200958e9050565b905067016345785d8a000081108062006b265750678ac7230489e8000081115b1562006b4f5784848484604051630a5a604160e01b8152600401620012e394939291906200a5f5565b60375562007700565b62006bc9604051806040016040528060148152602001736d6178456c656374656456616c696461746f727360601b81525085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050620095319050565b1562006c81576020811462006bfb5783838383604051630a5a604160e01b8152600401620012e394939291906200a5f5565b604080516020601f840181900481028201810190925282815260009162006c3e9185858083850183828082843760009201919091525092939250506200958e9050565b905080158062006c4f57506101f481115b1562006c785784848484604051630a5a604160e01b8152600401620012e394939291906200a5f5565b60385562007700565b62006cea6040518060400160405280600c81526020016b1d5b989bdb9914195c9a5bd960a21b81525085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050620095319050565b1562006da7576020811462006d1c5783838383604051630a5a604160e01b8152600401620012e394939291906200a5f5565b604080516020601f840181900481028201810190925282815260009162006d5f9185858083850183828082843760009201919091525092939250506200958e9050565b90506203f48081108062006d75575062278d0081115b1562006d9e5784848484604051630a5a604160e01b8152600401620012e394939291906200a5f5565b60395562007700565b62006e1560405180604001604052806011815260200170726564656c65676174654665655261746560781b81525085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050620095319050565b1562006ec2576020811462006e475783838383604051630a5a604160e01b8152600401620012e394939291906200a5f5565b604080516020601f840181900481028201810190925282815260009162006e8a9185858083850183828082843760009201919091525092939250506200958e9050565b9050606481111562006eb95784848484604051630a5a604160e01b8152600401620012e394939291906200a5f5565b603a5562007700565b62006f3260405180604001604052806013815260200172191bdddb9d1a5b5954db185cda105b5bdd5b9d606a1b81525085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050620095319050565b1562006ff3576020811462006f645783838383604051630a5a604160e01b8152600401620012e394939291906200a5f5565b604080516020601f840181900481028201810190925282815260009162006fa79185858083850183828082843760009201919091525092939250506200958e9050565b9050674563918244f4000081108062006fc15750603c5481115b1562006fea5784848484604051630a5a604160e01b8152600401620012e394939291906200a5f5565b603b5562007700565b620070616040518060400160405280601181526020017019995b1bdb9e54db185cda105b5bdd5b9d607a1b81525085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050620095319050565b15620071245760208114620070935783838383604051630a5a604160e01b8152600401620012e394939291906200a5f5565b604080516020601f8401819004810282018101909252828152600091620070d69185858083850183828082843760009201919091525092939250506200958e9050565b905068056bc75e2d63100000811080620070f25750603b548111155b156200711b5784848484604051630a5a604160e01b8152600401620012e394939291906200a5f5565b603c5562007700565b620071916040518060400160405280601081526020016f646f776e74696d654a61696c54696d6560801b81525085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050620095319050565b156200724e5760208114620071c35783838383604051630a5a604160e01b8152600401620012e394939291906200a5f5565b604080516020601f8401819004810282018101909252828152600091620072069185858083850183828082843760009201919091525092939250506200958e9050565b90506202a3008110806200721c5750603e548110155b15620072455784848484604051630a5a604160e01b8152600401620012e394939291906200a5f5565b603d5562007700565b620072b96040518060400160405280600e81526020016d66656c6f6e794a61696c54696d6560901b81525085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050620095319050565b15620073765760208114620072eb5783838383604051630a5a604160e01b8152600401620012e394939291906200a5f5565b604080516020601f84018190048102820181019092528281526000916200732e9185858083850183828082843760009201919091525092939250506200958e9050565b9050620d2f00811080620073445750603d548111155b156200736d5784848484604051630a5a604160e01b8152600401620012e394939291906200a5f5565b603e5562007700565b620073f06040518060400160405280601c81526020017f6d617846656c6f6e794265747765656e42726561746865426c6f636b0000000081525085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050620095319050565b156200749c5760208114620074225783838383604051630a5a604160e01b8152600401620012e394939291906200a5f5565b604080516020601f8401819004810282018101909252828152600091620074659185858083850183828082843760009201919091525092939250506200958e9050565b905080600003620074935784848484604051630a5a604160e01b8152600401620012e394939291906200a5f5565b604a5562007700565b6200750a6040518060400160405280601181526020017039ba30b5b2a43ab1283937ba32b1ba37b960791b81525085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050620095319050565b15620075ca57601481146200753c5783838383604051630a5a604160e01b8152600401620012e394939291906200a5f5565b600062007584601484848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092939250506200958e9050565b90506001600160a01b038116620075b85784848484604051630a5a604160e01b8152600401620012e394939291906200a5f5565b620075c38162009593565b5062007700565b620076316040518060400160405280600a8152602001696d61784e6f646549447360b01b81525085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050620095319050565b15620076dd5760208114620076635783838383604051630a5a604160e01b8152600401620012e394939291906200a5f5565b604080516020601f8401819004810282018101909252828152600091620076a69185858083850183828082843760009201919091525092939250506200958e9050565b905080600003620076d45784848484604051630a5a604160e01b8152600401620012e394939291906200a5f5565b604e5562007700565b838383836040516325ee20d560e21b8152600401620012e394939291906200a5f5565b7ff1ce9b2cbf50eeb05769a29e2543fd350cab46894a7dd9978a12d534bb20e633848484846040516200773794939291906200a5f5565b60405180910390a150505050565b60005462010000900460ff16156200777057604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff1615620077a25760405163b1d02c3d60e01b815260040160405180910390fd5b816000816001600160401b03811115620077c057620077c062009853565b604051908082528060200260200182016040528015620077ea578160200160208202803683370190505b5090506000805b83811015620078e857620078338787838181106200781357620078136200a17e565b90506020020160208101906200782a9190620096e4565b603f9062008c2d565b620078515760405163056e881160e01b815260040160405180910390fd5b604160008888848181106200786a576200786a6200a17e565b9050602002016020810190620078819190620096e4565b6001600160a01b0390811682526020820192909252604001600020600201548451911692508290849083908110620078bd57620078bd6200a17e565b6001600160a01b0390921660209283029190910190910152620078e0816200a194565b9050620077f1565b50604051634484077560e01b8152612005906344840775906200331990859088906004016200a1e0565b606080600062007923603f62008f89565b90508085101562007ae75783156200793c57836200793e565b805b93506000846200794f87846200a1b0565b1162007967576200796186836200a1b0565b62007969565b845b9050806001600160401b0381111562007986576200798662009853565b604051908082528060200260200182016040528015620079b0578160200160208202803683370190505b509350806001600160401b03811115620079ce57620079ce62009853565b604051908082528060200260200182016040528015620079f8578160200160208202803683370190505b50925060005b8181101562007ae45762007a17620044d382896200a113565b85828151811062007a2c5762007a2c6200a17e565b60200260200101906001600160a01b031690816001600160a01b0316815250506041600086838151811062007a655762007a656200a17e565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060020160009054906101000a90046001600160a01b031684828151811062007ab95762007ab96200a17e565b6001600160a01b039092166020928302919091019091015262007adc816200a194565b9050620079fe565b50505b9250925092565b60008162007afe603f8262008c2d565b62007b1c5760405163056e881160e01b815260040160405180910390fd5b50506001600160a01b03166000908152604160205260409020600c015490565b336110011462007b6457604051630f22c43960e41b81526110016004820152602401620012e3565b60005462010000900460ff161562007b8f57604051631785c68160e01b815260040160405180910390fd5b6001600160a01b038082166000908152604360205260409020541662007bb7603f8262008c2d565b62007bd55760405163056e881160e01b815260040160405180910390fd5b6001600160a01b03811660009081526041602052604081209062007bfc610258426200a0f0565b604a546000828152604b60205260409020549192501162007c305760405163bd52fcdb60e01b815260040160405180910390fd5b6000818152604b6020526040812080546001929062007c519084906200a113565b90915550506001600160a01b0384166000908152604460205260409020541580159062007ca557506001600160a01b038416600090815260446020526040902054429062007ca390610258906200a113565b105b1562007cc4576040516330abb81d60e21b815260040160405180910390fd5b60008062007cd485600062008c50565b915091508162007cf757604051631b919bb160e11b815260040160405180910390fd5b6002840154603c5460405163045bc4d160e41b815260048101919091526000916001600160a01b0316906345bc4d10906024016020604051808303816000875af115801562007d4a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062007d7091906200a129565b905062007d7e858362008cd8565b856001600160a01b03167f6e9a2ee7aee95665e3a774a212eb11441b217e3e4656ab9563793094689aabb28383600060405162007dbe939291906200a143565b60405180910390a26002850154604051633041949b60e01b815261200591633041949b91620060f6916001600160a01b0316908a906004016200a0b0565b6001600160a01b038082166000908152604160209081526040808320815161018081018352815486168152600182015486169381019390935260028101549094169082015260038301546060820152600483018054929384938493849390929160808401919062007e6d906200a07a565b80601f016020809104026020016040519081016040528092919081815260200182805462007e9b906200a07a565b801562007eec5780601f1062007ec05761010080835404028352916020019162007eec565b820191906000526020600020905b81548152906001019060200180831162007ece57829003601f168201915b505050505081526020016005820160405180608001604052908160008201805462007f17906200a07a565b80601f016020809104026020016040519081016040528092919081815260200182805462007f45906200a07a565b801562007f965780601f1062007f6a5761010080835404028352916020019162007f96565b820191906000526020600020905b81548152906001019060200180831162007f7857829003601f168201915b5050505050815260200160018201805462007fb1906200a07a565b80601f016020809104026020016040519081016040528092919081815260200182805462007fdf906200a07a565b8015620080305780601f10620080045761010080835404028352916020019162008030565b820191906000526020600020905b8154815290600101906020018083116200801257829003601f168201915b505050505081526020016002820180546200804b906200a07a565b80601f016020809104026020016040519081016040528092919081815260200182805462008079906200a07a565b8015620080ca5780601f106200809e57610100808354040283529160200191620080ca565b820191906000526020600020905b815481529060010190602001808311620080ac57829003601f168201915b50505050508152602001600382018054620080e5906200a07a565b80601f016020809104026020016040519081016040528092919081815260200182805462008113906200a07a565b8015620081645780601f10620081385761010080835404028352916020019162008164565b820191906000526020600020905b8154815290600101906020018083116200814657829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152600d8301546001600160a01b031660a0830152805161026081019182905260c09092019190600e84019060139082845b815481526020019060010190808311620082035750505091909252505050606081015160e0820151610100909201519097919650945092505050565b60005462010000900460ff16156200826a57604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff16156200829c5760405163b1d02c3d60e01b815260040160405180910390fd5b620082a662008e2a565b620082b3603f8262008c2d565b620082d15760405163056e881160e01b815260040160405180910390fd5b6000620082dd62008e2a565b6001600160a01b0381166000908152604160205260409020600c8101549192509042906200830f90610258906200a113565b11156200832f57604051631f92cdbd60e11b815260040160405180910390fd5b60058101805462008340906200a07a565b80601f01602080910402602001604051908101604052809291908181526020018280546200836e906200a07a565b8015620083bf5780601f106200839357610100808354040283529160200191620083bf565b820191906000526020600020905b815481529060010190602001808311620083a157829003601f168201915b5050508287525085916005840191508190620083dc90826200a62b565b5060208201516001820190620083f390826200a62b565b50604082015160028201906200840a90826200a62b565b50606082015160038201906200842190826200a62b565b505042600c830155506040516001600160a01b038316907f85d6366b336ade7f106987ec7a8eac1e8799e508aeab045a39d2f63e0dc969d990600090a250505050565b60005462010000900460ff16156200848f57604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff1615620084c15760405163b1d02c3d60e01b815260040160405180910390fd5b828114620084e2576040516341abc80160e01b815260040160405180910390fd5b60005b838110156200855357620085408585838181106200850757620085076200a17e565b90506020020160208101906200851e9190620096e4565b8484848181106200853357620085336200a17e565b9050602002013562009425565b6200854b816200a194565b9050620084e5565b5050505050565b6001600160a01b0380821660009081526041602090815260408083208151610180810183528154861681526001820154861693810193909352600281015490941690820152600383015460608201526004830180549293849390916080840191620085c5906200a07a565b80601f0160208091040260200160405190810160405280929190818152602001828054620085f3906200a07a565b8015620086445780601f10620086185761010080835404028352916020019162008644565b820191906000526020600020905b8154815290600101906020018083116200862657829003601f168201915b50505050508152602001600582016040518060800160405290816000820180546200866f906200a07a565b80601f01602080910402602001604051908101604052809291908181526020018280546200869d906200a07a565b8015620086ee5780601f10620086c257610100808354040283529160200191620086ee565b820191906000526020600020905b815481529060010190602001808311620086d057829003601f168201915b5050505050815260200160018201805462008709906200a07a565b80601f016020809104026020016040519081016040528092919081815260200182805462008737906200a07a565b8015620087885780601f106200875c5761010080835404028352916020019162008788565b820191906000526020600020905b8154815290600101906020018083116200876a57829003601f168201915b50505050508152602001600282018054620087a3906200a07a565b80601f0160208091040260200160405190810160405280929190818152602001828054620087d1906200a07a565b8015620088225780601f10620087f65761010080835404028352916020019162008822565b820191906000526020600020905b8154815290600101906020018083116200880457829003601f168201915b505050505081526020016003820180546200883d906200a07a565b80601f01602080910402602001604051908101604052809291908181526020018280546200886b906200a07a565b8015620088bc5780601f106200889057610100808354040283529160200191620088bc565b820191906000526020600020905b8154815290600101906020018083116200889e57829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152600d8301546001600160a01b031660a0830152805161026081019182905260c09092019190600e84019060139082845b8154815260200190600101908083116200895b5750505091909252505050604001519392505050565b600062008993603f8462008c2d565b620089b15760405163056e881160e01b815260040160405180910390fd5b6001600160a01b038381166000908152604160205260409081902060020154905163aa1966cd60e01b81526004810185905291169063aa1966cd9060240162005a38565b60005462010000900460ff161562008a2057604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff161562008a525760405163b1d02c3d60e01b815260040160405180910390fd5b62008a5c62008e2a565b62008a69603f8262008c2d565b62008a875760405163056e881160e01b815260040160405180910390fd5b600062008a9362008e2a565b905062008aa4818787878762009144565b62008ac257604051631647e3cb60e11b815260040160405180910390fd5b60006001600160a01b03166045878760405162008ae19291906200a0ca565b908152604051908190036020019020546001600160a01b03161462008b19576040516311fdb94760e01b815260040160405180910390fd5b6001600160a01b0381166000908152604160205260409020600c810154429062008b4790610258906200a113565b111562008b6757604051631f92cdbd60e11b815260040160405180910390fd5b4260468260040160405162008b7d91906200a6f3565b908152604051908190036020019020556004810162008b9e8789836200a2de565b5042600c820155604051829060459062008bbc908a908a906200a0ca565b90815260405190819003602001812080546001600160a01b039384166001600160a01b0319909116179055908316907f783156582145bd0ff7924fae6953ba054cf1233eb60739a200ddb10de068ff0d9062008c1c908a908a906200a5af565b60405180910390a250505050505050565b6001600160a01b0381166000908152600183016020526040812054151562005a7c565b6000806000848460405160200162008c6a9291906200a771565b60408051601f1981840301815291815281516020928301206000818152604c9093529120549091504281111562008caa5760008093509350505062002647565b603e5462008cb990426200a113565b6000928352604c60205260409092208290555060019590945092505050565b6000600162008ce8603f62008f89565b62008cf491906200a1b0565b604954108015915062008d405760018301546040516001600160a01b03909116907f2afdc18061ac21cff7d9f11527ab9c8dec6fabd4edf6f894ed634bebd6a20d4590600090a2505050565b82600b015482111562008d5557600b83018290555b600a83015460ff166200643457600a8301805460ff191660019081179091556049805460009062008d889084906200a113565b909155505060018301546040516001600160a01b03909116907f4905ac32602da3fb8b4b7b00c285e5fc4c6c2308cc908b4a1e4e9625a29c90a390600090a2505050565b336000908152604360205260408120546001600160a01b03161562008e085750336000908152604360205260409020546001600160a01b031690565b62008e1262008e2a565b905090565b604e5460000362008e28576005604e555b565b336000908152604d60205260408120546001600160a01b03161562008e665750336000908152604d60205260409020546001600160a01b031690565b503390565b6001600160a01b0381166000908152604160205260409020600a81015460ff161562008e95575050565b6036546002820154604051630913db4760e01b81526001600160a01b03858116600483015290911690630913db4790602401602060405180830381865afa15801562008ee5573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062008f0b91906200a129565b10156200678f5762008f2d81603d544262008f2791906200a113565b62008cd8565b80546040516335409f7f60e01b81526001600160a01b039091166004820152611000906335409f7f90602401600060405180830381600087803b15801562008f7457600080fd5b505af1158015620062a0573d6000803e3d6000fd5b600062005a7f825490565b600062005a7c8383620095ff565b60008082905060038151108062008fba575060098151115b1562008fc95750600092915050565b60418160008151811062008fe15762008fe16200a17e565b016020015160f81c1080620090135750605a816000815181106200900957620090096200a17e565b016020015160f81c115b15620090225750600092915050565b60015b81518110156200913a5760308282815181106200904657620090466200a17e565b016020015160f81c108062009077575060398282815181106200906d576200906d6200a17e565b016020015160f81c115b8015620090c7575060418282815181106200909657620090966200a17e565b016020015160f81c1080620090c75750605a828281518110620090bd57620090bd6200a17e565b016020015160f81c115b80156200911757506061828281518110620090e657620090e66200a17e565b016020015160f81c1080620091175750607a8282815181106200910d576200910d6200a17e565b016020015160f81c115b1562009127575060009392505050565b62009132816200a194565b905062009025565b5060019392505050565b600060308414158062009158575060608214155b1562009167575060006200926b565b6000868686466040516020016200918294939291906200a7bb565b60408051808303601f1901815282825280516020918201208184528383019092529092506000919060208201818036833701905050905081602082015260008186868a8a604051602001620091dc9594939291906200a7e8565b60408051808303601f190181526001808452838301909252925060009190602082018180368337019050509050815160016020830182602086016066600019fa6200922657600080fd5b506000816000815181106200923f576200923f6200a17e565b016020015160f81c90506001811462009261576000955050505050506200926b565b6001955050505050505b95945050505050565b60008061200361dead6040516200928b906200969e565b6001600160a01b03928316815291166020820152606060408201819052600090820152608001604051809103906000f080158015620092ce573d6000803e3d6000fd5b509050806001600160a01b031663f399e22e3486866040518463ffffffff1660e01b8152600401620093029291906200a820565b6000604051808303818588803b1580156200931c57600080fd5b505af115801562009331573d6000803e3d6000fd5b50506040516001600160a01b038086169450881692507fd481492e4e93bb36b4c12a5af93f03be3bf04b454dfbc35dd2663fa26f44d5b09150600090a39392505050565b600062005a7c836001600160a01b0384166200962c565b600054610100900460ff16620093f95760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401620012e3565b600080546001600160a01b039092166301000000026301000000600160b81b0319909216919091179055565b8162009433603f8262008c2d565b620094515760405163056e881160e01b815260040160405180910390fd5b6001600160a01b03838116600090815260416020526040808220600201549051635569f64b60e11b8152336004820152602481018690529192169063aad3ec96906044016020604051808303816000875af1158015620094b5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620094db91906200a129565b9050336001600160a01b0316846001600160a01b03167ff7a40077ff7a04c7e61f6f26fb13774259ddf1b6bce9ecf26a8276cdd3992683836040516200952391815260200190565b60405180910390a350505050565b6000816040516020016200954691906200a846565b60405160208183030381529060405280519060200120836040516020016200956f91906200a846565b6040516020818303038152906040528051906020012014905092915050565b015190565b600080546040516001600160a01b0380851693630100000090930416917f44fc1b38a4abaa91ebd1b628a5b259a698f86238c8217d68f516e87769c60c0b91a3600080546001600160a01b039092166301000000026301000000600160b81b0319909216919091179055565b60008260000182815481106200961957620096196200a17e565b9060005260206000200154905092915050565b6000818152600183016020526040812054620096755750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562005a7f565b50600062005a7f565b50805460008255906000526020600020908101906200190e9190620096ac565b610e96806200a86583390190565b5b80821115620096c35760008155600101620096ad565b5090565b80356001600160a01b0381168114620096df57600080fd5b919050565b600060208284031215620096f757600080fd5b62005a7c82620096c7565b60008083601f8401126200971557600080fd5b5081356001600160401b038111156200972d57600080fd5b6020830191508360208285010111156200264757600080fd5b600080602083850312156200975a57600080fd5b82356001600160401b038111156200977157600080fd5b6200977f8582860162009702565b90969095509350505050565b600080600060408486031215620097a157600080fd5b833560ff81168114620097b357600080fd5b925060208401356001600160401b03811115620097cf57600080fd5b620097dd8682870162009702565b9497909650939450505050565b60005b8381101562009807578181015183820152602001620097ed565b50506000910152565b600081518084526200982a816020860160208601620097ea565b601f01601f19169290920160200192915050565b60208152600062005a7c602083018462009810565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b03811182821017156200988e576200988e62009853565b60405290565b60006001600160401b0380841115620098b157620098b162009853565b604051601f8501601f19908116603f01168101908282118183101715620098dc57620098dc62009853565b81604052809350858152868686011115620098f657600080fd5b858560208301376000602087830101525050509392505050565b6000602082840312156200992357600080fd5b81356001600160401b038111156200993a57600080fd5b8201601f810184136200994c57600080fd5b6200995d8482356020840162009894565b949350505050565b60008083601f8401126200997857600080fd5b5081356001600160401b038111156200999057600080fd5b6020830191508360208260051b85010111156200264757600080fd5b60008060208385031215620099c057600080fd5b82356001600160401b03811115620099d757600080fd5b6200977f8582860162009965565b600081518084526020808501945080840160005b8381101562009a205781516001600160a01b031687529582019590820190600101620099f9565b509495945050505050565b60408152600062009a406040830185620099e5565b6020838203818501528185518084528284019150828160051b8501018388016000805b8481101562009aba57878403601f19018652825180518086529088019088860190845b8181101562009aa45783518352928a0192918a019160010162009a86565b5050968801969450509186019160010162009a63565b50919a9950505050505050505050565b6000806040838503121562009ade57600080fd5b62009ae983620096c7565b946020939093013593505050565b80358015158114620096df57600080fd5b6000806000806080858703121562009b1f57600080fd5b62009b2a85620096c7565b935062009b3a60208601620096c7565b92506040850135915062009b516060860162009af7565b905092959194509250565b6001600160401b03811681146200190e57600080fd5b60006020828403121562009b8557600080fd5b813562009b928162009b5c565b9392505050565b6000806040838503121562009bad57600080fd5b50508035926020909101359150565b60808152600062009bd16080830187620099e5565b82810360208481019190915286518083528782019282019060005b8181101562009c0a5784518352938301939183019160010162009bec565b5050848103604086015286518082528282019350600581901b8201830183890160005b8381101562009c5f57601f1985840301875262009c4c83835162009810565b9686019692509085019060010162009c2d565b5050809550505050505082606083015295945050505050565b600080600080600080600087890360e081121562009c9557600080fd5b62009ca089620096c7565b975060208901356001600160401b038082111562009cbd57600080fd5b62009ccb8c838d0162009702565b909950975060408b013591508082111562009ce557600080fd5b62009cf38c838d0162009702565b90975095508591506060605f198401121562009d0e57600080fd5b60608b01945060c08b013592508083111562009d2957600080fd5b505088016080818b03121562009d3e57600080fd5b8091505092959891949750929550565b6000806040838503121562009d6257600080fd5b62009d6d83620096c7565b915062009d7d6020840162009af7565b90509250929050565b60208152600082516080602084015262009da460a084018262009810565b90506020840151601f198085840301604086015262009dc4838362009810565b9250604086015191508085840301606086015262009de3838362009810565b92506060860151915080858403016080860152506200926b828262009810565b6000806000806040858703121562009e1a57600080fd5b84356001600160401b038082111562009e3257600080fd5b62009e408883890162009702565b9096509450602087013591508082111562009e5a57600080fd5b5062009e698782880162009702565b95989497509550505050565b60008060006040848603121562009e8b57600080fd5b83356001600160401b0381111562009ea257600080fd5b62009eb08682870162009965565b909450925062009ec5905060208501620096c7565b90509250925092565b60608152600062009ee36060830186620099e5565b828103602084015262009ef78186620099e5565b915050826040830152949350505050565b600082601f83011262009f1a57600080fd5b62005a7c8383356020850162009894565b60006020828403121562009f3e57600080fd5b81356001600160401b038082111562009f5657600080fd5b908301906080828603121562009f6b57600080fd5b62009f7562009869565b82358281111562009f8557600080fd5b62009f938782860162009f08565b82525060208301358281111562009fa957600080fd5b62009fb78782860162009f08565b60208301525060408301358281111562009fd057600080fd5b62009fde8782860162009f08565b60408301525060608301358281111562009ff757600080fd5b6200a0058782860162009f08565b60608301525095945050505050565b600080600080604085870312156200a02b57600080fd5b84356001600160401b03808211156200a04357600080fd5b6200a0518883890162009965565b909650945060208701359150808211156200a06b57600080fd5b5062009e698782880162009965565b600181811c908216806200a08f57607f821691505b6020821081036200207957634e487b7160e01b600052602260045260246000fd5b6001600160a01b0392831681529116602082015260400190565b8183823760009101908152919050565b634e487b7160e01b600052601160045260246000fd5b6000826200a10e57634e487b7160e01b600052601260045260246000fd5b500490565b8082018082111562005a7f5762005a7f6200a0da565b6000602082840312156200a13c57600080fd5b5051919050565b8381526020810183905260608101600383106200a17057634e487b7160e01b600052602160045260246000fd5b826040830152949350505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200a1a9576200a1a96200a0da565b5060010190565b8181038181111562005a7f5762005a7f6200a0da565b808202811582820484141762005a7f5762005a7f6200a0da565b6040815260006200a1f56040830185620099e5565b905060018060a01b03831660208301529392505050565b6001600160401b038281168282160390808211156200a22f576200a22f6200a0da565b5092915050565b6000808335601e198436030181126200a24e57600080fd5b8301803591506001600160401b038211156200a26957600080fd5b6020019150368190038213156200264757600080fd5b601f8211156200643457600081815260208120601f850160051c810160208610156200a2a85750805b601f850160051c820191505b81811015620062a0578281556001016200a2b4565b600019600383901b1c191660019190911b1790565b6001600160401b038311156200a2f8576200a2f862009853565b6200a310836200a30983546200a07a565b836200a27f565b6000601f8411600181146200a34357600085156200a32e5750838201355b6200a33a86826200a2c9565b84555062008553565b600083815260209020601f19861690835b828110156200a37657868501358255602094850194600190920191016200a354565b50868210156200a3945760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b6200a3b282836200a236565b6001600160401b038111156200a3cc576200a3cc62009853565b6200a3e4816200a3dd85546200a07a565b856200a27f565b6000601f8211600181146200a41757600083156200a4025750838201355b6200a40e84826200a2c9565b8655506200a474565b600085815260209020601f19841690835b828110156200a44a57868501358255602094850194600190920191016200a428565b50848210156200a4685760001960f88660031b161c19848701351681555b505060018360011b0185555b505050506200a48760208301836200a236565b6200a4978183600186016200a2de565b50506200a4a860408301836200a236565b6200a4b88183600286016200a2de565b50506200a4c960608301836200a236565b6200a4d98183600386016200a2de565b50505050565b81356200a4ec8162009b5c565b6001600160401b03811690508154816001600160401b0319821617835560208401356200a5198162009b5c565b6fffffffffffffffff0000000000000000604091821b166fffffffffffffffffffffffffffffffff198316841781178555908501356200a5598162009b5c565b6001600160c01b0319929092169092179190911760809190911b67ffffffffffffffff60801b1617905550565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6020815260006200995d6020830184866200a586565b634e487b7160e01b600052603160045260246000fd5b6000816200a5ed576200a5ed6200a0da565b506000190190565b6040815260006200a60b6040830186886200a586565b82810360208401526200a6208185876200a586565b979650505050505050565b81516001600160401b038111156200a647576200a64762009853565b6200a65f816200a65884546200a07a565b846200a27f565b602080601f8311600181146200a69357600084156200a67e5750858301515b6200a68a85826200a2c9565b865550620062a0565b600085815260208120601f198616915b828110156200a6c4578886015182559484019460019091019084016200a6a3565b50858210156200a6e35787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60008083546200a703816200a07a565b600182811680156200a71e57600181146200a734576200a765565b60ff19841687528215158302870194506200a765565b8760005260208060002060005b858110156200a75c5781548a8201529084019082016200a741565b50505082870194505b50929695505050505050565b6bffffffffffffffffffffffff198360601b1681526000600383106200a7a757634e487b7160e01b600052602160045260246000fd5b5060f89190911b6014820152601501919050565b6bffffffffffffffffffffffff198560601b16815282846014830137601492019182015260340192915050565b600086516200a7fc818460208b01620097ea565b82018587823760009086019081528385823760009301928352509095945050505050565b6001600160a01b03831681526040602082018190526000906200995d9083018462009810565b600082516200a85a818460208701620097ea565b919091019291505056fe608060405260405162000e9638038062000e96833981016040819052620000269162000497565b828162000036828260006200004d565b50620000449050826200008a565b505050620005ca565b6200005883620000e5565b600082511180620000665750805b1562000085576200008383836200012760201b620001691760201c565b505b505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f620000b562000156565b604080516001600160a01b03928316815291841660208301520160405180910390a1620000e2816200018f565b50565b620000f08162000244565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606200014f838360405180606001604052806027815260200162000e6f60279139620002f8565b9392505050565b60006200018060008051602062000e4f83398151915260001b6200037760201b620001951760201c565b546001600160a01b0316919050565b6001600160a01b038116620001fa5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b806200022360008051602062000e4f83398151915260001b6200037760201b620001951760201c565b80546001600160a01b0319166001600160a01b039290921691909117905550565b6200025a816200037a60201b620001981760201c565b620002be5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401620001f1565b80620002237f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc60001b6200037760201b620001951760201c565b6060600080856001600160a01b03168560405162000317919062000577565b600060405180830381855af49150503d806000811462000354576040519150601f19603f3d011682016040523d82523d6000602084013e62000359565b606091505b5090925090506200036d8683838762000389565b9695505050505050565b90565b6001600160a01b03163b151590565b60608315620003fd578251600003620003f5576001600160a01b0385163b620003f55760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401620001f1565b508162000409565b62000409838362000411565b949350505050565b815115620004225781518083602001fd5b8060405162461bcd60e51b8152600401620001f1919062000595565b80516001600160a01b03811681146200045657600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b838110156200048e57818101518382015260200162000474565b50506000910152565b600080600060608486031215620004ad57600080fd5b620004b8846200043e565b9250620004c8602085016200043e565b60408501519092506001600160401b0380821115620004e657600080fd5b818601915086601f830112620004fb57600080fd5b8151818111156200051057620005106200045b565b604051601f8201601f19908116603f011681019083821181831017156200053b576200053b6200045b565b816040528281528960208487010111156200055557600080fd5b6200056883602083016020880162000471565b80955050505050509250925092565b600082516200058b81846020870162000471565b9190910192915050565b6020815260008251806020840152620005b681604085016020870162000471565b601f01601f19169190910160400192915050565b61087580620005da6000396000f3fe60806040523661001357610011610017565b005b6100115b61001f6101a7565b6001600160a01b0316330361015f5760606001600160e01b0319600035166364d3180d60e11b810161005a576100536101da565b9150610157565b63587086bd60e11b6001600160e01b031982160161007a57610053610231565b63070d7c6960e41b6001600160e01b031982160161009a57610053610277565b621eb96f60e61b6001600160e01b03198216016100b9576100536102a8565b63a39f25e560e01b6001600160e01b03198216016100d9576100536102e8565b60405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b815160208301f35b6101676102fc565b565b606061018e83836040518060600160405280602781526020016108426027913961030c565b9392505050565b90565b6001600160a01b03163b151590565b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b60606101e4610384565b60006101f33660048184610695565b81019061020091906106db565b905061021d8160405180602001604052806000815250600061038f565b505060408051602081019091526000815290565b60606000806102433660048184610695565b810190610250919061070c565b915091506102608282600161038f565b604051806020016040528060008152509250505090565b6060610281610384565b60006102903660048184610695565b81019061029d91906106db565b905061021d816103bb565b60606102b2610384565b60006102bc6101a7565b604080516001600160a01b03831660208201529192500160405160208183030381529060405291505090565b60606102f2610384565b60006102bc610412565b610167610307610412565b610421565b6060600080856001600160a01b03168560405161032991906107f2565b600060405180830381855af49150503d8060008114610364576040519150601f19603f3d011682016040523d82523d6000602084013e610369565b606091505b509150915061037a86838387610445565b9695505050505050565b341561016757600080fd5b610398836104c6565b6000825111806103a55750805b156103b6576103b48383610169565b505b505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6103e46101a7565b604080516001600160a01b03928316815291841660208301520160405180910390a161040f81610506565b50565b600061041c6105af565b905090565b3660008037600080366000845af43d6000803e808015610440573d6000f35b3d6000fd5b606083156104b45782516000036104ad576001600160a01b0385163b6104ad5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161014e565b50816104be565b6104be83836105d7565b949350505050565b6104cf81610601565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6001600160a01b03811661056b5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b606482015260840161014e565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6101cb565b8151156105e75781518083602001fd5b8060405162461bcd60e51b815260040161014e919061080e565b6001600160a01b0381163b61066e5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b606482015260840161014e565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc61058e565b600080858511156106a557600080fd5b838611156106b257600080fd5b5050820193919092039150565b80356001600160a01b03811681146106d657600080fd5b919050565b6000602082840312156106ed57600080fd5b61018e826106bf565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561071f57600080fd5b610728836106bf565b9150602083013567ffffffffffffffff8082111561074557600080fd5b818501915085601f83011261075957600080fd5b81358181111561076b5761076b6106f6565b604051601f8201601f19908116603f01168101908382118183101715610793576107936106f6565b816040528281528860208487010111156107ac57600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b60005b838110156107e95781810151838201526020016107d1565b50506000910152565b600082516108048184602087016107ce565b9190910192915050565b602081526000825180602084015261082d8160408501602087016107ce565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a164736f6c6343000811000ab53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a164736f6c6343000811000a \ No newline at end of file diff --git a/core/systemcontracts/maxwell/types.go b/core/systemcontracts/maxwell/types.go new file mode 100644 index 0000000000..41e41a8de1 --- /dev/null +++ b/core/systemcontracts/maxwell/types.go @@ -0,0 +1,21 @@ +package maxwell + +import _ "embed" + +// contract codes for Mainnet upgrade +var ( + //go:embed mainnet/StakeHubContract + MainnetStakeHubContract string +) + +// contract codes for Chapel upgrade +var ( + //go:embed chapel/StakeHubContract + ChapelStakeHubContract string +) + +// contract codes for Rialto upgrade +var ( + //go:embed rialto/StakeHubContract + RialtoStakeHubContract string +) diff --git a/core/systemcontracts/upgrade.go b/core/systemcontracts/upgrade.go index 543978e053..bd586e148f 100644 --- a/core/systemcontracts/upgrade.go +++ b/core/systemcontracts/upgrade.go @@ -18,6 +18,7 @@ import ( "github.com/ethereum/go-ethereum/core/systemcontracts/kepler" "github.com/ethereum/go-ethereum/core/systemcontracts/lorentz" "github.com/ethereum/go-ethereum/core/systemcontracts/luban" + "github.com/ethereum/go-ethereum/core/systemcontracts/maxwell" "github.com/ethereum/go-ethereum/core/systemcontracts/mirror" "github.com/ethereum/go-ethereum/core/systemcontracts/moran" "github.com/ethereum/go-ethereum/core/systemcontracts/niels" @@ -89,6 +90,8 @@ var ( pascalUpgrade = make(map[string]*Upgrade) lorentzUpgrade = make(map[string]*Upgrade) + + maxwellUpgrade = make(map[string]*Upgrade) ) func init() { @@ -984,13 +987,35 @@ func init() { }, } - lorentzUpgrade[rialtoNet] = &Upgrade{ - UpgradeName: "lorentz", + maxwellUpgrade[mainNet] = &Upgrade{ + UpgradeName: "maxwell", Configs: []*UpgradeConfig{ { - ContractAddr: common.HexToAddress(ValidatorContract), - CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/44ebc6c17a00bd24db3240141a78091528dcebbb", - Code: lorentz.RialtoValidatorContract, + ContractAddr: common.HexToAddress(StakeHubContract), + CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/bf3ac733f8aaf93ed88ca0ad2dcddd051166e4e1", + Code: maxwell.MainnetStakeHubContract, + }, + }, + } + + maxwellUpgrade[chapelNet] = &Upgrade{ + UpgradeName: "maxwell", + Configs: []*UpgradeConfig{ + { + ContractAddr: common.HexToAddress(StakeHubContract), + CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/bf3ac733f8aaf93ed88ca0ad2dcddd051166e4e1", + Code: maxwell.ChapelStakeHubContract, + }, + }, + } + + maxwellUpgrade[rialtoNet] = &Upgrade{ + UpgradeName: "maxwell", + Configs: []*UpgradeConfig{ + { + ContractAddr: common.HexToAddress(StakeHubContract), + CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/bf3ac733f8aaf93ed88ca0ad2dcddd051166e4e1", + Code: maxwell.RialtoStakeHubContract, }, }, } @@ -1105,6 +1130,10 @@ func upgradeBuildInSystemContract(config *params.ChainConfig, blockNumber *big.I applySystemContractUpgrade(lorentzUpgrade[network], blockNumber, statedb, logger) } + if config.IsOnMaxwell(blockNumber, lastBlockTime, blockTime) { + applySystemContractUpgrade(maxwellUpgrade[network], blockNumber, statedb, logger) + } + /* apply other upgrades */ diff --git a/core/txpool/legacypool/legacypool.go b/core/txpool/legacypool/legacypool.go index 56b3fc7329..a8d16fb33c 100644 --- a/core/txpool/legacypool/legacypool.go +++ b/core/txpool/legacypool/legacypool.go @@ -70,6 +70,10 @@ var ( // transactions is reached for specific accounts. ErrInflightTxLimitReached = errors.New("in-flight transaction limit reached for delegated accounts") + // ErrOutOfOrderTxFromDelegated is returned when the transaction with gapped + // nonce received from the accounts with delegation or pending delegation. + ErrOutOfOrderTxFromDelegated = errors.New("gapped-nonce tx from delegated accounts") + // ErrAuthorityReserved is returned if a transaction has an authorization // signed by an address which already has in-flight transactions known to the // pool. @@ -693,33 +697,39 @@ func (pool *LegacyPool) validateTx(tx *types.Transaction) error { return pool.validateAuth(tx) } +// checkDelegationLimit determines if the tx sender is delegated or has a +// pending delegation, and if so, ensures they have at most one in-flight +// **executable** transaction, e.g. disallow stacked and gapped transactions +// from the account. +func (pool *LegacyPool) checkDelegationLimit(tx *types.Transaction) error { + from, _ := types.Sender(pool.signer, tx) // validated + + // Short circuit if the sender has neither delegation nor pending delegation. + if pool.currentState.GetCodeHash(from) == types.EmptyCodeHash && pool.all.delegationTxsCount(from) == 0 { + return nil + } + pending := pool.pending[from] + if pending == nil { + // Transaction with gapped nonce is not supported for delegated accounts + if pool.pendingNonces.get(from) != tx.Nonce() { + return ErrOutOfOrderTxFromDelegated + } + return nil + } + // Transaction replacement is supported + if pending.Contains(tx.Nonce()) { + return nil + } + return ErrInflightTxLimitReached +} + // validateAuth verifies that the transaction complies with code authorization // restrictions brought by SetCode transaction type. func (pool *LegacyPool) validateAuth(tx *types.Transaction) error { - from, _ := types.Sender(pool.signer, tx) // validated - // Allow at most one in-flight tx for delegated accounts or those with a // pending authorization. - if pool.currentState.GetCodeHash(from) != types.EmptyCodeHash || len(pool.all.auths[from]) != 0 { - var ( - count int - exists bool - ) - pending := pool.pending[from] - if pending != nil { - count += pending.Len() - exists = pending.Contains(tx.Nonce()) - } - queue := pool.queue[from] - if queue != nil { - count += queue.Len() - exists = exists || queue.Contains(tx.Nonce()) - } - // Replace the existing in-flight transaction for delegated accounts - // are still supported - if count >= 1 && !exists { - return ErrInflightTxLimitReached - } + if err := pool.checkDelegationLimit(tx); err != nil { + return err } // Authorities cannot conflict with any pending or queued transactions. if auths := tx.SetCodeAuthorities(); len(auths) > 0 { @@ -1937,6 +1947,13 @@ func (t *lookup) removeAuthorities(tx *types.Transaction) { } } +// delegationTxsCount returns the number of pending authorizations for the specified address. +func (t *lookup) delegationTxsCount(addr common.Address) int { + t.lock.RLock() + defer t.lock.RUnlock() + return len(t.auths[addr]) +} + // numSlots calculates the number of slots needed for a single transaction. func numSlots(tx *types.Transaction) int { return int((tx.Size() + txSlotSize - 1) / txSlotSize) diff --git a/core/txpool/legacypool/legacypool_test.go b/core/txpool/legacypool/legacypool_test.go index 8e3b6dc45a..e559da794d 100644 --- a/core/txpool/legacypool/legacypool_test.go +++ b/core/txpool/legacypool/legacypool_test.go @@ -2363,6 +2363,11 @@ func TestSetCodeTransactions(t *testing.T) { aa := common.Address{0xaa, 0xaa} statedb.SetCode(addrA, append(types.DelegationPrefix, aa.Bytes()...)) statedb.SetCode(aa, []byte{byte(vm.ADDRESS), byte(vm.PUSH0), byte(vm.SSTORE)}) + + // Send gapped transaction, it should be rejected. + if err := pool.addRemoteSync(pricedTransaction(2, 100000, big.NewInt(1), keyA)); !errors.Is(err, ErrOutOfOrderTxFromDelegated) { + t.Fatalf("%s: error mismatch: want %v, have %v", name, ErrOutOfOrderTxFromDelegated, err) + } // Send transactions. First is accepted, second is rejected. if err := pool.addRemoteSync(pricedTransaction(0, 100000, big.NewInt(1), keyA)); err != nil { t.Fatalf("%s: failed to add remote transaction: %v", name, err) @@ -2370,7 +2375,7 @@ func TestSetCodeTransactions(t *testing.T) { if err := pool.addRemoteSync(pricedTransaction(1, 100000, big.NewInt(1), keyA)); !errors.Is(err, ErrInflightTxLimitReached) { t.Fatalf("%s: error mismatch: want %v, have %v", name, ErrInflightTxLimitReached, err) } - // Also check gapped transaction. + // Check gapped transaction again. if err := pool.addRemoteSync(pricedTransaction(2, 100000, big.NewInt(1), keyA)); !errors.Is(err, ErrInflightTxLimitReached) { t.Fatalf("%s: error mismatch: want %v, have %v", name, ErrInflightTxLimitReached, err) } diff --git a/core/types/transaction.go b/core/types/transaction.go index f47d354056..cd0de9c99f 100644 --- a/core/types/transaction.go +++ b/core/types/transaction.go @@ -100,6 +100,9 @@ type TxData interface { encode(*bytes.Buffer) error decode([]byte) error + + // sigHash returns the hash of the transaction that is ought to be signed + sigHash(*big.Int) common.Hash } // EncodeRLP implements rlp.Encoder diff --git a/core/types/transaction_signing.go b/core/types/transaction_signing.go index 030fc472a0..89c08aeddd 100644 --- a/core/types/transaction_signing.go +++ b/core/types/transaction_signing.go @@ -233,20 +233,7 @@ func (s pragueSigner) Hash(tx *Transaction) common.Hash { if tx.Type() != SetCodeTxType { return s.cancunSigner.Hash(tx) } - return prefixedRlpHash( - tx.Type(), - []interface{}{ - s.chainId, - tx.Nonce(), - tx.GasTipCap(), - tx.GasFeeCap(), - tx.Gas(), - tx.To(), - tx.Value(), - tx.Data(), - tx.AccessList(), - tx.SetCodeAuthorizations(), - }) + return tx.inner.sigHash(s.chainId) } type cancunSigner struct{ londonSigner } @@ -301,21 +288,7 @@ func (s cancunSigner) Hash(tx *Transaction) common.Hash { if tx.Type() != BlobTxType { return s.londonSigner.Hash(tx) } - return prefixedRlpHash( - tx.Type(), - []interface{}{ - s.chainId, - tx.Nonce(), - tx.GasTipCap(), - tx.GasFeeCap(), - tx.Gas(), - tx.To(), - tx.Value(), - tx.Data(), - tx.AccessList(), - tx.BlobGasFeeCap(), - tx.BlobHashes(), - }) + return tx.inner.sigHash(s.chainId) } type londonSigner struct{ eip2930Signer } @@ -369,19 +342,7 @@ func (s londonSigner) Hash(tx *Transaction) common.Hash { if tx.Type() != DynamicFeeTxType { return s.eip2930Signer.Hash(tx) } - return prefixedRlpHash( - tx.Type(), - []interface{}{ - s.chainId, - tx.Nonce(), - tx.GasTipCap(), - tx.GasFeeCap(), - tx.Gas(), - tx.To(), - tx.Value(), - tx.Data(), - tx.AccessList(), - }) + return tx.inner.sigHash(s.chainId) } type eip2930Signer struct{ EIP155Signer } @@ -444,18 +405,7 @@ func (s eip2930Signer) Hash(tx *Transaction) common.Hash { case LegacyTxType: return s.EIP155Signer.Hash(tx) case AccessListTxType: - return prefixedRlpHash( - tx.Type(), - []interface{}{ - s.chainId, - tx.Nonce(), - tx.GasPrice(), - tx.Gas(), - tx.To(), - tx.Value(), - tx.Data(), - tx.AccessList(), - }) + return tx.inner.sigHash(s.chainId) default: // This _should_ not happen, but in case someone sends in a bad // json struct via RPC, it's probably more prudent to return an @@ -525,15 +475,7 @@ func (s EIP155Signer) SignatureValues(tx *Transaction, sig []byte) (R, S, V *big // Hash returns the hash to be signed by the sender. // It does not uniquely identify the transaction. func (s EIP155Signer) Hash(tx *Transaction) common.Hash { - return rlpHash([]interface{}{ - tx.Nonce(), - tx.GasPrice(), - tx.Gas(), - tx.To(), - tx.Value(), - tx.Data(), - s.chainId, uint(0), uint(0), - }) + return tx.inner.sigHash(s.chainId) } // HomesteadSigner implements Signer interface using the @@ -597,7 +539,7 @@ func (fs FrontierSigner) SignatureValues(tx *Transaction, sig []byte) (r, s, v * // Hash returns the hash to be signed by the sender. // It does not uniquely identify the transaction. func (fs FrontierSigner) Hash(tx *Transaction) common.Hash { - return rlpHash([]interface{}{ + return rlpHash([]any{ tx.Nonce(), tx.GasPrice(), tx.Gas(), diff --git a/core/types/transaction_test.go b/core/types/transaction_test.go index 17a7dda357..8922448d97 100644 --- a/core/types/transaction_test.go +++ b/core/types/transaction_test.go @@ -576,3 +576,20 @@ func TestYParityJSONUnmarshalling(t *testing.T) { } } } + +func BenchmarkHash(b *testing.B) { + signer := NewLondonSigner(big.NewInt(1)) + to := common.Address{} + tx := NewTx(&DynamicFeeTx{ + ChainID: big.NewInt(123), + Nonce: 1, + Gas: 1000000, + To: &to, + Value: big.NewInt(1), + GasTipCap: big.NewInt(500), + GasFeeCap: big.NewInt(500), + }) + for i := 0; i < b.N; i++ { + signer.Hash(tx) + } +} diff --git a/core/types/tx_access_list.go b/core/types/tx_access_list.go index 730a77b752..915de9a8ab 100644 --- a/core/types/tx_access_list.go +++ b/core/types/tx_access_list.go @@ -127,3 +127,18 @@ func (tx *AccessListTx) encode(b *bytes.Buffer) error { func (tx *AccessListTx) decode(input []byte) error { return rlp.DecodeBytes(input, tx) } + +func (tx *AccessListTx) sigHash(chainID *big.Int) common.Hash { + return prefixedRlpHash( + AccessListTxType, + []any{ + chainID, + tx.Nonce, + tx.GasPrice, + tx.Gas, + tx.To, + tx.Value, + tx.Data, + tx.AccessList, + }) +} diff --git a/core/types/tx_blob.go b/core/types/tx_blob.go index 9edf17d088..d9d7ac5871 100644 --- a/core/types/tx_blob.go +++ b/core/types/tx_blob.go @@ -242,3 +242,21 @@ func (tx *BlobTx) decode(input []byte) error { } return nil } + +func (tx *BlobTx) sigHash(chainID *big.Int) common.Hash { + return prefixedRlpHash( + BlobTxType, + []any{ + chainID, + tx.Nonce, + tx.GasTipCap, + tx.GasFeeCap, + tx.Gas, + tx.To, + tx.Value, + tx.Data, + tx.AccessList, + tx.BlobFeeCap, + tx.BlobHashes, + }) +} diff --git a/core/types/tx_dynamic_fee.go b/core/types/tx_dynamic_fee.go index 981755cf70..bba81464f8 100644 --- a/core/types/tx_dynamic_fee.go +++ b/core/types/tx_dynamic_fee.go @@ -123,3 +123,19 @@ func (tx *DynamicFeeTx) encode(b *bytes.Buffer) error { func (tx *DynamicFeeTx) decode(input []byte) error { return rlp.DecodeBytes(input, tx) } + +func (tx *DynamicFeeTx) sigHash(chainID *big.Int) common.Hash { + return prefixedRlpHash( + DynamicFeeTxType, + []any{ + chainID, + tx.Nonce, + tx.GasTipCap, + tx.GasFeeCap, + tx.Gas, + tx.To, + tx.Value, + tx.Data, + tx.AccessList, + }) +} diff --git a/core/types/tx_legacy.go b/core/types/tx_legacy.go index 71025b78fc..49f0a98809 100644 --- a/core/types/tx_legacy.go +++ b/core/types/tx_legacy.go @@ -123,3 +123,16 @@ func (tx *LegacyTx) encode(*bytes.Buffer) error { func (tx *LegacyTx) decode([]byte) error { panic("decode called on LegacyTx)") } + +// OBS: This is the post-EIP155 hash, the pre-EIP155 does not contain a chainID. +func (tx *LegacyTx) sigHash(chainID *big.Int) common.Hash { + return rlpHash([]any{ + tx.Nonce, + tx.GasPrice, + tx.Gas, + tx.To, + tx.Value, + tx.Data, + chainID, uint(0), uint(0), + }) +} diff --git a/core/types/tx_setcode.go b/core/types/tx_setcode.go index 01e4ea6ac7..a85c744cfe 100644 --- a/core/types/tx_setcode.go +++ b/core/types/tx_setcode.go @@ -223,3 +223,20 @@ func (tx *SetCodeTx) encode(b *bytes.Buffer) error { func (tx *SetCodeTx) decode(input []byte) error { return rlp.DecodeBytes(input, tx) } + +func (tx *SetCodeTx) sigHash(chainID *big.Int) common.Hash { + return prefixedRlpHash( + SetCodeTxType, + []any{ + chainID, + tx.Nonce, + tx.GasTipCap, + tx.GasFeeCap, + tx.Gas, + tx.To, + tx.Value, + tx.Data, + tx.AccessList, + tx.AuthList, + }) +} diff --git a/core/vm/instructions.go b/core/vm/instructions.go index c9eea33507..ba76a1b935 100644 --- a/core/vm/instructions.go +++ b/core/vm/instructions.go @@ -971,6 +971,23 @@ func opPush1(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]by return nil, nil } +// opPush2 is a specialized version of pushN +func opPush2(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + var ( + codeLen = uint64(len(scope.Contract.Code)) + integer = new(uint256.Int) + ) + if *pc+2 < codeLen { + scope.Stack.push(integer.SetBytes2(scope.Contract.Code[*pc+1 : *pc+3])) + } else if *pc+1 < codeLen { + scope.Stack.push(integer.SetUint64(uint64(scope.Contract.Code[*pc+1]) << 8)) + } else { + scope.Stack.push(integer.Clear()) + } + *pc += 2 + return nil, nil +} + // make push instruction function func makePush(size uint64, pushByteSize int) executionFunc { return func(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { diff --git a/core/vm/jump_table.go b/core/vm/jump_table.go index 299ee4c558..8ab0a6c8cc 100644 --- a/core/vm/jump_table.go +++ b/core/vm/jump_table.go @@ -631,7 +631,7 @@ func newFrontierInstructionSet() JumpTable { maxStack: maxStack(0, 1), }, PUSH2: { - execute: makePush(2, 2), + execute: opPush2, constantGas: GasFastestStep, minStack: minStack(0, 1), maxStack: maxStack(0, 1), diff --git a/core/vote/vote_manager.go b/core/vote/vote_manager.go index 841dae4c3f..e1effef60f 100644 --- a/core/vote/vote_manager.go +++ b/core/vote/vote_manager.go @@ -17,7 +17,12 @@ import ( "github.com/ethereum/go-ethereum/metrics" ) -const blocksNumberSinceMining = 5 // the number of blocks need to wait before voting, counting from the validator begin to mine +// Many validators maintain backup machines. +// When switching from a primary node to a backup (e.g., due to failure), +// the new node may cast votes for the same block height that the previous node already voted on. +// To avoid double-voting issues, the node should wait for a few blocks +// before participating in voting after it starts mining. +const blocksNumberSinceMining = 20 var diffInTurn = big.NewInt(2) // Block difficulty for in-turn signatures var votesManagerCounter = metrics.NewRegisteredCounter("votesManager/local", nil) diff --git a/core/vote/vote_pool_test.go b/core/vote/vote_pool_test.go index 8fb3f3daec..0e7e2a98d1 100644 --- a/core/vote/vote_pool_test.go +++ b/core/vote/vote_pool_test.go @@ -123,11 +123,10 @@ func (journal *VoteJournal) verifyJournal(size, lastLatestVoteNumber int) bool { lastIndex, _ := journal.walLog.LastIndex() firstIndex, _ := journal.walLog.FirstIndex() if int(lastIndex)-int(firstIndex)+1 == size { - return true - } - lastVote, _ := journal.ReadVote(lastIndex) - if lastVote != nil && lastVote.Data.TargetNumber == uint64(lastLatestVoteNumber) { - return true + lastVote, _ := journal.ReadVote(lastIndex) + if lastVote != nil && lastVote.Data.TargetNumber == uint64(lastLatestVoteNumber)+blocksNumberSinceMining { + return true + } } } return false @@ -283,10 +282,10 @@ func testVotePool(t *testing.T, isValidRules bool) { t.Fatalf("journal failed") } - // Test future votes scenario: votes number within latestBlockHeader ~ latestBlockHeader + 13 + // Test future votes scenario: votes number within latestBlockHeader ~ latestBlockHeader + 11 futureVote := &types.VoteEnvelope{ Data: &types.VoteData{ - TargetNumber: 279, + TargetNumber: 294, }, } if err := voteManager.signer.SignVote(futureVote); err != nil { @@ -306,7 +305,7 @@ func testVotePool(t *testing.T, isValidRules bool) { // Test duplicate vote case, shouldn'd be put into vote pool duplicateVote := &types.VoteEnvelope{ Data: &types.VoteData{ - TargetNumber: 279, + TargetNumber: 294, }, } if err := voteManager.signer.SignVote(duplicateVote); err != nil { @@ -335,14 +334,14 @@ func testVotePool(t *testing.T, isValidRules bool) { t.Fatalf("put vote failed") } - // Test transfer votes from future to cur, latest block header is #288 after the following generation + // Test transfer votes from future to cur, latest block header is #308 after the following generation // For the above BlockNumber 279, it did not have blockHash, should be assigned as well below. - curNumber := 268 + curNumber := 288 var futureBlockHash common.Hash for i := 0; i < 20; i++ { bs, _ = core.GenerateChain(params.TestChainConfig, bs[len(bs)-1], ethash.NewFaker(), db, 1, nil) curNumber += 1 - if curNumber == 279 { + if curNumber == 294 { futureBlockHash = bs[0].Hash() futureVotesMap := votePool.futureVotes voteBox := futureVotesMap[common.Hash{}] diff --git a/eth/backend.go b/eth/backend.go index 9c84faeee9..0352cd70f8 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -18,6 +18,7 @@ package eth import ( + "context" "encoding/json" "errors" "fmt" @@ -130,8 +131,8 @@ type Ethereum struct { shutdownTracker *shutdowncheck.ShutdownTracker // Tracks if and when the node has shutdown ungracefully - votePool *vote.VotePool - stopReportCh chan struct{} + votePool *vote.VotePool + stopCh chan struct{} } // New creates a new Ethereum object (including the initialisation of the common Ethereum object), @@ -252,7 +253,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { p2pServer: stack.Server(), discmix: enode.NewFairMix(0), shutdownTracker: shutdowncheck.NewShutdownTracker(chainDb), - stopReportCh: make(chan struct{}, 1), + stopCh: make(chan struct{}), } eth.APIBackend = &EthAPIBackend{stack.Config().ExtRPCEnabled(), stack.Config().AllowUnprotectedTxs, eth, nil} @@ -372,18 +373,22 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { // Permit the downloader to use the trie cache allowance during fast sync cacheLimit := cacheConfig.TrieCleanLimit + cacheConfig.TrieDirtyLimit + cacheConfig.SnapshotLimit if eth.handler, err = newHandler(&handlerConfig{ - NodeID: eth.p2pServer.Self().ID(), - Database: chainDb, - Chain: eth.blockchain, - TxPool: eth.txPool, - Network: networkID, - Sync: config.SyncMode, - BloomCache: uint64(cacheLimit), - EventMux: eth.eventMux, - RequiredBlocks: config.RequiredBlocks, - DirectBroadcast: config.DirectBroadcast, - DisablePeerTxBroadcast: config.DisablePeerTxBroadcast, - PeerSet: peers, + NodeID: eth.p2pServer.Self().ID(), + Database: chainDb, + Chain: eth.blockchain, + TxPool: eth.txPool, + Network: networkID, + Sync: config.SyncMode, + BloomCache: uint64(cacheLimit), + EventMux: eth.eventMux, + RequiredBlocks: config.RequiredBlocks, + DirectBroadcast: config.DirectBroadcast, + EnableEVNFeatures: stack.Config().EnableEVNFeatures, + EVNNodeIdsWhitelist: stack.Config().P2P.EVNNodeIdsWhitelist, + ProxyedValidatorNodeIDs: stack.Config().P2P.ProxyedValidatorNodeIDs, + DisablePeerTxBroadcast: config.DisablePeerTxBroadcast, + PeerSet: peers, + EnableQuickBlockFetching: stack.Config().EnableQuickBlockFetching, }); err != nil { return nil, err } @@ -516,6 +521,158 @@ func (s *Ethereum) SetEtherbase(etherbase common.Address) { s.miner.SetEtherbase(etherbase) } +// waitForSyncAndMaxwell waits for the node to be fully synced and Maxwell fork to be active +func (s *Ethereum) waitForSyncAndMaxwell(parlia *parlia.Parlia) { + ticker := time.NewTicker(30 * time.Second) + defer ticker.Stop() + retryCount := 0 + for { + select { + case <-s.stopCh: + return + case <-ticker.C: + if !s.Synced() { + continue + } + // Check if Maxwell fork is active + header := s.blockchain.CurrentHeader() + if header == nil { + continue + } + chainConfig := s.blockchain.Config() + if !chainConfig.IsMaxwell(header.Number, header.Time) { + continue + } + log.Info("Node is synced and Maxwell fork is active, proceeding with node ID registration") + err := s.updateNodeID(parlia) + if err == nil { + return + } + retryCount++ + if retryCount > 3 { + log.Error("Failed to update node ID exceed max retry count", "retryCount", retryCount, "err", err) + return + } + } + } +} + +// updateNodeID registers the node ID with the StakeHub contract +func (s *Ethereum) updateNodeID(parlia *parlia.Parlia) error { + nonce, err := s.APIBackend.GetPoolNonce(context.Background(), s.etherbase) + if err != nil { + return fmt.Errorf("failed to get nonce: %v", err) + } + + // Get currently registered node IDs + registeredIDs, err := parlia.GetNodeIDs() + if err != nil { + log.Error("Failed to get registered node IDs", "err", err) + return err + } + + // Create a set of registered IDs for quick lookup + registeredSet := make(map[enode.ID]struct{}, len(registeredIDs)) + for _, id := range registeredIDs { + registeredSet[id] = struct{}{} + } + + // Handle removals first + if err := s.handleRemovals(parlia, nonce, registeredSet); err != nil { + return err + } + nonce++ + + // Handle additions + return s.handleAdditions(parlia, nonce, registeredSet) +} + +func (s *Ethereum) handleRemovals(parlia *parlia.Parlia, nonce uint64, registeredSet map[enode.ID]struct{}) error { + if len(s.config.EVNNodeIDsToRemove) == 0 { + return nil + } + + // Handle wildcard removal + if len(s.config.EVNNodeIDsToRemove) == 1 { + var zeroID enode.ID // This will be all zeros + if s.config.EVNNodeIDsToRemove[0] == zeroID { + trx, err := parlia.RemoveNodeIDs([]enode.ID{}, nonce) + if err != nil { + return fmt.Errorf("failed to create node ID removal transaction: %v", err) + } + if err := s.txPool.Add([]*types.Transaction{trx}, false); err != nil { + return fmt.Errorf("failed to add node ID removal transaction to pool: %v", err) + } + log.Info("Submitted node ID removal transaction for all node IDs") + return nil + } + } + + // Create a set of node IDs to add for quick lookup + addSet := make(map[enode.ID]struct{}, len(s.config.EVNNodeIDsToAdd)) + for _, id := range s.config.EVNNodeIDsToAdd { + addSet[id] = struct{}{} + } + + // Filter out node IDs that are in the add set + nodeIDsToRemove := make([]enode.ID, 0, len(s.config.EVNNodeIDsToRemove)) + for _, id := range s.config.EVNNodeIDsToRemove { + if _, exists := registeredSet[id]; exists { + if _, exists := addSet[id]; !exists { + nodeIDsToRemove = append(nodeIDsToRemove, id) + } else { + log.Debug("Skipping node ID removal", "id", id, "reason", "also in EVNNodeIDsToAdd") + } + } else { + log.Debug("Skipping node ID removal", "id", id, "reason", "not registered") + } + } + + if len(nodeIDsToRemove) == 0 { + log.Debug("No node IDs to remove after filtering") + return nil + } + + trx, err := parlia.RemoveNodeIDs(nodeIDsToRemove, nonce) + if err != nil { + return fmt.Errorf("failed to create node ID removal transaction: %v", err) + } + if errs := s.txPool.Add([]*types.Transaction{trx}, false); len(errs) > 0 && errs[0] != nil { + return fmt.Errorf("failed to add node ID removal transaction to pool: %v", errs) + } + log.Info("Submitted node ID removal transaction", "nodeIDs", nodeIDsToRemove) + return nil +} + +func (s *Ethereum) handleAdditions(parlia *parlia.Parlia, nonce uint64, registeredSet map[enode.ID]struct{}) error { + if len(s.config.EVNNodeIDsToAdd) == 0 { + return nil + } + + // Filter out already registered IDs in a single pass + nodeIDsToAdd := make([]enode.ID, 0, len(s.config.EVNNodeIDsToAdd)) + for _, id := range s.config.EVNNodeIDsToAdd { + if _, exists := registeredSet[id]; !exists { + nodeIDsToAdd = append(nodeIDsToAdd, id) + } + } + + if len(nodeIDsToAdd) == 0 { + log.Info("No new node IDs to register after deduplication") + return nil + } + + trx, err := parlia.AddNodeIDs(nodeIDsToAdd, nonce) + if err != nil { + return fmt.Errorf("failed to create node ID registration transaction: %v", err) + } + if errs := s.txPool.Add([]*types.Transaction{trx}, false); len(errs) > 0 && errs[0] != nil { + return fmt.Errorf("failed to add node ID registration transaction to pool: %v", errs) + } + log.Info("Submitted node ID registration transaction", "nodeIDs", nodeIDsToAdd) + return nil +} + // StartMining starts the miner with the given number of CPU threads. If mining // is already running, this method adjust the number of threads allowed to use // and updates the minimum price required by the transaction pool. @@ -541,6 +698,11 @@ func (s *Ethereum) StartMining() error { return fmt.Errorf("signer missing: %v", err) } parlia.Authorize(eb, wallet.SignData, wallet.SignTx) + + // Start a goroutine to handle node ID registration after sync + go func() { + s.waitForSyncAndMaxwell(parlia) + }() } go s.miner.Start() @@ -692,7 +854,7 @@ func (s *Ethereum) Stop() error { s.eventMux.Stop() // stop report loop - s.stopReportCh <- struct{}{} + close(s.stopCh) return nil } @@ -763,7 +925,7 @@ func (s *Ethereum) reportRecentBlocksLoop() { if startMiningTime < blockMsTime { startMiningTimer.Update(time.Duration(blockMsTime - startMiningTime)) } - case <-s.stopReportCh: + case <-s.stopCh: return } } diff --git a/eth/downloader/downloader.go b/eth/downloader/downloader.go index 788474cb49..50e20a4536 100644 --- a/eth/downloader/downloader.go +++ b/eth/downloader/downloader.go @@ -506,6 +506,8 @@ func (d *Downloader) syncWithPeer(p *peerConnection, hash common.Hash, td, ttd * return errLaggingPeer } } + + log.Debug("try sync chain from peer", "remote", p.id, "local", localHeight, "remote", remoteHeight) d.syncStatsLock.Lock() if d.syncStatsChainHeight <= origin || d.syncStatsChainOrigin > origin { d.syncStatsChainOrigin = origin diff --git a/eth/ethconfig/config.go b/eth/ethconfig/config.go index de3fc353c1..1ec64a122d 100644 --- a/eth/ethconfig/config.go +++ b/eth/ethconfig/config.go @@ -35,6 +35,7 @@ import ( "github.com/ethereum/go-ethereum/internal/ethapi" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/miner/minerconfig" + "github.com/ethereum/go-ethereum/p2p/enode" "github.com/ethereum/go-ethereum/params" ) @@ -93,7 +94,8 @@ type Config struct { // transactions) or is continuously under high pressure (e.g., mempool is always full), then you can consider // to turn it on. DisablePeerTxBroadcast bool - + EVNNodeIDsToAdd []enode.ID + EVNNodeIDsToRemove []enode.ID // This can be set to list of enrtree:// URLs which will be queried for // nodes to connect to. EthDiscoveryURLs []string diff --git a/eth/ethconfig/gen_config.go b/eth/ethconfig/gen_config.go index b834241706..8089b03538 100644 --- a/eth/ethconfig/gen_config.go +++ b/eth/ethconfig/gen_config.go @@ -11,6 +11,7 @@ import ( "github.com/ethereum/go-ethereum/core/txpool/legacypool" "github.com/ethereum/go-ethereum/eth/gasprice" "github.com/ethereum/go-ethereum/miner/minerconfig" + "github.com/ethereum/go-ethereum/p2p/enode" ) // MarshalTOML marshals as TOML. @@ -20,6 +21,8 @@ func (c Config) MarshalTOML() (interface{}, error) { NetworkId uint64 SyncMode SyncMode DisablePeerTxBroadcast bool + EVNNodeIDsToAdd []enode.ID + EVNNodeIDsToRemove []enode.ID EthDiscoveryURLs []string SnapDiscoveryURLs []string TrustDiscoveryURLs []string @@ -74,6 +77,8 @@ func (c Config) MarshalTOML() (interface{}, error) { enc.NetworkId = c.NetworkId enc.SyncMode = c.SyncMode enc.DisablePeerTxBroadcast = c.DisablePeerTxBroadcast + enc.EVNNodeIDsToAdd = c.EVNNodeIDsToAdd + enc.EVNNodeIDsToRemove = c.EVNNodeIDsToRemove enc.EthDiscoveryURLs = c.EthDiscoveryURLs enc.SnapDiscoveryURLs = c.SnapDiscoveryURLs enc.TrustDiscoveryURLs = c.TrustDiscoveryURLs @@ -132,6 +137,8 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error { NetworkId *uint64 SyncMode *SyncMode DisablePeerTxBroadcast *bool + EVNNodeIDsToAdd []enode.ID + EVNNodeIDsToRemove []enode.ID EthDiscoveryURLs []string SnapDiscoveryURLs []string TrustDiscoveryURLs []string @@ -197,6 +204,12 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error { if dec.DisablePeerTxBroadcast != nil { c.DisablePeerTxBroadcast = *dec.DisablePeerTxBroadcast } + if dec.EVNNodeIDsToAdd != nil { + c.EVNNodeIDsToAdd = dec.EVNNodeIDsToAdd + } + if dec.EVNNodeIDsToRemove != nil { + c.EVNNodeIDsToRemove = dec.EVNNodeIDsToRemove + } if dec.EthDiscoveryURLs != nil { c.EthDiscoveryURLs = dec.EthDiscoveryURLs } diff --git a/eth/fetcher/block_fetcher.go b/eth/fetcher/block_fetcher.go index 72e49d862a..312cf08c80 100644 --- a/eth/fetcher/block_fetcher.go +++ b/eth/fetcher/block_fetcher.go @@ -67,6 +67,12 @@ var ( bodyFilterInMeter = metrics.NewRegisteredMeter("eth/fetcher/block/filter/bodies/in", nil) bodyFilterOutMeter = metrics.NewRegisteredMeter("eth/fetcher/block/filter/bodies/out", nil) + legacyBlockFetchingTimer = metrics.NewRegisteredTimer("eth/fetcher/block/legacy/cost", nil) + quickBlockFetchingTimer = metrics.NewRegisteredTimer("eth/fetcher/block/quick/cost", nil) + quickBlockFetchingErrMeter = metrics.NewRegisteredMeter("eth/fetcher/block/quick/err", nil) + quickBlockFetchingFallbackMeter = metrics.NewRegisteredMeter("eth/fetcher/block/quick/fallback", nil) + quickBlockFetchingSuccessMeter = metrics.NewRegisteredMeter("eth/fetcher/block/quick/success", nil) + blockInsertFailRecords = mapset.NewSet[common.Hash]() blockInsertFailRecordslimit = 1000 blockInsertFailGauge = metrics.NewRegisteredGauge("chain/insert/failed", nil) @@ -99,6 +105,9 @@ type chainInsertFn func(types.Blocks) (int, error) // peerDropFn is a callback type for dropping a peer detected as malicious. type peerDropFn func(id string) +// fetchRangeBlocksFn is a callback type for fetching a range of blocks from a peer. +type fetchRangeBlocksFn func(peer string, startHeight uint64, startHash common.Hash, count uint64) ([]*types.Block, error) + // blockAnnounce is the hash notification of the availability of a new block in the // network. type blockAnnounce struct { @@ -138,6 +147,14 @@ type blockOrHeaderInject struct { block *types.Block // Used for normal mode fetcher which imports full block. } +type BlockFetchingEntry struct { + announce *blockAnnounce + + // results + blocks []*types.Block + err error +} + // number returns the block number of the injected object. func (inject *blockOrHeaderInject) number() uint64 { if inject.header != nil { @@ -161,8 +178,9 @@ type BlockFetcher struct { notify chan *blockAnnounce inject chan *blockOrHeaderInject - headerFilter chan chan *headerFilterTask - bodyFilter chan chan *bodyFilterTask + headerFilter chan chan *headerFilterTask + bodyFilter chan chan *bodyFilterTask + quickBlockFetchingCh chan *BlockFetchingEntry done chan common.Hash quit chan struct{} @@ -189,6 +207,7 @@ type BlockFetcher struct { chainFinalizedHeight chainFinalizedHeightFn // Retrieves the current chain's finalized height insertChain chainInsertFn // Injects a batch of blocks into the chain dropPeer peerDropFn // Drops a peer for misbehaving + fetchRangeBlocks fetchRangeBlocksFn // Fetches a range of blocks from a peer // Testing hooks announceChangeHook func(common.Hash, bool) // Method to call upon adding or deleting a hash from the blockAnnounce list @@ -200,12 +219,14 @@ type BlockFetcher struct { // NewBlockFetcher creates a block fetcher to retrieve blocks based on hash announcements. func NewBlockFetcher(getBlock blockRetrievalFn, verifyHeader headerVerifierFn, broadcastBlock blockBroadcasterFn, - chainHeight chainHeightFn, chainFinalizedHeight chainFinalizedHeightFn, insertChain chainInsertFn, dropPeer peerDropFn) *BlockFetcher { + chainHeight chainHeightFn, chainFinalizedHeight chainFinalizedHeightFn, insertChain chainInsertFn, dropPeer peerDropFn, + fetchRangeBlocks fetchRangeBlocksFn) *BlockFetcher { return &BlockFetcher{ notify: make(chan *blockAnnounce), inject: make(chan *blockOrHeaderInject), headerFilter: make(chan chan *headerFilterTask), bodyFilter: make(chan chan *bodyFilterTask), + quickBlockFetchingCh: make(chan *BlockFetchingEntry), done: make(chan common.Hash), quit: make(chan struct{}), requeue: make(chan *blockOrHeaderInject), @@ -224,6 +245,7 @@ func NewBlockFetcher(getBlock blockRetrievalFn, verifyHeader headerVerifierFn, b chainFinalizedHeight: chainFinalizedHeight, insertChain: insertChain, dropPeer: dropPeer, + fetchRangeBlocks: fetchRangeBlocks, } } @@ -329,6 +351,21 @@ func (f *BlockFetcher) FilterBodies(peer string, transactions [][]*types.Transac } } +func (f *BlockFetcher) asyncFetchRangeBlocks(announce *blockAnnounce) { + go func() { + if f.fetchRangeBlocks == nil { + return + } + log.Debug("Quick block fetching", "peer", announce.origin, "hash", announce.hash) + blocks, err := f.fetchRangeBlocks(announce.origin, announce.number, announce.hash, 1) + f.quickBlockFetchingCh <- &BlockFetchingEntry{ + announce: announce, + blocks: blocks, + err: err, + } + }() +} + // Loop is the main fetcher loop, checking and processing various notification // events. func (f *BlockFetcher) loop() { @@ -417,6 +454,12 @@ func (f *BlockFetcher) loop() { if f.announceChangeHook != nil && len(f.announced[notification.hash]) == 1 { f.announceChangeHook(notification.hash, true) } + // if there enable range fetching, just request the first announce and wait for response, + // and if it gets timeout and wait for later header & body fetching. + if f.fetchRangeBlocks != nil && len(f.announced[notification.hash]) == 1 { + f.asyncFetchRangeBlocks(notification) + } + // schedule the first arrive announce hash if len(f.announced) == 1 { f.rescheduleFetch(fetchTimer) } @@ -468,7 +511,7 @@ func (f *BlockFetcher) loop() { } // Send out all block header requests for peer, hashes := range request { - log.Trace("Fetching scheduled headers", "peer", peer, "list", hashes) + log.Debug("Fetching scheduled headers", "peer", peer, "list", hashes) // Create a closure of the fetch and schedule in on a new thread fetchHeader := f.fetching[hashes[0]].fetchHeader @@ -477,6 +520,9 @@ func (f *BlockFetcher) loop() { if f.fetchingHook != nil { f.fetchingHook(hashes) } + if f.fetchRangeBlocks != nil { + quickBlockFetchingFallbackMeter.Mark(1) + } for _, hash := range hashes { headerFetchMeter.Mark(1) go func(hash common.Hash) { @@ -527,7 +573,7 @@ func (f *BlockFetcher) loop() { } // Send out all block body requests for peer, hashes := range request { - log.Trace("Fetching scheduled bodies", "peer", peer, "list", hashes) + log.Debug("Fetching scheduled bodies", "peer", peer, "list", hashes) // Create a closure of the fetch and schedule in on a new thread if f.completingHook != nil { @@ -717,7 +763,33 @@ func (f *BlockFetcher) loop() { for _, block := range blocks { if announce := f.completing[block.Hash()]; announce != nil { f.enqueue(announce.origin, nil, block) + legacyBlockFetchingTimer.UpdateSince(announce.time) + } + } + case entry := <-f.quickBlockFetchingCh: + annHash := entry.announce.hash + // if there is error or timeout, and the shcedule have not started, just retry the fetch + if entry.err != nil { + quickBlockFetchingErrMeter.Mark(1) + log.Debug("Quick block fetching err", "hash", annHash, "err", entry.err) + if _, ok := f.fetching[annHash]; !ok && len(f.announced[annHash]) > 1 { + // Pick the last peer to retrieve from, but ignore the current one + next := f.announced[annHash][len(f.announced[annHash])-1] + if next.origin != entry.announce.origin { + f.asyncFetchRangeBlocks(next) + } + } + continue + } + quickBlockFetchingSuccessMeter.Mark(1) + for _, block := range entry.blocks { + hash := block.Hash() + f.forgetHash(hash) + if f.getBlock(hash) != nil { + continue } + f.enqueue(entry.announce.origin, nil, block) + quickBlockFetchingTimer.UpdateSince(entry.announce.time) } } } diff --git a/eth/fetcher/block_fetcher_test.go b/eth/fetcher/block_fetcher_test.go index 36dda2ccb4..0ff06a3231 100644 --- a/eth/fetcher/block_fetcher_test.go +++ b/eth/fetcher/block_fetcher_test.go @@ -19,6 +19,7 @@ package fetcher import ( "errors" "math/big" + "os" "sync" "sync/atomic" "testing" @@ -31,6 +32,7 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/eth/protocols/eth" + "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/trie" "github.com/ethereum/go-ethereum/triedb" @@ -103,7 +105,10 @@ func newTester() *fetcherTester { drops: make(map[string]bool), } tester.fetcher = NewBlockFetcher(tester.getBlock, tester.verifyHeader, tester.broadcastBlock, - tester.chainHeight, tester.chainFinalizedHeight, tester.insertChain, tester.dropPeer) + tester.chainHeight, tester.chainFinalizedHeight, tester.insertChain, tester.dropPeer, + func(peer string, startHeight uint64, startHash common.Hash, count uint64) ([]*types.Block, error) { + return nil, errors.New("not implemented") + }) tester.fetcher.Start() return tester @@ -935,3 +940,385 @@ func TestBlockMemoryExhaustionAttack(t *testing.T) { } verifyImportDone(t, imported) } + +// mockBlockRetriever simulates block retrieval from the local chain +type mockBlockRetriever struct { + blocks map[common.Hash]*types.Block +} + +func newMockBlockRetriever() *mockBlockRetriever { + return &mockBlockRetriever{ + blocks: make(map[common.Hash]*types.Block), + } +} + +func (m *mockBlockRetriever) getBlock(hash common.Hash) *types.Block { + return m.blocks[hash] +} + +// mockHeaderRequester simulates header requests +type mockHeaderRequester struct { + headers map[common.Hash]*types.Header + delay time.Duration +} + +func newMockHeaderRequester(delay time.Duration) *mockHeaderRequester { + return &mockHeaderRequester{ + headers: make(map[common.Hash]*types.Header), + delay: delay, + } +} + +func (m *mockHeaderRequester) requestHeader(hash common.Hash, ch chan *eth.Response) (*eth.Request, error) { + go func() { + time.Sleep(m.delay) + if header, ok := m.headers[hash]; ok { + ch <- ð.Response{ + Res: ð.BlockHeadersRequest{header}, + } + } else { + ch <- ð.Response{ + Res: ð.BlockHeadersRequest{}, + } + } + }() + return ð.Request{}, nil +} + +// mockBodyRequester simulates body requests +type mockBodyRequester struct { + bodies map[common.Hash]*types.Body + delay time.Duration +} + +func newMockBodyRequester(delay time.Duration) *mockBodyRequester { + return &mockBodyRequester{ + bodies: make(map[common.Hash]*types.Body), + delay: delay, + } +} + +func (m *mockBodyRequester) requestBodies(hashes []common.Hash, ch chan *eth.Response) (*eth.Request, error) { + go func() { + time.Sleep(m.delay) + var bodies []*eth.BlockBody + for _, hash := range hashes { + if body, ok := m.bodies[hash]; ok { + bodies = append(bodies, ð.BlockBody{ + Transactions: body.Transactions, + Uncles: body.Uncles, + }) + } + } + ch <- ð.Response{ + Res: (*eth.BlockBodiesResponse)(&bodies), + } + }() + return ð.Request{}, nil +} + +// TestBlockFetcherMultiplePeers tests block synchronization between multiple peers +func TestBlockFetcherMultiplePeers(t *testing.T) { + // Setup test environment + log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(os.Stdout, log.LevelTrace, true))) + + // Create test blocks + parent := types.NewBlock(&types.Header{ + Number: big.NewInt(1), + ParentHash: common.Hash{}, + }, nil, nil, nil) + block := types.NewBlock(&types.Header{ + Number: big.NewInt(2), + ParentHash: parent.Hash(), + }, nil, nil, nil) + + // Create block storage + blockStore := make(map[common.Hash]*types.Block) + blockStore[parent.Hash()] = parent + + // Create fetcher + fetcher := NewBlockFetcher( + // getBlock + func(hash common.Hash) *types.Block { + return blockStore[hash] + }, + // verifyHeader + func(header *types.Header) error { + return nil + }, + // broadcastBlock + func(block *types.Block, propagate bool) {}, + // chainHeight - returns the height of the highest block in the chain + func() uint64 { + var maxHeight uint64 = 0 + for _, block := range blockStore { + height := block.NumberU64() + if height > maxHeight { + maxHeight = height + } + } + return maxHeight + }, + // chainFinalizedHeight + func() uint64 { return 0 }, + // insertChain + func(blocks types.Blocks) (int, error) { + for _, b := range blocks { + blockStore[b.Hash()] = b + } + return len(blocks), nil + }, + // dropPeer + func(id string) {}, + // fetchRangeBlocks + func(peer string, startHeight uint64, startHash common.Hash, count uint64) ([]*types.Block, error) { + return nil, errors.New("not implemented") + }, + ) + + // Start fetcher + fetcher.Start() + defer fetcher.Stop() + + // Test case 1: Normal download process + t.Run("normal download", func(t *testing.T) { + // Create request functions + headerRequester := func(hash common.Hash, sink chan *eth.Response) (*eth.Request, error) { + go func() { + // Return requested header + headers := []*types.Header{block.Header()} + res := ð.Response{ + Req: ð.Request{}, + Res: (*eth.BlockHeadersRequest)(&headers), + Done: make(chan error, 1), + } + sink <- res + }() + return ð.Request{}, nil + } + + bodyRequester := func(hashes []common.Hash, sink chan *eth.Response) (*eth.Request, error) { + go func() { + // Return requested body + bodies := make([]*eth.BlockBody, 0) + for _, hash := range hashes { + if hash == block.Hash() { + bodies = append(bodies, ð.BlockBody{ + Transactions: block.Transactions(), + Uncles: block.Uncles(), + }) + } + } + res := ð.Response{ + Req: ð.Request{}, + Res: (*eth.BlockBodiesResponse)(&bodies), + Done: make(chan error, 1), + } + sink <- res + }() + return ð.Request{}, nil + } + + // Peer1 sends block notification + err := fetcher.Notify("peer1", block.Hash(), block.NumberU64(), time.Now(), + headerRequester, bodyRequester) + if err != nil { + t.Fatalf("Notify failed: %v", err) + } + + // Wait for the block to be processed + for i := 0; i < 20; i++ { + time.Sleep(50 * time.Millisecond) + if blockStore[block.Hash()] != nil { + break + } + } + + // Verify if the block was downloaded correctly + if fetchedBlock := blockStore[block.Hash()]; fetchedBlock == nil { + t.Error("Block was not downloaded") + } + }) + + // Test case 2: Download timeout + t.Run("download timeout", func(t *testing.T) { + // Create a header requester with timeout + slowHeaderRequester := func(hash common.Hash, sink chan *eth.Response) (*eth.Request, error) { + go func() { + // Intentionally not returning any content, simulating timeout + time.Sleep(2 * fetchTimeout) + }() + return ð.Request{}, nil + } + + bodyRequester := func(hashes []common.Hash, sink chan *eth.Response) (*eth.Request, error) { + go func() { + // This won't be called + }() + return ð.Request{}, nil + } + + // Peer2 sends block notification + err := fetcher.Notify("peer2", block.Hash(), block.NumberU64(), time.Now(), + slowHeaderRequester, bodyRequester) + if err != nil { + t.Fatalf("Notify failed: %v", err) + } + + // Wait for timeout + time.Sleep(fetchTimeout + 100*time.Millisecond) + }) + + // Test case 3: Simplified single block notification test + t.Run("single block announcement", func(t *testing.T) { + // Create a new block + newBlock := types.NewBlock(&types.Header{ + Number: big.NewInt(3), + ParentHash: block.Hash(), // Parent block is from the previous test + }, nil, nil, nil) + + // Create request functions + headerRequester := func(hash common.Hash, sink chan *eth.Response) (*eth.Request, error) { + go func() { + // Return requested header + headers := []*types.Header{newBlock.Header()} + res := ð.Response{ + Req: ð.Request{}, + Res: (*eth.BlockHeadersRequest)(&headers), + Done: make(chan error, 1), + } + sink <- res + }() + return ð.Request{}, nil + } + + bodyRequester := func(hashes []common.Hash, sink chan *eth.Response) (*eth.Request, error) { + go func() { + // Return requested body + bodies := make([]*eth.BlockBody, 0) + for _, hash := range hashes { + if hash == newBlock.Hash() { + bodies = append(bodies, ð.BlockBody{ + Transactions: newBlock.Transactions(), + Uncles: newBlock.Uncles(), + }) + } + } + res := ð.Response{ + Req: ð.Request{}, + Res: (*eth.BlockBodiesResponse)(&bodies), + Done: make(chan error, 1), + } + sink <- res + }() + return ð.Request{}, nil + } + + // Send block notification + err := fetcher.Notify("peer1", newBlock.Hash(), newBlock.NumberU64(), time.Now(), + headerRequester, bodyRequester) + if err != nil { + t.Fatalf("Notify failed: %v", err) + } + + // Wait for the block to be processed + for i := 0; i < 20; i++ { + time.Sleep(50 * time.Millisecond) + if blockStore[newBlock.Hash()] != nil { + break + } + } + + // Verify if the block was downloaded correctly + if fetchedBlock := blockStore[newBlock.Hash()]; fetchedBlock == nil { + t.Error("New block was not downloaded") + } + }) +} + +// TestQuickBlockFetching tests the quick block fetching feature +func TestQuickBlockFetching(t *testing.T) { + // Setup test environment + log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(os.Stdout, log.LevelInfo, true))) + + // Create mock block retriever + blockRetriever := newMockBlockRetriever() + headerRequester := newMockHeaderRequester(50 * time.Millisecond) + bodyRequester := newMockBodyRequester(50 * time.Millisecond) + + // Create blockchain + parent := types.NewBlock(&types.Header{ + Number: big.NewInt(10), + ParentHash: common.Hash{}, + }, nil, nil, nil) + blockRetriever.blocks[parent.Hash()] = parent + + // Generate child block + block := types.NewBlock(&types.Header{ + Number: big.NewInt(11), + ParentHash: parent.Hash(), + }, nil, nil, nil) + + // Prepare quick fetching response + var fetchRangeBlocksCalled atomic.Bool + var fetchRangeBlocksHash common.Hash + var fetchRangeBlocksNumber uint64 + + // Create fetcher with quick block fetching support + fetcher := NewBlockFetcher( + blockRetriever.getBlock, + func(header *types.Header) error { return nil }, + func(block *types.Block, propagate bool) {}, + func() uint64 { return 10 }, // Current height + func() uint64 { return 5 }, // Finalized height + func(blocks types.Blocks) (int, error) { + // Add blocks to local blockchain + for _, block := range blocks { + blockRetriever.blocks[block.Hash()] = block + } + return len(blocks), nil + }, + func(id string) {}, + // fetchRangeBlocks function simulates quick block fetching + func(peer string, startHeight uint64, startHash common.Hash, count uint64) ([]*types.Block, error) { + fetchRangeBlocksCalled.Store(true) + fetchRangeBlocksHash = startHash + fetchRangeBlocksNumber = startHeight + + // Return requested block + return []*types.Block{block}, nil + }, + ) + + // Start fetcher + fetcher.Start() + defer fetcher.Stop() + + // Send block notification + err := fetcher.Notify("peer1", block.Hash(), block.NumberU64(), time.Now(), + headerRequester.requestHeader, bodyRequester.requestBodies) + if err != nil { + t.Fatalf("Notify failed: %v", err) + } + + // Wait for block to be fetched via quick path + time.Sleep(200 * time.Millisecond) + + // Verify if fetchRangeBlocks was called + if !fetchRangeBlocksCalled.Load() { + t.Error("fetchRangeBlocks was not called") + } + + // Verify if fetchRangeBlocks parameters are correct + if fetchRangeBlocksHash != block.Hash() { + t.Errorf("Expected hash %s, got %s", block.Hash().String(), fetchRangeBlocksHash.String()) + } + if fetchRangeBlocksNumber != block.NumberU64() { + t.Errorf("Expected number %d, got %d", block.NumberU64(), fetchRangeBlocksNumber) + } + + // Verify if block was imported correctly + if fetchedBlock := blockRetriever.getBlock(block.Hash()); fetchedBlock == nil { + t.Error("Block was not imported through quick block fetching") + } +} diff --git a/eth/handler.go b/eth/handler.go index 8f65f502e5..0e435837f1 100644 --- a/eth/handler.go +++ b/eth/handler.go @@ -18,6 +18,7 @@ package eth import ( "errors" + "fmt" "math" "math/big" "strings" @@ -27,6 +28,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/consensus/beacon" + "github.com/ethereum/go-ethereum/consensus/parlia" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/forkid" "github.com/ethereum/go-ethereum/core/monitor" @@ -113,26 +115,33 @@ type votePool interface { // handlerConfig is the collection of initialization parameters to create a full // node network handler. type handlerConfig struct { - NodeID enode.ID // P2P node ID used for tx propagation topology - Database ethdb.Database // Database for direct sync insertions - Chain *core.BlockChain // Blockchain to serve data from - TxPool txPool // Transaction pool to propagate from - VotePool votePool - Network uint64 // Network identifier to adfvertise - Sync ethconfig.SyncMode // Whether to snap or full sync - BloomCache uint64 // Megabytes to alloc for snap sync bloom - EventMux *event.TypeMux // Legacy event mux, deprecate for `feed` - RequiredBlocks map[uint64]common.Hash // Hard coded map of required block hashes for sync challenges - DirectBroadcast bool - DisablePeerTxBroadcast bool - PeerSet *peerSet + NodeID enode.ID // P2P node ID used for tx propagation topology + Database ethdb.Database // Database for direct sync insertions + Chain *core.BlockChain // Blockchain to serve data from + TxPool txPool // Transaction pool to propagate from + VotePool votePool + Network uint64 // Network identifier to adfvertise + Sync ethconfig.SyncMode // Whether to snap or full sync + BloomCache uint64 // Megabytes to alloc for snap sync bloom + EventMux *event.TypeMux // Legacy event mux, deprecate for `feed` + RequiredBlocks map[uint64]common.Hash // Hard coded map of required block hashes for sync challenges + DirectBroadcast bool + DisablePeerTxBroadcast bool + PeerSet *peerSet + EnableQuickBlockFetching bool + EnableEVNFeatures bool + EVNNodeIdsWhitelist []enode.ID + ProxyedValidatorNodeIDs []enode.ID } type handler struct { - nodeID enode.ID - networkID uint64 - forkFilter forkid.Filter // Fork ID filter, constant across the lifetime of the node - disablePeerTxBroadcast bool + nodeID enode.ID + networkID uint64 + forkFilter forkid.Filter // Fork ID filter, constant across the lifetime of the node + disablePeerTxBroadcast bool + enableEVNFeatures bool + evnNodeIdsWhitelistMap map[enode.ID]struct{} + proxyedValidatorNodeIDMap map[enode.ID]struct{} snapSync atomic.Bool // Flag whether snap sync is enabled (gets disabled if we already have blocks) synced atomic.Bool // Flag whether we're considered synchronised (enables transaction processing) @@ -187,23 +196,32 @@ func newHandler(config *handlerConfig) (*handler, error) { config.PeerSet = newPeerSet() // Nicety initialization for tests } h := &handler{ - nodeID: config.NodeID, - networkID: config.Network, - forkFilter: forkid.NewFilter(config.Chain), - disablePeerTxBroadcast: config.DisablePeerTxBroadcast, - eventMux: config.EventMux, - database: config.Database, - txpool: config.TxPool, - votepool: config.VotePool, - chain: config.Chain, - peers: config.PeerSet, - peersPerIP: make(map[string]int), - requiredBlocks: config.RequiredBlocks, - directBroadcast: config.DirectBroadcast, - quitSync: make(chan struct{}), - handlerDoneCh: make(chan struct{}), - handlerStartCh: make(chan struct{}), - stopCh: make(chan struct{}), + nodeID: config.NodeID, + networkID: config.Network, + forkFilter: forkid.NewFilter(config.Chain), + disablePeerTxBroadcast: config.DisablePeerTxBroadcast, + eventMux: config.EventMux, + database: config.Database, + txpool: config.TxPool, + votepool: config.VotePool, + chain: config.Chain, + peers: config.PeerSet, + peersPerIP: make(map[string]int), + requiredBlocks: config.RequiredBlocks, + directBroadcast: config.DirectBroadcast, + enableEVNFeatures: config.EnableEVNFeatures, + evnNodeIdsWhitelistMap: make(map[enode.ID]struct{}), + proxyedValidatorNodeIDMap: make(map[enode.ID]struct{}), + quitSync: make(chan struct{}), + handlerDoneCh: make(chan struct{}), + handlerStartCh: make(chan struct{}), + stopCh: make(chan struct{}), + } + for _, nodeID := range config.EVNNodeIdsWhitelist { + h.evnNodeIdsWhitelistMap[nodeID] = struct{}{} + } + for _, nodeID := range config.ProxyedValidatorNodeIDs { + h.proxyedValidatorNodeIDMap[nodeID] = struct{}{} } if config.Sync == ethconfig.FullSync { // The database seems empty as the current block is the genesis. Yet the snap @@ -294,8 +312,48 @@ func newHandler(config *handlerConfig) (*handler, error) { h.BroadcastBlock(block, propagate) } + fetchRangeBlocks := func(peer string, startHeight uint64, startHash common.Hash, count uint64) ([]*types.Block, error) { + p := h.peers.peer(peer) + if p == nil { + return nil, errors.New("peer not found") + } + if p.bscExt == nil { + return nil, fmt.Errorf("peer does not support bsc protocol, peer: %v", p.ID()) + } + if p.bscExt.Version() != bsc.Bsc2 { + return nil, fmt.Errorf("remote peer does not support the required Bsc2 protocol version, peer: %v", p.ID()) + } + res, err := p.bscExt.RequestBlocksByRange(startHeight, startHash, count) + if err != nil { + return nil, err + } + + blocks := make([]*types.Block, len(res)) + for i, item := range res { + block := types.NewBlockWithHeader(item.Header).WithBody(types.Body{Transactions: item.Txs, Uncles: item.Uncles}) + block = block.WithSidecars(item.Sidecars) + block.ReceivedAt = time.Now() + if err := block.SanityCheck(); err != nil { + return nil, err + } + if len(block.Sidecars()) > 0 { + for _, sidecar := range block.Sidecars() { + if err := sidecar.SanityCheck(block.Number(), block.Hash()); err != nil { + return nil, err + } + } + } + blocks[i] = block + } + return blocks, err + } + + if !config.EnableQuickBlockFetching { + fetchRangeBlocks = nil + } + h.blockFetcher = fetcher.NewBlockFetcher(h.chain.GetBlockByHash, validator, broadcastBlockWithCheck, - heighter, finalizeHeighter, inserter, h.removePeer) + heighter, finalizeHeighter, inserter, h.removePeer, fetchRangeBlocks) fetchTx := func(peer string, hashes []common.Hash) error { p := h.peers.peer(peer) @@ -328,6 +386,8 @@ func newHandler(config *handlerConfig) (*handler, error) { // protoTracker tracks the number of active protocol handlers. func (h *handler) protoTracker() { defer h.wg.Done() + updateTicker := time.NewTicker(10 * time.Second) + defer updateTicker.Stop() var active int for { select { @@ -335,6 +395,12 @@ func (h *handler) protoTracker() { active++ case <-h.handlerDoneCh: active-- + case <-updateTicker.C: + if h.enableEVNFeatures { + // add onchain validator p2p node list later, it will enable the direct broadcast + no tx broadcast feature + // here check & enable peer broadcast features periodically, and it's a simple way to handle the peer change and the list change scenarios. + h.peers.enableEVNFeatures(h.queryValidatorNodeIDsMap(), h.evnNodeIdsWhitelistMap, h.proxyedValidatorNodeIDMap) + } case <-h.quitSync: // Wait for all active handlers to finish. for ; active > 0; active-- { @@ -767,21 +833,78 @@ func (h *handler) BroadcastBlock(block *types.Block, propagate bool) { } for _, peer := range transfer { + log.Debug("broadcast block to peer", "hash", hash, "peer", peer.ID(), "ProxyedValidatorFlag", peer.ProxyedValidatorFlag.Load(), "EVNPeerFlag", peer.EVNPeerFlag.Load()) peer.AsyncSendNewBlock(block, td) } - log.Trace("Propagated block", "hash", hash, "recipients", len(transfer), "duration", common.PrettyDuration(time.Since(block.ReceivedAt))) + // check if the block should be broadcast to more peers in EVN + fullBroadcastInEVN := h.needFullBroadcastInEVN(block) + var morePeers []*ethPeer + for i := len(transfer); i < len(peers); i++ { + if peers[i].ProxyedValidatorFlag.Load() { + morePeers = append(morePeers, peers[i]) + continue + } + if fullBroadcastInEVN && peers[i].EVNPeerFlag.Load() { + morePeers = append(morePeers, peers[i]) + continue + } + } + for _, peer := range morePeers { + log.Debug("broadcast block to extra peer", "hash", hash, "peer", peer.ID(), "ProxyedValidatorFlag", peer.ProxyedValidatorFlag.Load(), "EVNPeerFlag", peer.EVNPeerFlag.Load()) + peer.AsyncSendNewBlock(block, td) + } + + log.Trace("Propagated block", "hash", hash, "recipients", len(transfer), "extra", len(morePeers), "duration", common.PrettyDuration(time.Since(block.ReceivedAt))) return } // Otherwise if the block is indeed in our own chain, announce it if h.chain.HasBlock(hash, block.NumberU64()) { for _, peer := range peers { + log.Debug("Announced block to peer", "hash", hash, "peer", peer.ID(), "ProxyedValidatorFlag", peer.ProxyedValidatorFlag.Load(), "EVNPeerFlag", peer.EVNPeerFlag.Load()) peer.AsyncSendNewBlockHash(block) } log.Trace("Announced block", "hash", hash, "recipients", len(peers), "duration", common.PrettyDuration(time.Since(block.ReceivedAt))) } } +// needFullBroadcastInEVN checks if the block should be broadcast to EVN peers +// if the block is mined by self or received from proxyed validator, just broadcast to all EVN peers +// if not, skip it. +func (h *handler) needFullBroadcastInEVN(block *types.Block) bool { + if !h.enableEVNFeatures { + return false + } + parlia, ok := h.chain.Engine().(*parlia.Parlia) + if !ok { + return false + } + if parlia.ConsensusAddress() == block.Coinbase() { + return true + } + + return h.peers.isProxyedValidator(block.Coinbase(), h.proxyedValidatorNodeIDMap) +} + +func (h *handler) queryValidatorNodeIDsMap() map[common.Address][]enode.ID { + latest := h.chain.CurrentHeader() + if !h.chain.Config().IsMaxwell(latest.Number, latest.Time) { + return nil + } + + log.Debug("queryValidatorNodeIDs after maxwell", "number", latest.Number, "time", latest.Time) + parlia, ok := h.chain.Engine().(*parlia.Parlia) + if !ok { + return nil + } + + nodeIDsMap, err := parlia.GetNodeIDsMap() + if err != nil { + return nil + } + return nodeIDsMap +} + // BroadcastTransactions will propagate a batch of transactions // - To a square root of all peers for non-blob transactions // - And, separately, as announcements to all peers which are not known to diff --git a/eth/handler_eth.go b/eth/handler_eth.go index 06c60f70a2..cb4831c088 100644 --- a/eth/handler_eth.go +++ b/eth/handler_eth.go @@ -26,6 +26,7 @@ import ( "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/eth/protocols/eth" + "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/p2p/enode" ) @@ -101,6 +102,7 @@ func (h *ethHandler) handleBlockAnnounces(peer *eth.Peer, hashes []common.Hash, } } + log.Debug("handleBlockAnnounces", "peer", peer.ID(), "numbers", numbers, "hashes", hashes) for i := 0; i < len(unknownHashes); i++ { h.blockFetcher.Notify(peer.ID(), unknownHashes[i], unknownNumbers[i], time.Now(), peer.RequestOneHeader, peer.RequestBodies) } @@ -128,6 +130,7 @@ func (h *ethHandler) handleBlockBroadcast(peer *eth.Peer, packet *eth.NewBlockPa } // Schedule the block for import + log.Debug("handleBlockBroadcast", "peer", peer.ID(), "block", block.Number(), "hash", block.Hash()) h.blockFetcher.Enqueue(peer.ID(), block) stats := h.chain.GetBlockStats(block.Hash()) if stats.RecvNewBlockTime.Load() == 0 { diff --git a/eth/peerset.go b/eth/peerset.go index 38a3471139..706cd36bdf 100644 --- a/eth/peerset.go +++ b/eth/peerset.go @@ -29,7 +29,10 @@ import ( "github.com/ethereum/go-ethereum/eth/protocols/eth" "github.com/ethereum/go-ethereum/eth/protocols/snap" "github.com/ethereum/go-ethereum/eth/protocols/trust" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/p2p" + "github.com/ethereum/go-ethereum/p2p/enode" ) var ( @@ -68,12 +71,20 @@ const ( tryWaitTimeout = 100 * time.Millisecond ) +var ( + evnProxedPeerGuage = metrics.NewRegisteredGauge("evn/peer/proxed", nil) + evnWhiteListPeerGuage = metrics.NewRegisteredGauge("evn/peer/whiteList", nil) + evnOnchainValidatorPeerGuage = metrics.NewRegisteredGauge("evn/peer/onchainValidator", nil) +) + // peerSet represents the collection of active peers currently participating in // the `eth` protocol, with or without the `snap` extension. type peerSet struct { peers map[string]*ethPeer // Peers connected on the `eth` protocol snapPeers int // Number of `snap` compatible peers for connection prioritization + validatorNodeIDsMap map[common.Address][]enode.ID + snapWait map[string]chan *snap.Peer // Peers connected on `eth` waiting for their snap extension snapPend map[string]*snap.Peer // Peers connected on the `snap` protocol, but not yet on `eth` @@ -433,6 +444,98 @@ func (ps *peerSet) peer(id string) *ethPeer { return ps.peers[id] } +// enableEVNFeatures enables the given features for the given peers. +func (ps *peerSet) enableEVNFeatures(validatorNodeIDsMap map[common.Address][]enode.ID, evnWhitelistMap map[enode.ID]struct{}, proxyedNodeIDMap map[enode.ID]struct{}) { + // clone current all peers, and update the validatorNodeIDsMap + ps.lock.Lock() + peers := make([]*ethPeer, 0, len(ps.peers)) + for _, peer := range ps.peers { + peers = append(peers, peer) + } + ps.validatorNodeIDsMap = validatorNodeIDsMap + ps.lock.Unlock() + + // convert to nodeID filter map, avoid too slow operation for slices.Contains + valNodeIDMap := make(map[enode.ID]struct{}) + for _, nodeIDs := range validatorNodeIDsMap { + for _, nodeID := range nodeIDs { + valNodeIDMap[nodeID] = struct{}{} + } + } + + var ( + proxyedPeerCnt int64 = 0 + whiteListPeerCnt int64 = 0 + onchainValidatorPeerCnt int64 = 0 + ) + for _, peer := range peers { + nodeID := peer.NodeID() + _, isValidatorPeer := valNodeIDMap[nodeID] + _, isWhitelistPeer := evnWhitelistMap[nodeID] + _, isProxyedPeer := proxyedNodeIDMap[nodeID] + + if isProxyedPeer { + log.Debug("enable ProxyedValidatorFlag for", "peer", nodeID) + peer.ProxyedValidatorFlag.Store(true) + proxyedPeerCnt++ + } else { + peer.ProxyedValidatorFlag.Store(false) + } + + if isValidatorPeer || isWhitelistPeer { + log.Debug("enable EVNPeerFlag for", "peer", nodeID) + peer.EVNPeerFlag.Store(true) + } else { + peer.EVNPeerFlag.Store(false) + } + // if the peer is in the valNodeIDs and not in the proxyedList, enable the no tx broadcast feature + // the node also need to forward tx to the proxyedList + if isValidatorPeer && !isProxyedPeer { + log.Debug("enable NoTxBroadcastFlag for", "peer", nodeID) + peer.NoTxBroadcastFlag.Store(true) + } else { + peer.NoTxBroadcastFlag.Store(false) + } + + // Note: In the future, it need to check proxyed validator whether belong to EnhancedValidatorNetwork or not. + if isProxyedPeer && isValidatorPeer { + log.Warn("proyxed validator is registered on-chain", "id", nodeID) + } + + if isValidatorPeer { + onchainValidatorPeerCnt++ + } + if isWhitelistPeer { + whiteListPeerCnt++ + } + } + evnProxedPeerGuage.Update(proxyedPeerCnt) + evnWhiteListPeerGuage.Update(whiteListPeerCnt) + evnOnchainValidatorPeerGuage.Update(onchainValidatorPeerCnt) + log.Info("enable EVN features", "total", len(peers), "proxyedPeerCnt", proxyedPeerCnt, "whiteListPeerCnt", whiteListPeerCnt, "onchainValidatorPeerCnt", onchainValidatorPeerCnt) +} + +// isProxyedValidator checks if the given address is a connected proxyed validator. +func (ps *peerSet) isProxyedValidator(address common.Address, proxyedNodeIDMap map[enode.ID]struct{}) bool { + ps.lock.RLock() + defer ps.lock.RUnlock() + + if ps.validatorNodeIDsMap == nil { + return false + } + + nodeIDs := ps.validatorNodeIDsMap[address] + for _, id := range nodeIDs { + if ps.peers[id.String()] == nil { + continue + } + if _, ok := proxyedNodeIDMap[id]; ok { + return true + } + } + return false +} + // headPeers retrieves a specified number list of peers. func (ps *peerSet) headPeers(num uint) []*ethPeer { ps.lock.RLock() @@ -475,6 +578,10 @@ func (ps *peerSet) peersWithoutTransaction(hash common.Hash) []*ethPeer { list := make([]*ethPeer, 0, len(ps.peers)) for _, p := range ps.peers { + if p.NoTxBroadcastFlag.Load() { + log.Debug("skip peer with no tx broadcast feature", "peer", p.ID()) + continue + } if !p.KnownTransaction(hash) { list = append(list, p) } diff --git a/eth/peerset_test.go b/eth/peerset_test.go new file mode 100644 index 0000000000..249966e0da --- /dev/null +++ b/eth/peerset_test.go @@ -0,0 +1,357 @@ +package eth + +import ( + "reflect" + "testing" + + "sync/atomic" + + "github.com/ethereum/go-ethereum/common" +) + +// mockPeer is a simplified p2p.Peer for testing purposes +type mockPeer struct { + id string + enableDirectBroadcast atomic.Bool + enableNoTxBroadcast atomic.Bool +} + +func (p *mockPeer) ID() string { + return p.id +} + +// mockEthPeer is a simplified eth.Peer for testing purposes +type mockEthPeer struct { + peer *mockPeer +} + +func (p *mockEthPeer) ID() string { + return p.peer.ID() +} + +// Create a test mockEthPeer +func newMockEthPeer(id string) *mockEthPeer { + return &mockEthPeer{ + peer: &mockPeer{ + id: id, + }, + } +} + +// Test the functionality of enablePeerFeatures method +func TestEnablePeerFeatures(t *testing.T) { + tests := []struct { + name string + validatorMap map[common.Address][]string + directList []string + noTxList []string + proxyedList []string + peers map[string]*mockEthPeer + expectations map[string]struct { + directBroadcast bool + noTxBroadcast bool + } + }{ + { + name: "Empty Lists Test", + validatorMap: map[common.Address][]string{}, + directList: []string{}, + noTxList: []string{}, + proxyedList: []string{}, + peers: map[string]*mockEthPeer{ + "peer1": newMockEthPeer("peer1"), + "peer2": newMockEthPeer("peer2"), + }, + expectations: map[string]struct { + directBroadcast bool + noTxBroadcast bool + }{ + "peer1": {directBroadcast: false, noTxBroadcast: false}, + "peer2": {directBroadcast: false, noTxBroadcast: false}, + }, + }, + { + name: "Validator Node Test", + validatorMap: map[common.Address][]string{ + common.HexToAddress("0x1"): {"peer1"}, + }, + directList: []string{}, + noTxList: []string{}, + proxyedList: []string{}, + peers: map[string]*mockEthPeer{ + "peer1": newMockEthPeer("peer1"), + "peer2": newMockEthPeer("peer2"), + }, + expectations: map[string]struct { + directBroadcast bool + noTxBroadcast bool + }{ + "peer1": {directBroadcast: true, noTxBroadcast: false}, + "peer2": {directBroadcast: false, noTxBroadcast: false}, + }, + }, + { + name: "Direct Broadcast Node Test", + validatorMap: map[common.Address][]string{}, + directList: []string{"peer2"}, + noTxList: []string{}, + proxyedList: []string{}, + peers: map[string]*mockEthPeer{ + "peer1": newMockEthPeer("peer1"), + "peer2": newMockEthPeer("peer2"), + }, + expectations: map[string]struct { + directBroadcast bool + noTxBroadcast bool + }{ + "peer1": {directBroadcast: false, noTxBroadcast: false}, + "peer2": {directBroadcast: true, noTxBroadcast: false}, + }, + }, + { + name: "No Transaction Broadcast Node Test", + validatorMap: map[common.Address][]string{}, + directList: []string{}, + noTxList: []string{"peer1"}, + proxyedList: []string{}, + peers: map[string]*mockEthPeer{ + "peer1": newMockEthPeer("peer1"), + "peer2": newMockEthPeer("peer2"), + }, + expectations: map[string]struct { + directBroadcast bool + noTxBroadcast bool + }{ + "peer1": {directBroadcast: false, noTxBroadcast: true}, + "peer2": {directBroadcast: false, noTxBroadcast: false}, + }, + }, + { + name: "Proxy Node Test", + validatorMap: map[common.Address][]string{}, + directList: []string{}, + noTxList: []string{"peer1", "peer2"}, + proxyedList: []string{"peer2"}, + peers: map[string]*mockEthPeer{ + "peer1": newMockEthPeer("peer1"), + "peer2": newMockEthPeer("peer2"), + }, + expectations: map[string]struct { + directBroadcast bool + noTxBroadcast bool + }{ + "peer1": {directBroadcast: false, noTxBroadcast: true}, + "peer2": {directBroadcast: false, noTxBroadcast: false}, // Node in proxyedList should not enable noTxBroadcast + }, + }, + { + name: "Combined Test", + validatorMap: map[common.Address][]string{ + common.HexToAddress("0x1"): {"peer1", "peer3"}, + }, + directList: []string{"peer2"}, + noTxList: []string{"peer1", "peer2", "peer4"}, + proxyedList: []string{"peer2"}, + peers: map[string]*mockEthPeer{ + "peer1": newMockEthPeer("peer1"), + "peer2": newMockEthPeer("peer2"), + "peer3": newMockEthPeer("peer3"), + "peer4": newMockEthPeer("peer4"), + }, + expectations: map[string]struct { + directBroadcast bool + noTxBroadcast bool + }{ + "peer1": {directBroadcast: true, noTxBroadcast: true}, + "peer2": {directBroadcast: true, noTxBroadcast: false}, // In proxyedList + "peer3": {directBroadcast: true, noTxBroadcast: false}, + "peer4": {directBroadcast: false, noTxBroadcast: true}, + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // Create a special peerSet to mock enablePeerFeatures + mockPeerSet := &mockPeerSet{ + peers: tt.peers, + } + + // Call the test method + mockPeerSet.enablePeerFeatures(tt.validatorMap, tt.directList, tt.noTxList, tt.proxyedList) + + // Verify that consensusAddressMap is set correctly + if !reflect.DeepEqual(mockPeerSet.consensusAddressMap, tt.validatorMap) { + t.Errorf("consensusAddressMap = %v, want %v", mockPeerSet.consensusAddressMap, tt.validatorMap) + } + + // Verify that each peer's settings match the expected values + for id, expect := range tt.expectations { + peer := mockPeerSet.peers[id] + if peer.peer.enableDirectBroadcast.Load() != expect.directBroadcast { + t.Errorf("peer %s, EnableDirectBroadcast = %v, want %v", id, peer.peer.enableDirectBroadcast.Load(), expect.directBroadcast) + } + if peer.peer.enableNoTxBroadcast.Load() != expect.noTxBroadcast { + t.Errorf("peer %s, EnableNoTxBroadcast = %v, want %v", id, peer.peer.enableNoTxBroadcast.Load(), expect.noTxBroadcast) + } + } + }) + } +} + +// mockPeerSet is a simplified peerSet for testing purposes +type mockPeerSet struct { + peers map[string]*mockEthPeer + consensusAddressMap map[common.Address][]string +} + +// Mock the functionality of enablePeerFeatures method +func (ps *mockPeerSet) enablePeerFeatures(validatorMap map[common.Address][]string, directList []string, noTxList []string, proxyedList []string) { + ps.consensusAddressMap = validatorMap + var valNodeIDs []string + for _, nodeIDs := range validatorMap { + valNodeIDs = append(valNodeIDs, nodeIDs...) + } + + // Similar to the implementation in peerset.go + for _, peer := range ps.peers { + nodeID := peer.ID() + if contains(directList, nodeID) || contains(valNodeIDs, nodeID) { + peer.peer.enableDirectBroadcast.Store(true) + } + // if the peer is in the noTxList and not in the proxyedList, enable the no tx broadcast feature + if contains(noTxList, nodeID) && !contains(proxyedList, nodeID) { + peer.peer.enableNoTxBroadcast.Store(true) + } + } +} + +// Test the functionality of existProxyedValidator method +func TestExistProxyedValidator(t *testing.T) { + tests := []struct { + name string + address common.Address + proxyedList []string + validatorMap map[common.Address][]string + peers map[string]*mockEthPeer + expectExisting bool + }{ + { + name: "Empty Validator Map", + address: common.HexToAddress("0x1"), + proxyedList: []string{"peer1"}, + validatorMap: nil, + peers: map[string]*mockEthPeer{}, + expectExisting: false, + }, + { + name: "Validator Not In Map", + address: common.HexToAddress("0x1"), + proxyedList: []string{"peer1"}, + validatorMap: map[common.Address][]string{ + common.HexToAddress("0x2"): {"peer2"}, + }, + peers: map[string]*mockEthPeer{ + "peer1": newMockEthPeer("peer1"), + "peer2": newMockEthPeer("peer2"), + }, + expectExisting: false, + }, + { + name: "Validator In Map But Node Not In Proxy List", + address: common.HexToAddress("0x1"), + proxyedList: []string{"peer2"}, + validatorMap: map[common.Address][]string{ + common.HexToAddress("0x1"): {"peer1"}, + }, + peers: map[string]*mockEthPeer{ + "peer1": newMockEthPeer("peer1"), + "peer2": newMockEthPeer("peer2"), + }, + expectExisting: false, + }, + { + name: "Validator In Map And Node In Proxy List", + address: common.HexToAddress("0x1"), + proxyedList: []string{"peer1"}, + validatorMap: map[common.Address][]string{ + common.HexToAddress("0x1"): {"peer1"}, + }, + peers: map[string]*mockEthPeer{ + "peer1": newMockEthPeer("peer1"), + "peer2": newMockEthPeer("peer2"), + }, + expectExisting: true, + }, + { + name: "Validator Has Multiple Nodes And Some In Proxy List", + address: common.HexToAddress("0x1"), + proxyedList: []string{"peer2"}, + validatorMap: map[common.Address][]string{ + common.HexToAddress("0x1"): {"peer1", "peer2", "peer3"}, + }, + peers: map[string]*mockEthPeer{ + "peer1": newMockEthPeer("peer1"), + "peer2": newMockEthPeer("peer2"), + "peer3": newMockEthPeer("peer3"), + }, + expectExisting: true, + }, + { + name: "Validator Node Not Connected", + address: common.HexToAddress("0x1"), + proxyedList: []string{"peer1"}, + validatorMap: map[common.Address][]string{ + common.HexToAddress("0x1"): {"peer1"}, + }, + peers: map[string]*mockEthPeer{}, // Empty peers set, indicating validator node is not connected + expectExisting: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // Create a special peerSet to mock existProxyedValidator + mockPeerSet := &mockPeerSet{ + peers: tt.peers, + consensusAddressMap: tt.validatorMap, + } + + // Test method + result := existProxyedValidator(mockPeerSet, tt.address, tt.proxyedList) + + // Verify result + if result != tt.expectExisting { + t.Errorf("existProxyedValidator() = %v, want %v", result, tt.expectExisting) + } + }) + } +} + +// Mock the functionality of existProxyedValidator method +func existProxyedValidator(ps *mockPeerSet, address common.Address, proxyedList []string) bool { + if ps.consensusAddressMap == nil { + return false + } + + peerIDs := ps.consensusAddressMap[address] + for _, peerID := range peerIDs { + if ps.peers[peerID] == nil { + continue + } + if contains(proxyedList, peerID) { + return true + } + } + return false +} + +// contains checks if a string slice contains a specific string +func contains(slice []string, str string) bool { + for _, s := range slice { + if s == str { + return true + } + } + return false +} diff --git a/eth/protocols/bsc/dispatcher.go b/eth/protocols/bsc/dispatcher.go new file mode 100644 index 0000000000..eb63bec1d5 --- /dev/null +++ b/eth/protocols/bsc/dispatcher.go @@ -0,0 +1,115 @@ +package bsc + +import ( + "errors" + "fmt" + "math/rand" + "sync" + "time" + + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/p2p" +) + +type Request struct { + code uint64 + want uint64 + requestID uint64 + data interface{} + resCh chan interface{} + cancelCh chan string + timeout time.Duration +} + +type Response struct { + code uint64 + requestID uint64 + data interface{} +} + +// Dispatcher handles message requests and responses +type Dispatcher struct { + peer *Peer + requests map[uint64]*Request + mu sync.Mutex +} + +// NewDispatcher creates a new message dispatcher +func NewDispatcher(peer *Peer) *Dispatcher { + return &Dispatcher{ + peer: peer, + requests: make(map[uint64]*Request), + } +} + +// GenRequestID get requestID for packet +func (d *Dispatcher) GenRequestID() uint64 { + return rand.Uint64() +} + +// DispatchRequest send the request, and block until the later response +func (d *Dispatcher) DispatchRequest(req *Request) (interface{}, error) { + // record the request before sending + d.mu.Lock() + d.requests[req.requestID] = req + d.mu.Unlock() + + log.Debug("send BlocksByRange request", "code", req.code, "requestId", req.requestID) + err := p2p.Send(d.peer.rw, req.code, req.data) + if err != nil { + return nil, err + } + req.resCh = make(chan interface{}, 1) + req.cancelCh = make(chan string, 1) + + // clean the requests when the request is done + defer func() { + d.mu.Lock() + delete(d.requests, req.requestID) + d.mu.Unlock() + }() + + timeout := time.NewTimer(req.timeout) + select { + case res := <-req.resCh: + return res, nil + case <-timeout.C: + req.cancelCh <- "timeout" + return nil, errors.New("request timeout") + case <-d.peer.term: + return nil, errors.New("peer disconnected") + } +} + +// getRequestByResp get the request by the response, and delete the request if it is matched +func (d *Dispatcher) getRequestByResp(res *Response) (*Request, error) { + d.mu.Lock() + defer d.mu.Unlock() + req := d.requests[res.requestID] + if req == nil { + return nil, errors.New("missing the request") + } + + if req.want != res.code { + return nil, fmt.Errorf("response mismatch: %d != %d", res.code, req.want) + } + log.Debug("get the request, then clean it", "requestId", req.requestID) + delete(d.requests, req.requestID) + return req, nil +} + +func (d *Dispatcher) DispatchResponse(res *Response) error { + req, err := d.getRequestByResp(res) + if err != nil { + return err + } + + select { + case req.resCh <- res.data: + return nil + case reason := <-req.cancelCh: + return fmt.Errorf("request cancelled: %d , reason: %s", res.requestID, reason) + case <-d.peer.term: + return errors.New("peer disconnected") + } +} diff --git a/eth/protocols/bsc/handler.go b/eth/protocols/bsc/handler.go index 04f5ff3795..37d3d29f9b 100644 --- a/eth/protocols/bsc/handler.go +++ b/eth/protocols/bsc/handler.go @@ -4,13 +4,19 @@ import ( "fmt" "time" + "github.com/ethereum/go-ethereum/log" + + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/p2p/enode" "github.com/ethereum/go-ethereum/p2p/enr" ) +const MaxRequestRangeBlocksCount = 64 + // Handler is a callback to invoke from an outside runner after the boilerplate // exchanges have passed. type Handler func(peer *Peer) error @@ -82,6 +88,12 @@ var bsc1 = map[uint64]msgHandler{ VotesMsg: handleVotes, } +var bsc2 = map[uint64]msgHandler{ + VotesMsg: handleVotes, + GetBlocksByRangeMsg: handleGetBlocksByRange, + BlocksByRangeMsg: handleBlocksByRange, +} + // handleMessage is invoked whenever an inbound message is received from a // remote peer on the `bsc` protocol. The remote connection is torn down upon // returning any error. @@ -97,6 +109,9 @@ func handleMessage(backend Backend, peer *Peer) error { defer msg.Discard() var handlers = bsc1 + if peer.Version() >= Bsc2 { + handlers = bsc2 + } // Track the amount of time it takes to serve the request and run the handler if metrics.Enabled() { @@ -126,6 +141,61 @@ func handleVotes(backend Backend, msg Decoder, peer *Peer) error { return backend.Handle(peer, ann) } +func handleGetBlocksByRange(backend Backend, msg Decoder, peer *Peer) error { + req := new(GetBlocksByRangePacket) + if err := msg.Decode(req); err != nil { + return fmt.Errorf("msg %v, decode err: %v", GetBlocksByRangeMsg, err) + } + + log.Debug("receive GetBlocksByRange request", "from", peer.id, "req", req) + // Validate request parameters + if req.Count == 0 || req.Count > MaxRequestRangeBlocksCount { // Limit maximum request count + return fmt.Errorf("msg %v, invalid count: %v", GetBlocksByRangeMsg, req.Count) + } + + // Get requested blocks + blocks := make([]*BlockData, 0, req.Count) + var block *types.Block + // Prioritize blockHash query, get block & sidecars from db + if req.StartBlockHash != (common.Hash{}) { + block = backend.Chain().GetBlockByHash(req.StartBlockHash) + } else { + block = backend.Chain().GetBlockByNumber(req.StartBlockHeight) + } + if block == nil { + return fmt.Errorf("msg %v, cannot get start block: %v, %v", GetBlocksByRangeMsg, req.StartBlockHeight, req.StartBlockHash) + } + blocks = append(blocks, NewBlockData(block)) + for i := uint64(1); i < req.Count; i++ { + block = backend.Chain().GetBlockByHash(block.ParentHash()) + if block == nil { + break + } + blocks = append(blocks, NewBlockData(block)) + } + + log.Debug("reply GetBlocksByRange msg", "from", peer.id, "req", req.Count, "blocks", len(blocks)) + return p2p.Send(peer.rw, BlocksByRangeMsg, &BlocksByRangePacket{ + RequestId: req.RequestId, + Blocks: blocks, + }) +} + +func handleBlocksByRange(backend Backend, msg Decoder, peer *Peer) error { + res := new(BlocksByRangePacket) + if err := msg.Decode(res); err != nil { + return fmt.Errorf("%w: message %v: %v", errDecode, msg, err) + } + + err := peer.dispatcher.DispatchResponse(&Response{ + requestID: res.RequestId, + data: res, + code: BlocksByRangeMsg, + }) + log.Debug("receive BlocksByRange response", "from", peer.id, "requestId", res.RequestId, "blocks", len(res.Blocks), "err", err) + return nil +} + // NodeInfo represents a short summary of the `bsc` sub-protocol metadata // known about the host peer. type NodeInfo struct{} diff --git a/eth/protocols/bsc/handler_test.go b/eth/protocols/bsc/handler_test.go new file mode 100644 index 0000000000..fc90037318 --- /dev/null +++ b/eth/protocols/bsc/handler_test.go @@ -0,0 +1,249 @@ +package bsc + +import ( + "math/big" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/p2p/enode" +) + +// mockBackend implements the Backend interface for testing +type mockBackend struct { + chain *core.BlockChain +} + +func (b *mockBackend) Chain() *core.BlockChain { + return b.chain +} + +func (b *mockBackend) RunPeer(peer *Peer, handler Handler) error { + return nil +} + +func (b *mockBackend) PeerInfo(id enode.ID) interface{} { + return nil +} + +func (b *mockBackend) Handle(peer *Peer, packet Packet) error { + return nil +} + +// mockMsg implements the Decoder interface for testing +type mockMsg struct { + code uint64 + data interface{} +} + +func (m *mockMsg) Decode(val interface{}) error { + // Simple implementation for testing + switch v := val.(type) { + case *GetBlocksByRangePacket: + *v = *m.data.(*GetBlocksByRangePacket) + case *BlocksByRangePacket: + *v = *m.data.(*BlocksByRangePacket) + } + return nil +} + +// mockPeer implements a mock of the Peer for testing +type mockPeer struct { + *Peer + sentResponses map[uint64]interface{} +} + +func newMockPeer() *mockPeer { + mp := &mockPeer{ + Peer: &Peer{}, + sentResponses: make(map[uint64]interface{}), + } + mp.id = "mock-peer-id" + mp.logger = log.New("peer", mp.id) + mp.term = make(chan struct{}) + mp.dispatcher = &Dispatcher{ + peer: mp.Peer, + requests: make(map[uint64]*Request), + } + return mp +} + +func (mp *mockPeer) Log() log.Logger { + return mp.logger +} + +func TestHandleGetBlocksByRange(t *testing.T) { + t.Skip("Skipping test as it requires a more complete BlockChain mock") + + // Setup test environment + backend := &mockBackend{ + chain: &core.BlockChain{}, // You might want to use a more sophisticated mock + } + + // Create a more complete mock peer + mockPeer := newMockPeer() + peer := mockPeer.Peer + + // Test cases + tests := []struct { + name string + msg *mockMsg + wantErr bool + }{ + { + name: "Valid request with block hash", + msg: &mockMsg{ + code: GetBlocksByRangeMsg, + data: &GetBlocksByRangePacket{ + RequestId: 1, + StartBlockHash: common.HexToHash("0x123"), + StartBlockHeight: 100, + Count: 5, + }, + }, + wantErr: true, // Changed to true since we expect errors due to mock implementation + }, + { + name: "Valid request with block height", + msg: &mockMsg{ + code: GetBlocksByRangeMsg, + data: &GetBlocksByRangePacket{ + RequestId: 2, + StartBlockHeight: 100, + Count: 5, + }, + }, + wantErr: true, // Changed to true since we expect errors due to mock implementation + }, + { + name: "Invalid count", + msg: &mockMsg{ + code: GetBlocksByRangeMsg, + data: &GetBlocksByRangePacket{ + RequestId: 3, + StartBlockHeight: 100, + Count: 0, + }, + }, + wantErr: true, + }, + { + name: "Invalid request ID", + msg: &mockMsg{ + code: GetBlocksByRangeMsg, + data: &GetBlocksByRangePacket{ + RequestId: 0, + StartBlockHeight: 100, + Count: 5, + }, + }, + wantErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := handleGetBlocksByRange(backend, tt.msg, peer) + if (err != nil) != tt.wantErr { + t.Errorf("handleGetBlocksByRange() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func TestHandleBlocksByRange(t *testing.T) { + // Setup test environment + backend := &mockBackend{ + chain: &core.BlockChain{}, // You might want to use a more sophisticated mock + } + + // Create a more complete mock peer + mockPeer := newMockPeer() + peer := mockPeer.Peer + + // Create test blocks + blocks := make([]*types.Block, 3) + for i := 0; i < 3; i++ { + header := &types.Header{ + Number: big.NewInt(int64(100 - i)), + ParentHash: common.HexToHash("0x123"), + } + body := &types.Body{ + Transactions: []*types.Transaction{}, + Uncles: []*types.Header{}, + } + blocks[i] = types.NewBlock(header, body, []*types.Receipt{}, nil) + } + + // Convert blocks to BlockData + blockDataList := make([]*BlockData, len(blocks)) + for i, block := range blocks { + blockDataList[i] = NewBlockData(block) + } + + // Test cases + tests := []struct { + name string + msg *mockMsg + wantErr bool + }{ + { + name: "Valid blocks response", + msg: &mockMsg{ + code: BlocksByRangeMsg, + data: &BlocksByRangePacket{ + RequestId: 1, + Blocks: blockDataList, + }, + }, + wantErr: false, + }, + { + name: "Empty blocks response", + msg: &mockMsg{ + code: BlocksByRangeMsg, + data: &BlocksByRangePacket{ + RequestId: 2, + Blocks: []*BlockData{}, + }, + }, + wantErr: false, + }, + { + name: "Invalid request ID", + msg: &mockMsg{ + code: BlocksByRangeMsg, + data: &BlocksByRangePacket{ + RequestId: 0, + Blocks: blockDataList, + }, + }, + wantErr: false, + }, + { + name: "Non-continuous blocks", + msg: &mockMsg{ + code: BlocksByRangeMsg, + data: &BlocksByRangePacket{ + RequestId: 3, + Blocks: []*BlockData{ + blockDataList[0], + blockDataList[2], // Skip block 1 to create discontinuity + }, + }, + }, + wantErr: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := handleBlocksByRange(backend, tt.msg, peer) + if (err != nil) != tt.wantErr { + t.Errorf("handleBlocksByRange() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/eth/protocols/bsc/peer.go b/eth/protocols/bsc/peer.go index c6c09026e8..3bddc9cc3e 100644 --- a/eth/protocols/bsc/peer.go +++ b/eth/protocols/bsc/peer.go @@ -3,6 +3,8 @@ package bsc import ( "time" + "errors" + mapset "github.com/deckarep/golang-set/v2" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" @@ -21,8 +23,8 @@ const ( // used to avoid of DDOS attack // It's the max number of received votes per second from one peer // 21 validators exist now, so 21 votes will be produced every one block interval - // so the limit is 7 = 21/3, here set it to 10 with a buffer. - receiveRateLimitPerSecond = 10 + // so the limit is 28 = 21/0.75, here set it to 40 with a buffer. + receiveRateLimitPerSecond = 40 // the time span of one period secondsPerPeriod = float64(30) @@ -35,6 +37,7 @@ type Peer struct { voteBroadcast chan []*types.VoteEnvelope // Channel used to queue votes propagation requests periodBegin time.Time // Begin time of the latest period for votes counting periodCounter uint // Votes number in the latest period + dispatcher *Dispatcher // Message request-response dispatcher *p2p.Peer // The embedded P2P package peer rw p2p.MsgReadWriter // Input/output streams for bsc @@ -59,6 +62,7 @@ func NewPeer(version uint, p *p2p.Peer, rw p2p.MsgReadWriter) *Peer { logger: log.New("peer", id[:8]), term: make(chan struct{}), } + peer.dispatcher = NewDispatcher(peer) go peer.broadcastVotes() return peer } @@ -181,3 +185,32 @@ func (k *knownCache) add(hashes ...common.Hash) { func (k *knownCache) contains(hash common.Hash) bool { return k.hashes.Contains(hash) } + +// RequestBlocksByRange send GetBlocksByRangeMsg by request start block hash +func (p *Peer) RequestBlocksByRange(startHeight uint64, startHash common.Hash, count uint64) ([]*BlockData, error) { + requestID := p.dispatcher.GenRequestID() + res, err := p.dispatcher.DispatchRequest(&Request{ + code: GetBlocksByRangeMsg, + want: BlocksByRangeMsg, + requestID: requestID, + data: &GetBlocksByRangePacket{ + RequestId: requestID, + StartBlockHeight: startHeight, + StartBlockHash: startHash, + Count: count, + }, + timeout: 400 * time.Millisecond, + }) + log.Debug("RequestBlocksByRange result", "requestID", requestID, "ret", res == nil, "err", err) + if err != nil { + return nil, err + } + + // Type assertion to get response object + ret, ok := res.(*BlocksByRangePacket) + if !ok { + return nil, errors.New("unexpected response type") + } + + return ret.Blocks, nil +} diff --git a/eth/protocols/bsc/protocol.go b/eth/protocols/bsc/protocol.go index a063531f07..50a08599af 100644 --- a/eth/protocols/bsc/protocol.go +++ b/eth/protocols/bsc/protocol.go @@ -3,6 +3,7 @@ package bsc import ( "errors" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/rlp" ) @@ -10,6 +11,7 @@ import ( // Constants to match up protocol versions and messages const ( Bsc1 = 1 + Bsc2 = 2 ) // ProtocolName is the official short name of the `bsc` protocol used during @@ -18,18 +20,20 @@ const ProtocolName = "bsc" // ProtocolVersions are the supported versions of the `bsc` protocol (first // is primary). -var ProtocolVersions = []uint{Bsc1} +var ProtocolVersions = []uint{Bsc1, Bsc2} // protocolLengths are the number of implemented message corresponding to // different protocol versions. -var protocolLengths = map[uint]uint64{Bsc1: 2} +var protocolLengths = map[uint]uint64{Bsc1: 2, Bsc2: 4} // maxMessageSize is the maximum cap on the size of a protocol message. const maxMessageSize = 10 * 1024 * 1024 const ( - BscCapMsg = 0x00 // bsc capability msg used upon handshake - VotesMsg = 0x01 + BscCapMsg = 0x00 // bsc capability msg used upon handshake + VotesMsg = 0x01 + GetBlocksByRangeMsg = 0x02 // it can request (StartBlockHeight-Count, StartBlockHeight] range blocks from remote peer + BlocksByRangeMsg = 0x03 // the replied blocks from remote peer ) var defaultExtra = []byte{0x00} @@ -64,3 +68,41 @@ func (*BscCapPacket) Kind() byte { return BscCapMsg } func (*VotesPacket) Name() string { return "Votes" } func (*VotesPacket) Kind() byte { return VotesMsg } + +type GetBlocksByRangePacket struct { + RequestId uint64 + StartBlockHeight uint64 // The start block height expected to be obtained from + StartBlockHash common.Hash // The start block hash expected to be obtained from + Count uint64 // Get the number of blocks from the start +} + +func (*GetBlocksByRangePacket) Name() string { return "GetBlocksByRange" } +func (*GetBlocksByRangePacket) Kind() byte { return GetBlocksByRangeMsg } + +// BlockData contains types.extblock + sidecars +type BlockData struct { + Header *types.Header + Txs []*types.Transaction + Uncles []*types.Header + Withdrawals []*types.Withdrawal `rlp:"optional"` + Sidecars types.BlobSidecars `rlp:"optional"` +} + +// NewBlockData creates a new BlockData object from a block +func NewBlockData(block *types.Block) *BlockData { + return &BlockData{ + Header: block.Header(), + Txs: block.Transactions(), + Uncles: block.Uncles(), + Withdrawals: block.Withdrawals(), + Sidecars: block.Sidecars(), + } +} + +type BlocksByRangePacket struct { + RequestId uint64 + Blocks []*BlockData +} + +func (*BlocksByRangePacket) Name() string { return "BlocksByRange" } +func (*BlocksByRangePacket) Kind() byte { return BlocksByRangeMsg } diff --git a/eth/protocols/eth/handler_test.go b/eth/protocols/eth/handler_test.go index effa73c1de..4b12892f96 100644 --- a/eth/protocols/eth/handler_test.go +++ b/eth/protocols/eth/handler_test.go @@ -283,6 +283,34 @@ func testGetBlockHeaders(t *testing.T, protocol uint) { backend.chain.GetBlockByNumber(0).Hash(), }, }, + // Check a corner case where skipping causes overflow with reverse=false + { + &GetBlockHeadersRequest{Origin: HashOrNumber{Number: 1}, Amount: 2, Reverse: false, Skip: math.MaxUint64 - 1}, + []common.Hash{ + backend.chain.GetBlockByNumber(1).Hash(), + }, + }, + // Check a corner case where skipping causes overflow with reverse=true + { + &GetBlockHeadersRequest{Origin: HashOrNumber{Number: 1}, Amount: 2, Reverse: true, Skip: math.MaxUint64 - 1}, + []common.Hash{ + backend.chain.GetBlockByNumber(1).Hash(), + }, + }, + // Check another corner case where skipping causes overflow with reverse=false + { + &GetBlockHeadersRequest{Origin: HashOrNumber{Number: 1}, Amount: 2, Reverse: false, Skip: math.MaxUint64}, + []common.Hash{ + backend.chain.GetBlockByNumber(1).Hash(), + }, + }, + // Check another corner case where skipping causes overflow with reverse=true + { + &GetBlockHeadersRequest{Origin: HashOrNumber{Number: 1}, Amount: 2, Reverse: true, Skip: math.MaxUint64}, + []common.Hash{ + backend.chain.GetBlockByNumber(1).Hash(), + }, + }, // Check a corner case where skipping overflow loops back into the chain start { &GetBlockHeadersRequest{Origin: HashOrNumber{Hash: backend.chain.GetBlockByNumber(3).Hash()}, Amount: 2, Reverse: false, Skip: math.MaxUint64 - 1}, diff --git a/eth/protocols/eth/handlers.go b/eth/protocols/eth/handlers.go index 56b437e560..05cea4a592 100644 --- a/eth/protocols/eth/handlers.go +++ b/eth/protocols/eth/handlers.go @@ -127,15 +127,22 @@ func serviceNonContiguousBlockHeaderQuery(chain *core.BlockChain, query *GetBloc } case query.Reverse: // Number based traversal towards the genesis block - if query.Origin.Number >= query.Skip+1 { - query.Origin.Number -= query.Skip + 1 - } else { + current := query.Origin.Number + ancestor := current - (query.Skip + 1) + if ancestor >= current { // check for underflow unknown = true + } else { + query.Origin.Number = ancestor } case !query.Reverse: - // Number based traversal towards the leaf block - query.Origin.Number += query.Skip + 1 + current := query.Origin.Number + next := current + query.Skip + 1 + if next <= current { // check for overflow + unknown = true + } else { + query.Origin.Number = next + } } } return headers diff --git a/eth/protocols/eth/peer.go b/eth/protocols/eth/peer.go index 3d3e6305ae..958c6961b0 100644 --- a/eth/protocols/eth/peer.go +++ b/eth/protocols/eth/peer.go @@ -25,6 +25,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/p2p" + "github.com/ethereum/go-ethereum/p2p/enode" "github.com/ethereum/go-ethereum/rlp" ) @@ -139,6 +140,11 @@ func (p *Peer) ID() string { return p.id } +// NodeID retrieves the peer's unique identifier. +func (p *Peer) NodeID() enode.ID { + return p.Peer.ID() +} + // Version retrieves the peer's negotiated `eth` protocol version. func (p *Peer) Version() uint { return p.version diff --git a/eth/protocols/eth/protocol.go b/eth/protocols/eth/protocol.go index 91c7298471..826e2a9f35 100644 --- a/eth/protocols/eth/protocol.go +++ b/eth/protocols/eth/protocol.go @@ -25,7 +25,6 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/forkid" "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rlp" ) @@ -47,7 +46,7 @@ var ProtocolVersions = []uint{ETH68} var protocolLengths = map[uint]uint64{ETH68: 17} // maxMessageSize is the maximum cap on the size of a protocol message. -var maxMessageSize = params.MaxMessageSize +const maxMessageSize = 10 * 1024 * 1024 const ( StatusMsg = 0x00 diff --git a/eth/state_accessor.go b/eth/state_accessor.go index e9fefce391..eca90d44b0 100644 --- a/eth/state_accessor.go +++ b/eth/state_accessor.go @@ -241,7 +241,7 @@ func (eth *Ethereum) stateAtTransaction(ctx context.Context, block *types.Block, if err != nil { return nil, vm.BlockContext{}, nil, nil, err } - // upgrade build-in system contract before normal txs if Feynman is not enabled + // upgrade built-in system contract before normal txs if Feynman is not enabled systemcontracts.TryUpdateBuildInSystemContract(eth.blockchain.Config(), block.Number(), parent.Time(), block.Time(), statedb, true) // Insert parent beacon block root in the state as per EIP-4788. context := core.NewEVMBlockContext(block.Header(), eth.blockchain, nil) @@ -262,7 +262,7 @@ func (eth *Ethereum) stateAtTransaction(ctx context.Context, block *types.Block, beforeSystemTx = true ) for idx, tx := range block.Transactions() { - // upgrade build-in system contract before system txs if Feynman is enabled + // upgrade built-in system contract before system txs if Feynman is enabled if beforeSystemTx { if posa, ok := eth.Engine().(consensus.PoSA); ok { if isSystem, _ := posa.IsSystemTransaction(tx, block.Header()); isSystem { diff --git a/eth/sync.go b/eth/sync.go index 80844e2b5a..5e50aa31f6 100644 --- a/eth/sync.go +++ b/eth/sync.go @@ -250,9 +250,6 @@ func (h *handler) doSync(op *chainSyncOp) error { // degenerate connectivity, but it should be healthy for the mainnet too to // more reliably update peers or the local TD state. if block := h.chain.GetBlock(head.Hash(), head.Number.Uint64()); block != nil { - if h.chain.Config().IsCancun(block.Number(), block.Time()) { - block = block.WithSidecars(h.chain.GetSidecarsByHash(block.Hash())) - } h.BroadcastBlock(block, false) } } diff --git a/eth/tracers/api.go b/eth/tracers/api.go index 0405d08e1c..0327bf266e 100644 --- a/eth/tracers/api.go +++ b/eth/tracers/api.go @@ -279,7 +279,7 @@ func (api *API) traceChain(start, end *types.Block, config *TraceConfig, closed ) // Trace all the transactions contained within for i, tx := range task.block.Transactions() { - // upgrade build-in system contract before system txs if Feynman is enabled + // upgrade built-in system contract before system txs if Feynman is enabled if beforeSystemTx { if posa, ok := api.backend.Engine().(consensus.PoSA); ok { if isSystem, _ := posa.IsSystemTransaction(tx, task.block.Header()); isSystem { @@ -402,7 +402,7 @@ func (api *API) traceChain(start, end *types.Block, config *TraceConfig, closed break } - // upgrade build-in system contract before normal txs if Feynman is not enabled + // upgrade built-in system contract before normal txs if Feynman is not enabled systemcontracts.TryUpdateBuildInSystemContract(api.backend.ChainConfig(), next.Number(), block.Time(), next.Time(), statedb, true) // Insert block's parent beacon block root in the state @@ -558,7 +558,7 @@ func (api *API) IntermediateRoots(ctx context.Context, hash common.Hash, config } defer release() - // upgrade build-in system contract before normal txs if Feynman is not enabled + // upgrade built-in system contract before normal txs if Feynman is not enabled systemcontracts.TryUpdateBuildInSystemContract(api.backend.ChainConfig(), block.Number(), parent.Time(), block.Time(), statedb, true) var ( @@ -649,7 +649,7 @@ func (api *API) traceBlock(ctx context.Context, block *types.Block, config *Trac } defer release() - // upgrade build-in system contract before normal txs if Feynman is not enabled + // upgrade built-in system contract before normal txs if Feynman is not enabled systemcontracts.TryUpdateBuildInSystemContract(api.backend.ChainConfig(), block.Number(), parent.Time(), block.Time(), statedb, true) blockCtx := core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil) evm := vm.NewEVM(blockCtx, statedb, api.backend.ChainConfig(), vm.Config{}) @@ -678,7 +678,7 @@ func (api *API) traceBlock(ctx context.Context, block *types.Block, config *Trac beforeSystemTx = true ) for i, tx := range txs { - // upgrade build-in system contract before system txs if Feynman is enabled + // upgrade built-in system contract before system txs if Feynman is enabled if beforeSystemTx { if posa, ok := api.backend.Engine().(consensus.PoSA); ok { if isSystem, _ := posa.IsSystemTransaction(tx, block.Header()); isSystem { @@ -771,7 +771,7 @@ func (api *API) traceBlockParallel(ctx context.Context, block *types.Block, stat txloop: for i, tx := range txs { - // upgrade build-in system contract before system txs if Feynman is enabled + // upgrade built-in system contract before system txs if Feynman is enabled if beforeSystemTx { if posa, ok := api.backend.Engine().(consensus.PoSA); ok { if isSystem, _ := posa.IsSystemTransaction(tx, block.Header()); isSystem { @@ -845,7 +845,7 @@ func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block } defer release() - // upgrade build-in system contract before normal txs if Feynman is not enabled + // upgrade built-in system contract before normal txs if Feynman is not enabled systemcontracts.TryUpdateBuildInSystemContract(api.backend.ChainConfig(), block.Number(), parent.Time(), block.Time(), statedb, true) // Retrieve the tracing configurations, or use default values @@ -884,7 +884,7 @@ func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block core.ProcessParentBlockHash(block.ParentHash(), evm) } for i, tx := range block.Transactions() { - // upgrade build-in system contract before system txs if Feynman is enabled + // upgrade built-in system contract before system txs if Feynman is enabled if beforeSystemTx { if posa, ok := api.backend.Engine().(consensus.PoSA); ok { if isSystem, _ := posa.IsSystemTransaction(tx, block.Header()); isSystem { @@ -1068,7 +1068,7 @@ func (api *API) TraceCall(ctx context.Context, args ethapi.TransactionArgs, bloc } defer release() - // upgrade build-in system contract before tracing if Feynman is not enabled + // upgrade built-in system contract before tracing if Feynman is not enabled if block.NumberU64() > 0 { parent, err := api.blockByNumberAndHash(ctx, rpc.BlockNumber(block.NumberU64()-1), block.ParentHash()) if err != nil { diff --git a/eth/tracers/logger/access_list_tracer.go b/eth/tracers/logger/access_list_tracer.go index e8231461b0..0d51f40522 100644 --- a/eth/tracers/logger/access_list_tracer.go +++ b/eth/tracers/logger/access_list_tracer.go @@ -103,16 +103,10 @@ type AccessListTracer struct { // NewAccessListTracer creates a new tracer that can generate AccessLists. // An optional AccessList can be specified to occupy slots and addresses in // the resulting accesslist. -func NewAccessListTracer(acl types.AccessList, from, to common.Address, precompiles []common.Address) *AccessListTracer { - excl := map[common.Address]struct{}{ - from: {}, to: {}, - } - for _, addr := range precompiles { - excl[addr] = struct{}{} - } +func NewAccessListTracer(acl types.AccessList, addressesToExclude map[common.Address]struct{}) *AccessListTracer { list := newAccessList() for _, al := range acl { - if _, ok := excl[al.Address]; !ok { + if _, ok := addressesToExclude[al.Address]; !ok { list.addAddress(al.Address) } for _, slot := range al.StorageKeys { @@ -120,7 +114,7 @@ func NewAccessListTracer(acl types.AccessList, from, to common.Address, precompi } } return &AccessListTracer{ - excl: excl, + excl: addressesToExclude, list: list, } } diff --git a/eth/tracers/logger/logger.go b/eth/tracers/logger/logger.go index 469de54b02..136f3c3177 100644 --- a/eth/tracers/logger/logger.go +++ b/eth/tracers/logger/logger.go @@ -177,14 +177,14 @@ func (s *StructLog) toLegacyJSON() json.RawMessage { if len(s.ReturnData) > 0 { msg.ReturnData = hexutil.Bytes(s.ReturnData).String() } - if s.Memory != nil { + if len(s.Memory) > 0 { memory := make([]string, 0, (len(s.Memory)+31)/32) for i := 0; i+32 <= len(s.Memory); i += 32 { memory = append(memory, fmt.Sprintf("%x", s.Memory[i:i+32])) } msg.Memory = &memory } - if s.Storage != nil { + if len(s.Storage) > 0 { storage := make(map[string]string) for i, storageValue := range s.Storage { storage[fmt.Sprintf("%x", i)] = fmt.Sprintf("%x", storageValue) diff --git a/ethclient/ethclient.go b/ethclient/ethclient.go index 7ed02bd7ad..dca263aa20 100644 --- a/ethclient/ethclient.go +++ b/ethclient/ethclient.go @@ -674,6 +674,15 @@ func (ec *Client) SuggestGasTipCap(ctx context.Context) (*big.Int, error) { return (*big.Int)(&hex), nil } +// BlobBaseFee retrieves the current blob base fee. +func (ec *Client) BlobBaseFee(ctx context.Context) (*big.Int, error) { + var hex hexutil.Big + if err := ec.c.CallContext(ctx, &hex, "eth_blobBaseFee"); err != nil { + return nil, err + } + return (*big.Int)(&hex), nil +} + type feeHistoryResultMarshaling struct { OldestBlock *hexutil.Big `json:"oldestBlock"` Reward [][]*hexutil.Big `json:"reward,omitempty"` @@ -708,9 +717,13 @@ func (ec *Client) FeeHistory(ctx context.Context, blockCount uint64, lastBlock * } // EstimateGas tries to estimate the gas needed to execute a specific transaction based on -// the current pending state of the backend blockchain. There is no guarantee that this is -// the true gas limit requirement as other transactions may be added or removed by miners, -// but it should provide a basis for setting a reasonable default. +// the current state of the backend blockchain. There is no guarantee that this is the +// true gas limit requirement as other transactions may be added or removed by miners, but +// it should provide a basis for setting a reasonable default. +// +// Note that the state used by this method is implementation-defined by the remote RPC +// server, but it's reasonable to assume that it will either be the pending or latest +// state. func (ec *Client) EstimateGas(ctx context.Context, msg ethereum.CallMsg) (uint64, error) { var hex hexutil.Uint64 err := ec.c.CallContext(ctx, &hex, "eth_estimateGas", toCallArg(msg)) @@ -720,6 +733,28 @@ func (ec *Client) EstimateGas(ctx context.Context, msg ethereum.CallMsg) (uint64 return uint64(hex), nil } +// EstimateGasAtBlock is almost the same as EstimateGas except that it selects the block height +// instead of using the remote RPC's default state for gas estimation. +func (ec *Client) EstimateGasAtBlock(ctx context.Context, msg ethereum.CallMsg, blockNumber *big.Int) (uint64, error) { + var hex hexutil.Uint64 + err := ec.c.CallContext(ctx, &hex, "eth_estimateGas", toCallArg(msg), toBlockNumArg(blockNumber)) + if err != nil { + return 0, err + } + return uint64(hex), nil +} + +// EstimateGasAtBlockHash is almost the same as EstimateGas except that it selects the block +// hash instead of using the remote RPC's default state for gas estimation. +func (ec *Client) EstimateGasAtBlockHash(ctx context.Context, msg ethereum.CallMsg, blockHash common.Hash) (uint64, error) { + var hex hexutil.Uint64 + err := ec.c.CallContext(ctx, &hex, "eth_estimateGas", toCallArg(msg), rpc.BlockNumberOrHashWithHash(blockHash, false)) + if err != nil { + return 0, err + } + return uint64(hex), nil +} + // SendTransaction injects a signed transaction into the pending pool for execution. // // If the transaction was a contract creation use the TransactionReceipt method to get the @@ -852,6 +887,9 @@ func toCallArg(msg ethereum.CallMsg) interface{} { if msg.BlobHashes != nil { arg["blobVersionedHashes"] = msg.BlobHashes } + if msg.AuthorizationList != nil { + arg["authorizationList"] = msg.AuthorizationList + } return arg } diff --git a/ethclient/ethclient_test.go b/ethclient/ethclient_test.go index 2f39199337..6fb21245e9 100644 --- a/ethclient/ethclient_test.go +++ b/ethclient/ethclient_test.go @@ -532,6 +532,15 @@ func testStatusFunctions(t *testing.T, client *rpc.Client) { t.Fatalf("unexpected gas tip cap: %v", gasTipCap) } + // // BlobBaseFee + // blobBaseFee, err := ec.BlobBaseFee(context.Background()) + // if err != nil { + // t.Fatalf("unexpected error: %v", err) + // } + // if blobBaseFee.Cmp(big.NewInt(1)) != 0 { + // t.Fatalf("unexpected blob base fee: %v", blobBaseFee) + // } + // FeeHistory history, err := ec.FeeHistory(context.Background(), 1, big.NewInt(2), []float64{95, 99}) if err != nil { @@ -616,6 +625,33 @@ func testSendTransactionConditional(t *testing.T, client *rpc.Client) { if err := sendTransactionConditional(ec); err != nil { t.Fatalf("error: %v", err) } + // Use HeaderByNumber to get a header for EstimateGasAtBlock and EstimateGasAtBlockHash + latestHeader, err := ec.HeaderByNumber(context.Background(), nil) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + // EstimateGasAtBlock + msg := ethereum.CallMsg{ + From: testAddr, + To: &common.Address{}, + Gas: 21000, + Value: big.NewInt(1), + } + gas, err := ec.EstimateGasAtBlock(context.Background(), msg, latestHeader.Number) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if gas != 21000 { + t.Fatalf("unexpected gas limit: %v", gas) + } + // EstimateGasAtBlockHash + gas, err = ec.EstimateGasAtBlockHash(context.Background(), msg, latestHeader.Hash()) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if gas != 21000 { + t.Fatalf("unexpected gas limit: %v", gas) + } } func sendTransactionConditional(ec *ethclient.Client) error { diff --git a/ethclient/gethclient/gethclient.go b/ethclient/gethclient/gethclient.go index 02b2598b37..90115d09a8 100644 --- a/ethclient/gethclient/gethclient.go +++ b/ethclient/gethclient/gethclient.go @@ -33,6 +33,9 @@ import ( "github.com/ethereum/go-ethereum/rpc" ) +// MaxGetProofKeys is the maximum number of keys allowed in a GetProof request +const MaxGetProofKeys = 512 + // Client is a wrapper around rpc.Client that implements geth-specific functionality. // // If you want to use the standardized Ethereum RPC functionality, use ethclient.Client instead. @@ -100,6 +103,14 @@ func (ec *Client) GetProof(ctx context.Context, account common.Address, keys []s // Avoid keys being 'null'. if keys == nil { keys = []string{} + } else { + // Remove duplicate keys + keys = removeDuplicates(keys) + } + + // Reject requests with too many keys + if len(keys) > MaxGetProofKeys { + return nil, fmt.Errorf("too many keys: %d (maximum %d)", len(keys), MaxGetProofKeys) } var res accountResult @@ -251,6 +262,9 @@ func toCallArg(msg ethereum.CallMsg) interface{} { if msg.BlobHashes != nil { arg["blobVersionedHashes"] = msg.BlobHashes } + if msg.AuthorizationList != nil { + arg["authorizationList"] = msg.AuthorizationList + } return arg } @@ -348,3 +362,21 @@ func (o BlockOverrides) MarshalJSON() ([]byte, error) { } return json.Marshal(output) } + +// removeDuplicates removes duplicate values from a string slice while preserving order +func removeDuplicates(slice []string) []string { + seen := make(map[string]struct{}) + result := make([]string, 0, len(slice)) + + for _, item := range slice { + // Skip empty strings because they are considered invalid or irrelevant in this context. + if item == "" { + continue + } + if _, exists := seen[item]; !exists { + seen[item] = struct{}{} + result = append(result, item) + } + } + return result +} diff --git a/ethclient/gethclient/gethclient_test.go b/ethclient/gethclient/gethclient_test.go index e75607bce1..322af8436d 100644 --- a/ethclient/gethclient/gethclient_test.go +++ b/ethclient/gethclient/gethclient_test.go @@ -599,3 +599,83 @@ func testCallContractWithBlockOverrides(t *testing.T, client *rpc.Client) { t.Fatalf("unexpected result: %x", res) } } + +func TestGetProofDeduplication(t *testing.T) { + backend, _ := newTestBackend(t) + client := backend.Attach() + defer backend.Close() + defer client.Close() + + ec := New(client) + + // Test cases + tests := []struct { + name string + keys []string + expected int + }{ + { + name: "nil keys", + keys: nil, + expected: 0, + }, + { + name: "empty keys", + keys: []string{}, + expected: 0, + }, + { + name: "no duplicates", + keys: []string{testSlot.String(), testSlot.String()}, + expected: 1, + }, + { + name: "with empty strings", + keys: []string{testSlot.String(), "", testSlot.String()}, + expected: 1, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result, err := ec.GetProof(context.Background(), testAddr, tt.keys, nil) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if len(result.StorageProof) != tt.expected { + t.Errorf("expected %d storage proofs, got %d", tt.expected, len(result.StorageProof)) + } + }) + } +} + +func TestGetProofMaxKeys(t *testing.T) { + backend, _ := newTestBackend(t) + client := backend.Attach() + defer backend.Close() + defer client.Close() + + ec := New(client) + + // Create a slice with MaxGetProofKeys + 1 keys + keys := make([]string, MaxGetProofKeys+1) + for i := 0; i < MaxGetProofKeys+1; i++ { + keys[i] = common.BigToHash(big.NewInt(int64(i))).String() + } + + // Test that it fails with too many keys + _, err := ec.GetProof(context.Background(), testAddr, keys, nil) + if err == nil { + t.Error("expected error for too many keys, got nil") + } + if err.Error() != "too many keys: 513 (maximum 512)" { + t.Errorf("unexpected error message: %v", err) + } + + // Test that it succeeds with exactly MaxGetProofKeys + keys = keys[:MaxGetProofKeys] + _, err = ec.GetProof(context.Background(), testAddr, keys, nil) + if err != nil { + t.Errorf("unexpected error with valid number of keys: %v", err) + } +} diff --git a/ethdb/pebble/pebble.go b/ethdb/pebble/pebble.go index 3e217e1b13..54c96bc779 100644 --- a/ethdb/pebble/pebble.go +++ b/ethdb/pebble/pebble.go @@ -146,7 +146,7 @@ func (l panicLogger) Fatalf(format string, args ...interface{}) { // New returns a wrapped pebble DB object. The namespace is the prefix that the // metrics reporting should use for surfacing internal stats. -func New(file string, cache int, handles int, namespace string, readonly bool) (*Database, error) { +func New(file string, cache int, handles int, namespace string, readonly bool, ephemeral bool) (*Database, error) { // Ensure we have some minimal caching and file guarantees if cache < minCache { cache = minCache diff --git a/interfaces.go b/interfaces.go index 53e2e3ae16..54a215d6e7 100644 --- a/interfaces.go +++ b/interfaces.go @@ -156,6 +156,9 @@ type CallMsg struct { // For BlobTxType BlobGasFeeCap *big.Int BlobHashes []common.Hash + + // For SetCodeTxType + AuthorizationList []types.SetCodeAuthorization } // A ContractCaller provides contract calls, essentially transactions that are executed by diff --git a/internal/debug/api.go b/internal/debug/api.go index 5e93585bf8..1bac36e908 100644 --- a/internal/debug/api.go +++ b/internal/debug/api.go @@ -35,6 +35,7 @@ import ( "sync" "time" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/log" "github.com/hashicorp/go-bexpr" ) @@ -237,6 +238,24 @@ func (*HandlerT) SetGCPercent(v int) int { return debug.SetGCPercent(v) } +// SetMemoryLimit sets the GOMEMLIMIT for the process. It returns the previous limit. +// Note: +// +// - The input limit is provided as bytes. A negative input does not adjust the limit +// +// - A zero limit or a limit that's lower than the amount of memory used by the Go +// runtime may cause the garbage collector to run nearly continuously. However, +// the application may still make progress. +// +// - Setting the limit too low will cause Geth to become unresponsive. +// +// - Geth also allocates memory off-heap, particularly for fastCache and Pebble, +// which can be non-trivial (a few gigabytes by default). +func (*HandlerT) SetMemoryLimit(limit int64) int64 { + log.Info("Setting memory limit", "size", common.PrettyDuration(limit)) + return debug.SetMemoryLimit(limit) +} + func writeProfile(name, file string) error { p := pprof.Lookup(name) log.Info("Writing profile records", "count", p.Count(), "type", name, "dump", file) diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index fdd3f85352..24b734180d 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -564,7 +564,7 @@ func (api *BlockChainAPI) getFinalizedNumber(ctx context.Context, verifiedValida lastHeader := latestHeader confirmedValSet := make(map[common.Address]struct{}, valLen) confirmedValSet[lastHeader.Coinbase] = struct{}{} - epochLength := int(500) // TODO(Nathan)(BEP-524 Phase Two): use `maxwellEpochLength` instead + epochLength := int(1000) // maxwellEpochLength for count := 1; int64(len(confirmedValSet)) < verifiedValidatorNum && count <= epochLength && lastHeader.Number.Int64() > max(fastFinalizedHeader.Number.Int64(), 1); count++ { lastHeader, err = api.b.HeaderByHash(ctx, lastHeader.ParentHash) if err != nil { // impossible @@ -1072,8 +1072,7 @@ func (api *BlockChainAPI) Call(ctx context.Context, args TransactionArgs, blockN if err != nil { return nil, err } - // If the result contains a revert reason, try to unpack and return it. - if len(result.Revert()) > 0 { + if errors.Is(result.Err, vm.ErrExecutionReverted) { return nil, newRevertError(result.Revert()) } return result.Return(), result.Err @@ -1153,7 +1152,7 @@ func DoEstimateGas(ctx context.Context, b Backend, args TransactionArgs, blockNr // Run the gas estimation and wrap any revertals into a custom return estimate, revert, err := gasestimator.Estimate(ctx, call, opts, gasCap) if err != nil { - if len(revert) > 0 { + if errors.Is(err, vm.ErrExecutionReverted) { return 0, newRevertError(revert) } return 0, err @@ -1633,12 +1632,13 @@ type accessListResult struct { // CreateAccessList creates an EIP-2930 type AccessList for the given transaction. // Reexec and BlockNrOrHash can be specified to create the accessList on top of a certain state. -func (api *BlockChainAPI) CreateAccessList(ctx context.Context, args TransactionArgs, blockNrOrHash *rpc.BlockNumberOrHash) (*accessListResult, error) { +// StateOverrides can be used to create the accessList while taking into account state changes from previous transactions. +func (api *BlockChainAPI) CreateAccessList(ctx context.Context, args TransactionArgs, blockNrOrHash *rpc.BlockNumberOrHash, stateOverrides *override.StateOverride) (*accessListResult, error) { bNrOrHash := rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber) if blockNrOrHash != nil { bNrOrHash = *blockNrOrHash } - acl, gasUsed, vmerr, err := AccessList(ctx, api.b, bNrOrHash, args) + acl, gasUsed, vmerr, err := AccessList(ctx, api.b, bNrOrHash, args, stateOverrides) if err != nil { return nil, err } @@ -1652,13 +1652,22 @@ func (api *BlockChainAPI) CreateAccessList(ctx context.Context, args Transaction // AccessList creates an access list for the given transaction. // If the accesslist creation fails an error is returned. // If the transaction itself fails, an vmErr is returned. -func AccessList(ctx context.Context, b Backend, blockNrOrHash rpc.BlockNumberOrHash, args TransactionArgs) (acl types.AccessList, gasUsed uint64, vmErr error, err error) { +func AccessList(ctx context.Context, b Backend, blockNrOrHash rpc.BlockNumberOrHash, args TransactionArgs, stateOverrides *override.StateOverride) (acl types.AccessList, gasUsed uint64, vmErr error, err error) { // Retrieve the execution context db, header, err := b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash) if db == nil || err != nil { return nil, 0, nil, err } + // Apply state overrides immediately after StateAndHeaderByNumberOrHash. + // If not applied here, there could be cases where user-specified overrides (e.g., nonce) + // may conflict with default values from the database, leading to inconsistencies. + if stateOverrides != nil { + if err := stateOverrides.Apply(db, nil); err != nil { + return nil, 0, nil, err + } + } + // Ensure any missing fields are filled, extract the recipient and input data if err = args.setFeeDefaults(ctx, b, header); err != nil { return nil, 0, nil, err @@ -1682,10 +1691,33 @@ func AccessList(ctx context.Context, b Backend, blockNrOrHash rpc.BlockNumberOrH // Retrieve the precompiles since they don't need to be added to the access list precompiles := vm.ActivePrecompiles(b.ChainConfig().Rules(header.Number, isPostMerge, header.Time)) + // addressesToExclude contains sender, receiver, precompiles and valid authorizations + addressesToExclude := map[common.Address]struct{}{args.from(): {}, to: {}} + for _, addr := range precompiles { + addressesToExclude[addr] = struct{}{} + } + + // Prevent redundant operations if args contain more authorizations than EVM may handle + maxAuthorizations := uint64(*args.Gas) / params.CallNewAccountGas + if uint64(len(args.AuthorizationList)) > maxAuthorizations { + return nil, 0, nil, errors.New("insufficient gas to process all authorizations") + } + + for _, auth := range args.AuthorizationList { + // Duplicating stateTransition.validateAuthorization() logic + if (!auth.ChainID.IsZero() && auth.ChainID.CmpBig(b.ChainConfig().ChainID) != 0) || auth.Nonce+1 < auth.Nonce { + continue + } + + if authority, err := auth.Authority(); err == nil { + addressesToExclude[authority] = struct{}{} + } + } + // Create an initial tracer - prevTracer := logger.NewAccessListTracer(nil, args.from(), to, precompiles) + prevTracer := logger.NewAccessListTracer(nil, addressesToExclude) if args.AccessList != nil { - prevTracer = logger.NewAccessListTracer(*args.AccessList, args.from(), to, precompiles) + prevTracer = logger.NewAccessListTracer(*args.AccessList, addressesToExclude) } for { if err := ctx.Err(); err != nil { @@ -1702,7 +1734,7 @@ func AccessList(ctx context.Context, b Backend, blockNrOrHash rpc.BlockNumberOrH msg := args.ToMessage(header.BaseFee, true, true) // Apply the transaction with the access list tracer - tracer := logger.NewAccessListTracer(accessList, args.from(), to, precompiles) + tracer := logger.NewAccessListTracer(accessList, addressesToExclude) config := vm.Config{Tracer: tracer.Hooks(), NoBaseFee: true} evm := b.GetEVM(ctx, statedb, header, &config, nil) diff --git a/internal/ethapi/api_test.go b/internal/ethapi/api_test.go index 75c48c8246..774d2db699 100644 --- a/internal/ethapi/api_test.go +++ b/internal/ethapi/api_test.go @@ -707,6 +707,11 @@ func TestEstimateGas(t *testing.T) { b.SetPoS() })) + setCodeAuthorization, _ := types.SignSetCode(accounts[0].key, types.SetCodeAuthorization{ + Address: accounts[0].addr, + Nonce: uint64(genBlocks + 1), + }) + var testSuite = []struct { blockNumber rpc.BlockNumber call TransactionArgs @@ -885,6 +890,50 @@ func TestEstimateGas(t *testing.T) { }, want: 21000, }, + // Should be able to estimate SetCodeTx. + { + blockNumber: rpc.LatestBlockNumber, + call: TransactionArgs{ + From: &accounts[0].addr, + To: &accounts[1].addr, + Value: (*hexutil.Big)(big.NewInt(0)), + AuthorizationList: []types.SetCodeAuthorization{setCodeAuthorization}, + }, + want: 46000, + }, + // Should retrieve the code of 0xef0001 || accounts[0].addr and return an invalid opcode error. + { + blockNumber: rpc.LatestBlockNumber, + call: TransactionArgs{ + From: &accounts[0].addr, + To: &accounts[0].addr, + Value: (*hexutil.Big)(big.NewInt(0)), + AuthorizationList: []types.SetCodeAuthorization{setCodeAuthorization}, + }, + expectErr: errors.New("invalid opcode: opcode 0xef not defined"), + }, + // SetCodeTx with empty authorization list should fail. + { + blockNumber: rpc.LatestBlockNumber, + call: TransactionArgs{ + From: &accounts[0].addr, + To: &common.Address{}, + Value: (*hexutil.Big)(big.NewInt(0)), + AuthorizationList: []types.SetCodeAuthorization{}, + }, + expectErr: core.ErrEmptyAuthList, + }, + // SetCodeTx with nil `to` should fail. + { + blockNumber: rpc.LatestBlockNumber, + call: TransactionArgs{ + From: &accounts[0].addr, + To: nil, + Value: (*hexutil.Big)(big.NewInt(0)), + AuthorizationList: []types.SetCodeAuthorization{setCodeAuthorization}, + }, + expectErr: core.ErrSetCodeTxCreate, + }, } for i, tc := range testSuite { result, err := api.EstimateGas(context.Background(), tc.call, &rpc.BlockNumberOrHash{BlockNumber: &tc.blockNumber}, &tc.overrides, &tc.blockOverrides) @@ -894,7 +943,7 @@ func TestEstimateGas(t *testing.T) { continue } if !errors.Is(err, tc.expectErr) { - if !reflect.DeepEqual(err, tc.expectErr) { + if err.Error() != tc.expectErr.Error() { t.Errorf("test %d: error mismatch, want %v, have %v", i, tc.expectErr, err) } } @@ -3761,3 +3810,76 @@ func testRPCResponseWithFile(t *testing.T, testid int, result interface{}, rpc s func addressToHash(a common.Address) common.Hash { return common.BytesToHash(a.Bytes()) } + +func TestCreateAccessListWithStateOverrides(t *testing.T) { + // Initialize test backend + genesis := &core.Genesis{ + Config: params.TestChainConfig, + Alloc: types.GenesisAlloc{ + common.HexToAddress("0x71562b71999873db5b286df957af199ec94617f7"): {Balance: big.NewInt(1000000000000000000)}, + }, + } + backend := newTestBackend(t, 1, genesis, ethash.NewFaker(), nil) + + // Create a new BlockChainAPI instance + api := NewBlockChainAPI(backend) + + // Create test contract code - a simple storage contract + // + // SPDX-License-Identifier: MIT + // pragma solidity ^0.8.0; + // + // contract SimpleStorage { + // uint256 private value; + // + // function retrieve() public view returns (uint256) { + // return value; + // } + // } + var ( + contractCode = hexutil.Bytes(common.Hex2Bytes("6080604052348015600f57600080fd5b506004361060285760003560e01c80632e64cec114602d575b600080fd5b60336047565b604051603e91906067565b60405180910390f35b60008054905090565b6000819050919050565b6061816050565b82525050565b6000602082019050607a6000830184605a565b9291505056")) + // Create state overrides with more complete state + contractAddr = common.HexToAddress("0x1234567890123456789012345678901234567890") + nonce = hexutil.Uint64(1) + overrides = &override.StateOverride{ + contractAddr: override.OverrideAccount{ + Code: &contractCode, + Balance: (*hexutil.Big)(big.NewInt(1000000000000000000)), + Nonce: &nonce, + State: map[common.Hash]common.Hash{ + common.Hash{}: common.HexToHash("0x000000000000000000000000000000000000000000000000000000000000002a"), + }, + }, + } + ) + + // Create transaction arguments with gas and value + var ( + from = common.HexToAddress("0x71562b71999873db5b286df957af199ec94617f7") + data = hexutil.Bytes(common.Hex2Bytes("2e64cec1")) // retrieve() + gas = hexutil.Uint64(100000) + args = TransactionArgs{ + From: &from, + To: &contractAddr, + Data: &data, + Gas: &gas, + Value: new(hexutil.Big), + } + ) + // Call CreateAccessList + result, err := api.CreateAccessList(context.Background(), args, nil, overrides) + if err != nil { + t.Fatalf("Failed to create access list: %v", err) + } + if err != nil || result == nil { + t.Fatalf("Failed to create access list: %v", err) + } + require.NotNil(t, result.Accesslist) + + // Verify access list contains the contract address and storage slot + expected := &types.AccessList{{ + Address: contractAddr, + StorageKeys: []common.Hash{{}}, + }} + require.Equal(t, expected, result.Accesslist) +} diff --git a/internal/ethapi/errors.go b/internal/ethapi/errors.go index ae38061234..62c401ab75 100644 --- a/internal/ethapi/errors.go +++ b/internal/ethapi/errors.go @@ -44,6 +44,10 @@ func (e *revertError) ErrorData() interface{} { return e.reason } +func (e *revertError) Error() string { + return fmt.Sprintf("%v: %s", e.error, e.reason) +} + // newRevertError creates a revertError instance with the provided revert data. func newRevertError(revert []byte) *revertError { err := vm.ErrExecutionReverted diff --git a/internal/web3ext/web3ext.go b/internal/web3ext/web3ext.go index f901732d78..62e612a9ea 100644 --- a/internal/web3ext/web3ext.go +++ b/internal/web3ext/web3ext.go @@ -255,6 +255,11 @@ web3._extend({ call: 'debug_setGCPercent', params: 1, }), + new web3._extend.Method({ + name: 'setMemoryLimit', + call: 'debug_setMemoryLimit', + params: 1, + }), new web3._extend.Method({ name: 'memStats', call: 'debug_memStats', diff --git a/log/root.go b/log/root.go index c0c73a2632..021f5ee615 100644 --- a/log/root.go +++ b/log/root.go @@ -3,19 +3,25 @@ package log import ( "log/slog" "os" - "sync/atomic" + "sync" "time" ) -var root atomic.Value +var ( + rootLock sync.RWMutex + root Logger +) func init() { - root.Store(&logger{slog.New(DiscardHandler())}) + root = &logger{slog.New(DiscardHandler())} } // SetDefault sets the default global logger func SetDefault(l Logger) { - root.Store(l) + rootLock.Lock() + defer rootLock.Unlock() + + root = l if lg, ok := l.(*logger); ok { slog.SetDefault(lg.inner) } @@ -23,7 +29,10 @@ func SetDefault(l Logger) { // Root returns the root logger func Root() Logger { - return root.Load().(Logger) + rootLock.RLock() + defer rootLock.RUnlock() + + return root } // The following functions bypass the exported logger methods (logger.Debug, diff --git a/log/root_test.go b/log/root_test.go new file mode 100644 index 0000000000..b9b22af669 --- /dev/null +++ b/log/root_test.go @@ -0,0 +1,19 @@ +package log + +import ( + "testing" +) + +// SetDefault should properly set the default logger when custom loggers are +// provided. +func TestSetDefaultCustomLogger(t *testing.T) { + type customLogger struct { + Logger // Implement the Logger interface + } + + customLog := &customLogger{} + SetDefault(customLog) + if Root() != customLog { + t.Error("expected custom logger to be set as default") + } +} diff --git a/miner/bid_simulator.go b/miner/bid_simulator.go index da5be60841..f398811c31 100644 --- a/miner/bid_simulator.go +++ b/miner/bid_simulator.go @@ -54,6 +54,7 @@ var ( Timeout: 5 * time.Second, Transport: transport, } + errBetterBid = errors.New("simulation abort due to better bid arrived") ) type bidWorker interface { @@ -113,6 +114,7 @@ type bidSimulator struct { simBidMu sync.RWMutex simulatingBid map[common.Hash]*BidRuntime // prevBlockHash -> bidRuntime, in the process of simulation + bidsToSim map[uint64][]*BidRuntime // blockNumber --> bidRuntime list, used to discard envs maxBidsPerBuilder uint32 // Maximum number of bids allowed per builder per block } @@ -143,6 +145,7 @@ func newBidSimulator( bestBid: make(map[common.Hash]*BidRuntime), bestBidToRun: make(map[common.Hash]*types.Bid), simulatingBid: make(map[common.Hash]*BidRuntime), + bidsToSim: make(map[uint64][]*BidRuntime), } if delayLeftOver != nil { b.delayLeftOver = *delayLeftOver @@ -265,12 +268,6 @@ func (b *bidSimulator) SetBestBid(prevBlockHash common.Hash, bid *BidRuntime) { b.bestBidMu.Lock() defer b.bestBidMu.Unlock() - // must discard the environment of the last best bid, otherwise it will cause memory leak - last := b.bestBid[prevBlockHash] - if last != nil && last.env != nil { - last.env.discard() - } - b.bestBid[prevBlockHash] = bid } @@ -330,6 +327,21 @@ func (b *bidSimulator) RemoveSimulatingBid(prevBlockHash common.Hash) { delete(b.simulatingBid, prevBlockHash) } +func (b *bidSimulator) AddBidToSim(bidRuntime *BidRuntime) { + b.simBidMu.Lock() + defer b.simBidMu.Unlock() + + if bidRuntime == nil || bidRuntime.bid == nil { + return + } + + blockNumber := bidRuntime.bid.BlockNumber + if _, ok := b.bidsToSim[blockNumber]; !ok { + b.bidsToSim[blockNumber] = make([]*BidRuntime, 0, 10) + } + b.bidsToSim[blockNumber] = append(b.bidsToSim[blockNumber], bidRuntime) +} + func (b *bidSimulator) mainLoop() { defer b.chainHeadSub.Unsubscribe() @@ -478,7 +490,7 @@ func (b *bidSimulator) newBidLoop() { // get block interval for current block by using parent header func (b *bidSimulator) getBlockInterval(parentHeader *types.Header) uint64 { if parentHeader == nil { - return 1500 // lorentzBlockInterval + return 750 // maxwellBlockInterval } parlia, _ := b.engine.(*parlia.Parlia) // only `Number` and `ParentHash` are used when `BlockInterval` @@ -501,20 +513,19 @@ func (b *bidSimulator) clearLoop() { delete(b.pending, blockNumber) b.pendingMu.Unlock() - b.bestBidMu.Lock() - if bid, ok := b.bestBid[parentHash]; ok { - bid.env.discard() + clearThreshold := b.chain.GetFinalizedNumber(b.chain.GetHeaderByHash(parentHash)) + if blockNumber > b.chain.TriesInMemory() { + clearThreshold = max(clearThreshold, blockNumber-b.chain.TriesInMemory()) } - delete(b.bestBid, parentHash) + + b.bestBidMu.Lock() for k, v := range b.bestBid { - if v.bid.BlockNumber <= blockNumber-b.chain.TriesInMemory() { - v.env.discard() + if v.bid.BlockNumber <= clearThreshold { delete(b.bestBid, k) } } - delete(b.bestBidToRun, parentHash) for k, v := range b.bestBidToRun { - if v.BlockNumber <= blockNumber-b.chain.TriesInMemory() { + if v.BlockNumber <= clearThreshold { delete(b.bestBidToRun, k) } } @@ -522,11 +533,21 @@ func (b *bidSimulator) clearLoop() { b.simBidMu.Lock() for k, v := range b.simulatingBid { - if v.bid.BlockNumber <= blockNumber-b.chain.TriesInMemory() { - v.env.discard() + if v.bid.BlockNumber <= clearThreshold { delete(b.simulatingBid, k) } } + for blockNumber, bidList := range b.bidsToSim { + if blockNumber <= clearThreshold { + for _, bid := range bidList { + if bid.env != nil { + // envs for simulating only discard here + bid.env.discard() + } + } + delete(b.bidsToSim, blockNumber) + } + } b.simBidMu.Unlock() } @@ -631,17 +652,14 @@ func (b *bidSimulator) simBid(interruptCh chan int32, bidRuntime *BidRuntime) { if bidRuntime.env != nil { logCtx = append(logCtx, "gasLimit", bidRuntime.env.header.GasLimit) - - if err != nil || !success { - bidRuntime.env.discard() - } } if err != nil { logCtx = append(logCtx, "err", err) log.Info("BidSimulator: simulation failed", logCtx...) - - go b.reportIssue(bidRuntime, err) + if err != errBetterBid { + go b.reportIssue(bidRuntime, err) + } } b.RemoveSimulatingBid(parentHash) @@ -675,6 +693,7 @@ func (b *bidSimulator) simBid(interruptCh chan int32, bidRuntime *BidRuntime) { }, false); err != nil { return } + b.AddBidToSim(bidRuntime) // if the left time is not enough to do simulation, return delay := b.engine.Delay(b.chain, bidRuntime.env.header, &b.delayLeftOver) @@ -713,7 +732,7 @@ func (b *bidSimulator) simBid(interruptCh chan int32, bidRuntime *BidRuntime) { for _, tx := range bidRuntime.bid.Txs { select { case <-interruptCh: - err = errors.New("simulation abort due to better bid arrived") + err = errBetterBid return case <-b.exitCh: @@ -814,14 +833,6 @@ func (b *bidSimulator) simBid(interruptCh chan int32, bidRuntime *BidRuntime) { return } - // check bid size - if bidRuntime.env.size+blockReserveSize > params.MaxMessageSize { - log.Error("BidSimulator: failed to check bid size", "builder", bidRuntime.bid.Builder, - "bidHash", bidRuntime.bid.Hash(), "env.size", bidRuntime.env.size) - err = errors.New("invalid bid size") - return - } - bestBid := b.GetBestBid(parentHash) if bestBid == nil { winResult := "true[first]" @@ -993,7 +1004,6 @@ func (r *BidRuntime) commitTransaction(chain *core.BlockChain, chainConfig *para } r.env.tcount++ - r.env.size += uint32(tx.Size()) return nil } diff --git a/miner/minerconfig/config.go b/miner/minerconfig/config.go index 7c37112d44..d9d0fb9e27 100644 --- a/miner/minerconfig/config.go +++ b/miner/minerconfig/config.go @@ -28,7 +28,9 @@ import ( ) var ( - defaultDelayLeftOver = 50 * time.Millisecond + defaultDelayLeftOver = 50 * time.Millisecond + defaultRecommit = 10 * time.Second + defaultMaxWaitProposalInSecs = uint64(45) // default configurations for MEV defaultGreedyMergeTx bool = true defaultValidatorCommission uint64 = 100 @@ -39,17 +41,16 @@ var ( // Config is the configuration parameters of mining. type Config struct { - Etherbase common.Address `toml:",omitempty"` // Public address for block mining rewards - ExtraData hexutil.Bytes `toml:",omitempty"` // Block extra data set by the miner - DelayLeftOver *time.Duration `toml:",omitempty"` // Time reserved to finalize a block(calculate root, distribute income...) - GasFloor uint64 // Target gas floor for mined blocks. - GasCeil uint64 // Target gas ceiling for mined blocks. - GasPrice *big.Int // Minimum gas price for mining a transaction - Recommit time.Duration // The time interval for miner to re-create mining work. - VoteEnable bool // Whether to vote when mining - MaxWaitProposalInSecs uint64 // The maximum time to wait for the proposal to be done, it's aimed to prevent validator being slashed when restarting - - DisableVoteAttestation bool // Whether to skip assembling vote attestation + Etherbase common.Address `toml:",omitempty"` // Public address for block mining rewards + ExtraData hexutil.Bytes `toml:",omitempty"` // Block extra data set by the miner + DelayLeftOver *time.Duration `toml:",omitempty"` // Time reserved to finalize a block(calculate root, distribute income...) + GasFloor uint64 // Target gas floor for mined blocks. + GasCeil uint64 // Target gas ceiling for mined blocks. + GasPrice *big.Int // Minimum gas price for mining a transaction + Recommit *time.Duration `toml:",omitempty"` // The time interval for miner to re-create mining work. + VoteEnable bool // Whether to vote when mining + MaxWaitProposalInSecs *uint64 `toml:",omitempty"` // The maximum time to wait for the proposal to be done, it's aimed to prevent validator being slashed when restarting + DisableVoteAttestation bool // Whether to skip assembling vote attestation Mev MevConfig // Mev configuration } @@ -63,12 +64,12 @@ var DefaultConfig = Config{ // consensus-layer usually will wait a half slot of time(6s) // for payload generation. It should be enough for Geth to // run 3 rounds. - Recommit: 3 * time.Second, + Recommit: &defaultRecommit, DelayLeftOver: &defaultDelayLeftOver, - // The default value is set to 30 seconds. - // Because the avg restart time in mainnet is around 30s, so the node try to wait for the next multi-proposals to be done. - MaxWaitProposalInSecs: 30, + // The default value is set to 45 seconds. + // Because the avg restart time in mainnet could be 30+ seconds, so the node try to wait for the next multi-proposals to be done. + MaxWaitProposalInSecs: &defaultMaxWaitProposalInSecs, Mev: DefaultMevConfig, } @@ -106,11 +107,20 @@ func ApplyDefaultMinerConfig(cfg *Config) { log.Warn("ApplyDefaultMinerConfig cfg == nil") return } + // check [Eth.Miner] if cfg.DelayLeftOver == nil { cfg.DelayLeftOver = &defaultDelayLeftOver log.Info("ApplyDefaultMinerConfig", "DelayLeftOver", *cfg.DelayLeftOver) } + if cfg.MaxWaitProposalInSecs == nil { + cfg.MaxWaitProposalInSecs = &defaultMaxWaitProposalInSecs + log.Info("ApplyDefaultMinerConfig", "MaxWaitProposalInSecs", *cfg.MaxWaitProposalInSecs) + } + if cfg.Recommit == nil { + cfg.Recommit = &defaultRecommit + log.Info("ApplyDefaultMinerConfig", "Recommit", *cfg.Recommit) + } // check [Eth.Miner.Mev] if cfg.Mev.GreedyMergeTx == nil { diff --git a/miner/worker.go b/miner/worker.go index 8a5bb0ebe1..8684909879 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -69,12 +69,6 @@ const ( // the current 4 mining loops could have asynchronous risk of mining block with // save height, keep recently mined blocks to avoid double sign for safety, recentMinedCacheLimit = 20 - - // Reserve block size for the following 3 components: - // a. System transactions at the end of the block - // b. Seal in the block header - // c. Overhead from RLP encoding - blockReserveSize = 100 * 1024 ) var ( @@ -100,7 +94,6 @@ type environment struct { signer types.Signer state *state.StateDB // apply state changes here tcount int // tx count in cycle - size uint32 // almost accurate block size, gasPool *core.GasPool // available gas used to pack transactions coinbase common.Address evm *vm.EVM @@ -120,7 +113,6 @@ func (env *environment) copy() *environment { signer: env.signer, state: env.state.Copy(), tcount: env.tcount, - size: env.size, coinbase: env.coinbase, header: types.CopyHeader(env.header), receipts: copyReceipts(env.receipts), @@ -290,7 +282,10 @@ func newWorker(config *minerconfig.Config, engine consensus.Engine, eth Backend, worker.chainHeadSub = eth.BlockChain().SubscribeChainHeadEvent(worker.chainHeadCh) // Sanitize recommit interval if the user-specified one is too short. - recommit := worker.config.Recommit + recommit := minRecommitInterval + if worker.config.Recommit != nil && *worker.config.Recommit > minRecommitInterval { + recommit = *worker.config.Recommit + } if recommit < minRecommitInterval { log.Warn("Sanitizing miner recommit interval", "provided", recommit, "updated", minRecommitInterval) recommit = minRecommitInterval @@ -465,10 +460,12 @@ func (w *worker) newWorkLoop(recommit time.Duration) { if p, ok := w.engine.(*parlia.Parlia); ok { signedRecent, err := p.SignRecently(w.chain, head.Header) if err != nil { + timer.Reset(recommit) log.Debug("Not allowed to propose block", "err", err) continue } if signedRecent { + timer.Reset(recommit) log.Info("Signed recently, must wait") continue } @@ -817,6 +814,7 @@ func (w *worker) commitTransactions(env *environment, plainTxs, blobTxs *transac processorCapacity = plainTxs.CurrentSize() } bloomProcessors := core.NewAsyncReceiptBloomGenerator(processorCapacity) + defer bloomProcessors.Close() stopPrefetchCh := make(chan struct{}) defer close(stopPrefetchCh) @@ -922,13 +920,6 @@ LOOP: txs.Pop() continue } - // If we don't have enough size left for the next transaction, skip it. - if env.size+uint32(tx.Size())+blockReserveSize > params.MaxMessageSize { - log.Trace("Not enough size left for transaction", "hash", ltx.Hash, - "env.size", env.size, "needed", uint32(tx.Size())) - txs.Pop() - continue - } // Error may be ignored here. The error has already been checked // during transaction acceptance in the transaction pool. from, _ := types.Sender(env.signer, tx) @@ -954,7 +945,6 @@ LOOP: // Everything ok, collect the logs and shift in the next transaction from the same account coalescedLogs = append(coalescedLogs, logs...) env.tcount++ - env.size += uint32(tx.Size()) // size of BlobTxSidecar included txs.Shift() default: @@ -964,7 +954,6 @@ LOOP: txs.Pop() } } - bloomProcessors.Close() if !w.isRunning() && len(coalescedLogs) > 0 { // We don't push the pendingLogsEvent while we are sealing. The reason is that // when we are sealing, the worker will regenerate a sealing block every 3 seconds. @@ -1080,7 +1069,7 @@ func (w *worker) prepareWork(genParams *generateParams, witness bool) (*environm return nil, err } - // Handle upgrade build-in system contract code + // Handle upgrade built-in system contract code systemcontracts.TryUpdateBuildInSystemContract(w.chainConfig, header.Number, parent.Time, header.Time, env.state, true) if header.ParentBeaconRoot != nil { @@ -1090,9 +1079,6 @@ func (w *worker) prepareWork(genParams *generateParams, witness bool) (*environm if w.chainConfig.IsPrague(header.Number, header.Time) { core.ProcessParentBlockHash(header.ParentHash, env.evm) } - - env.size = uint32(env.header.Size()) - return env, nil } @@ -1187,7 +1173,7 @@ func (w *worker) generateWork(params *generateParams, witness bool) *newPayloadR if !params.noTxs { interrupt := new(atomic.Int32) - timer := time.AfterFunc(w.config.Recommit, func() { + timer := time.AfterFunc(*w.config.Recommit, func() { interrupt.Store(commitInterruptTimeout) }) defer timer.Stop() @@ -1406,7 +1392,6 @@ LOOP: // when out-turn, use bestWork to prevent bundle leakage. // when in-turn, compare with remote work. - from := bestWork.coinbase if w.bidFetcher != nil && bestWork.header.Difficulty.Cmp(diffInTurn) == 0 { inturnBlocksGauge.Inc(1) // We want to start sealing the block as late as possible here if mev is enabled, so we could give builder the chance to send their final bid. @@ -1453,11 +1438,10 @@ LOOP: bidWinGauge.Inc(1) bestWork = bestBid.env - from = bestBid.bid.Builder log.Info("[BUILDER BLOCK]", "block", bestWork.header.Number.Uint64(), - "builder", from, + "builder", bestBid.bid.Builder, "blockReward", weiToEtherStringF6(bestBid.packedBlockReward), "validatorReward", weiToEtherStringF6(bestBid.packedValidatorReward), "bid", bestBid.bid.Hash().TerminalString(), @@ -1466,8 +1450,6 @@ LOOP: } } - metrics.GetOrRegisterCounter(fmt.Sprintf("block/from/%v", from), nil).Inc(1) - w.commit(bestWork, w.fullTaskHook, true, start) // Swap out the old work with the new one, terminating any leftover @@ -1566,7 +1548,7 @@ func (w *worker) tryWaitProposalDoneWhenStopping() { } log.Info("Checking miner's next proposal block", "current", currentBlock, - "proposalStart", startBlock, "proposalEnd", endBlock, "maxWait", w.config.MaxWaitProposalInSecs) + "proposalStart", startBlock, "proposalEnd", endBlock, "maxWait", *w.config.MaxWaitProposalInSecs) if endBlock <= currentBlock { log.Warn("next proposal end block has passed, ignore") return @@ -1575,7 +1557,7 @@ func (w *worker) tryWaitProposalDoneWhenStopping() { if err != nil { log.Debug("failed to get BlockInterval when tryWaitProposalDoneWhenStopping") } - if startBlock > currentBlock && ((startBlock-currentBlock)*blockInterval/1000) > w.config.MaxWaitProposalInSecs { + if startBlock > currentBlock && ((startBlock-currentBlock)*blockInterval/1000) > *w.config.MaxWaitProposalInSecs { log.Warn("the next proposal start block is too far, just skip waiting") return } diff --git a/miner/worker_test.go b/miner/worker_test.go index 47d63105d6..b162c22ec2 100644 --- a/miner/worker_test.go +++ b/miner/worker_test.go @@ -66,9 +66,9 @@ var ( // Test transactions pendingTxs []*types.Transaction newTxs []*types.Transaction - + oneSecond = time.Second testConfig = &minerconfig.Config{ - Recommit: time.Second, + Recommit: &oneSecond, GasCeil: params.GenesisGasLimit, } ) diff --git a/node/api.go b/node/api.go index c11e2b97cd..97986cb608 100644 --- a/node/api.go +++ b/node/api.go @@ -257,6 +257,7 @@ func (api *adminAPI) StartWS(host *string, port *int, allowedOrigins *string, ap Modules: api.node.config.WSModules, Origins: api.node.config.WSOrigins, // ExposeAll: api.node.config.WSExposeAll, + messageSizeLimit: api.node.config.WSMessageSizeLimit, rpcEndpointConfig: rpcEndpointConfig{ batchItemLimit: api.node.config.BatchRequestLimit, batchResponseSizeLimit: api.node.config.BatchResponseMaxSize, diff --git a/node/config.go b/node/config.go index a3dcd3c9f8..bc8679756a 100644 --- a/node/config.go +++ b/node/config.go @@ -93,9 +93,17 @@ type Config struct { // DirectBroadcast enable directly broadcast mined block to all peers DirectBroadcast bool `toml:",omitempty"` + // EnableEVNFeatures enables the direct broadcast feature and disables the transaction broadcast feature. + // Used mainly for validators or sentry nodes, which can be recognized by the StakHub contract. + // Note: EVN = Enhanced Validator Network, Validator and sentry nodes need to set this flag to true. + EnableEVNFeatures bool `toml:",omitempty"` + // DisableSnapProtocol disable the snap protocol DisableSnapProtocol bool `toml:",omitempty"` + // EnableQuickBlockFetching indicates whether to fetch new blocks using new messages. + EnableQuickBlockFetching bool `toml:",omitempty"` + // RangeLimit enable 5000 blocks limit when handle range query RangeLimit bool `toml:",omitempty"` @@ -185,6 +193,10 @@ type Config struct { // private APIs to untrusted users is a major security risk. WSExposeAll bool `toml:",omitempty"` + // WSMessageSizeLimit specifies the maximum size in bytes for a single WebSocket message. + // If this field is zero, the default message size limit will be used. + WSMessageSizeLimit int64 `toml:",omitempty"` + // GraphQLCors is the Cross-Origin Resource Sharing header to send to requesting // clients. Please be aware that CORS is a browser enforced security, it's fully // useless for custom HTTP clients. diff --git a/node/database.go b/node/database.go index 3210cf0d1d..b01e535957 100644 --- a/node/database.go +++ b/node/database.go @@ -41,6 +41,10 @@ type openOptions struct { IsLastOffset bool PruneAncientData bool MultiDataBase bool + // Ephemeral means that filesystem sync operations should be avoided: + // data integrity in the face of a crash is not important. This option + // should typically be used in tests. + Ephemeral bool } // openDatabase opens both a disk-based key-value database such as leveldb or pebble, but also @@ -88,7 +92,7 @@ func openKeyValueDatabase(o openOptions) (ethdb.Database, error) { } if o.Type == rawdb.DBPebble || existingDb == rawdb.DBPebble { log.Info("Using pebble as the backing database") - return newPebbleDBDatabase(o.Directory, o.Cache, o.Handles, o.Namespace, o.ReadOnly) + return newPebbleDBDatabase(o.Directory, o.Cache, o.Handles, o.Namespace, o.ReadOnly, o.Ephemeral) } if o.Type == rawdb.DBLeveldb || existingDb == rawdb.DBLeveldb { log.Info("Using leveldb as the backing database") @@ -96,7 +100,7 @@ func openKeyValueDatabase(o openOptions) (ethdb.Database, error) { } // No pre-existing database, no user-requested one either. Default to Pebble. log.Info("Defaulting to pebble as the backing database") - return newPebbleDBDatabase(o.Directory, o.Cache, o.Handles, o.Namespace, o.ReadOnly) + return newPebbleDBDatabase(o.Directory, o.Cache, o.Handles, o.Namespace, o.ReadOnly, o.Ephemeral) } // newLevelDBDatabase creates a persistent key-value database without a freezer @@ -112,8 +116,8 @@ func newLevelDBDatabase(file string, cache int, handles int, namespace string, r // newPebbleDBDatabase creates a persistent key-value database without a freezer // moving immutable chain segments into cold storage. -func newPebbleDBDatabase(file string, cache int, handles int, namespace string, readonly bool) (ethdb.Database, error) { - db, err := pebble.New(file, cache, handles, namespace, readonly) +func newPebbleDBDatabase(file string, cache int, handles int, namespace string, readonly bool, ephemeral bool) (ethdb.Database, error) { + db, err := pebble.New(file, cache, handles, namespace, readonly, ephemeral) if err != nil { return nil, err } diff --git a/node/node.go b/node/node.go index 8a7b7d3cce..7fa1fd9aea 100644 --- a/node/node.go +++ b/node/node.go @@ -468,6 +468,7 @@ func (n *Node) startRPC() error { Modules: n.config.WSModules, Origins: n.config.WSOrigins, prefix: n.config.WSPathPrefix, + messageSizeLimit: n.config.WSMessageSizeLimit, rpcEndpointConfig: rpcConfig, }); err != nil { return err diff --git a/node/rpcstack.go b/node/rpcstack.go index 6d3828ec2b..b1082b5b51 100644 --- a/node/rpcstack.go +++ b/node/rpcstack.go @@ -47,9 +47,10 @@ type httpConfig struct { // wsConfig is the JSON-RPC/Websocket configuration type wsConfig struct { - Origins []string - Modules []string - prefix string // path prefix on which to mount ws handler + Origins []string + Modules []string + prefix string // path prefix on which to mount ws handler + messageSizeLimit int64 rpcEndpointConfig } @@ -349,7 +350,7 @@ func (h *httpServer) enableWS(apis []rpc.API, config wsConfig) error { } h.wsConfig = config h.wsHandler.Store(&rpcHandler{ - Handler: NewWSHandlerStack(srv.WebsocketHandler(config.Origins), config.jwtSecret), + Handler: NewWSHandlerStack(srv.WebsocketHandler(config.Origins, config.messageSizeLimit), config.jwtSecret), server: srv, }) return nil diff --git a/p2p/config.go b/p2p/config.go index f99dee1fe8..476a4510cc 100644 --- a/p2p/config.go +++ b/p2p/config.go @@ -87,6 +87,14 @@ type Config struct { // allowed to connect, even above the peer limit. TrustedNodes []*enode.Node + // EVNNodeIdsWhitelist is a list of NodeIDs that should be directly broadcast block to + // the list is another choice for non-validator nodes to get block quickly + EVNNodeIdsWhitelist []enode.ID `toml:",omitempty"` + + // ProxyedValidatorNodeIDs is a list of validator NodeIDs that the local node proxies, + // it usually used for sentry nodes + ProxyedValidatorNodeIDs []enode.ID `toml:",omitempty"` + // Connectivity can be restricted to certain IP networks. // If this option is set to a non-nil value, only hosts which match one of the // IP networks contained in the list are considered. diff --git a/p2p/config_toml.go b/p2p/config_toml.go index 03b76e6564..2264ab2584 100644 --- a/p2p/config_toml.go +++ b/p2p/config_toml.go @@ -16,31 +16,33 @@ var _ = (*configMarshaling)(nil) // MarshalTOML marshals as TOML. func (c Config) MarshalTOML() (interface{}, error) { type Config struct { - PrivateKey *ecdsa.PrivateKey `toml:"-"` - MaxPeers int - MaxPeersPerIP int `toml:",omitempty"` - MaxPendingPeers int `toml:",omitempty"` - DialRatio int `toml:",omitempty"` - NoDiscovery bool - DiscoveryV4 bool `toml:",omitempty"` - DiscoveryV5 bool `toml:",omitempty"` - Name string `toml:"-"` - BootstrapNodes []*enode.Node - BootstrapNodesV5 []*enode.Node `toml:",omitempty"` - StaticNodes []*enode.Node - VerifyNodes []*enode.Node - TrustedNodes []*enode.Node - NetRestrict *netutil.Netlist `toml:",omitempty"` - NodeDatabase string `toml:",omitempty"` - Protocols []Protocol `toml:"-" json:"-"` - ListenAddr string - DiscAddr string - NAT nat.Interface `toml:",omitempty"` - Dialer NodeDialer `toml:"-"` - NoDial bool `toml:",omitempty"` - EnableMsgEvents bool - Logger log.Logger `toml:"-"` - PeerFilterPatterns []string + PrivateKey *ecdsa.PrivateKey `toml:"-"` + MaxPeers int + MaxPeersPerIP int `toml:",omitempty"` + MaxPendingPeers int `toml:",omitempty"` + DialRatio int `toml:",omitempty"` + NoDiscovery bool + DiscoveryV4 bool `toml:",omitempty"` + DiscoveryV5 bool `toml:",omitempty"` + Name string `toml:"-"` + BootstrapNodes []*enode.Node + BootstrapNodesV5 []*enode.Node `toml:",omitempty"` + StaticNodes []*enode.Node + VerifyNodes []*enode.Node + TrustedNodes []*enode.Node + EVNNodeIdsWhitelist []enode.ID `toml:",omitempty"` + ProxyedValidatorNodeIDs []enode.ID `toml:",omitempty"` + NetRestrict *netutil.Netlist `toml:",omitempty"` + NodeDatabase string `toml:",omitempty"` + Protocols []Protocol `toml:"-" json:"-"` + ListenAddr string + DiscAddr string + NAT nat.Interface `toml:",omitempty"` + Dialer NodeDialer `toml:"-"` + NoDial bool `toml:",omitempty"` + EnableMsgEvents bool + Logger log.Logger `toml:"-"` + PeerFilterPatterns []string } var enc Config enc.PrivateKey = c.PrivateKey @@ -57,6 +59,8 @@ func (c Config) MarshalTOML() (interface{}, error) { enc.StaticNodes = c.StaticNodes enc.VerifyNodes = c.VerifyNodes enc.TrustedNodes = c.TrustedNodes + enc.EVNNodeIdsWhitelist = c.EVNNodeIdsWhitelist + enc.ProxyedValidatorNodeIDs = c.ProxyedValidatorNodeIDs enc.NetRestrict = c.NetRestrict enc.NodeDatabase = c.NodeDatabase enc.Protocols = c.Protocols @@ -74,31 +78,33 @@ func (c Config) MarshalTOML() (interface{}, error) { // UnmarshalTOML unmarshals from TOML. func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error { type Config struct { - PrivateKey *ecdsa.PrivateKey `toml:"-"` - MaxPeers *int - MaxPeersPerIP *int `toml:",omitempty"` - MaxPendingPeers *int `toml:",omitempty"` - DialRatio *int `toml:",omitempty"` - NoDiscovery *bool - DiscoveryV4 *bool `toml:",omitempty"` - DiscoveryV5 *bool `toml:",omitempty"` - Name *string `toml:"-"` - BootstrapNodes []*enode.Node - BootstrapNodesV5 []*enode.Node `toml:",omitempty"` - StaticNodes []*enode.Node - VerifyNodes []*enode.Node - TrustedNodes []*enode.Node - NetRestrict *netutil.Netlist `toml:",omitempty"` - NodeDatabase *string `toml:",omitempty"` - Protocols []Protocol `toml:"-" json:"-"` - ListenAddr *string - DiscAddr *string - NAT *configNAT `toml:",omitempty"` - Dialer NodeDialer `toml:"-"` - NoDial *bool `toml:",omitempty"` - EnableMsgEvents *bool - Logger log.Logger `toml:"-"` - PeerFilterPatterns []string + PrivateKey *ecdsa.PrivateKey `toml:"-"` + MaxPeers *int + MaxPeersPerIP *int `toml:",omitempty"` + MaxPendingPeers *int `toml:",omitempty"` + DialRatio *int `toml:",omitempty"` + NoDiscovery *bool + DiscoveryV4 *bool `toml:",omitempty"` + DiscoveryV5 *bool `toml:",omitempty"` + Name *string `toml:"-"` + BootstrapNodes []*enode.Node + BootstrapNodesV5 []*enode.Node `toml:",omitempty"` + StaticNodes []*enode.Node + VerifyNodes []*enode.Node + TrustedNodes []*enode.Node + EVNNodeIdsWhitelist []enode.ID `toml:",omitempty"` + ProxyedValidatorNodeIDs []enode.ID `toml:",omitempty"` + NetRestrict *netutil.Netlist `toml:",omitempty"` + NodeDatabase *string `toml:",omitempty"` + Protocols []Protocol `toml:"-" json:"-"` + ListenAddr *string + DiscAddr *string + NAT *configNAT `toml:",omitempty"` + Dialer NodeDialer `toml:"-"` + NoDial *bool `toml:",omitempty"` + EnableMsgEvents *bool + Logger log.Logger `toml:"-"` + PeerFilterPatterns []string } var dec Config if err := unmarshal(&dec); err != nil { @@ -146,6 +152,12 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error { if dec.TrustedNodes != nil { c.TrustedNodes = dec.TrustedNodes } + if dec.EVNNodeIdsWhitelist != nil { + c.EVNNodeIdsWhitelist = dec.EVNNodeIdsWhitelist + } + if dec.ProxyedValidatorNodeIDs != nil { + c.ProxyedValidatorNodeIDs = dec.ProxyedValidatorNodeIDs + } if dec.NetRestrict != nil { c.NetRestrict = dec.NetRestrict } diff --git a/p2p/enode/idscheme.go b/p2p/enode/idscheme.go index db7841c047..aedc4d81a4 100644 --- a/p2p/enode/idscheme.go +++ b/p2p/enode/idscheme.go @@ -90,6 +90,12 @@ func (V4ID) NodeAddr(r *enr.Record) []byte { return crypto.Keccak256(buf) } +func V4NodeIDFromPublicKey(data []byte) ID { + var id ID + copy(id[:], crypto.Keccak256(data[:])) + return id +} + // Secp256k1 is the "secp256k1" key, which holds a public key. type Secp256k1 ecdsa.PublicKey diff --git a/p2p/enode/node.go b/p2p/enode/node.go index d6f2ac7ff5..93ea8c1252 100644 --- a/p2p/enode/node.go +++ b/p2p/enode/node.go @@ -323,6 +323,15 @@ func (n ID) MarshalText() ([]byte, error) { // UnmarshalText implements the encoding.TextUnmarshaler interface. func (n *ID) UnmarshalText(text []byte) error { + // here can parse the V4 public key to id + if len(text) == 128 { + data, err := hex.DecodeString(strings.TrimPrefix(string(text), "0x")) + if err != nil { + return err + } + *n = V4NodeIDFromPublicKey(data) + return nil + } id, err := ParseID(string(text)) if err != nil { return err diff --git a/p2p/enode/node_test.go b/p2p/enode/node_test.go index e9fe631f34..62fffcd657 100644 --- a/p2p/enode/node_test.go +++ b/p2p/enode/node_test.go @@ -22,12 +22,14 @@ import ( "fmt" "math/big" "net/netip" + "strings" "testing" "testing/quick" "github.com/ethereum/go-ethereum/p2p/enr" "github.com/ethereum/go-ethereum/rlp" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) var pyRecord, _ = hex.DecodeString("f884b8407098ad865b00a582051940cb9cf36836572411a47278783077011599ed5cd16b76f2635f4e234738f30813a89eb9137e3e3df5266e3a1f11df72ecf1145ccb9c01826964827634826970847f00000189736563703235366b31a103ca634cae0d49acb401d8a4c6b6fe8c55b70d115bf400769cc1400f3258cd31388375647082765f") @@ -386,3 +388,60 @@ func TestID_logdistEqual(t *testing.T) { t.Errorf("LogDist(x, x) != 0") } } + +func TestV4NodeIDFromPublicKey(t *testing.T) { + tests := []struct { + url string + }{ + { + url: "enode://69a90b35164ef862185d9f4d2c5eff79b92acd1360574c0edf36044055dc766d87285a820233ae5700e11c9ba06ce1cf23c1c68a4556121109776ce2a3990bba@127.0.0.1:30311", + }, + { + url: "enode://df1e8eb59e42cad3c4551b2a53e31a7e55a2fdde1287babd1e94b0836550b489ba16c40932e4dacb16cba346bd442c432265a299c4aca63ee7bb0f832b9f45eb@127.0.0.1:30311", + }, + { + url: "enr:-Je4QEeZoiY8OrUxlckLuU8leuuSfnrveD8PdUnCvHavJJzcGQn7nKikWNV_ZxbRtPt6si-tQNwT_aIYpksq3O2Hzblbg2V0aMfGhPCv0OOAgmlkgnY0gmlwhIe10fKJc2VjcDI1NmsxoQNGM7sxj2Wuen_j9kqzHEmjqSxct1UxxbA9kwl7ha7NRIN0Y3CCdl-DdWRwgnZf", + }, + { + url: "enr:-IS4QHCYrYZbAKWCBRlAy5zzaDZXJBGkcnh4MHcBFZntXNFrdvJjX04jRzjzCBOonrkTfj499SZuOh8R33Ls8RRcy5wBgmlkgnY0gmlwhH8AAAGJc2VjcDI1NmsxoQPKY0yuDUmstAHYpMa2_oxVtw0RW_QAdpzBQA8yWM0xOIN1ZHCCdl8", + }, + } + for _, test := range tests { + node, err := Parse(ValidSchemes, test.url) + require.NoError(t, err) + enodeUrl := node.URLv4() + parts := strings.Split(enodeUrl, "@") + raw, _ := hex.DecodeString(parts[0][8:]) + assert.Equal(t, node.id, V4NodeIDFromPublicKey(raw), node.ID()) + } +} + +func TestNodeID_UnmarshalText(t *testing.T) { + tests := []struct { + pubkey string + id string + }{ + { + pubkey: "69a90b35164ef862185d9f4d2c5eff79b92acd1360574c0edf36044055dc766d87285a820233ae5700e11c9ba06ce1cf23c1c68a4556121109776ce2a3990bba", + id: "7248fb6372d6ef91b4929f35b7738e7d1e23033bc4a158cf01b01377970102e0", + }, + { + pubkey: "df1e8eb59e42cad3c4551b2a53e31a7e55a2fdde1287babd1e94b0836550b489ba16c40932e4dacb16cba346bd442c432265a299c4aca63ee7bb0f832b9f45eb", + id: "477bb318d8bc6b2a040b5de9313b4edc8e978a5ecbf8fd75f5590e2a07fa21fc", + }, + { + pubkey: "4633bb318f65ae7a7fe3f64ab31c49a3a92c5cb75531c5b03d93097b85aecd44acda3a032c8a315d27f01e1fe6c5b297622d78875f72d48f1d0c1635af04fb1d", + id: "009eef756b05e36100f55bc3a7b88031daeb83a3ebb66c4ccef0677ec477df3e", + }, + { + pubkey: "ca634cae0d49acb401d8a4c6b6fe8c55b70d115bf400769cc1400f3258cd31387574077f301b421bc84df7266c44e9e6d569fc56be00812904767bf5ccd1fc7f", + id: "a448f24c6d18e575453db13171562b71999873db5b286df957af199ec94617f7", + }, + } + for _, test := range tests { + var id1, id2 ID + id1.UnmarshalText([]byte(test.id)) + id2.UnmarshalText([]byte(test.pubkey)) + assert.Equal(t, id1, id2) + } +} diff --git a/p2p/peer.go b/p2p/peer.go index 8e561a978d..1ad36fd5ce 100644 --- a/p2p/peer.go +++ b/p2p/peer.go @@ -125,6 +125,10 @@ type Peer struct { testRemoteAddr string // for testing latency atomic.Int64 // mill second latency, estimated by ping msg + + EVNPeerFlag atomic.Bool // it indicates the peer is in the validator network, it will directly broadcast when miner/sentry broadcast mined block. + ProxyedValidatorFlag atomic.Bool // it indicates the peer is proxyed by sentry node, it will directly broadcast in any scenario. + NoTxBroadcastFlag atomic.Bool // it indicates the peer is connected by validator that registered on chain, it will not broadcast tx to other validator node. } // NewPeer returns a peer for testing purposes. @@ -581,8 +585,11 @@ type PeerInfo struct { Trusted bool `json:"trusted"` Static bool `json:"static"` } `json:"network"` - Protocols map[string]interface{} `json:"protocols"` // Sub-protocol specific metadata fields - Latency int64 `json:"latency"` // the estimate latency from ping msg + Protocols map[string]interface{} `json:"protocols"` // Sub-protocol specific metadata fields + Latency int64 `json:"latency"` // the estimate latency from ping msg + EVNPeerFlag bool `json:"evnPeerFlag"` + ProxyedValidatorFlag bool `json:"proxyedValidatorFlag"` + NoTxBroadcastFlag bool `json:"noTxBroadcastFlag"` } // Info gathers and returns a collection of metadata known about a peer. @@ -594,12 +601,15 @@ func (p *Peer) Info() *PeerInfo { } // Assemble the generic peer metadata info := &PeerInfo{ - Enode: p.Node().URLv4(), - ID: p.ID().String(), - Name: p.Fullname(), - Caps: caps, - Protocols: make(map[string]interface{}, len(p.running)), - Latency: p.latency.Load(), + Enode: p.Node().URLv4(), + ID: p.ID().String(), + Name: p.Fullname(), + Caps: caps, + Protocols: make(map[string]interface{}, len(p.running)), + Latency: p.latency.Load(), + EVNPeerFlag: p.EVNPeerFlag.Load(), + ProxyedValidatorFlag: p.ProxyedValidatorFlag.Load(), + NoTxBroadcastFlag: p.NoTxBroadcastFlag.Load(), } if p.Node().Seq() > 0 { info.ENR = p.Node().String() diff --git a/params/config.go b/params/config.go index 2524ae77c8..b530bee47d 100644 --- a/params/config.go +++ b/params/config.go @@ -236,7 +236,7 @@ var ( PascalTime: newUint64(1740452880), // 2025-02-25 03:08:00 AM UTC PragueTime: newUint64(1740452880), // 2025-02-25 03:08:00 AM UTC LorentzTime: newUint64(1744097580), // 2025-04-08 07:33:00 AM UTC - MaxwellTime: nil, + MaxwellTime: newUint64(1748243100), // 2025-05-26 07:05:00 AM UTC Parlia: &ParliaConfig{}, BlobScheduleConfig: &BlobScheduleConfig{ diff --git a/params/network_params.go b/params/network_params.go index 19683a6e5e..1de7245cb4 100644 --- a/params/network_params.go +++ b/params/network_params.go @@ -37,5 +37,5 @@ var ( // considered immutable (i.e. soft finality). It is used by the downloader as a // hard limit against deep ancestors, by the blockchain against deep reorgs, by // the freezer as the cutoff threshold and by clique as the snapshot trust limit. - FullImmutabilityThreshold uint64 = 90000 + FullImmutabilityThreshold uint64 = 360_000 ) diff --git a/params/protocol_params.go b/params/protocol_params.go index 74a9ec3fb9..89b8c966ce 100644 --- a/params/protocol_params.go +++ b/params/protocol_params.go @@ -29,8 +29,6 @@ const ( GenesisGasLimit uint64 = 4712388 // Gas limit of the Genesis block. PayBidTxGasLimit uint64 = 25000 // Gas limit of the PayBidTx in the types.BidArgs. - MaxMessageSize uint32 = 10 * 1024 * 1024 // MaxMessageSize is the maximum cap on the size of a eth protocol message. - MaximumExtraDataSize uint64 = 32 // Maximum size extra data may be after Genesis. ForkIDSize uint64 = 4 // The length of fork id ExpByteGas uint64 = 10 // Times ceil(log256(exponent)) for the EXP instruction. @@ -194,10 +192,10 @@ const ( ) var ( - // lorentzBlockInterval = 1.5 - MinTimeDurationForBlobRequests uint64 = uint64(float64(24*3600) * 18.2) // it keeps blob data available for 18.2 days in local - MinBlocksForBlobRequests uint64 = uint64(float64(MinTimeDurationForBlobRequests) / 1.5) // ref: https://github.com/bnb-chain/BEPs/blob/master/BEPs/BEP-524.md#421-change-table. - DefaultExtraReserveForBlobRequests uint64 = uint64(24 * 3600 / 1.5) // it adds more time for expired blobs for some request cases, like expiry blob when remote peer is syncing, default 1 day. + // maxwellBlockInterval = 0.75 + MinTimeDurationForBlobRequests uint64 = uint64(float64(24*3600) * 18.2) // it keeps blob data available for 18.2 days in local + MinBlocksForBlobRequests uint64 = uint64(float64(MinTimeDurationForBlobRequests) / 0.75) // ref: https://github.com/bnb-chain/BEPs/blob/master/BEPs/BEP-524.md#421-change-table. + DefaultExtraReserveForBlobRequests uint64 = uint64(24 * 3600 / 0.75) // it adds more time for expired blobs for some request cases, like expiry blob when remote peer is syncing, default 1 day. BreatheBlockInterval uint64 = 24 * 3600 // Controls the interval for updateValidatorSetV2 diff --git a/rpc/client_test.go b/rpc/client_test.go index 6c1a4f8f6c..a7ebbad5a6 100644 --- a/rpc/client_test.go +++ b/rpc/client_test.go @@ -680,7 +680,7 @@ func TestClientSubscriptionChannelClose(t *testing.T) { var ( srv = NewServer() - httpsrv = httptest.NewServer(srv.WebsocketHandler(nil)) + httpsrv = httptest.NewServer(srv.WebsocketHandler(nil, 0)) wsURL = "ws:" + strings.TrimPrefix(httpsrv.URL, "http:") ) defer srv.Stop() @@ -848,7 +848,7 @@ func TestClientReconnect(t *testing.T) { if err != nil { t.Fatal("can't listen:", err) } - go http.Serve(l, srv.WebsocketHandler([]string{"*"})) + go http.Serve(l, srv.WebsocketHandler([]string{"*"}, 0)) return srv, l } @@ -914,7 +914,7 @@ func httpTestClient(srv *Server, transport string, fl *flakeyListener) (*Client, var hs *httptest.Server switch transport { case "ws": - hs = httptest.NewUnstartedServer(srv.WebsocketHandler([]string{"*"})) + hs = httptest.NewUnstartedServer(srv.WebsocketHandler([]string{"*"}, 0)) case "http": hs = httptest.NewUnstartedServer(srv) default: diff --git a/rpc/handler.go b/rpc/handler.go index 5b4399d6a6..08b2e74962 100644 --- a/rpc/handler.go +++ b/rpc/handler.go @@ -516,6 +516,10 @@ func (h *handler) handleCall(cp *callProc, msg *jsonrpcMessage) *jsonrpcMessage if msg.isUnsubscribe() { callb = h.unsubscribeCb } else { + // Check method name length + if len(msg.Method) > maxMethodNameLength { + return msg.errorResponse(&invalidRequestError{fmt.Sprintf("method name too long: %d > %d", len(msg.Method), maxMethodNameLength)}) + } callb = h.reg.callback(msg.Method) } if callb == nil { @@ -552,6 +556,11 @@ func (h *handler) handleSubscribe(cp *callProc, msg *jsonrpcMessage) *jsonrpcMes return msg.errorResponse(ErrNotificationsUnsupported) } + // Check method name length + if len(msg.Method) > maxMethodNameLength { + return msg.errorResponse(&invalidRequestError{fmt.Sprintf("subscription name too long: %d > %d", len(msg.Method), maxMethodNameLength)}) + } + // Subscription method name is first argument. name, err := parseSubscriptionName(msg.Params) if err != nil { diff --git a/rpc/http.go b/rpc/http.go index 14bd8ec0d8..59fcc9141a 100644 --- a/rpc/http.go +++ b/rpc/http.go @@ -27,6 +27,7 @@ import ( "mime" "net/http" "net/url" + "slices" "strconv" "sync" "time" @@ -364,10 +365,8 @@ func (s *Server) validateRequest(r *http.Request) (int, error) { } // Check content-type if mt, _, err := mime.ParseMediaType(r.Header.Get("content-type")); err == nil { - for _, accepted := range acceptedContentTypes { - if accepted == mt { - return 0, nil - } + if slices.Contains(acceptedContentTypes, mt) { + return 0, nil } } // Invalid content-type diff --git a/rpc/json-rpc-api.md b/rpc/json-rpc-api.md new file mode 100644 index 0000000000..4a398bf07a --- /dev/null +++ b/rpc/json-rpc-api.md @@ -0,0 +1,157 @@ +## RPC API Reference + +This document provides a comprehensive list of JSON-RPC API methods supported. Each API is listed with its required parameters and their formats. + +### API Categories + +| Command | Parameters | +|-------------------------------------------------|--------------------------------------------------| +| **Admin API** | | +| admin_nodeInfo() | - | +| admin_peers() | - | +| admin_addPeer(url) | `String` | +| | | +| **Web3 API** | | +| web3_clientVersion() | - | +| web3_sha3(data) | `String` | +| | | +| **Network API** | | +| net_listening() | - | +| net_peerCount() | - | +| net_version() | - | +| | | +| **Ethereum API (Chain State)** | | +| eth_blockNumber() | - | +| eth_chainID/eth_chainId() | - | +| eth_protocolVersion() | - | +| eth_syncing() | - | +| eth_gasPrice() | - | +| eth_maxPriorityFeePerGas() | - | +| eth_feeHistory() | - | +| | | +| **Ethereum API (Blocks)** | | +| eth_getBlockByHash(...) | `BlockHash`, `Boolean` | +| eth_getBlockByNumber(...) | `BlockNumber\|Tag`, `Boolean` | +| eth_getBlockTransactionCountByHash(...) | `BlockHash` | +| eth_getBlockTransactionCountByNumber(...) | `BlockNumber\|Tag` | +| eth_getUncleByBlockHashAndIndex(...) | `BlockHash`, `Integer` | +| eth_getUncleByBlockNumberAndIndex(...) | `BlockNumber\|Tag`, `Integer` | +| eth_getUncleCountByBlockHash(...) | `BlockHash` | +| eth_getUncleCountByBlockNumber(...) | `BlockNumber\|Tag` | +| | | +| **Ethereum API (Transactions)** | | +| eth_getTransactionByHash(...) | `TxHash` | +| eth_getRawTransactionByHash(...) | `TxHash` | +| eth_getTransactionByBlockHashAndIndex(...) | `BlockHash`, `Integer` | +| eth_retRawTransactionByBlockHashAndIndex(...) | `BlockHash`, `Integer` | +| eth_getTransactionByBlockNumberAndIndex(...) | `BlockNumber\|Tag`, `Integer` | +| eth_retRawTransactionByBlockNumberAndIndex(...) | `BlockNumber\|Tag`, `Integer` | +| eth_getTransactionReceipt(...) | `TxHash` | +| eth_getBlockReceipts(...) | `BlockNumber\|Tag` | +| | | +| **Ethereum API (State Reading)** | | +| eth_estimateGas(...) | `TxCallObject`, `BlockNumber\|Tag` | +| eth_getBalance(...) | `Address`, `BlockNumber\|Tag` | +| eth_getCode(...) | `Address`, `BlockNumber\|Tag` | +| eth_getTransactionCount(...) | `Address`, `BlockNumber\|Tag` | +| eth_getStorageAt(...) | `Address`, `Integer`, `BlockNumber\|Tag` | +| eth_call(...) | `TxCallObject`, `BlockNumber\|Tag` | +| eth_createAccessList(...) | `TxCallObject`, `BlockNumber\|Tag` | +| eth_simulateV1(...) | `BlockStateCalls`, `BlockNumber\|Tag` | +| | | +| **Ethereum API (Filters)** | | +| eth_newFilter(...) | `FilterOptions` | +| eth_newBlockFilter() | - | +| eth_newPendingTransactionFilter() | - | +| eth_getFilterLogs(...) | `FilterId` | +| eth_getFilterChanges(...) | `FilterId` | +| eth_uninstallFilter(...) | `FilterId` | +| eth_getLogs(...) | `FilterOptions` | +| | | +| **Ethereum API (Account Operations)** | | +| eth_accounts() | - | +| eth_sendRawTransaction(...) | `SignedTxData` | +| eth_sendTransaction(...) | `TransactionObject` | +| eth_signTransaction(...) | `TransactionObject` | +| eth_signTypedData(...) | `Address`, `TypedData` | +| eth_getProof(...) | `Address`, `Array`,`BlockNumber\|Tag`| +| | | +| **Ethereum API (Mining)** | | +| eth_mining() | - | +| eth_coinbase() | - | +| eth_hashrate() | - | +| eth_submitHashrate(...) | `HashRate`, `ClientID` | +| eth_getWork() | - | +| eth_submitWork(...) | `Nonce`, `PowHash`, `Digest` | +| | | +| **Ethereum API (Pub/Sub)** | | +| eth_subscribe(...) | `String`, `Object` | +| eth_unsubscribe(...) | `SubscriptionId` | +| | | +| **Engine API** | | +| engine_newPayloadV1(...) | `ExecutionPayloadV1` | +| engine_newPayloadV2(...) | `ExecutionPayloadV2` | +| engine_newPayloadV3(...) | `ExecutionPayloadV3` | +| engine_forkchoiceUpdatedV1(...) | `ForkchoiceState`, `PayloadAttributes` | +| engine_forkchoiceUpdatedV2(...) | `ForkchoiceState`, `PayloadAttributes` | +| engine_forkchoiceUpdatedV3(...) | `ForkchoiceState`, `PayloadAttributes` | +| engine_getPayloadV1(...) | `PayloadId` | +| engine_getPayloadV2(...) | `PayloadId` | +| engine_getPayloadV3(...) | `PayloadId` | +| | | +| **Debug API** | | +| debug_getRawReceipts(...) | `BlockNumber\|Tag` | +| debug_accountRange(...) | `BlockNumber\|Tag`, `AccountKey`, `Integer`, `Boolean` | +| debug_accountAt(...) | `BlockNumber\|Tag`, `AccountIndex` | +| debug_getModifiedAccountsByNumber(...) | `StartBlock`, `EndBlock` | +| debug_getModifiedAccountsByHash(...) | `StartHash`, `EndHash` | +| debug_storageRangeAt(...) | `BlockHash`, `TxIndex`, `Address`, `StartKey`, `Integer` | +| debug_traceBlockByHash(...) | `BlockHash`, `TraceConfig` | +| debug_traceBlockByNumber(...) | `BlockNumber\|Tag`, `TraceConfig` | +| debug_traceTransaction(...) | `TxHash`, `TraceConfig` | +| debug_traceCall(...) | `TxCallObject`, `BlockNumber\|Tag`, `TraceConfig`| +| | | +| **Transaction Pool API** | | +| txpool_content() | - | +| txpool_contentFrom(...) | `Address` | +| txpool_status() | - | +| | | +| **BSC-Specific APIs** | | +| eth_getHeaderByNumber(...) | `BlockNumber\|Tag` with "finalized" | +| eth_getBlockByNumber(...) | `BlockNumber\|Tag` with "finalized", `Boolean` | +| eth_newFinalizedHeaderFilter() | - | +| eth_getFinalizedHeader(...) | `VerifiedValidatorNum` | +| eth_getFinalizedBlock(...) | `VerifiedValidatorNum`, `Boolean` | +| | | +| eth_getBlobSidecarByTxHash(...) | `TxHash`, `Boolean` | +| eth_getBlobSidecars(...) | `BlockNumber\|Tag\|BlockHash`, `Boolean` | +| | | +| eth_health() | - | +| eth_getTransactionsByBlockNumber(...) | `BlockNumber\|Tag` | +| eth_getTransactionDataAndReceipt(...) | `TxHash` | +| | | + +### Parameter Types + +- `BlockNumber` - Hexadecimal block number +- `Tag` - String tag like "latest", "earliest", "pending", "safe", "finalized" +- `BlockHash` - 32-byte hash of a block +- `TxHash` - 32-byte hash of a transaction +- `Address` - 20-byte Ethereum address +- `Boolean` - true or false +- `Integer` - Numeric value +- `String` - Text string +- `TxCallObject` - Transaction call object with from/to/gas/value/data +- `FilterOptions` - Options for event filtering +- `FilterId` - ID of a previously created filter +- `VerifiedValidatorNum` - Number of validators that must verify a block +- `TraceConfig` - Configuration options for tracing +- `BlockStateCalls` - Series of transactions to simulate with optional state and block overrides + +### Notes + +- Methods that show (...) have parameters that were simplified for readability. +- APIs marked with "BSC-Specific" are only available on BSC nodes. +- Parameters in backticks (`) represent the expected data type. +- Some methods accept multiple parameter formats; consult detailed documentation for complete usage. + diff --git a/rpc/json.go b/rpc/json.go index e932389d17..0b73f07e2f 100644 --- a/rpc/json.go +++ b/rpc/json.go @@ -35,6 +35,7 @@ const ( subscribeMethodSuffix = "_subscribe" unsubscribeMethodSuffix = "_unsubscribe" notificationMethodSuffix = "_subscription" + maxMethodNameLength = 256 defaultWriteTimeout = 10 * time.Second // used if context has no deadline ) diff --git a/rpc/websocket.go b/rpc/websocket.go index 9f67caf859..e211b4d7b9 100644 --- a/rpc/websocket.go +++ b/rpc/websocket.go @@ -47,7 +47,7 @@ var wsBufferPool = new(sync.Pool) // // allowedOrigins should be a comma-separated list of allowed origin URLs. // To allow connections with any origin, pass "*". -func (s *Server) WebsocketHandler(allowedOrigins []string) http.Handler { +func (s *Server) WebsocketHandler(allowedOrigins []string, messageSizeLimit int64) http.Handler { var upgrader = websocket.Upgrader{ ReadBufferSize: wsReadBuffer, WriteBufferSize: wsWriteBuffer, @@ -60,7 +60,11 @@ func (s *Server) WebsocketHandler(allowedOrigins []string) http.Handler { log.Debug("WebSocket upgrade failed", "err", err) return } - codec := newWebsocketCodec(conn, r.Host, r.Header, wsDefaultReadLimit) + limit := int64(wsDefaultReadLimit) + if messageSizeLimit > 0 { + limit = messageSizeLimit + } + codec := newWebsocketCodec(conn, r.Host, r.Header, limit) s.ServeCodec(codec, 0) }) } diff --git a/rpc/websocket_test.go b/rpc/websocket_test.go index 10a998b351..678bc26d5e 100644 --- a/rpc/websocket_test.go +++ b/rpc/websocket_test.go @@ -53,7 +53,7 @@ func TestWebsocketOriginCheck(t *testing.T) { var ( srv = newTestServer() - httpsrv = httptest.NewServer(srv.WebsocketHandler([]string{"http://example.com"})) + httpsrv = httptest.NewServer(srv.WebsocketHandler([]string{"http://example.com"}, 0)) wsURL = "ws:" + strings.TrimPrefix(httpsrv.URL, "http:") ) defer srv.Stop() @@ -83,7 +83,7 @@ func TestWebsocketLargeCall(t *testing.T) { var ( srv = newTestServer() - httpsrv = httptest.NewServer(srv.WebsocketHandler([]string{"*"})) + httpsrv = httptest.NewServer(srv.WebsocketHandler([]string{"*"}, 0)) wsURL = "ws:" + strings.TrimPrefix(httpsrv.URL, "http:") ) defer srv.Stop() @@ -119,7 +119,7 @@ func TestWebsocketLargeRead(t *testing.T) { var ( srv = newTestServer() - httpsrv = httptest.NewServer(srv.WebsocketHandler([]string{"*"})) + httpsrv = httptest.NewServer(srv.WebsocketHandler([]string{"*"}, 0)) wsURL = "ws:" + strings.TrimPrefix(httpsrv.URL, "http:") ) defer srv.Stop() @@ -178,7 +178,7 @@ func TestWebsocketPeerInfo(t *testing.T) { var ( s = newTestServer() - ts = httptest.NewServer(s.WebsocketHandler([]string{"origin.example.com"})) + ts = httptest.NewServer(s.WebsocketHandler([]string{"origin.example.com"}, 0)) tsurl = "ws:" + strings.TrimPrefix(ts.URL, "http:") ) defer s.Stop() @@ -265,7 +265,7 @@ func TestClientWebsocketLargeMessage(t *testing.T) { var ( srv = NewServer() - httpsrv = httptest.NewServer(srv.WebsocketHandler(nil)) + httpsrv = httptest.NewServer(srv.WebsocketHandler(nil, 0)) wsURL = "ws:" + strings.TrimPrefix(httpsrv.URL, "http:") ) defer srv.Stop() @@ -391,3 +391,77 @@ func wsPingTestHandler(t *testing.T, conn *websocket.Conn, shutdown, sendPing <- } } } + +func TestWebsocketMethodNameLengthLimit(t *testing.T) { + t.Parallel() + + var ( + srv = newTestServer() + httpsrv = httptest.NewServer(srv.WebsocketHandler([]string{"*"}, 0)) + wsURL = "ws:" + strings.TrimPrefix(httpsrv.URL, "http:") + ) + defer srv.Stop() + defer httpsrv.Close() + + client, err := DialWebsocket(context.Background(), wsURL, "") + if err != nil { + t.Fatalf("can't dial: %v", err) + } + defer client.Close() + + // Test cases + tests := []struct { + name string + method string + params []interface{} + expectedError string + isSubscription bool + }{ + { + name: "valid method name", + method: "test_echo", + params: []interface{}{"test", 1}, + expectedError: "", + isSubscription: false, + }, + { + name: "method name too long", + method: "test_" + string(make([]byte, maxMethodNameLength+1)), + params: []interface{}{"test", 1}, + expectedError: "method name too long", + isSubscription: false, + }, + { + name: "valid subscription", + method: "nftest_subscribe", + params: []interface{}{"someSubscription", 1, 2}, + expectedError: "", + isSubscription: true, + }, + { + name: "subscription name too long", + method: string(make([]byte, maxMethodNameLength+1)) + "_subscribe", + params: []interface{}{"newHeads"}, + expectedError: "subscription name too long", + isSubscription: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + var result interface{} + err := client.Call(&result, tt.method, tt.params...) + if tt.expectedError == "" { + if err != nil { + t.Errorf("unexpected error: %v", err) + } + } else { + if err == nil { + t.Error("expected error, got nil") + } else if !strings.Contains(err.Error(), tt.expectedError) { + t.Errorf("expected error containing %q, got %q", tt.expectedError, err.Error()) + } + } + }) + } +} diff --git a/version/version.go b/version/version.go index 8e6d3fde67..fc7cb355af 100644 --- a/version/version.go +++ b/version/version.go @@ -19,6 +19,6 @@ package version const ( Major = 1 // Major version component of the current release Minor = 5 // Minor version component of the current release - Patch = 11 // Patch version component of the current release + Patch = 13 // Patch version component of the current release Meta = "" // Version metadata to append to the version string )