diff --git a/cmd/blockchaincmd/add_validator.go b/cmd/blockchaincmd/add_validator.go index df9fd9f18..67729811d 100644 --- a/cmd/blockchaincmd/add_validator.go +++ b/cmd/blockchaincmd/add_validator.go @@ -12,6 +12,7 @@ import ( "github.com/ava-labs/avalanche-cli/pkg/cobrautils" "github.com/ava-labs/avalanche-cli/pkg/constants" "github.com/ava-labs/avalanche-cli/pkg/contract" + "github.com/ava-labs/avalanche-cli/pkg/evm" "github.com/ava-labs/avalanche-cli/pkg/keychain" "github.com/ava-labs/avalanche-cli/pkg/models" "github.com/ava-labs/avalanche-cli/pkg/networkoptions" @@ -31,31 +32,31 @@ import ( "github.com/ava-labs/avalanchego/utils/logging" "github.com/ava-labs/avalanchego/utils/units" warpMessage "github.com/ava-labs/avalanchego/vms/platformvm/warp/message" + "github.com/ethereum/go-ethereum/common" "github.com/spf13/cobra" ) var ( - nodeIDStr string - nodeEndpoint string - balanceAVAX float64 - weight uint64 - startTimeStr string - duration time.Duration - defaultValidatorParams bool - useDefaultStartTime bool - useDefaultDuration bool - useDefaultWeight bool - waitForTxAcceptance bool - publicKey string - pop string - remainingBalanceOwnerAddr string - disableOwnerAddr string - rpcURL string - aggregatorLogLevel string - aggregatorLogToStdout bool - delegationFee uint16 - + nodeIDStr string + nodeEndpoint string + balanceAVAX float64 + weight uint64 + startTimeStr string + duration time.Duration + defaultValidatorParams bool + useDefaultStartTime bool + useDefaultDuration bool + useDefaultWeight bool + waitForTxAcceptance bool + publicKey string + pop string + remainingBalanceOwnerAddr string + disableOwnerAddr string + rpcURL string + aggregatorLogLevel string + aggregatorLogToStdout bool + delegationFee uint16 errNoSubnetID = errors.New("failed to find the subnet ID for this subnet, has it been deployed/created on this network?") errMutuallyExclusiveDurationOptions = errors.New("--use-default-duration/--use-default-validator-params and --staking-period are mutually exclusive") errMutuallyExclusiveStartOptions = errors.New("--use-default-start-time/--use-default-validator-params and --start-time are mutually exclusive") @@ -65,6 +66,8 @@ var ( aggregatorAllowPrivatePeers bool clusterNameFlagValue string createLocalValidator bool + externalValidatorManagerOwner bool + validatorManagerOwner string ) const ( @@ -122,8 +125,10 @@ Testnet or Mainnet.`, cmd.Flags().BoolVar(&waitForTxAcceptance, "wait-for-tx-acceptance", true, "(for Subnets, not L1s) just issue the add validator tx, without waiting for its acceptance") cmd.Flags().Uint16Var(&delegationFee, "delegation-fee", 100, "(PoS only) delegation fee (in bips)") cmd.Flags().StringVar(&subnetIDstr, "subnet-id", "", "subnet ID (only if blockchain name is not provided)") - cmd.Flags().StringVar(&validatorManagerOwnerAddress, "validator-manager-owner", "", "validator manager owner address (only if blockchain name is not provided)") cmd.Flags().Uint64Var(&weight, validatorWeightFlag, uint64(constants.DefaultStakeWeight), "set the weight of the validator") + cmd.Flags().StringVar(&validatorManagerOwner, "validator-manager-owner", "", "force using this address to issue transactions to the validator manager") + cmd.Flags().BoolVar(&externalValidatorManagerOwner, "external-evm-signature", false, "set this value to true when signing validator manager tx outside of cli (for multisig or ledger)") + cmd.Flags().StringVar(&initiateTxHash, "initiate-tx-hash", "", "initiate tx is already issued, with the given hash") return cmd } @@ -404,17 +409,26 @@ func CallAddValidator( return fmt.Errorf("unable to find Validator Manager address") } validatorManagerAddress = sc.Networks[network.Name()].ValidatorManagerAddress - ownerPrivateKeyFound, _, _, ownerPrivateKey, err := contract.SearchForManagedKey( - app, - network, - common.HexToAddress(sc.ValidatorManagerOwner), - true, - ) - if err != nil { - return err + + if validatorManagerOwner == "" { + validatorManagerOwner = sc.ValidatorManagerOwner } - if !ownerPrivateKeyFound { - return fmt.Errorf("private key for Validator manager owner %s is not found", sc.ValidatorManagerOwner) + + var ownerPrivateKey string + if !externalValidatorManagerOwner { + var ownerPrivateKeyFound bool + ownerPrivateKeyFound, _, _, ownerPrivateKey, err = contract.SearchForManagedKey( + app, + network, + common.HexToAddress(validatorManagerOwner), + true, + ) + if err != nil { + return err + } + if !ownerPrivateKeyFound { + return fmt.Errorf("private key for Validator manager owner %s is not found", validatorManagerOwner) + } } pos := sc.PoS() @@ -428,7 +442,14 @@ func CallAddValidator( } } } - ux.Logger.PrintToUser(logging.Yellow.Wrap("Validation manager owner %s pays for the initialization of the validator's registration (Blockchain gas token)"), sc.ValidatorManagerOwner) + + if sc.UseACP99 { + ux.Logger.PrintToUser(logging.Yellow.Wrap("Validator Manager Protocol: ACP99")) + } else { + ux.Logger.PrintToUser(logging.Yellow.Wrap("Validator Manager Protocol: v1.0.0")) + } + + ux.Logger.PrintToUser(logging.Yellow.Wrap("Validation manager owner %s pays for the initialization of the validator's registration (Blockchain gas token)"), validatorManagerOwner) if rpcURL == "" { rpcURL, _, err = contract.GetBlockchainEndpoints( @@ -523,12 +544,14 @@ func CallAddValidator( } aggregatorCtx, aggregatorCancel := sdkutils.GetTimedContext(constants.SignatureAggregatorTimeout) defer aggregatorCancel() - signedMessage, validationID, err := validatormanager.InitValidatorRegistration( + signedMessage, validationID, rawTx, err := validatormanager.InitValidatorRegistration( aggregatorCtx, app, network, rpcURL, chainSpec, + externalValidatorManagerOwner, + validatorManagerOwner, ownerPrivateKey, nodeID, blsInfo.PublicKey[:], @@ -543,10 +566,15 @@ func CallAddValidator( delegationFee, duration, validatorManagerAddress, + sc.UseACP99, + initiateTxHash, ) if err != nil { return err } + if rawTx != nil { + return evm.TxDump("Initializing Validator Registration", rawTx) + } ux.Logger.PrintToUser("ValidationID: %s", validationID) txID, _, err := deployer.RegisterL1Validator(balance, blsInfo, signedMessage) @@ -566,21 +594,27 @@ func CallAddValidator( aggregatorCtx, aggregatorCancel = sdkutils.GetTimedContext(constants.SignatureAggregatorTimeout) defer aggregatorCancel() - if err := validatormanager.FinishValidatorRegistration( + rawTx, err = validatormanager.FinishValidatorRegistration( aggregatorCtx, app, network, rpcURL, chainSpec, + externalValidatorManagerOwner, + validatorManagerOwner, ownerPrivateKey, validationID, extraAggregatorPeers, aggregatorAllowPrivatePeers, aggregatorLogger, validatorManagerAddress, - ); err != nil { + ) + if err != nil { return err } + if rawTx != nil { + return evm.TxDump("Finish Validator Registration", rawTx) + } ux.Logger.PrintToUser(" NodeID: %s", nodeID) ux.Logger.PrintToUser(" Network: %s", network.Name()) diff --git a/cmd/blockchaincmd/change_weight.go b/cmd/blockchaincmd/change_weight.go index be8a7b9b7..e78577969 100644 --- a/cmd/blockchaincmd/change_weight.go +++ b/cmd/blockchaincmd/change_weight.go @@ -4,28 +4,40 @@ package blockchaincmd import ( "fmt" + "strings" + "github.com/ava-labs/avalanche-cli/pkg/blockchain" "github.com/ava-labs/avalanche-cli/pkg/cobrautils" "github.com/ava-labs/avalanche-cli/pkg/constants" "github.com/ava-labs/avalanche-cli/pkg/contract" + "github.com/ava-labs/avalanche-cli/pkg/evm" "github.com/ava-labs/avalanche-cli/pkg/key" "github.com/ava-labs/avalanche-cli/pkg/keychain" + "github.com/ava-labs/avalanche-cli/pkg/models" "github.com/ava-labs/avalanche-cli/pkg/networkoptions" "github.com/ava-labs/avalanche-cli/pkg/node" "github.com/ava-labs/avalanche-cli/pkg/prompts" "github.com/ava-labs/avalanche-cli/pkg/subnet" "github.com/ava-labs/avalanche-cli/pkg/utils" "github.com/ava-labs/avalanche-cli/pkg/ux" + "github.com/ava-labs/avalanche-cli/pkg/validatormanager" + sdkutils "github.com/ava-labs/avalanche-cli/sdk/utils" "github.com/ava-labs/avalanche-cli/sdk/validator" "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/utils/crypto/bls" "github.com/ava-labs/avalanchego/utils/formatting" "github.com/ava-labs/avalanchego/utils/formatting/address" + "github.com/ava-labs/avalanchego/utils/logging" "github.com/ava-labs/avalanchego/utils/units" + + "github.com/ethereum/go-ethereum/common" "github.com/spf13/cobra" ) -var newWeight uint64 +var ( + newWeight uint64 + initiateTxHash string +) // avalanche blockchain addValidator func newChangeWeightCmd() *cobra.Command { @@ -47,6 +59,14 @@ The L1 has to be a Proof of Authority L1.`, cmd.Flags().StringVar(&nodeEndpoint, "node-endpoint", "", "gather node id/bls from publicly available avalanchego apis on the given endpoint") cmd.Flags().BoolVarP(&useLedger, "ledger", "g", false, "use ledger instead of key (always true on mainnet, defaults to false on fuji/devnet)") cmd.Flags().StringSliceVar(&ledgerAddresses, "ledger-addrs", []string{}, "use the given ledger addresses") + cmd.Flags().BoolVar(&externalValidatorManagerOwner, "external-evm-signature", false, "set this value to true when signing validator manager tx outside of cli (for multisig or ledger)") + cmd.Flags().StringVar(&validatorManagerOwner, "validator-manager-owner", "", "force using this address to issue transactions to the validator manager") + cmd.Flags().StringSliceVar(&aggregatorExtraEndpoints, "aggregator-extra-endpoints", nil, "endpoints for extra nodes that are needed in signature aggregation") + cmd.Flags().BoolVar(&aggregatorAllowPrivatePeers, "aggregator-allow-private-peers", true, "allow the signature aggregator to connect to peers with private IP") + cmd.Flags().StringVar(&aggregatorLogLevel, "aggregator-log-level", constants.DefaultAggregatorLogLevel, "log level to use with signature aggregator") + cmd.Flags().BoolVar(&aggregatorLogToStdout, "aggregator-log-to-stdout", false, "use stdout for signature aggregator logs") + cmd.Flags().StringVar(&rpcURL, "rpc", "", "connect to validator manager at the given rpc endpoint") + cmd.Flags().StringVar(&initiateTxHash, "initiate-tx-hash", "", "initiate tx is already issued, with the given hash") return cmd } @@ -163,31 +183,60 @@ func setWeight(_ *cobra.Command, args []string) error { } allowedChange := float64(totalWeight) * constants.MaxL1TotalWeightChange - - if float64(validatorInfo.Weight) > allowedChange { - return fmt.Errorf("can't make change: current validator weight %d exceeds max allowed weight change of %d", validatorInfo.Weight, uint64(allowedChange)) + allowedWeightFunction := func(v uint64) error { + delta := uint64(0) + if v > validatorInfo.Weight { + delta = v - validatorInfo.Weight + } else { + delta = validatorInfo.Weight - v + } + if delta > uint64(allowedChange) { + return fmt.Errorf("weight change %d exceeds max allowed weight change of %d", delta, uint64(allowedChange)) + } + return nil } - allowedChange = float64(totalWeight-validatorInfo.Weight) * constants.MaxL1TotalWeightChange + if !sc.UseACP99 { + if float64(validatorInfo.Weight) > allowedChange { + return fmt.Errorf("can't make change: current validator weight %d exceeds max allowed weight change of %d", validatorInfo.Weight, uint64(allowedChange)) + } + allowedChange = float64(totalWeight-validatorInfo.Weight) * constants.MaxL1TotalWeightChange + allowedWeightFunction = func(v uint64) error { + if v > uint64(allowedChange) { + return fmt.Errorf("new weight exceeds max allowed weight change of %d", uint64(allowedChange)) + } + return nil + } + } if newWeight == 0 { ux.Logger.PrintToUser("Current validator weight is %d", validatorInfo.Weight) newWeight, err = app.Prompt.CaptureWeight( "What weight would you like to assign to the validator?", - func(v uint64) error { - if v > uint64(allowedChange) { - return fmt.Errorf("weight exceeds max allowed weight change of %d", uint64(allowedChange)) - } - return nil - }, + allowedWeightFunction, ) if err != nil { return err } } - if float64(newWeight) > allowedChange { - return fmt.Errorf("can't make change: desired validator weight %d exceeds max allowed weight change of %d", newWeight, uint64(allowedChange)) + if err := allowedWeightFunction(newWeight); err != nil { + return err + } + + deployer := subnet.NewPublicDeployer(app, kc, network) + + if sc.UseACP99 { + ux.Logger.PrintToUser(logging.Yellow.Wrap("Validator Manager Protocol: ACP99")) + return changeWeightACP99( + deployer, + network, + blockchainName, + nodeID, + newWeight, + ) + } else { + ux.Logger.PrintToUser(logging.Yellow.Wrap("Validator Manager Protocol: v1.0.0")) } publicKey, err = formatting.Encode(formatting.HexNC, bls.PublicKeyToCompressedBytes(validatorInfo.PublicKey)) @@ -202,8 +251,6 @@ func setWeight(_ *cobra.Command, args []string) error { } } - deployer := subnet.NewPublicDeployer(app, kc, network) - var remainingBalanceOwnerAddr, disableOwnerAddr string hrp := key.GetHRP(network.ID) if validatorInfo.RemainingBalanceOwner != nil && len(validatorInfo.RemainingBalanceOwner.Addrs) > 0 { @@ -260,3 +307,149 @@ func setWeight(_ *cobra.Command, args []string) error { sc, ) } + +func changeWeightACP99( + deployer *subnet.PublicDeployer, + network models.Network, + blockchainName string, + nodeID ids.NodeID, + weight uint64, +) error { + chainSpec := contract.ChainSpec{ + BlockchainName: blockchainName, + } + + sc, err := app.LoadSidecar(chainSpec.BlockchainName) + if err != nil { + return fmt.Errorf("failed to load sidecar: %w", err) + } + + if validatorManagerOwner == "" { + validatorManagerOwner = sc.ValidatorManagerOwner + } + + var ownerPrivateKey string + if !externalValidatorManagerOwner { + var ownerPrivateKeyFound bool + ownerPrivateKeyFound, _, _, ownerPrivateKey, err = contract.SearchForManagedKey( + app, + network, + common.HexToAddress(validatorManagerOwner), + true, + ) + if err != nil { + return err + } + if !ownerPrivateKeyFound { + return fmt.Errorf("not private key found for Validator manager owner %s", validatorManagerOwner) + } + } + ux.Logger.PrintToUser(logging.Yellow.Wrap("Validator manager owner %s pays for the initialization of the validator's weight change (Blockchain gas token)"), validatorManagerOwner) + + if sc.Networks[network.Name()].ValidatorManagerAddress == "" { + return fmt.Errorf("unable to find Validator Manager address") + } + validatorManagerAddress = sc.Networks[network.Name()].ValidatorManagerAddress + + ux.Logger.PrintToUser(logging.Yellow.Wrap("RPC Endpoint: %s"), rpcURL) + + clusterName := sc.Networks[network.Name()].ClusterName + extraAggregatorPeers, err := blockchain.GetAggregatorExtraPeers(app, clusterName, aggregatorExtraEndpoints) + if err != nil { + return err + } + aggregatorLogger, err := utils.NewLogger( + constants.SignatureAggregatorLogName, + aggregatorLogLevel, + constants.DefaultAggregatorLogLevel, + app.GetAggregatorLogDir(clusterName), + aggregatorLogToStdout, + ux.Logger.PrintToUser, + ) + if err != nil { + return err + } + + aggregatorCtx, aggregatorCancel := sdkutils.GetTimedContext(constants.SignatureAggregatorTimeout) + defer aggregatorCancel() + + signedMessage, validationID, rawTx, err := validatormanager.InitValidatorWeightChange( + aggregatorCtx, + ux.Logger.PrintToUser, + app, + network, + rpcURL, + chainSpec, + externalValidatorManagerOwner, + validatorManagerOwner, + ownerPrivateKey, + nodeID, + extraAggregatorPeers, + aggregatorAllowPrivatePeers, + aggregatorLogger, + validatorManagerAddress, + weight, + initiateTxHash, + ) + if err != nil { + return err + } + if rawTx != nil { + return evm.TxDump("Initializing Validator Weight Change", rawTx) + } + + ux.Logger.PrintToUser("ValidationID: %s", validationID) + + validatorInfo, err := validator.GetValidatorInfo(network.SDKNetwork(), validationID) + if err != nil { + return err + } + if validatorInfo.Weight == newWeight { + ux.Logger.PrintToUser(logging.LightBlue.Wrap("The new Weight was already set on the P-Chain. Proceeding to the next step")) + } else { + txID, _, err := deployer.SetL1ValidatorWeight(signedMessage) + if err != nil { + if !strings.Contains(err.Error(), "could not load L1 validator: not found") { + return err + } + ux.Logger.PrintToUser(logging.LightBlue.Wrap("The Validation ID was already removed on the P-Chain. Proceeding to the next step")) + } else { + ux.Logger.PrintToUser("SetL1ValidatorWeightTx ID: %s", txID) + if err := blockchain.UpdatePChainHeight( + "Waiting for P-Chain to update validator information ...", + ); err != nil { + return err + } + } + } + + aggregatorCtx, aggregatorCancel = sdkutils.GetTimedContext(constants.SignatureAggregatorTimeout) + defer aggregatorCancel() + rawTx, err = validatormanager.FinishValidatorWeightChange( + aggregatorCtx, + app, + network, + rpcURL, + chainSpec, + externalValidatorManagerOwner, + validatorManagerOwner, + ownerPrivateKey, + validationID, + extraAggregatorPeers, + aggregatorAllowPrivatePeers, + aggregatorLogger, + validatorManagerAddress, + signedMessage, + newWeight, + ) + if err != nil { + return err + } + if rawTx != nil { + return evm.TxDump("Finish Validator Weight Change", rawTx) + } + + ux.Logger.GreenCheckmarkToUser("Weight change successfully made") + + return nil +} diff --git a/cmd/blockchaincmd/convert.go b/cmd/blockchaincmd/convert.go index 085af091e..0356bfb85 100644 --- a/cmd/blockchaincmd/convert.go +++ b/cmd/blockchaincmd/convert.go @@ -261,7 +261,14 @@ func InitializeValidatorManager( pos bool, validatorManagerAddrStr string, proxyContractOwner string, + useACP99 bool, ) (bool, error) { + if useACP99 { + ux.Logger.PrintToUser(logging.Yellow.Wrap("Validator Manager Protocol: ACP99")) + } else { + ux.Logger.PrintToUser(logging.Yellow.Wrap("Validator Manager Protocol: v1.0.0")) + } + var err error clusterName := clusterNameFlagValue switch { @@ -403,6 +410,7 @@ func InitializeValidatorManager( aggregatorAllowPrivatePeers, aggregatorLogger, validatorManagerAddrStr, + useACP99, ); err != nil { return tracked, err } @@ -768,6 +776,7 @@ func convertBlockchain(_ *cobra.Command, args []string) error { sidecar.ValidatorManagement == models.ProofOfStake, validatorManagerAddress, sidecar.ProxyContractOwner, + sidecar.UseACP99, ); err != nil { return err } diff --git a/cmd/blockchaincmd/create.go b/cmd/blockchaincmd/create.go index 69da4c362..f43e7642e 100644 --- a/cmd/blockchaincmd/create.go +++ b/cmd/blockchaincmd/create.go @@ -55,6 +55,7 @@ type CreateFlags struct { validatorManagerOwner string proxyContractOwner string enableDebugging bool + useACP99 bool } var ( @@ -123,6 +124,7 @@ configuration, pass the -f flag.`, cmd.Flags().BoolVar(&sovereign, "sovereign", true, "set to false if creating non-sovereign blockchain") cmd.Flags().Uint64Var(&createFlags.rewardBasisPoints, "reward-basis-points", 100, "(PoS only) reward basis points for PoS Reward Calculator") cmd.Flags().BoolVar(&createFlags.enableDebugging, "debug", true, "enable blockchain debugging") + cmd.Flags().BoolVar(&createFlags.useACP99, "acp99", true, "use ACP99 contracts instead of v1.0.0 for validator managers") return cmd } @@ -335,6 +337,7 @@ func createBlockchainConfig(cmd *cobra.Command, args []string) error { createFlags.addICMRegistryToGenesis, sc.ProxyContractOwner, createFlags.rewardBasisPoints, + createFlags.useACP99, ) if err != nil { return err @@ -348,6 +351,7 @@ func createBlockchainConfig(cmd *cobra.Command, args []string) error { tokenSymbol, true, sovereign, + createFlags.useACP99, ); err != nil { return err } diff --git a/cmd/blockchaincmd/deploy.go b/cmd/blockchaincmd/deploy.go index 7081612ed..d6d9713b8 100644 --- a/cmd/blockchaincmd/deploy.go +++ b/cmd/blockchaincmd/deploy.go @@ -93,7 +93,6 @@ var ( poSWeightToValueFactor uint64 deployBalanceAVAX float64 validatorManagerAddress string - validatorManagerOwnerAddress string errMutuallyExlusiveControlKeys = errors.New("--control-keys and --same-control-key are mutually exclusive") ErrMutuallyExlusiveKeyLedger = errors.New("key source flags --key, --ledger/--ledger-addrs are mutually exclusive") ErrStoredKeyOnMainnet = errors.New("key --key is not available for mainnet operations") @@ -820,6 +819,7 @@ func deployBlockchain(cmd *cobra.Command, args []string) error { sidecar.ValidatorManagement == models.ProofOfStake, validatorManagerStr, sidecar.ProxyContractOwner, + sidecar.UseACP99, ) if err != nil { return err diff --git a/cmd/blockchaincmd/describe.go b/cmd/blockchaincmd/describe.go index deaeeb7d0..3cba54cf4 100644 --- a/cmd/blockchaincmd/describe.go +++ b/cmd/blockchaincmd/describe.go @@ -352,6 +352,11 @@ func printSmartContracts(sc models.Sidecar, genesis core.Genesis) { } else { description = "Native Token Staking Manager" } + if sc.UseACP99 { + description = "ACP99 Compatible " + description + } else { + description = "v1.0.0 Compatible " + description + } case address == common.HexToAddress(validatorManagerSDK.ProxyContractAddress): description = "Transparent Proxy" case address == common.HexToAddress(validatorManagerSDK.ProxyAdminContractAddress): diff --git a/cmd/blockchaincmd/export_test.go b/cmd/blockchaincmd/export_test.go index 1b4295a33..4537ad872 100644 --- a/cmd/blockchaincmd/export_test.go +++ b/cmd/blockchaincmd/export_test.go @@ -45,6 +45,7 @@ func TestExportImportSubnet(t *testing.T) { "Test", false, true, + true, ) require.NoError(err) err = app.WriteGenesisFile(testSubnet, genBytes) diff --git a/cmd/blockchaincmd/import_public.go b/cmd/blockchaincmd/import_public.go index f27ed2a82..312c0ac99 100644 --- a/cmd/blockchaincmd/import_public.go +++ b/cmd/blockchaincmd/import_public.go @@ -249,10 +249,6 @@ func importL1(blockchainIDStr string, rpcURL string, network models.Network) (mo return models.Sidecar{}, fmt.Errorf("unable to import non sovereign Subnets") } validatorManagerAddress = "0x" + hex.EncodeToString(subnetInfo.ManagerAddress) - fmt.Printf("obtained blockchainid %s \n", blockchainID.String()) - fmt.Printf("obtained subnetid %s \n", subnetID.String()) - - fmt.Printf("obtained validatorManagerAddress %s \n", validatorManagerAddress) // add validator without blockchain arg is only for l1s sc = models.Sidecar{ diff --git a/cmd/blockchaincmd/remove_validator.go b/cmd/blockchaincmd/remove_validator.go index 941c24873..2d33b404d 100644 --- a/cmd/blockchaincmd/remove_validator.go +++ b/cmd/blockchaincmd/remove_validator.go @@ -12,6 +12,7 @@ import ( "github.com/ava-labs/avalanche-cli/pkg/cobrautils" "github.com/ava-labs/avalanche-cli/pkg/constants" "github.com/ava-labs/avalanche-cli/pkg/contract" + "github.com/ava-labs/avalanche-cli/pkg/evm" "github.com/ava-labs/avalanche-cli/pkg/keychain" "github.com/ava-labs/avalanche-cli/pkg/models" "github.com/ava-labs/avalanche-cli/pkg/networkoptions" @@ -27,9 +28,8 @@ import ( "github.com/ava-labs/avalanchego/api/info" "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/utils/logging" - "github.com/ava-labs/avalanchego/vms/platformvm/warp" - "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common" "github.com/spf13/cobra" ) @@ -66,6 +66,9 @@ these prompts by providing the values with flags.`, cmd.Flags().BoolVar(&aggregatorLogToStdout, "aggregator-log-to-stdout", false, "use stdout for signature aggregator logs") cmd.Flags().Uint64Var(&uptimeSec, "uptime", 0, "validator's uptime in seconds. If not provided, it will be automatically calculated") cmd.Flags().BoolVar(&force, "force", false, "force validator removal even if it's not getting rewarded") + cmd.Flags().BoolVar(&externalValidatorManagerOwner, "external-evm-signature", false, "set this value to true when signing validator manager tx outside of cli (for multisig or ledger)") + cmd.Flags().StringVar(&validatorManagerOwner, "validator-manager-owner", "", "force using this address to issue transactions to the validator manager") + cmd.Flags().StringVar(&initiateTxHash, "initiate-tx-hash", "", "initiate tx is already issued, with the given hash") return cmd } @@ -146,6 +149,36 @@ func removeValidator(_ *cobra.Command, args []string) error { if err != nil { return err } + if validatorKind == validatorsdk.NonValidator { + // it may be unregistered from P-Chain, but registered on validator manager + // due to a previous partial removal operation + if rpcURL == "" { + rpcURL, _, err = contract.GetBlockchainEndpoints( + app, + network, + contract.ChainSpec{ + BlockchainName: blockchainName, + }, + true, + false, + ) + if err != nil { + return err + } + } + validatorManagerAddress = sc.Networks[network.Name()].ValidatorManagerAddress + validationID, err := validatorsdk.GetRegisteredValidator( + rpcURL, + common.HexToAddress(validatorManagerAddress), + nodeID, + ) + if err != nil { + return err + } + if validationID != ids.Empty { + validatorKind = validatorsdk.SovereignValidator + } + } if validatorKind == validatorsdk.NonValidator { return fmt.Errorf("node %s is not a validator of subnet %s on %s", nodeID, subnetID, network.Name()) } @@ -234,19 +267,35 @@ func removeValidatorSOV( if err != nil { return fmt.Errorf("failed to load sidecar: %w", err) } - ownerPrivateKeyFound, _, _, ownerPrivateKey, err := contract.SearchForManagedKey( - app, - network, - common.HexToAddress(sc.ValidatorManagerOwner), - true, - ) - if err != nil { - return err + + if validatorManagerOwner == "" { + validatorManagerOwner = sc.ValidatorManagerOwner } - if !ownerPrivateKeyFound { - return fmt.Errorf("not private key found for Validator manager owner %s", sc.ValidatorManagerOwner) + + var ownerPrivateKey string + if !externalValidatorManagerOwner { + var ownerPrivateKeyFound bool + ownerPrivateKeyFound, _, _, ownerPrivateKey, err = contract.SearchForManagedKey( + app, + network, + common.HexToAddress(validatorManagerOwner), + true, + ) + if err != nil { + return err + } + if !ownerPrivateKeyFound { + return fmt.Errorf("not private key found for Validator manager owner %s", validatorManagerOwner) + } + } + + if sc.UseACP99 { + ux.Logger.PrintToUser(logging.Yellow.Wrap("Validator Manager Protocol: ACP99")) + } else { + ux.Logger.PrintToUser(logging.Yellow.Wrap("Validator Manager Protocol: v1.0.0")) } - ux.Logger.PrintToUser(logging.Yellow.Wrap("Validator manager owner %s pays for the initialization of the validator's removal (Blockchain gas token)"), sc.ValidatorManagerOwner) + + ux.Logger.PrintToUser(logging.Yellow.Wrap("Validator manager owner %s pays for the initialization of the validator's removal (Blockchain gas token)"), validatorManagerOwner) if sc.Networks[network.Name()].ValidatorManagerAddress == "" { return fmt.Errorf("unable to find Validator Manager address") @@ -266,6 +315,7 @@ func removeValidatorSOV( } } ux.Logger.PrintToUser(logging.Yellow.Wrap("RPC Endpoint: %s"), rpcURL) + clusterName := sc.Networks[network.Name()].ClusterName extraAggregatorPeers, err := blockchain.GetAggregatorExtraPeers(app, clusterName, aggregatorExtraEndpoints) if err != nil { @@ -275,7 +325,7 @@ func removeValidatorSOV( constants.SignatureAggregatorLogName, aggregatorLogLevel, constants.DefaultAggregatorLogLevel, - app.GetAggregatorLogDir(clusterNameFlagValue), + app.GetAggregatorLogDir(clusterName), aggregatorLogToStdout, ux.Logger.PrintToUser, ) @@ -286,19 +336,18 @@ func removeValidatorSOV( ux.Logger.PrintToUser(logging.Yellow.Wrap("Forcing removal of %s as it is a PoS bootstrap validator"), nodeID) } - var ( - signedMessage *warp.Message - validationID ids.ID - ) aggregatorCtx, aggregatorCancel := sdkutils.GetTimedContext(constants.SignatureAggregatorTimeout) defer aggregatorCancel() + // try to remove the validator. If err is "delegator ineligible for rewards" confirm with user and force remove - signedMessage, validationID, err = validatormanager.InitValidatorRemoval( + signedMessage, validationID, rawTx, err := validatormanager.InitValidatorRemoval( aggregatorCtx, app, network, rpcURL, chainSpec, + externalValidatorManagerOwner, + validatorManagerOwner, ownerPrivateKey, nodeID, extraAggregatorPeers, @@ -308,6 +357,8 @@ func removeValidatorSOV( uptimeSec, isBootstrapValidator || force, validatorManagerAddress, + sc.UseACP99, + initiateTxHash, ) if err != nil && errors.Is(err, validatormanagerSDK.ErrValidatorIneligibleForRewards) { ux.Logger.PrintToUser("Calculated rewards is zero. Validator %s is not eligible for rewards", nodeID) @@ -320,12 +371,14 @@ func removeValidatorSOV( } aggregatorCtx, aggregatorCancel = sdkutils.GetTimedContext(constants.SignatureAggregatorTimeout) defer aggregatorCancel() - signedMessage, validationID, err = validatormanager.InitValidatorRemoval( + signedMessage, validationID, _, err = validatormanager.InitValidatorRemoval( aggregatorCtx, app, network, rpcURL, chainSpec, + externalValidatorManagerOwner, + validatorManagerOwner, ownerPrivateKey, nodeID, extraAggregatorPeers, @@ -335,6 +388,8 @@ func removeValidatorSOV( uptimeSec, true, // force validatorManagerAddress, + sc.UseACP99, + initiateTxHash, ) if err != nil { return err @@ -342,6 +397,9 @@ func removeValidatorSOV( } else if err != nil { return err } + if rawTx != nil { + return evm.TxDump("Initializing Validator Removal", rawTx) + } ux.Logger.PrintToUser("ValidationID: %s", validationID) txID, _, err := deployer.SetL1ValidatorWeight(signedMessage) @@ -361,21 +419,29 @@ func removeValidatorSOV( aggregatorCtx, aggregatorCancel = sdkutils.GetTimedContext(constants.SignatureAggregatorTimeout) defer aggregatorCancel() - if err := validatormanager.FinishValidatorRemoval( + rawTx, err = validatormanager.FinishValidatorRemoval( aggregatorCtx, app, network, rpcURL, chainSpec, + externalValidatorManagerOwner, + validatorManagerOwner, ownerPrivateKey, validationID, extraAggregatorPeers, aggregatorAllowPrivatePeers, aggregatorLogger, validatorManagerAddress, - ); err != nil { + sc.PoA() && sc.UseACP99, + ) + if err != nil { return err } + if rawTx != nil { + return evm.TxDump("Finish Validator Removal", rawTx) + } + ux.Logger.GreenCheckmarkToUser("Validator successfully removed from the Subnet") return nil diff --git a/cmd/contractcmd/init_validator_manager.go b/cmd/contractcmd/init_validator_manager.go index 6f9efeeb3..03fbc8de9 100644 --- a/cmd/contractcmd/init_validator_manager.go +++ b/cmd/contractcmd/init_validator_manager.go @@ -210,6 +210,7 @@ func initValidatorManager(_ *cobra.Command, args []string) error { validatorManagerFlags.aggregatorAllowPrivatePeers, aggregatorLogger, validatorManagerAddress, + sc.UseACP99, ); err != nil { return err } diff --git a/cmd/nodecmd/local.go b/cmd/nodecmd/local.go index 9bed7f0c5..e4b39c1f9 100644 --- a/cmd/nodecmd/local.go +++ b/cmd/nodecmd/local.go @@ -63,6 +63,7 @@ var ( latestAvagoReleaseVersion bool latestAvagoPreReleaseVersion bool validatorManagerAddress string + useACP99 bool ) // const snapshotName = "local_snapshot" @@ -289,6 +290,7 @@ This command can only be used to validate Proof of Stake L1.`, cmd.Flags().StringVar(&disableOwnerAddr, "disable-owner", "", "P-Chain address that will able to disable the validator with a P-Chain transaction") cmd.Flags().Uint64Var(&minimumStakeDuration, "minimum-stake-duration", constants.PoSL1MinimumStakeDurationSeconds, "minimum stake duration (in seconds)") cmd.Flags().StringVar(&validatorManagerAddress, "validator-manager-address", "", "validator manager address") + cmd.Flags().BoolVar(&useACP99, "acp99", true, "use ACP99 contracts instead of v1.0.0 for validator managers") return cmd } @@ -477,6 +479,12 @@ func localValidate(_ *cobra.Command, args []string) error { return err } + if useACP99 { + ux.Logger.PrintToUser(logging.Yellow.Wrap("Validator Manager Protocol: ACP99")) + } else { + ux.Logger.PrintToUser(logging.Yellow.Wrap("Validator Manager Protocol: v1.0.0")) + } + for _, node := range status.ClusterInfo.NodeInfos { if err = addAsValidator(network, node.Name, @@ -488,6 +496,7 @@ func localValidate(_ *cobra.Command, args []string) error { balance, payerPrivateKey, validatorManagerAddress, + useACP99, ); err != nil { return err } @@ -508,6 +517,7 @@ func addAsValidator(network models.Network, balance uint64, payerPrivateKey string, validatorManagerAddressStr string, + useACP99 bool, ) error { var nodeIDStr string // get node data @@ -541,12 +551,14 @@ func addAsValidator(network models.Network, aggregatorCtx, aggregatorCancel := sdkutils.GetTimedContext(constants.SignatureAggregatorTimeout) defer aggregatorCancel() - signedMessage, validationID, err := validatormanager.InitValidatorRegistration( + signedMessage, validationID, _, err := validatormanager.InitValidatorRegistration( aggregatorCtx, app, network, rpcURL, chainSpec, + false, + "", payerPrivateKey, nodeID, blsInfo.PublicKey[:], @@ -561,6 +573,8 @@ func addAsValidator(network models.Network, delegationFee, time.Duration(minimumStakeDuration)*time.Second, validatorManagerAddressStr, + useACP99, + "", ) if err != nil { return err @@ -585,12 +599,14 @@ func addAsValidator(network models.Network, aggregatorCtx, aggregatorCancel = sdkutils.GetTimedContext(constants.SignatureAggregatorTimeout) defer aggregatorCancel() - if err := validatormanager.FinishValidatorRegistration( + if _, err := validatormanager.FinishValidatorRegistration( aggregatorCtx, app, network, rpcURL, chainSpec, + false, + "", payerPrivateKey, validationID, extraAggregatorPeers, diff --git a/pkg/contract/contract.go b/pkg/contract/contract.go index 2b862f2cd..ace6e51ce 100644 --- a/pkg/contract/contract.go +++ b/pkg/contract/contract.go @@ -6,7 +6,6 @@ import ( _ "embed" "encoding/hex" "encoding/json" - "errors" "fmt" "math/big" "reflect" @@ -289,11 +288,20 @@ func ParseSpec( return name, string(abiBytes), nil } +func idempotentSigner( + _ common.Address, + tx *types.Transaction, +) (*types.Transaction, error) { + return tx, nil +} + // get method name and types from [methodsSpec], then call it // at the smart contract [contractAddress] with the given [params]. // also send [payment] tokens to it func TxToMethod( rpcURL string, + generateRawTxOnly bool, + from common.Address, privateKey string, contractAddress common.Address, payment *big.Int, @@ -302,6 +310,15 @@ func TxToMethod( methodSpec string, params ...interface{}, ) (*types.Transaction, *types.Receipt, error) { + if privateKey == "" && from == (common.Address{}) { + return nil, nil, fmt.Errorf("from address and private key can't be both empty at TxToMethod") + } + if privateKey != "" && from != (common.Address{}) { + return nil, nil, fmt.Errorf("from address and private key can't be both defined at TxToMethod") + } + if !generateRawTxOnly && privateKey == "" { + return nil, nil, fmt.Errorf("from private key must be defined to be able to sign the tx at TxToMethod") + } methodName, methodABI, err := ParseSpec(methodSpec, nil, false, false, payment != nil, false, params...) if err != nil { return nil, nil, err @@ -319,15 +336,25 @@ func TxToMethod( } defer client.Close() contract := bind.NewBoundContract(contractAddress, *abi, client, client, client) - txOpts, err := evm.GetTxOptsWithSigner(client, privateKey) - if err != nil { - return nil, nil, err + var txOpts *bind.TransactOpts + if generateRawTxOnly { + txOpts = &bind.TransactOpts{ + From: from, + Signer: idempotentSigner, + NoSend: true, + } + } else { + txOpts, err = evm.GetTxOptsWithSigner(client, privateKey) + if err != nil { + return nil, nil, err + } } txOpts.Value = payment tx, err := contract.Transact(txOpts, methodName, params...) if err != nil { trace, traceCallErr := DebugTraceCall( rpcURL, + from, privateKey, contractAddress, payment, @@ -339,18 +366,18 @@ func TxToMethod( ux.Logger.PrintToUser("Verify --debug flag value when calling 'blockchain create'") return tx, nil, err } - if errorFromSignature, err := evm.GetErrorFromTrace(trace, errorSignatureToError); err != nil && !errors.Is(err, evm.ErrUnknownErrorSelector) { - ux.Logger.RedXToUser("failed to match error selector on trace: %s", err) - ux.Logger.PrintToUser("error trace for %s error:", description) - ux.Logger.PrintToUser("%#v", trace) - } else if errorFromSignature != nil { + if errorFromSignature, err := evm.GetErrorFromTrace(trace, errorSignatureToError); errorFromSignature != nil { return tx, nil, errorFromSignature } else { + ux.Logger.RedXToUser("failed to match error selector on trace: %s", err) ux.Logger.PrintToUser("error trace for %s error:", description) ux.Logger.PrintToUser("%#v", trace) } return tx, nil, err } + if generateRawTxOnly { + return tx, nil, nil + } receipt, success, err := evm.WaitForTransaction(client, tx) if err != nil { return tx, nil, err @@ -373,6 +400,8 @@ func TxToMethod( // also send [payment] tokens to it func TxToMethodWithWarpMessage( rpcURL string, + generateRawTxOnly bool, + from common.Address, privateKey string, contractAddress common.Address, warpMessage *avalancheWarp.Message, @@ -382,6 +411,15 @@ func TxToMethodWithWarpMessage( methodSpec string, params ...interface{}, ) (*types.Transaction, *types.Receipt, error) { + if privateKey == "" && from == (common.Address{}) { + return nil, nil, fmt.Errorf("from address and private key can't be both empty at TxToMethod") + } + if privateKey != "" && from != (common.Address{}) { + return nil, nil, fmt.Errorf("from address and private key can't be both defined at TxToMethod") + } + if !generateRawTxOnly && privateKey == "" { + return nil, nil, fmt.Errorf("from private key must be defined to be able to sign the tx at TxToMethod") + } methodName, methodABI, err := ParseSpec(methodSpec, nil, false, false, false, false, params...) if err != nil { return nil, nil, err @@ -402,8 +440,10 @@ func TxToMethodWithWarpMessage( return nil, nil, err } defer client.Close() - tx, err := evm.GetSignedTxToMethodWithWarpMessage( + tx, err := evm.GetTxToMethodWithWarpMessage( client, + generateRawTxOnly, + from, privateKey, warpMessage, contractAddress, @@ -413,6 +453,9 @@ func TxToMethodWithWarpMessage( if err != nil { return nil, nil, err } + if generateRawTxOnly { + return tx, nil, nil + } if err := evm.SendTransaction(client, tx); err != nil { return tx, nil, err } @@ -460,13 +503,11 @@ func handleFailedReceiptStatus( ux.Logger.PrintToUser("Verify --debug flag value when calling 'blockchain create'") return tx, receipt, err } - if errorFromSignature, err := evm.GetErrorFromTrace(trace, errorSignatureToError); err != nil && !errors.Is(err, evm.ErrUnknownErrorSelector) { - printFailedReceiptStatusMessage(rpcURL, description, tx) - ux.Logger.RedXToUser("failed to match error selector on trace: %s", err) - } else if errorFromSignature != nil { + if errorFromSignature, err := evm.GetErrorFromTrace(trace, errorSignatureToError); errorFromSignature != nil { return tx, receipt, errorFromSignature } else { printFailedReceiptStatusMessage(rpcURL, description, tx) + ux.Logger.RedXToUser("failed to match error selector on trace: %s", err) ux.Logger.PrintToUser("error trace:") ux.Logger.PrintToUser("%#v", trace) } @@ -489,6 +530,7 @@ func DebugTraceTransaction( func DebugTraceCall( rpcURL string, + from common.Address, privateKey string, contractAddress common.Address, payment *big.Int, @@ -515,11 +557,13 @@ func DebugTraceCall( return nil, err } defer client.Close() - pk, err := crypto.HexToECDSA(privateKey) - if err != nil { - return nil, err + if from == (common.Address{}) { + pk, err := crypto.HexToECDSA(privateKey) + if err != nil { + return nil, err + } + from = crypto.PubkeyToAddress(pk.PublicKey) } - from := crypto.PubkeyToAddress(pk.PublicKey) data := map[string]string{ "from": from.Hex(), "to": contractAddress.Hex(), diff --git a/pkg/docker/ssh.go b/pkg/docker/ssh.go index dcc8ce727..2b4afff22 100644 --- a/pkg/docker/ssh.go +++ b/pkg/docker/ssh.go @@ -44,7 +44,7 @@ func ComposeSSHSetupNode( return fmt.Errorf("failed to create directory %s: %w", dir, err) } } - ux.Logger.Info("avalancheCLI folder structure created on remote host %s after %s", folderStructure, time.Since(startTime)) + ux.Logger.Info("avalancheCLI folder structure created on remote host %s after %s ", folderStructure, time.Since(startTime)) avagoDockerImage := fmt.Sprintf("%s:%s", constants.AvalancheGoDockerImage, avalancheGoVersion) ux.Logger.Info("Preparing AvalancheGo Docker image %s on %s[%s]", avagoDockerImage, host.NodeID, host.IP) diff --git a/pkg/evm/evm.go b/pkg/evm/evm.go index a0c14ac33..416425899 100644 --- a/pkg/evm/evm.go +++ b/pkg/evm/evm.go @@ -264,8 +264,10 @@ func FundAddress( return nil } -func GetSignedTxToMethodWithWarpMessage( +func GetTxToMethodWithWarpMessage( client ethclient.Client, + generateRawTxOnly bool, + from common.Address, privateKeyStr string, warpMessage *avalancheWarp.Message, contract common.Address, @@ -273,12 +275,29 @@ func GetSignedTxToMethodWithWarpMessage( value *big.Int, ) (*types.Transaction, error) { const defaultGasLimit = 2_000_000 - privateKey, err := crypto.HexToECDSA(privateKeyStr) - if err != nil { - return nil, err + var ( + privateKey *ecdsa.PrivateKey + err error + ) + if privateKeyStr == "" && from == (common.Address{}) { + return nil, fmt.Errorf("from address and private key can't be both empty at GetTxToMethodWithWarpMessage") + } + if privateKeyStr != "" && from != (common.Address{}) { + return nil, fmt.Errorf("from address and private key can't be both defined at GetTxToMethodWithWarpMessage") + } + if !generateRawTxOnly && privateKeyStr == "" { + return nil, fmt.Errorf("from private key must be defined to be able to sign the tx at GetTxToMethodWithWarpMessage") + } + if privateKeyStr != "" { + privateKey, err = crypto.HexToECDSA(privateKeyStr) + if err != nil { + return nil, err + } + if from == (common.Address{}) { + from = crypto.PubkeyToAddress(privateKey.PublicKey) + } } - address := crypto.PubkeyToAddress(privateKey.PublicKey) - gasFeeCap, gasTipCap, nonce, err := CalculateTxParams(client, address.Hex()) + gasFeeCap, gasTipCap, nonce, err := CalculateTxParams(client, from.Hex()) if err != nil { return nil, err } @@ -293,7 +312,7 @@ func GetSignedTxToMethodWithWarpMessage( }, } msg := interfaces.CallMsg{ - From: address, + From: from, To: &contract, GasPrice: nil, GasTipCap: gasTipCap, @@ -320,6 +339,9 @@ func GetSignedTxToMethodWithWarpMessage( Data: callData, AccessList: accessList, }) + if generateRawTxOnly { + return tx, nil + } txSigner := types.LatestSignerForChainID(chainID) return types.SignTx(tx, txSigner, privateKey) } @@ -804,3 +826,24 @@ func TransactionError(tx *types.Transaction, err error, msg string, args ...inte args = append(args, err) return fmt.Errorf(msg+msgSuffix, args...) } + +func TxDump(description string, tx *types.Transaction) error { + bs, err := tx.MarshalBinary() + if err != nil { + return fmt.Errorf("failure marshalling raw evm tx: %w", err) + } + ux.Logger.PrintToUser("Tx Dump For %s:", description) + ux.Logger.PrintToUser("0x%s", hex.EncodeToString(bs)) + ux.Logger.PrintToUser("Calldata Dump:") + ux.Logger.PrintToUser("0x%s", hex.EncodeToString(tx.Data())) + if len(tx.AccessList()) > 0 { + ux.Logger.PrintToUser("Access List Dump:") + for _, t := range tx.AccessList() { + ux.Logger.PrintToUser(" Address: %s", t.Address) + for _, s := range t.StorageKeys { + ux.Logger.PrintToUser(" Storage: %s", s) + } + } + } + return nil +} diff --git a/pkg/ictt/deploy.go b/pkg/ictt/deploy.go index 724dcb96c..c9bf2f5ff 100644 --- a/pkg/ictt/deploy.go +++ b/pkg/ictt/deploy.go @@ -38,6 +38,8 @@ func RegisterRemote( } _, _, err := contract.TxToMethod( rpcURL, + false, + common.Address{}, privateKey, remoteAddress, nil, diff --git a/pkg/ictt/operate.go b/pkg/ictt/operate.go index 00edabe65..87a4d5cde 100644 --- a/pkg/ictt/operate.go +++ b/pkg/ictt/operate.go @@ -228,6 +228,8 @@ func ERC20TokenHomeSend( } if _, _, err := contract.TxToMethod( rpcURL, + false, + common.Address{}, privateKey, tokenAddress, nil, @@ -251,6 +253,8 @@ func ERC20TokenHomeSend( } _, _, err = contract.TxToMethod( rpcURL, + false, + common.Address{}, privateKey, homeAddress, nil, @@ -298,6 +302,8 @@ func NativeTokenHomeSend( } _, _, err = contract.TxToMethod( rpcURL, + false, + common.Address{}, privateKey, homeAddress, amount, @@ -320,6 +326,8 @@ func ERC20TokenRemoteSend( ) error { if _, _, err := contract.TxToMethod( rpcURL, + false, + common.Address{}, privateKey, remoteAddress, nil, @@ -353,6 +361,8 @@ func ERC20TokenRemoteSend( } _, _, err := contract.TxToMethod( rpcURL, + false, + common.Address{}, privateKey, remoteAddress, nil, @@ -396,6 +406,8 @@ func NativeTokenRemoteSend( } _, _, err := contract.TxToMethod( rpcURL, + false, + common.Address{}, privateKey, remoteAddress, amount, @@ -417,6 +429,8 @@ func NativeTokenHomeAddCollateral( ) error { _, _, err := contract.TxToMethod( rpcURL, + false, + common.Address{}, privateKey, homeAddress, amount, @@ -443,6 +457,8 @@ func ERC20TokenHomeAddCollateral( } if _, _, err := contract.TxToMethod( rpcURL, + false, + common.Address{}, privateKey, tokenAddress, nil, @@ -456,6 +472,8 @@ func ERC20TokenHomeAddCollateral( } _, _, err = contract.TxToMethod( rpcURL, + false, + common.Address{}, privateKey, homeAddress, nil, diff --git a/pkg/interchain/operate.go b/pkg/interchain/operate.go index da4182239..19a69a5d2 100644 --- a/pkg/interchain/operate.go +++ b/pkg/interchain/operate.go @@ -88,6 +88,8 @@ func SendCrossChainMessage( } return contract.TxToMethod( rpcURL, + false, + common.Address{}, privateKey, messengerAddress, nil, diff --git a/pkg/models/sidecar.go b/pkg/models/sidecar.go index 00bfd5b43..a7a8688ae 100644 --- a/pkg/models/sidecar.go +++ b/pkg/models/sidecar.go @@ -50,6 +50,7 @@ type Sidecar struct { ProxyContractOwner string // Subnet defaults to Sovereign post ACP-77 Sovereign bool + UseACP99 bool } func (sc Sidecar) GetVMID() (string, error) { diff --git a/pkg/precompiles/allowlist.go b/pkg/precompiles/allowlist.go index 7f8624285..7180a1eea 100644 --- a/pkg/precompiles/allowlist.go +++ b/pkg/precompiles/allowlist.go @@ -19,6 +19,8 @@ func SetAdmin( ) error { _, _, err := contract.TxToMethod( rpcURL, + false, + common.Address{}, privateKey, precompile, nil, @@ -38,6 +40,8 @@ func SetManager( ) error { _, _, err := contract.TxToMethod( rpcURL, + false, + common.Address{}, privateKey, precompile, nil, @@ -57,6 +61,8 @@ func SetEnabled( ) error { _, _, err := contract.TxToMethod( rpcURL, + false, + common.Address{}, privateKey, precompile, nil, @@ -76,6 +82,8 @@ func SetNone( ) error { _, _, err := contract.TxToMethod( rpcURL, + false, + common.Address{}, privateKey, precompile, nil, diff --git a/pkg/utils/common.go b/pkg/utils/common.go index b2c109448..f9e5c1a79 100644 --- a/pkg/utils/common.go +++ b/pkg/utils/common.go @@ -643,3 +643,12 @@ func VMID(vmName string) (ids.ID, error) { copy(b, []byte(vmName)) return ids.ToID(b) } + +func PointersSlice[T any](input []T) []*T { + output := make([]*T, 0, len(input)) + for _, e := range input { + e := e + output = append(output, &e) + } + return output +} diff --git a/pkg/validatormanager/deployed_validator_manager_bytecode_acp99.txt b/pkg/validatormanager/deployed_validator_manager_bytecode_acp99.txt new file mode 100644 index 000000000..ff56f4dce --- /dev/null +++ b/pkg/validatormanager/deployed_validator_manager_bytecode_acp99.txt @@ -0,0 +1,2 @@ +0x608060405234801561000f575f80fd5b5060043610610187575f3560e01c8063a3a65e48116100d9578063c974d1b611610093578063df93d8de1161006e578063df93d8de1461039e578063ed285ae1146103a8578063f2fde38b146103bb578063fd7ac5e7146103ce575f80fd5b8063c974d1b614610346578063ce161f141461034e578063d5f20ff61461037e575f80fd5b8063a3a65e48146102d0578063b6e6a2ca146102e3578063b771b3bc146102f6578063bb0b193814610304578063bc5fbfec1461030c578063bee0a03f14610333575f80fd5b80636610966911610144578063736c87be1161011f578063736c87be1461024c5780638280a25a1461025f5780638da5cb5b146102795780639681d940146102bd575f80fd5b8063661096691461020b578063715018a61461023d578063732214f814610245575f80fd5b80630322ed981461018b57806309c1df66146101a057806320d91b7a146101c55780635dc1f535146101d857806360305d62146101ee57806363e2ca97146101ee575b5f80fd5b61019e610199366004612893565b6103e1565b005b6101a8610674565b6040516001600160401b0390911681526020015b60405180910390f35b61019e6101d33660046128d3565b61068f565b6101e0610c48565b6040519081526020016101bc565b6101f6601481565b60405163ffffffff90911681526020016101bc565b61021e61021936600461293c565b610c57565b604080516001600160401b0390931683526020830191909152016101bc565b61019e610c77565b6101e05f81565b61019e61025a36600461296a565b610c8a565b610267603081565b60405160ff90911681526020016101bc565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b03165b6040516001600160a01b0390911681526020016101bc565b6101e06102cb36600461298b565b610d96565b6101e06102de36600461298b565b61114a565b61019e6102f1366004612893565b611341565b6102a56005600160991b0181565b6101a8611355565b6101e07fe92546d698950ddd38910d2e15ed1d923cd0a7b3dde9e2a6a3f380565559cb0081565b61019e610341366004612893565b611377565b610267601481565b61036161035c36600461298b565b611498565b604080519283526001600160401b039091166020830152016101bc565b61039161038c366004612893565b611623565b6040516101bc9190612a25565b6101a86202a30081565b6101e06103b6366004612cbe565b6117aa565b61019e6103c9366004612d82565b6117cc565b6101e06103dc366004612d9d565b611806565b5f6103ea61183f565b5f838152600580830160205260408083208151610100810190925280549495509293909291839160ff1690811115610424576104246129a4565b6005811115610435576104356129a4565b815260200160018201805461044990612e08565b80601f016020809104026020016040519081016040528092919081815260200182805461047590612e08565b80156104c05780601f10610497576101008083540402835291602001916104c0565b820191905f5260205f20905b8154815290600101906020018083116104a357829003601f168201915b505050918352505060028201546001600160401b038082166020840152600160401b80830482166040850152600160801b830482166060850152600160c01b9092048116608084015260039384015480821660a0850152919091041660c09091015290915081516005811115610538576105386129a4565b14610574575f8381526005830160205260409081902054905163170cc93360e21b815261056b9160ff1690600401612e3a565b60405180910390fd5b606081015160405163854a893f60e01b8152600481018590526001600160401b0390911660248201525f60448201526005600160991b019063ee5b48eb9073__$fd0c147b4031eef6079b0498cbafa865f0$__9063854a893f906064015f60405180830381865af41580156105eb573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526106129190810190612e92565b6040518263ffffffff1660e01b815260040161062e9190612ec3565b6020604051808303815f875af115801561064a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061066e9190612ed5565b50505050565b5f61067d61183f565b600101546001600160401b0316919050565b5f61069861183f565b600781015490915060ff16156106c157604051637fab81e560e01b815260040160405180910390fd5b6005600160991b016001600160a01b0316634213cf786040518163ffffffff1660e01b8152600401602060405180830381865afa158015610704573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107289190612ed5565b836020013514610751576040516372b0a7e760e11b81526020840135600482015260240161056b565b306107626060850160408601612d82565b6001600160a01b0316146107a5576107806060840160408501612d82565b604051632f88120d60e21b81526001600160a01b03909116600482015260240161056b565b5f6107b36060850185612eec565b905090505f805b828163ffffffff161015610a39575f6107d66060880188612eec565b8363ffffffff168181106107ec576107ec612f31565b90506020028101906107fe9190612f45565b61080790612f63565b80516040519192505f91600688019161081f91612fde565b9081526020016040518091039020541461084f57805160405163a41f772f60e01b815261056b9190600401612ec3565b805151601414610875578051604051633e08a12560e11b815261056b9190600401612ec3565b5f6002885f0135846040516020016108a492919091825260e01b6001600160e01b031916602082015260240190565b60408051601f19818403018152908290526108be91612fde565b602060405180830381855afa1580156108d9573d5f803e3d5ffd5b5050506040513d601f19601f820116820180604052508101906108fc9190612ed5565b90508086600601835f01516040516109149190612fde565b90815260408051918290036020908101909220929092555f8381526005890190915220805460ff191660021781558251600190910190610954908261303a565b50604082810180515f84815260058a016020529290922060028101805492516001600160401b0394851667ffffffffffffffff60801b90941693909317600160c01b858516021790556003018054429093166001600160801b0319909316929092179091556109c39085613109565b8251602001519094506bffffffffffffffffffffffff1916817f9d9c026e2cadfec89cccc2cd72705360eca1beba24774f3363f4bb33faabc7d78460400151604051610a1e91906001600160401b0391909116815260200190565b60405180910390a3505080610a3290613129565b90506107ba565b506003830180546fffffffffffffffff00000000000000001916600160401b6001600160401b0384168102919091179091556001840154606491610a81910460ff168361314b565b6001600160401b03161015610ab457604051633e1a785160e01b81526001600160401b038216600482015260240161056b565b5f73__$fd0c147b4031eef6079b0498cbafa865f0$__634d847884610ad887611863565b604001516040518263ffffffff1660e01b8152600401610af89190612ec3565b602060405180830381865af4158015610b13573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b379190612ed5565b90505f73__$fd0c147b4031eef6079b0498cbafa865f0$__6387418b8e886040518263ffffffff1660e01b8152600401610b7191906132a1565b5f60405180830381865af4158015610b8b573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610bb29190810190612e92565b90505f600282604051610bc59190612fde565b602060405180830381855afa158015610be0573d5f803e3d5ffd5b5050506040513d601f19601f82011682018060405250810190610c039190612ed5565b9050828114610c2f5760405163baaea89d60e01b8152600481018290526024810184905260440161056b565b5050506007909201805460ff1916600117905550505050565b5f610c5161183f565b54919050565b5f80610c61611979565b610c6b84846119d4565b915091505b9250929050565b610c7f611979565b610c885f611b9c565b565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff1615906001600160401b03165f81158015610cce5750825b90505f826001600160401b03166001148015610ce95750303b155b905081158015610cf7575080155b15610d155760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff191660011785558315610d3f57845460ff60401b1916600160401b1785555b610d4886611c0c565b8315610d8e57845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b505050505050565b5f610d9f611979565b5f610da861183f565b90505f8073__$fd0c147b4031eef6079b0498cbafa865f0$__63021de88f610dcf87611863565b604001516040518263ffffffff1660e01b8152600401610def9190612ec3565b6040805180830381865af4158015610e09573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e2d9190613344565b915091508015610e5457604051632d07135360e01b8152811515600482015260240161056b565b5f8281526005808501602052604080832081516101008101909252805491929091839160ff90911690811115610e8c57610e8c6129a4565b6005811115610e9d57610e9d6129a4565b8152602001600182018054610eb190612e08565b80601f0160208091040260200160405190810160405280929190818152602001828054610edd90612e08565b8015610f285780601f10610eff57610100808354040283529160200191610f28565b820191905f5260205f20905b815481529060010190602001808311610f0b57829003601f168201915b505050918352505060028201546001600160401b038082166020840152600160401b80830482166040850152600160801b830482166060850152600160c01b9092048116608084015260039384015480821660a0850152919091041660c09091015290915081516005811115610fa057610fa06129a4565b14158015610fc15750600181516005811115610fbe57610fbe6129a4565b14155b15610fe257805160405163170cc93360e21b815261056b9190600401612e3a565b600381516005811115610ff757610ff76129a4565b03611005576004815261100a565b600581525b8360060181602001516040516110209190612fde565b90815260408051602092819003830190205f90819055858152600587810190935220825181548493839160ff1916906001908490811115611063576110636129a4565b02179055506020820151600182019061107c908261303a565b506040828101516002830180546060860151608087015160a08801516001600160401b039586166001600160801b031994851617600160401b9387168402176001600160801b0316600160801b928716929092026001600160c01b031691909117600160c01b918616919091021790925560c08601516003909501805460e09097015195841696909116959095179390911602919091179091555183907fafaccef7080649a725bc30a35359a257a4a27225be352875c80bdf6b5f04080c905f90a25090925050505b919050565b5f611153611979565b5f61115c61183f565b90505f8073__$fd0c147b4031eef6079b0498cbafa865f0$__63021de88f61118387611863565b604001516040518263ffffffff1660e01b81526004016111a39190612ec3565b6040805180830381865af41580156111bd573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111e19190613344565b915091508061120757604051632d07135360e01b8152811515600482015260240161056b565b5f8281526004840160205260409020805461122190612e08565b90505f036112455760405163089938b360e11b81526004810183905260240161056b565b60015f838152600580860160205260409091205460ff169081111561126c5761126c6129a4565b1461129f575f8281526005840160205260409081902054905163170cc93360e21b815261056b9160ff1690600401612e3a565b5f82815260048401602052604081206112b791612849565b5f828152600584016020908152604091829020805460ff1916600290811782556003820180546001600160401b0342811667ffffffffffffffff19909216919091179091559101549251600160c01b90930416825283917f967ae87813a3b5f201dd9bcba778d457176eafe6f41facee1c718091d3952d06910160405180910390a2509392505050565b611349611979565b61135281611c32565b50565b5f61135e61183f565b60030154600160401b90046001600160401b0316919050565b5f61138061183f565b5f838152600482016020526040902080549192509061139e90612e08565b90505f036113c25760405163089938b360e11b81526004810183905260240161056b565b60015f838152600580840160205260409091205460ff16908111156113e9576113e96129a4565b1461141c575f8281526005820160205260409081902054905163170cc93360e21b815261056b9160ff1690600401612e3a565b5f8281526004808301602052604091829020915163ee5b48eb60e01b81526005600160991b019263ee5b48eb926114539201613365565b6020604051808303815f875af115801561146f573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114939190612ed5565b505050565b5f806114a2611979565b5f6114ac84611863565b90505f805f73__$fd0c147b4031eef6079b0498cbafa865f0$__6350782b0f85604001516040518263ffffffff1660e01b81526004016114ec9190612ec3565b606060405180830381865af4158015611507573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061152b91906133ef565b9250925092505f61153a61183f565b5f8581526005820160205260409020600201549091506001600160401b03808516600160401b90920416101561158e57604051632e19bc2d60e11b81526001600160401b038416600482015260240161056b565b5f8481526005820160205260409081902060020180546001600160401b038616600160801b0267ffffffffffffffff60801b199091161790555184907fc917996591802ecedcfced71321d4bb5320f7dfbacf5477dffe1dbf8b8839ff99061160e90869086906001600160401b0392831681529116602082015260400190565b60405180910390a25091945092505050915091565b60408051610100810182525f8082526060602083018190529282018190529181018290526080810182905260a0810182905260c0810182905260e081018290529061166c61183f565b5f84815260058083016020526040918290208251610100810190935280549394509192839160ff909116908111156116a6576116a66129a4565b60058111156116b7576116b76129a4565b81526020016001820180546116cb90612e08565b80601f01602080910402602001604051908101604052809291908181526020018280546116f790612e08565b80156117425780601f1061171957610100808354040283529160200191611742565b820191905f5260205f20905b81548152906001019060200180831161172557829003601f168201915b505050918352505060028201546001600160401b038082166020840152600160401b80830482166040850152600160801b830482166060850152600160c01b9092048116608084015260039093015480841660a08401520490911660c0909101529392505050565b5f6117b3611979565b6117c1878787878787611f1d565b979650505050505050565b6117d4611979565b6001600160a01b0381166117fd57604051631e4fbdf760e01b81525f600482015260240161056b565b61135281611b9c565b5f8061181061183f565b905080600601848460405161182692919061342f565b9081526020016040518091039020549150505b92915050565b7fe92546d698950ddd38910d2e15ed1d923cd0a7b3dde9e2a6a3f380565559cb0090565b60408051606080820183525f8083526020830152918101919091526040516306f8253560e41b815263ffffffff831660048201525f9081906005600160991b0190636f825350906024015f60405180830381865afa1580156118c7573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526118ee919081019061343e565b915091508061191057604051636b2f19e960e01b815260040160405180910390fd5b815115611936578151604051636ba589a560e01b8152600481019190915260240161056b565b60208201516001600160a01b031615611972576020820151604051624de75d60e31b81526001600160a01b03909116600482015260240161056b565b5092915050565b336119ab7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6001600160a01b031614610c885760405163118cdaa760e01b815233600482015260240161056b565b5f805f6119df61183f565b5f868152600582016020526040902060020154909150600160c01b90046001600160401b0316611a0f8582612307565b5f611a1987612574565b5f88815260058501602052604080822060020180546001600160c01b0316600160c01b6001600160401b038c811691820292909217909255915163854a893f60e01b8152600481018c905291841660248301526044820152919250906005600160991b019063ee5b48eb9073__$fd0c147b4031eef6079b0498cbafa865f0$__9063854a893f906064015f60405180830381865af4158015611abd573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052611ae49190810190612e92565b6040518263ffffffff1660e01b8152600401611b009190612ec3565b6020604051808303815f875af1158015611b1c573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611b409190612ed5565b604080516001600160401b038581168252602082018490528a1681830152905191925089917f6e350dd49b060d87f297206fd309234ed43156d890ced0f139ecf704310481d39181900360600190a29097909650945050505050565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080546001600160a01b031981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a3505050565b611c146125dd565b611c29611c246020830183612d82565b612626565b61135281612637565b5f611c3b61183f565b5f838152600580830160205260408083208151610100810190925280549495509293909291839160ff1690811115611c7557611c756129a4565b6005811115611c8657611c866129a4565b8152602001600182018054611c9a90612e08565b80601f0160208091040260200160405190810160405280929190818152602001828054611cc690612e08565b8015611d115780601f10611ce857610100808354040283529160200191611d11565b820191905f5260205f20905b815481529060010190602001808311611cf457829003601f168201915b50505091835250506002828101546001600160401b038082166020850152600160401b80830482166040860152600160801b830482166060860152600160c01b9092048116608085015260039094015480851660a08501520490921660c09091015290915081516005811115611d8957611d896129a4565b14611dbc575f8381526005830160205260409081902054905163170cc93360e21b815261056b9160ff1690600401612e3a565b60038152426001600160401b031660e08201525f83815260058381016020526040909120825181548493839160ff1916906001908490811115611e0157611e016129a4565b021790555060208201516001820190611e1a908261303a565b5060408201516002820180546060850151608086015160a08701516001600160401b039586166001600160801b031994851617600160401b9387168402176001600160801b0316600160801b928716929092026001600160c01b031691909117600160c01b918616919091021790925560c08501516003909401805460e090960151948416959091169490941792909116021790555f611eba84826119d4565b915050837fbae388a94e7f18411fe57098f12f418b8e1a8273e0532a90188a3a059b897273828460a0015142604051611f0f939291909283526001600160401b03918216602084015216604082015260600190565b60405180910390a250505050565b5f611f2661183f565b6007015460ff16611f4a57604051637fab81e560e01b815260040160405180910390fd5b5f611f5361183f565b905042866001600160401b0316111580611f825750611f756202a300426134cb565b866001600160401b031610155b15611fab57604051635879da1360e11b81526001600160401b038716600482015260240161056b565b60038101546001600160401b0390611fce90600160401b900482168583166134cb565b1115611ff857604051633e1a785160e01b81526001600160401b038416600482015260240161056b565b6120018561271e565b61200a8461271e565b86516030146120315786516040516326475b2f60e11b815260040161056b91815260200190565b87516014146120555787604051633e08a12560e11b815260040161056b9190612ec3565b5f801b816006018960405161206a9190612fde565b90815260200160405180910390205414612099578760405163a41f772f60e01b815260040161056b9190612ec3565b6120a3835f612307565b5f8073__$fd0c147b4031eef6079b0498cbafa865f0$__63eb97ce516040518060e00160405280865f015481526020018d81526020018c81526020018b6001600160401b031681526020018a8152602001898152602001886001600160401b03168152506040518263ffffffff1660e01b81526004016121239190613544565b5f60405180830381865af415801561213d573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261216491908101906135fb565b5f82815260048601602052604090209193509150612182828261303a565b5081836006018b6040516121969190612fde565b9081526040519081900360200181209190915563ee5b48eb60e01b81525f906005600160991b019063ee5b48eb906121d2908590600401612ec3565b6020604051808303815f875af11580156121ee573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906122129190612ed5565b5f8481526005860160205260409020805460ff1916600190811782559192500161223c8c8261303a565b505f8381526005850160205260409020600281018054600160c01b6001600160401b038a1690810267ffffffffffffffff60801b9092161717905560030180546001600160801b03191690556122938b6020015190565b6bffffffffffffffffffffffff1916837f5881be437bdcb008bfa5f20e32d3e335ccf8ab90ef2818852a251625260af35d838c8a6040516122f0939291909283526001600160401b03918216602084015216604082015260600190565b60405180910390a350909998505050505050505050565b5f61231061183f565b90505f826001600160401b0316846001600160401b0316111561233e57612337838561363e565b905061234b565b612348848461363e565b90505b60408051608081018252600284015480825260038501546001600160401b038082166020850152600160401b8204811694840194909452600160801b90049092166060820152429115806123b85750600184015481516123b4916001600160401b0316906134cb565b8210155b156123e0576001600160401b03808416606083015282825260408201511660208201526123ff565b82816060018181516123f29190613109565b6001600160401b03169052505b606081015161240f90606461314b565b602082015160018601546001600160401b03929092169161243a9190600160401b900460ff1661314b565b6001600160401b0316101561247357606081015160405163dfae880160e01b81526001600160401b03909116600482015260240161056b565b85816040018181516124859190613109565b6001600160401b03169052506040810180518691906124a590839061363e565b6001600160401b0316905250600184015460408201516064916124d391600160401b90910460ff169061314b565b6001600160401b0316101561250c576040808201519051633e1a785160e01b81526001600160401b03909116600482015260240161056b565b8051600285015560208101516003909401805460408301516060909301516001600160401b03908116600160801b0267ffffffffffffffff60801b19948216600160401b026001600160801b0319909316919097161717919091169390931790925550505050565b5f8061257e61183f565b5f84815260058201602052604090206002018054919250906008906125b290600160401b90046001600160401b031661365e565b91906101000a8154816001600160401b0302191690836001600160401b031602179055915050919050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff16610c8857604051631afcd79f60e31b815260040160405180910390fd5b61262e6125dd565b61135281612841565b61263f6125dd565b5f61264861183f565b60208301358155905060146126636080840160608501613679565b60ff161180612682575061267d6080830160608401613679565b60ff16155b156126b6576126976080830160608401613679565b604051634a59bbff60e11b815260ff909116600482015260240161056b565b6126c66080830160608401613679565b60018201805460ff92909216600160401b0260ff60401b199092169190911790556126f76060830160408401613699565b600191909101805467ffffffffffffffff19166001600160401b0390921691909117905550565b805163ffffffff16158015612737575060208101515115155b1561276b57805160208201515160405163c08a0f1d60e01b815263ffffffff9092166004830152602482015260440161056b565b602081015151815163ffffffff1611156127ae57805160208201515160405163c08a0f1d60e01b815263ffffffff9092166004830152602482015260440161056b565b60015b81602001515181101561283d5760208201516127ce6001836136b4565b815181106127de576127de612f31565b60200260200101516001600160a01b03168260200151828151811061280557612805612f31565b60200260200101516001600160a01b0316101561283557604051630dbc8d5f60e31b815260040160405180910390fd5b6001016127b1565b5050565b6117d46125dd565b50805461285590612e08565b5f825580601f10612864575050565b601f0160209004905f5260205f209081019061135291905b8082111561288f575f815560010161287c565b5090565b5f602082840312156128a3575f80fd5b5035919050565b5f608082840312156128ba575f80fd5b50919050565b803563ffffffff81168114611145575f80fd5b5f80604083850312156128e4575f80fd5b82356001600160401b038111156128f9575f80fd5b612905858286016128aa565b925050612914602084016128c0565b90509250929050565b6001600160401b0381168114611352575f80fd5b80356111458161291d565b5f806040838503121561294d575f80fd5b82359150602083013561295f8161291d565b809150509250929050565b5f6080828403121561297a575f80fd5b61298483836128aa565b9392505050565b5f6020828403121561299b575f80fd5b612984826128c0565b634e487b7160e01b5f52602160045260245ffd5b600681106129d457634e487b7160e01b5f52602160045260245ffd5b9052565b5f5b838110156129f25781810151838201526020016129da565b50505f910152565b5f8151808452612a118160208601602086016129d8565b601f01601f19169290920160200192915050565b60208152612a376020820183516129b8565b5f6020830151610100806040850152612a546101208501836129fa565b915060408501516001600160401b03808216606087015280606088015116608087015250506080850151612a9360a08601826001600160401b03169052565b5060a08501516001600160401b03811660c08601525060c08501516001600160401b03811660e08601525060e08501516001600160401b038116858301525090949350505050565b634e487b7160e01b5f52604160045260245ffd5b604080519081016001600160401b0381118282101715612b1157612b11612adb565b60405290565b604051606081016001600160401b0381118282101715612b1157612b11612adb565b604051601f8201601f191681016001600160401b0381118282101715612b6157612b61612adb565b604052919050565b5f6001600160401b03821115612b8157612b81612adb565b50601f01601f191660200190565b5f82601f830112612b9e575f80fd5b8135612bb1612bac82612b69565b612b39565b818152846020838601011115612bc5575f80fd5b816020850160208301375f918101602001919091529392505050565b6001600160a01b0381168114611352575f80fd5b5f60408284031215612c05575f80fd5b612c0d612aef565b9050612c18826128c0565b81526020808301356001600160401b0380821115612c34575f80fd5b818501915085601f830112612c47575f80fd5b813581811115612c5957612c59612adb565b8060051b9150612c6a848301612b39565b8181529183018401918481019088841115612c83575f80fd5b938501935b83851015612cad5784359250612c9d83612be1565b8282529385019390850190612c88565b808688015250505050505092915050565b5f805f805f8060c08789031215612cd3575f80fd5b86356001600160401b0380821115612ce9575f80fd5b612cf58a838b01612b8f565b97506020890135915080821115612d0a575f80fd5b612d168a838b01612b8f565b9650612d2460408a01612931565b95506060890135915080821115612d39575f80fd5b612d458a838b01612bf5565b94506080890135915080821115612d5a575f80fd5b50612d6789828a01612bf5565b925050612d7660a08801612931565b90509295509295509295565b5f60208284031215612d92575f80fd5b813561298481612be1565b5f8060208385031215612dae575f80fd5b82356001600160401b0380821115612dc4575f80fd5b818501915085601f830112612dd7575f80fd5b813581811115612de5575f80fd5b866020828501011115612df6575f80fd5b60209290920196919550909350505050565b600181811c90821680612e1c57607f821691505b6020821081036128ba57634e487b7160e01b5f52602260045260245ffd5b6020810161183982846129b8565b5f82601f830112612e57575f80fd5b8151612e65612bac82612b69565b818152846020838601011115612e79575f80fd5b612e8a8260208301602087016129d8565b949350505050565b5f60208284031215612ea2575f80fd5b81516001600160401b03811115612eb7575f80fd5b612e8a84828501612e48565b602081525f61298460208301846129fa565b5f60208284031215612ee5575f80fd5b5051919050565b5f808335601e19843603018112612f01575f80fd5b8301803591506001600160401b03821115612f1a575f80fd5b6020019150600581901b3603821315610c70575f80fd5b634e487b7160e01b5f52603260045260245ffd5b5f8235605e19833603018112612f59575f80fd5b9190910192915050565b5f60608236031215612f73575f80fd5b612f7b612b17565b82356001600160401b0380821115612f91575f80fd5b612f9d36838701612b8f565b83526020850135915080821115612fb2575f80fd5b50612fbf36828601612b8f565b6020830152506040830135612fd38161291d565b604082015292915050565b5f8251612f598184602087016129d8565b601f82111561149357805f5260205f20601f840160051c810160208510156130145750805b601f840160051c820191505b81811015613033575f8155600101613020565b5050505050565b81516001600160401b0381111561305357613053612adb565b613067816130618454612e08565b84612fef565b602080601f83116001811461309a575f84156130835750858301515b5f19600386901b1c1916600185901b178555610d8e565b5f85815260208120601f198616915b828110156130c8578886015182559484019460019091019084016130a9565b50858210156130e557878501515f19600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b5f52601160045260245ffd5b6001600160401b03818116838216019080821115611972576119726130f5565b5f63ffffffff808316818103613141576131416130f5565b6001019392505050565b6001600160401b0381811683821602808216919082811461316e5761316e6130f5565b505092915050565b5f808335601e1984360301811261318b575f80fd5b83016020810192503590506001600160401b038111156131a9575f80fd5b803603821315610c70575f80fd5b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b5f8383855260208086019550808560051b830101845f5b8781101561329457848303601f19018952813536889003605e1901811261321b575f80fd5b870160606132298280613176565b82875261323983880182846131b7565b9250505061324986830183613176565b8683038888015261325b8382846131b7565b9250505060408083013592506132708361291d565b6001600160401b0392909216949091019390935297830197908301906001016131f6565b5090979650505050505050565b6020815281356020820152602082013560408201525f60408301356132c581612be1565b6001600160a01b031660608381019190915283013536849003601e190181126132ec575f80fd5b83016020810190356001600160401b03811115613307575f80fd5b8060051b3603821315613318575f80fd5b60808085015261332c60a0850182846131df565b95945050505050565b80518015158114611145575f80fd5b5f8060408385031215613355575f80fd5b8251915061291460208401613335565b5f60208083525f845461337781612e08565b806020870152604060018084165f811461339857600181146133b4576133e1565b60ff19851660408a0152604084151560051b8a010195506133e1565b895f5260205f205f5b858110156133d85781548b82018601529083019088016133bd565b8a016040019650505b509398975050505050505050565b5f805f60608486031215613401575f80fd5b8351925060208401516134138161291d565b60408501519092506134248161291d565b809150509250925092565b818382375f9101908152919050565b5f806040838503121561344f575f80fd5b82516001600160401b0380821115613465575f80fd5b9084019060608287031215613478575f80fd5b613480612b17565b82518152602083015161349281612be1565b60208201526040830151828111156134a8575f80fd5b6134b488828601612e48565b604083015250935061291491505060208401613335565b80820180821115611839576118396130f5565b5f6040830163ffffffff8351168452602080840151604060208701528281518085526060880191506020830194505f92505b808310156135395784516001600160a01b03168252938301936001929092019190830190613510565b509695505050505050565b60208152815160208201525f602083015160e0604084015261356a6101008401826129fa565b90506040840151601f198085840301606086015261358883836129fa565b92506001600160401b03606087015116608086015260808601519150808584030160a08601526135b883836134de565b925060a08601519150808584030160c0860152506135d682826134de565b91505060c08401516135f360e08501826001600160401b03169052565b509392505050565b5f806040838503121561360c575f80fd5b8251915060208301516001600160401b03811115613628575f80fd5b61363485828601612e48565b9150509250929050565b6001600160401b03828116828216039080821115611972576119726130f5565b5f6001600160401b03808316818103613141576131416130f5565b5f60208284031215613689575f80fd5b813560ff81168114612984575f80fd5b5f602082840312156136a9575f80fd5b81356129848161291d565b81810381811115611839576118396130f556fea164736f6c6343000819000a + diff --git a/pkg/validatormanager/deployed_validator_messages_bytecode_v1.0.0.txt b/pkg/validatormanager/deployed_validator_messages_bytecode_acp99.txt similarity index 100% rename from pkg/validatormanager/deployed_validator_messages_bytecode_v1.0.0.txt rename to pkg/validatormanager/deployed_validator_messages_bytecode_acp99.txt diff --git a/pkg/validatormanager/helpers.go b/pkg/validatormanager/helpers.go new file mode 100644 index 000000000..ce89edc3e --- /dev/null +++ b/pkg/validatormanager/helpers.go @@ -0,0 +1,99 @@ +// Copyright (C) 2022, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. +package validatormanager + +import ( + _ "embed" + "fmt" + "math/big" + + "github.com/ava-labs/avalanche-cli/pkg/evm" + "github.com/ava-labs/avalanche-cli/pkg/utils" + "github.com/ava-labs/avalanchego/ids" + warp "github.com/ava-labs/avalanchego/vms/platformvm/warp" + warpMessage "github.com/ava-labs/avalanchego/vms/platformvm/warp/message" + warpPayload "github.com/ava-labs/avalanchego/vms/platformvm/warp/payload" + "github.com/ava-labs/subnet-evm/core/types" + "github.com/ava-labs/subnet-evm/interfaces" + subnetEvmWarp "github.com/ava-labs/subnet-evm/precompile/contracts/warp" + + "github.com/ethereum/go-ethereum/common" +) + +func GetWarpMessagesFromLogs( + logs []*types.Log, +) []*warp.UnsignedMessage { + messages := []*warp.UnsignedMessage{} + for _, txLog := range logs { + msg, err := subnetEvmWarp.UnpackSendWarpEventDataToMessage(txLog.Data) + if err == nil { + messages = append(messages, msg) + } + } + return messages +} + +func GetWarpMessageFromLogs( + logs []*types.Log, +) (*warp.UnsignedMessage, error) { + messages := GetWarpMessagesFromLogs(logs) + if len(messages) == 0 { + return nil, fmt.Errorf("no warp message is present in evm logs") + } + return messages[0], nil +} + +func GetValidatorNonce( + rpcURL string, + validationID ids.ID, +) (uint64, error) { + client, err := evm.GetClient(rpcURL) + if err != nil { + return 0, err + } + ctx, cancel := utils.GetAPILargeContext() + defer cancel() + height, err := client.BlockNumber(ctx) + if err != nil { + return 0, err + } + count := uint64(0) + maxBlock := int64(height) + minBlock := int64(0) + for blockNumber := maxBlock; blockNumber >= minBlock; blockNumber-- { + ctx, cancel := utils.GetAPILargeContext() + defer cancel() + block, err := client.BlockByNumber(ctx, big.NewInt(blockNumber)) + if err != nil { + return 0, err + } + blockHash := block.Hash() + logs, err := client.FilterLogs(ctx, interfaces.FilterQuery{ + BlockHash: &blockHash, + Addresses: []common.Address{subnetEvmWarp.Module.Address}, + }) + if err != nil { + return 0, err + } + msgs := GetWarpMessagesFromLogs(utils.PointersSlice(logs)) + for _, msg := range msgs { + payload := msg.Payload + addressedCall, err := warpPayload.ParseAddressedCall(payload) + if err == nil { + weightMsg, err := warpMessage.ParseL1ValidatorWeight(addressedCall.Payload) + if err == nil { + if weightMsg.ValidationID == validationID { + count++ + } + } + regMsg, err := warpMessage.ParseRegisterL1Validator(addressedCall.Payload) + if err == nil { + if regMsg.ValidationID() == validationID { + return count, nil + } + } + } + } + } + return count, nil +} diff --git a/pkg/validatormanager/proxy.go b/pkg/validatormanager/proxy.go index 688d0ebdd..bf6620c5f 100644 --- a/pkg/validatormanager/proxy.go +++ b/pkg/validatormanager/proxy.go @@ -22,6 +22,8 @@ func SetupValidatorManagerAtProxy( ) (*types.Transaction, *types.Receipt, error) { return contract.TxToMethod( rpcURL, + false, + common.Address{}, proxyManagerPrivateKey, common.HexToAddress(validatorManagerSDK.ProxyAdminContractAddress), big.NewInt(0), diff --git a/pkg/validatormanager/registration.go b/pkg/validatormanager/registration.go index b457ecf4a..fe88b3477 100644 --- a/pkg/validatormanager/registration.go +++ b/pkg/validatormanager/registration.go @@ -82,6 +82,8 @@ func InitializeValidatorRegistrationPoSNative( return contract.TxToMethod( rpcURL, + false, + common.Address{}, managerOwnerPrivateKey, managerAddress, stakeAmount, @@ -98,6 +100,8 @@ func InitializeValidatorRegistrationPoSNative( func InitializeValidatorRegistrationPoA( rpcURL string, managerAddress common.Address, + generateRawTxOnly bool, + managerOwnerAddress common.Address, managerOwnerPrivateKey string, nodeID ids.NodeID, blsPublicKey []byte, @@ -105,18 +109,12 @@ func InitializeValidatorRegistrationPoA( balanceOwners warpMessage.PChainOwner, disableOwners warpMessage.PChainOwner, weight uint64, + useACP99 bool, ) (*types.Transaction, *types.Receipt, error) { type PChainOwner struct { Threshold uint32 Addresses []common.Address } - type ValidatorRegistrationInput struct { - NodeID []byte - BlsPublicKey []byte - RegistrationExpiry uint64 - RemainingBalanceOwner PChainOwner - DisableOwner PChainOwner - } balanceOwnersAux := PChainOwner{ Threshold: balanceOwners.Threshold, Addresses: utils.Map(balanceOwners.Addresses, func(addr ids.ShortID) common.Address { @@ -129,27 +127,54 @@ func InitializeValidatorRegistrationPoA( return common.BytesToAddress(addr[:]) }), } - validatorRegistrationInput := ValidatorRegistrationInput{ - NodeID: nodeID[:], - BlsPublicKey: blsPublicKey, - RegistrationExpiry: expiry, - RemainingBalanceOwner: balanceOwnersAux, - DisableOwner: disableOwnersAux, + if useACP99 { + return contract.TxToMethod( + rpcURL, + generateRawTxOnly, + managerOwnerAddress, + managerOwnerPrivateKey, + managerAddress, + big.NewInt(0), + "initialize validator registration", + validatormanager.ErrorSignatureToError, + "initiateValidatorRegistration(bytes,bytes,uint64,(uint32,[address]),(uint32,[address]),uint64)", + nodeID[:], + blsPublicKey, + expiry, + balanceOwnersAux, + disableOwnersAux, + weight, + ) + } + type ValidatorRegistrationInput struct { + NodeID []byte + BlsPublicKey []byte + RegistrationExpiry uint64 + RemainingBalanceOwner PChainOwner + DisableOwner PChainOwner } return contract.TxToMethod( rpcURL, + generateRawTxOnly, + managerOwnerAddress, managerOwnerPrivateKey, managerAddress, big.NewInt(0), "initialize validator registration", validatormanager.ErrorSignatureToError, "initializeValidatorRegistration((bytes,bytes,uint64,(uint32,[address]),(uint32,[address])),uint64)", - validatorRegistrationInput, + ValidatorRegistrationInput{ + NodeID: nodeID[:], + BlsPublicKey: blsPublicKey, + RegistrationExpiry: expiry, + RemainingBalanceOwner: balanceOwnersAux, + DisableOwner: disableOwnersAux, + }, weight, ) } -func GetSubnetValidatorRegistrationMessage( +func GetRegisterL1ValidatorMessage( ctx context.Context, rpcURL string, network models.Network, @@ -167,61 +192,82 @@ func GetSubnetValidatorRegistrationMessage( disableOwners warpMessage.PChainOwner, weight uint64, alreadyInitialized bool, + initiateTxHash string, + registerSubnetValidatorUnsignedMessage *warp.UnsignedMessage, ) (*warp.Message, ids.ID, error) { var ( - registerSubnetValidatorUnsignedMessage *warp.UnsignedMessage - validationID ids.ID - err error + validationID ids.ID + err error ) - if alreadyInitialized { - validationID, err = validator.GetRegisteredValidator( - rpcURL, - managerAddress, - nodeID, - ) - if err != nil { - return nil, ids.Empty, err - } - unsignedMessageBytes, err := GetRegistrationMessage( - rpcURL, - validationID, - ) - if err != nil { - return nil, ids.Empty, err - } - registerSubnetValidatorUnsignedMessage, err = warp.ParseUnsignedMessage(unsignedMessageBytes) - if err != nil { - return nil, ids.Empty, err + if registerSubnetValidatorUnsignedMessage == nil { + if alreadyInitialized { + validationID, err = validator.GetRegisteredValidator( + rpcURL, + managerAddress, + nodeID, + ) + if err != nil { + return nil, ids.Empty, err + } + if initiateTxHash != "" { + registerSubnetValidatorUnsignedMessage, err = GetRegisterL1ValidatorMessageFromTx( + rpcURL, + validationID, + initiateTxHash, + ) + if err != nil { + return nil, ids.Empty, err + } + } else { + registerSubnetValidatorUnsignedMessage, err = SearchForRegisterL1ValidatorMessage( + rpcURL, + validationID, + ) + if err != nil { + return nil, ids.Empty, err + } + } + } else { + addressedCallPayload, err := warpMessage.NewRegisterL1Validator( + subnetID, + nodeID, + blsPublicKey, + expiry, + balanceOwners, + disableOwners, + weight, + ) + if err != nil { + return nil, ids.Empty, err + } + validationID = addressedCallPayload.ValidationID() + registerSubnetValidatorAddressedCall, err := warpPayload.NewAddressedCall( + managerAddress.Bytes(), + addressedCallPayload.Bytes(), + ) + if err != nil { + return nil, ids.Empty, err + } + registerSubnetValidatorUnsignedMessage, err = warp.NewUnsignedMessage( + network.ID, + blockchainID, + registerSubnetValidatorAddressedCall.Bytes(), + ) + if err != nil { + return nil, ids.Empty, err + } } } else { - addressedCallPayload, err := warpMessage.NewRegisterL1Validator( - subnetID, - nodeID, - blsPublicKey, - expiry, - balanceOwners, - disableOwners, - weight, - ) + payload := registerSubnetValidatorUnsignedMessage.Payload + addressedCall, err := warpPayload.ParseAddressedCall(payload) if err != nil { - return nil, ids.Empty, err + return nil, ids.Empty, fmt.Errorf("unexpected format on given registration warp message: %w", err) } - validationID = addressedCallPayload.ValidationID() - registerSubnetValidatorAddressedCall, err := warpPayload.NewAddressedCall( - managerAddress.Bytes(), - addressedCallPayload.Bytes(), - ) - if err != nil { - return nil, ids.Empty, err - } - registerSubnetValidatorUnsignedMessage, err = warp.NewUnsignedMessage( - network.ID, - blockchainID, - registerSubnetValidatorAddressedCall.Bytes(), - ) + reg, err := warpMessage.ParseRegisterL1Validator(addressedCall.Payload) if err != nil { - return nil, ids.Empty, err + return nil, ids.Empty, fmt.Errorf("unexpected format on given registration warp message: %w", err) } + validationID = reg.ValidationID() } signatureAggregator, err := interchain.NewSignatureAggregator( ctx, @@ -260,7 +306,7 @@ func PoSWeightToValue( return value, nil } -func GetPChainSubnetValidatorRegistrationWarpMessage( +func GetPChainL1ValidatorRegistrationMessage( ctx context.Context, network models.Network, rpcURL string, @@ -317,14 +363,18 @@ func GetPChainSubnetValidatorRegistrationWarpMessage( func CompleteValidatorRegistration( rpcURL string, managerAddress common.Address, + generateRawTxOnly bool, + ownerAddress common.Address, privateKey string, // not need to be owner atm - subnetValidatorRegistrationSignedMessage *warp.Message, + l1ValidatorRegistrationSignedMessage *warp.Message, ) (*types.Transaction, *types.Receipt, error) { return contract.TxToMethodWithWarpMessage( rpcURL, + generateRawTxOnly, + ownerAddress, privateKey, managerAddress, - subnetValidatorRegistrationSignedMessage, + l1ValidatorRegistrationSignedMessage, big.NewInt(0), "complete validator registration", validatormanager.ErrorSignatureToError, @@ -339,6 +389,8 @@ func InitValidatorRegistration( network models.Network, rpcURL string, chainSpec contract.ChainSpec, + generateRawTxOnly bool, + ownerAddressStr string, ownerPrivateKey string, nodeID ids.NodeID, blsPublicKey []byte, @@ -349,18 +401,20 @@ func InitValidatorRegistration( aggregatorExtraPeerEndpoints []info.Peer, aggregatorAllowPrivatePeers bool, aggregatorLogger logging.Logger, - initWithPos bool, + isPos bool, delegationFee uint16, stakeDuration time.Duration, validatorManagerAddressStr string, -) (*warp.Message, ids.ID, error) { + useACP99 bool, + initiateTxHash string, +) (*warp.Message, ids.ID, *types.Transaction, error) { subnetID, err := contract.GetSubnetID( app, network, chainSpec, ) if err != nil { - return nil, ids.Empty, err + return nil, ids.Empty, nil, err } blockchainID, err := contract.GetBlockchainID( app, @@ -368,69 +422,89 @@ func InitValidatorRegistration( chainSpec, ) if err != nil { - return nil, ids.Empty, err + return nil, ids.Empty, nil, err } managerAddress := common.HexToAddress(validatorManagerAddressStr) - alreadyInitialized := false - if initWithPos { - stakeAmount, err := PoSWeightToValue( - rpcURL, - managerAddress, - weight, - ) - if err != nil { - return nil, ids.Empty, fmt.Errorf("failure obtaining value from weight: %w", err) - } - ux.Logger.PrintLineSeparator() - ux.Logger.PrintToUser("Initializing validator registration with PoS validator manager") - ux.Logger.PrintToUser("Using RPC URL: %s", rpcURL) - ux.Logger.PrintToUser("NodeID: %s staking %s tokens", nodeID.String(), stakeAmount) - ux.Logger.PrintLineSeparator() - tx, _, err := InitializeValidatorRegistrationPoSNative( - rpcURL, - managerAddress, - ownerPrivateKey, - nodeID, - blsPublicKey, - expiry, - balanceOwners, - disableOwners, - delegationFee, - stakeDuration, - stakeAmount, - ) - if err != nil { - if !errors.Is(err, validatormanager.ErrNodeAlreadyRegistered) { - return nil, ids.Empty, evm.TransactionError(tx, err, "failure initializing validator registration") + ownerAddress := common.HexToAddress(ownerAddressStr) + var receipt *types.Receipt + alreadyInitialized := initiateTxHash != "" + if !alreadyInitialized { + var tx *types.Transaction + if isPos { + stakeAmount, err := PoSWeightToValue( + rpcURL, + managerAddress, + weight, + ) + if err != nil { + return nil, ids.Empty, nil, fmt.Errorf("failure obtaining value from weight: %w", err) + } + ux.Logger.PrintLineSeparator() + ux.Logger.PrintToUser("Initializing validator registration with PoS validator manager") + ux.Logger.PrintToUser("Using RPC URL: %s", rpcURL) + ux.Logger.PrintToUser("NodeID: %s staking %s tokens", nodeID.String(), stakeAmount) + ux.Logger.PrintLineSeparator() + tx, receipt, err = InitializeValidatorRegistrationPoSNative( + rpcURL, + managerAddress, + ownerPrivateKey, + nodeID, + blsPublicKey, + expiry, + balanceOwners, + disableOwners, + delegationFee, + stakeDuration, + stakeAmount, + ) + if err != nil { + if !errors.Is(err, validatormanager.ErrNodeAlreadyRegistered) { + return nil, ids.Empty, nil, evm.TransactionError(tx, err, "failure initializing validator registration") + } + ux.Logger.PrintToUser(logging.LightBlue.Wrap("The validator registration was already initialized. Proceeding to the next step")) + alreadyInitialized = true } - ux.Logger.PrintToUser(logging.LightBlue.Wrap("The validator registration was already initialized. Proceeding to the next step")) - alreadyInitialized = true + ux.Logger.PrintToUser(fmt.Sprintf("Validator staked amount: %d", stakeAmount)) + } else { + managerAddress = common.HexToAddress(validatorManagerAddressStr) + tx, receipt, err = InitializeValidatorRegistrationPoA( + rpcURL, + managerAddress, + generateRawTxOnly, + ownerAddress, + ownerPrivateKey, + nodeID, + blsPublicKey, + expiry, + balanceOwners, + disableOwners, + weight, + useACP99, + ) + if err != nil { + if !errors.Is(err, validatormanager.ErrNodeAlreadyRegistered) { + return nil, ids.Empty, nil, evm.TransactionError(tx, err, "failure initializing validator registration") + } + ux.Logger.PrintToUser(logging.LightBlue.Wrap("The validator registration was already initialized. Proceeding to the next step")) + alreadyInitialized = true + } else if generateRawTxOnly { + return nil, ids.Empty, tx, nil + } + ux.Logger.PrintToUser(fmt.Sprintf("Validator weight: %d", weight)) } - ux.Logger.PrintToUser(fmt.Sprintf("Validator staked amount: %d", stakeAmount)) } else { - managerAddress = common.HexToAddress(validatorManagerAddressStr) - tx, _, err := InitializeValidatorRegistrationPoA( - rpcURL, - managerAddress, - ownerPrivateKey, - nodeID, - blsPublicKey, - expiry, - balanceOwners, - disableOwners, - weight, - ) + ux.Logger.PrintToUser(logging.LightBlue.Wrap("The validator registration was already initialized. Proceeding to the next step")) + } + + var unsignedMessage *warp.UnsignedMessage + if receipt != nil { + unsignedMessage, err = GetWarpMessageFromLogs(receipt.Logs) if err != nil { - if !errors.Is(err, validatormanager.ErrNodeAlreadyRegistered) { - return nil, ids.Empty, evm.TransactionError(tx, err, "failure initializing validator registration") - } - ux.Logger.PrintToUser(logging.LightBlue.Wrap("The validator registration was already initialized. Proceeding to the next step")) - alreadyInitialized = true + return nil, ids.Empty, nil, err } - ux.Logger.PrintToUser(fmt.Sprintf("Validator weight: %d", weight)) } - return GetSubnetValidatorRegistrationMessage( + signedMessage, validationID, err := GetRegisterL1ValidatorMessage( ctx, rpcURL, network, @@ -448,7 +522,11 @@ func InitValidatorRegistration( disableOwners, weight, alreadyInitialized, + initiateTxHash, + unsignedMessage, ) + + return signedMessage, validationID, nil, err } func FinishValidatorRegistration( @@ -457,23 +535,25 @@ func FinishValidatorRegistration( network models.Network, rpcURL string, chainSpec contract.ChainSpec, + generateRawTxOnly bool, + ownerAddressStr string, privateKey string, validationID ids.ID, aggregatorExtraPeerEndpoints []info.Peer, aggregatorAllowPrivatePeers bool, aggregatorLogger logging.Logger, validatorManagerAddressStr string, -) error { +) (*types.Transaction, error) { subnetID, err := contract.GetSubnetID( app, network, chainSpec, ) if err != nil { - return err + return nil, err } managerAddress := common.HexToAddress(validatorManagerAddressStr) - signedMessage, err := GetPChainSubnetValidatorRegistrationWarpMessage( + signedMessage, err := GetPChainL1ValidatorRegistrationMessage( ctx, network, rpcURL, @@ -486,34 +566,42 @@ func FinishValidatorRegistration( true, ) if err != nil { - return err + return nil, err } - if err := evm.SetupProposerVM( - rpcURL, - privateKey, - ); err != nil { - ux.Logger.RedXToUser("failure setting proposer VM on L1: %w", err) + if privateKey != "" { + if err := evm.SetupProposerVM( + rpcURL, + privateKey, + ); err != nil { + ux.Logger.RedXToUser("failure setting proposer VM on L1: %w", err) + } } + ownerAddress := common.HexToAddress(ownerAddressStr) tx, _, err := CompleteValidatorRegistration( rpcURL, managerAddress, + generateRawTxOnly, + ownerAddress, privateKey, signedMessage, ) if err != nil { if !errors.Is(err, validatormanager.ErrInvalidValidationID) { - return evm.TransactionError(tx, err, "failure completing validator registration") + return nil, evm.TransactionError(tx, err, "failure completing validator registration") } else { - return fmt.Errorf("the Validator was already fully registered on the Manager") + return nil, fmt.Errorf("the Validator was already fully registered on the Manager") } } - return nil + if generateRawTxOnly { + return tx, nil + } + return nil, nil } -func GetRegistrationMessage( +func SearchForRegisterL1ValidatorMessage( rpcURL string, validationID ids.ID, -) ([]byte, error) { +) (*warp.UnsignedMessage, error) { client, err := evm.GetClient(rpcURL) if err != nil { return nil, err @@ -524,10 +612,12 @@ func GetRegistrationMessage( if err != nil { return nil, err } - for blockNumber := uint64(0); blockNumber <= height; blockNumber++ { + maxBlock := int64(height) + minBlock := int64(0) + for blockNumber := maxBlock; blockNumber >= minBlock; blockNumber-- { ctx, cancel := utils.GetAPILargeContext() defer cancel() - block, err := client.BlockByNumber(ctx, big.NewInt(int64(blockNumber))) + block, err := client.BlockByNumber(ctx, big.NewInt(blockNumber)) if err != nil { return nil, err } @@ -539,17 +629,15 @@ func GetRegistrationMessage( if err != nil { return nil, err } - for _, txLog := range logs { - msg, err := subnetEvmWarp.UnpackSendWarpEventDataToMessage(txLog.Data) + msgs := GetWarpMessagesFromLogs(utils.PointersSlice(logs)) + for _, msg := range msgs { + payload := msg.Payload + addressedCall, err := warpPayload.ParseAddressedCall(payload) if err == nil { - payload := msg.Payload - addressedCall, err := warpPayload.ParseAddressedCall(payload) + reg, err := warpMessage.ParseRegisterL1Validator(addressedCall.Payload) if err == nil { - reg, err := warpMessage.ParseRegisterL1Validator(addressedCall.Payload) - if err == nil { - if reg.ValidationID() == validationID { - return msg.Bytes(), nil - } + if reg.ValidationID() == validationID { + return msg, nil } } } @@ -578,18 +666,14 @@ func GetRegistrationJustification( return proto.Marshal(&justification) } } - msg, err := GetRegistrationMessage( + msg, err := SearchForRegisterL1ValidatorMessage( rpcURL, validationID, ) if err != nil { return nil, err } - parsed, err := warp.ParseUnsignedMessage(msg) - if err != nil { - return nil, err - } - payload := parsed.Payload + payload := msg.Payload addressedCall, err := warpPayload.ParseAddressedCall(payload) if err != nil { return nil, err @@ -601,3 +685,34 @@ func GetRegistrationJustification( } return proto.Marshal(&justification) } + +func GetRegisterL1ValidatorMessageFromTx( + rpcURL string, + validationID ids.ID, + txHash string, +) (*warp.UnsignedMessage, error) { + client, err := evm.GetClient(rpcURL) + if err != nil { + return nil, err + } + ctx, cancel := utils.GetAPILargeContext() + defer cancel() + receipt, err := client.TransactionReceipt(ctx, common.HexToHash(txHash)) + if err != nil { + return nil, err + } + msgs := GetWarpMessagesFromLogs(receipt.Logs) + for _, msg := range msgs { + payload := msg.Payload + addressedCall, err := warpPayload.ParseAddressedCall(payload) + if err == nil { + reg, err := warpMessage.ParseRegisterL1Validator(addressedCall.Payload) + if err == nil { + if reg.ValidationID() == validationID { + return msg, nil + } + } + } + } + return nil, fmt.Errorf("register validator message not found on tx %s", txHash) +} diff --git a/pkg/validatormanager/removal.go b/pkg/validatormanager/removal.go index da3bd86bc..152d0638a 100644 --- a/pkg/validatormanager/removal.go +++ b/pkg/validatormanager/removal.go @@ -22,26 +22,31 @@ import ( "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/utils/logging" warp "github.com/ava-labs/avalanchego/vms/platformvm/warp" - warpMessage "github.com/ava-labs/avalanchego/vms/platformvm/warp/message" warpPayload "github.com/ava-labs/avalanchego/vms/platformvm/warp/payload" "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/warp/messages" + "github.com/ethereum/go-ethereum/common" ) func InitializeValidatorRemoval( rpcURL string, managerAddress common.Address, + generateRawTxOnly bool, + managerOwnerAddress common.Address, privateKey string, validationID ids.ID, isPoS bool, uptimeProofSignedMessage *warp.Message, force bool, + useACP99 bool, ) (*types.Transaction, *types.Receipt, error) { if isPoS { if force { return contract.TxToMethod( rpcURL, + false, + common.Address{}, privateKey, managerAddress, big.NewInt(0), @@ -56,6 +61,8 @@ func InitializeValidatorRemoval( // remove PoS validator with uptime proof return contract.TxToMethodWithWarpMessage( rpcURL, + false, + common.Address{}, privateKey, managerAddress, uptimeProofSignedMessage, @@ -69,8 +76,24 @@ func InitializeValidatorRemoval( ) } // PoA case + if useACP99 { + return contract.TxToMethod( + rpcURL, + generateRawTxOnly, + managerOwnerAddress, + privateKey, + managerAddress, + big.NewInt(0), + "POA validator removal initialization", + validatormanager.ErrorSignatureToError, + "initiateValidatorRemoval(bytes32)", + validationID, + ) + } return contract.TxToMethod( rpcURL, + generateRawTxOnly, + managerOwnerAddress, privateKey, managerAddress, big.NewInt(0), @@ -123,81 +146,33 @@ func GetUptimeProofMessage( return signatureAggregator.Sign(uptimeProofUnsignedMessage, nil) } -func GetSubnetValidatorWeightMessage( - ctx context.Context, - network models.Network, - aggregatorLogger logging.Logger, - aggregatorQuorumPercentage uint64, - aggregatorAllowPrivateIPs bool, - aggregatorExtraPeerEndpoints []info.Peer, - subnetID ids.ID, - blockchainID ids.ID, - managerAddress common.Address, - validationID ids.ID, - nonce uint64, - weight uint64, -) (*warp.Message, error) { - addressedCallPayload, err := warpMessage.NewL1ValidatorWeight( - validationID, - nonce, - weight, - ) - if err != nil { - return nil, err - } - addressedCall, err := warpPayload.NewAddressedCall( - managerAddress.Bytes(), - addressedCallPayload.Bytes(), - ) - if err != nil { - return nil, err - } - unsignedMessage, err := warp.NewUnsignedMessage( - network.ID, - blockchainID, - addressedCall.Bytes(), - ) - if err != nil { - return nil, err - } - signatureAggregator, err := interchain.NewSignatureAggregator( - ctx, - network, - aggregatorLogger, - subnetID, - aggregatorQuorumPercentage, - aggregatorAllowPrivateIPs, - aggregatorExtraPeerEndpoints, - ) - if err != nil { - return nil, err - } - return signatureAggregator.Sign(unsignedMessage, nil) -} - func InitValidatorRemoval( ctx context.Context, app *application.Avalanche, network models.Network, rpcURL string, chainSpec contract.ChainSpec, + generateRawTxOnly bool, + ownerAddressStr string, ownerPrivateKey string, nodeID ids.NodeID, aggregatorExtraPeerEndpoints []info.Peer, aggregatorAllowPrivatePeers bool, aggregatorLogger logging.Logger, - initWithPos bool, + isPoS bool, uptimeSec uint64, force bool, validatorManagerAddressStr string, -) (*warp.Message, ids.ID, error) { + useACP99 bool, + initiateTxHash string, +) (*warp.Message, ids.ID, *types.Transaction, error) { subnetID, err := contract.GetSubnetID( app, network, chainSpec, ) if err != nil { - return nil, ids.Empty, err + return nil, ids.Empty, nil, err } blockchainID, err := contract.GetBlockchainID( app, @@ -205,69 +180,109 @@ func InitValidatorRemoval( chainSpec, ) if err != nil { - return nil, ids.Empty, err + return nil, ids.Empty, nil, err } managerAddress := common.HexToAddress(validatorManagerAddressStr) + ownerAddress := common.HexToAddress(ownerAddressStr) validationID, err := validator.GetRegisteredValidator( rpcURL, managerAddress, nodeID, ) if err != nil { - return nil, ids.Empty, err + return nil, ids.Empty, nil, err } if validationID == ids.Empty { - return nil, ids.Empty, fmt.Errorf("node %s is not a L1 validator", nodeID) + return nil, ids.Empty, nil, fmt.Errorf("node %s is not a L1 validator", nodeID) + } + + var unsignedMessage *warp.UnsignedMessage + if initiateTxHash != "" { + unsignedMessage, err = GetL1ValidatorWeightMessageFromTx( + rpcURL, + validationID, + 0, + initiateTxHash, + ) + if err != nil { + return nil, ids.Empty, nil, err + } } - signedUptimeProof := &warp.Message{} - if initWithPos { - if uptimeSec == 0 { - uptimeSec, err = utils.GetL1ValidatorUptimeSeconds(rpcURL, nodeID) + var receipt *types.Receipt + if unsignedMessage == nil { + signedUptimeProof := &warp.Message{} + if isPoS { + if uptimeSec == 0 { + uptimeSec, err = utils.GetL1ValidatorUptimeSeconds(rpcURL, nodeID) + if err != nil { + return nil, ids.Empty, nil, evm.TransactionError(nil, err, "failure getting uptime data for nodeID: %s via %s ", nodeID, rpcURL) + } + } + ux.Logger.PrintToUser("Using uptime: %ds", uptimeSec) + signedUptimeProof, err = GetUptimeProofMessage( + ctx, + network, + aggregatorLogger, + 0, + aggregatorExtraPeerEndpoints, + subnetID, + blockchainID, + validationID, + uptimeSec, + ) if err != nil { - return nil, ids.Empty, evm.TransactionError(nil, err, "failure getting uptime data for nodeID: %s via %s ", nodeID, rpcURL) + return nil, ids.Empty, nil, evm.TransactionError(nil, err, "failure getting uptime proof") } } - ux.Logger.PrintToUser("Using uptime: %ds", uptimeSec) - signedUptimeProof, err = GetUptimeProofMessage( - ctx, - network, - aggregatorLogger, - 0, - aggregatorExtraPeerEndpoints, - subnetID, - blockchainID, + var tx *types.Transaction + tx, receipt, err = InitializeValidatorRemoval( + rpcURL, + managerAddress, + generateRawTxOnly, + ownerAddress, + ownerPrivateKey, validationID, - uptimeSec, + isPoS, + signedUptimeProof, // is empty for non-PoS + force, + useACP99, ) if err != nil { - return nil, ids.Empty, evm.TransactionError(nil, err, "failure getting uptime proof") + if !errors.Is(err, validatormanager.ErrInvalidValidatorStatus) { + return nil, ids.Empty, nil, evm.TransactionError(tx, err, "failure initializing validator removal") + } + ux.Logger.PrintToUser(logging.LightBlue.Wrap("The validator removal process was already initialized. Proceeding to the next step")) + } else if generateRawTxOnly { + return nil, ids.Empty, tx, nil } + } else { + ux.Logger.PrintToUser(logging.LightBlue.Wrap("The validator removal process was already initialized. Proceeding to the next step")) } - tx, _, err := InitializeValidatorRemoval( - rpcURL, - managerAddress, - ownerPrivateKey, - validationID, - initWithPos, - signedUptimeProof, // is empty for non-PoS - force, - ) - if err != nil { - if !errors.Is(err, validatormanager.ErrInvalidValidatorStatus) { - return nil, ids.Empty, evm.TransactionError(tx, err, "failure initializing validator removal") + + if receipt != nil { + unsignedMessage, err = GetWarpMessageFromLogs(receipt.Logs) + if err != nil { + return nil, ids.Empty, nil, err + } + } + + var nonce uint64 + if unsignedMessage == nil { + nonce, err = GetValidatorNonce(rpcURL, validationID) + if err != nil { + return nil, ids.Empty, nil, err } - ux.Logger.PrintToUser(logging.LightBlue.Wrap("The validator removal process was already initialized. Proceeding to the next step")) } - nonce := uint64(1) - signedMsg, err := GetSubnetValidatorWeightMessage( + signedMsg, err := GetL1ValidatorWeightMessage( ctx, network, aggregatorLogger, 0, aggregatorAllowPrivatePeers, aggregatorExtraPeerEndpoints, + unsignedMessage, subnetID, blockchainID, managerAddress, @@ -275,17 +290,37 @@ func InitValidatorRemoval( nonce, 0, ) - return signedMsg, validationID, err + return signedMsg, validationID, nil, err } func CompleteValidatorRemoval( rpcURL string, managerAddress common.Address, + generateRawTxOnly bool, + ownerAddress common.Address, privateKey string, // not need to be owner atm subnetValidatorRegistrationSignedMessage *warp.Message, + useACP99 bool, ) (*types.Transaction, *types.Receipt, error) { + if useACP99 { + return contract.TxToMethodWithWarpMessage( + rpcURL, + generateRawTxOnly, + ownerAddress, + privateKey, + managerAddress, + subnetValidatorRegistrationSignedMessage, + big.NewInt(0), + "complete poa validator removal", + validatormanager.ErrorSignatureToError, + "completeValidatorRemoval(uint32)", + uint32(0), + ) + } return contract.TxToMethodWithWarpMessage( rpcURL, + generateRawTxOnly, + ownerAddress, privateKey, managerAddress, subnetValidatorRegistrationSignedMessage, @@ -303,13 +338,16 @@ func FinishValidatorRemoval( network models.Network, rpcURL string, chainSpec contract.ChainSpec, + generateRawTxOnly bool, + ownerAddressStr string, privateKey string, validationID ids.ID, aggregatorExtraPeerEndpoints []info.Peer, aggregatorAllowPrivatePeers bool, aggregatorLogger logging.Logger, validatorManagerAddressStr string, -) error { + useACP99 bool, +) (*types.Transaction, error) { managerAddress := common.HexToAddress(validatorManagerAddressStr) subnetID, err := contract.GetSubnetID( app, @@ -317,9 +355,9 @@ func FinishValidatorRemoval( chainSpec, ) if err != nil { - return err + return nil, err } - signedMessage, err := GetPChainSubnetValidatorRegistrationWarpMessage( + signedMessage, err := GetPChainL1ValidatorRegistrationMessage( ctx, network, rpcURL, @@ -332,22 +370,31 @@ func FinishValidatorRemoval( false, ) if err != nil { - return err + return nil, err } - if err := evm.SetupProposerVM( - rpcURL, - privateKey, - ); err != nil { - ux.Logger.RedXToUser("failure setting proposer VM on L1: %w", err) + if privateKey != "" { + if err := evm.SetupProposerVM( + rpcURL, + privateKey, + ); err != nil { + ux.Logger.RedXToUser("failure setting proposer VM on L1: %w", err) + } } + ownerAddress := common.HexToAddress(ownerAddressStr) tx, _, err := CompleteValidatorRemoval( rpcURL, managerAddress, + generateRawTxOnly, + ownerAddress, privateKey, signedMessage, + useACP99, ) if err != nil { - return evm.TransactionError(tx, err, "failure completing validator removal") + return nil, evm.TransactionError(tx, err, "failure completing validator removal") + } + if generateRawTxOnly { + return tx, nil } - return nil + return nil, nil } diff --git a/pkg/validatormanager/validatormanager.go b/pkg/validatormanager/validatormanager.go index 10b912915..8a0310f54 100644 --- a/pkg/validatormanager/validatormanager.go +++ b/pkg/validatormanager/validatormanager.go @@ -20,13 +20,13 @@ import ( "github.com/ethereum/go-ethereum/common" ) -//go:embed deployed_validator_messages_bytecode_v1.0.0.txt -var deployedValidatorMessagesBytecode []byte +//go:embed deployed_validator_messages_bytecode_acp99.txt +var deployedValidatorMessagesACP99Bytecode []byte -func AddValidatorMessagesContractToAllocations( +func AddValidatorMessagesACP99ContractToAllocations( allocs core.GenesisAlloc, ) { - deployedValidatorMessagesBytes := common.FromHex(strings.TrimSpace(string(deployedValidatorMessagesBytecode))) + deployedValidatorMessagesBytes := common.FromHex(strings.TrimSpace(string(deployedValidatorMessagesACP99Bytecode))) allocs[common.HexToAddress(validatorManagerSDK.ValidatorMessagesContractAddress)] = core.GenesisAccount{ Balance: big.NewInt(0), Code: deployedValidatorMessagesBytes, @@ -58,6 +58,22 @@ func AddPoAValidatorManagerContractToAllocations( } } +//go:embed deployed_validator_manager_bytecode_acp99.txt +var deployedPoAValidatorManagerACP99Bytecode []byte + +func AddPoAValidatorManagerACP99ContractToAllocations( + allocs core.GenesisAlloc, +) { + deployedPoaValidatorManagerString := strings.TrimSpace(string(deployedPoAValidatorManagerACP99Bytecode)) + deployedPoaValidatorManagerString = fillValidatorMessagesAddressPlaceholder(deployedPoaValidatorManagerString) + deployedPoaValidatorManagerBytes := common.FromHex(deployedPoaValidatorManagerString) + allocs[common.HexToAddress(validatorManagerSDK.ValidatorContractAddress)] = core.GenesisAccount{ + Balance: big.NewInt(0), + Code: deployedPoaValidatorManagerBytes, + Nonce: 1, + } +} + //go:embed deployed_native_pos_validator_manager_bytecode.txt var deployedPoSValidatorManagerBytecode []byte @@ -186,6 +202,7 @@ func SetupPoA( aggregatorAllowPrivatePeers bool, aggregatorLogger logging.Logger, validatorManagerAddressStr string, + useACP99 bool, ) error { return subnet.InitializeProofOfAuthority( ctx, @@ -195,6 +212,7 @@ func SetupPoA( aggregatorAllowPrivatePeers, aggregatorLogger, validatorManagerAddressStr, + useACP99, ) } diff --git a/pkg/validatormanager/weight_update.go b/pkg/validatormanager/weight_update.go new file mode 100644 index 000000000..0eddf17cc --- /dev/null +++ b/pkg/validatormanager/weight_update.go @@ -0,0 +1,483 @@ +// Copyright (C) 2022, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. +package validatormanager + +import ( + "context" + _ "embed" + "fmt" + "math/big" + + "github.com/ava-labs/avalanche-cli/pkg/application" + "github.com/ava-labs/avalanche-cli/pkg/contract" + "github.com/ava-labs/avalanche-cli/pkg/evm" + "github.com/ava-labs/avalanche-cli/pkg/models" + "github.com/ava-labs/avalanche-cli/pkg/utils" + "github.com/ava-labs/avalanche-cli/pkg/ux" + "github.com/ava-labs/avalanche-cli/sdk/interchain" + "github.com/ava-labs/avalanche-cli/sdk/validator" + "github.com/ava-labs/avalanche-cli/sdk/validatormanager" + "github.com/ava-labs/avalanchego/api/info" + "github.com/ava-labs/avalanchego/ids" + avagoconstants "github.com/ava-labs/avalanchego/utils/constants" + "github.com/ava-labs/avalanchego/utils/logging" + warp "github.com/ava-labs/avalanchego/vms/platformvm/warp" + warpMessage "github.com/ava-labs/avalanchego/vms/platformvm/warp/message" + warpPayload "github.com/ava-labs/avalanchego/vms/platformvm/warp/payload" + "github.com/ava-labs/subnet-evm/core/types" + "github.com/ava-labs/subnet-evm/interfaces" + subnetEvmWarp "github.com/ava-labs/subnet-evm/precompile/contracts/warp" + + "github.com/ethereum/go-ethereum/common" +) + +func InitializeValidatorWeightChange( + rpcURL string, + managerAddress common.Address, + generateRawTxOnly bool, + managerOwnerAddress common.Address, + privateKey string, + validationID ids.ID, + weight uint64, +) (*types.Transaction, *types.Receipt, error) { + return contract.TxToMethod( + rpcURL, + generateRawTxOnly, + managerOwnerAddress, + privateKey, + managerAddress, + big.NewInt(0), + "POA validator weight change initialization", + validatormanager.ErrorSignatureToError, + "initiateValidatorWeightUpdate(bytes32,uint64)", + validationID, + weight, + ) +} + +func InitValidatorWeightChange( + ctx context.Context, + printFunc func(msg string, args ...interface{}), + app *application.Avalanche, + network models.Network, + rpcURL string, + chainSpec contract.ChainSpec, + generateRawTxOnly bool, + ownerAddressStr string, + ownerPrivateKey string, + nodeID ids.NodeID, + aggregatorExtraPeerEndpoints []info.Peer, + aggregatorAllowPrivatePeers bool, + aggregatorLogger logging.Logger, + validatorManagerAddressStr string, + weight uint64, + initiateTxHash string, +) (*warp.Message, ids.ID, *types.Transaction, error) { + subnetID, err := contract.GetSubnetID( + app, + network, + chainSpec, + ) + if err != nil { + return nil, ids.Empty, nil, err + } + blockchainID, err := contract.GetBlockchainID( + app, + network, + chainSpec, + ) + if err != nil { + return nil, ids.Empty, nil, err + } + managerAddress := common.HexToAddress(validatorManagerAddressStr) + ownerAddress := common.HexToAddress(ownerAddressStr) + validationID, err := validator.GetRegisteredValidator( + rpcURL, + managerAddress, + nodeID, + ) + if err != nil { + return nil, ids.Empty, nil, err + } + if validationID == ids.Empty { + return nil, ids.Empty, nil, fmt.Errorf("node %s is not a L1 validator", nodeID) + } + + var unsignedMessage *warp.UnsignedMessage + if initiateTxHash != "" { + unsignedMessage, err = GetL1ValidatorWeightMessageFromTx( + rpcURL, + validationID, + weight, + initiateTxHash, + ) + if err != nil { + return nil, ids.Empty, nil, err + } + } + + if unsignedMessage == nil { + unsignedMessage, err = SearchForL1ValidatorWeightMessage(rpcURL, validationID, weight) + if err != nil { + printFunc(logging.Red.Wrap("Failure checking for warp messages of previous operations: %s. Proceeding."), err) + } + } + + var receipt *types.Receipt + if unsignedMessage == nil { + var tx *types.Transaction + tx, receipt, err = InitializeValidatorWeightChange( + rpcURL, + managerAddress, + generateRawTxOnly, + ownerAddress, + ownerPrivateKey, + validationID, + weight, + ) + if err != nil { + return nil, ids.Empty, nil, evm.TransactionError(tx, err, "failure initializing validator weight change") + } else if generateRawTxOnly { + return nil, ids.Empty, tx, nil + } + } else { + printFunc(logging.LightBlue.Wrap("The validator weight change process was already initialized. Proceeding to the next step")) + } + + if receipt != nil { + unsignedMessage, err = GetWarpMessageFromLogs(receipt.Logs) + if err != nil { + return nil, ids.Empty, nil, err + } + } + + var nonce uint64 + if unsignedMessage == nil { + nonce, err = GetValidatorNonce(rpcURL, validationID) + if err != nil { + return nil, ids.Empty, nil, err + } + } + + signedMsg, err := GetL1ValidatorWeightMessage( + ctx, + network, + aggregatorLogger, + 0, + aggregatorAllowPrivatePeers, + aggregatorExtraPeerEndpoints, + unsignedMessage, + subnetID, + blockchainID, + managerAddress, + validationID, + nonce, + weight, + ) + return signedMsg, validationID, nil, err +} + +func CompleteValidatorWeightChange( + rpcURL string, + managerAddress common.Address, + generateRawTxOnly bool, + ownerAddress common.Address, + privateKey string, // not need to be owner atm + pchainL1ValidatorRegistrationSignedMessage *warp.Message, +) (*types.Transaction, *types.Receipt, error) { + return contract.TxToMethodWithWarpMessage( + rpcURL, + generateRawTxOnly, + ownerAddress, + privateKey, + managerAddress, + pchainL1ValidatorRegistrationSignedMessage, + big.NewInt(0), + "complete poa validator weight change", + validatormanager.ErrorSignatureToError, + "completeValidatorWeightUpdate(uint32)", + uint32(0), + ) +} + +func FinishValidatorWeightChange( + ctx context.Context, + app *application.Avalanche, + network models.Network, + rpcURL string, + chainSpec contract.ChainSpec, + generateRawTxOnly bool, + ownerAddressStr string, + privateKey string, + validationID ids.ID, + aggregatorExtraPeerEndpoints []info.Peer, + aggregatorAllowPrivatePeers bool, + aggregatorLogger logging.Logger, + validatorManagerAddressStr string, + l1ValidatorRegistrationSignedMessage *warp.Message, + weight uint64, +) (*types.Transaction, error) { + managerAddress := common.HexToAddress(validatorManagerAddressStr) + subnetID, err := contract.GetSubnetID( + app, + network, + chainSpec, + ) + if err != nil { + return nil, err + } + var nonce uint64 + if l1ValidatorRegistrationSignedMessage == nil { + nonce, err = GetValidatorNonce(rpcURL, validationID) + if err != nil { + return nil, err + } + } + signedMessage, err := GetPChainL1ValidatorWeightMessage( + ctx, + network, + aggregatorLogger, + 0, + aggregatorAllowPrivatePeers, + aggregatorExtraPeerEndpoints, + subnetID, + l1ValidatorRegistrationSignedMessage, + validationID, + nonce, + weight, + ) + if err != nil { + return nil, err + } + if privateKey != "" { + if err := evm.SetupProposerVM( + rpcURL, + privateKey, + ); err != nil { + ux.Logger.RedXToUser("failure setting proposer VM on L1: %w", err) + } + } + ownerAddress := common.HexToAddress(ownerAddressStr) + tx, _, err := CompleteValidatorWeightChange( + rpcURL, + managerAddress, + generateRawTxOnly, + ownerAddress, + privateKey, + signedMessage, + ) + if err != nil { + return nil, evm.TransactionError(tx, err, "failure completing validator weight change") + } + if generateRawTxOnly { + return tx, nil + } + return nil, nil +} + +func GetL1ValidatorWeightMessage( + ctx context.Context, + network models.Network, + aggregatorLogger logging.Logger, + aggregatorQuorumPercentage uint64, + aggregatorAllowPrivateIPs bool, + aggregatorExtraPeerEndpoints []info.Peer, + // message is given + unsignedMessage *warp.UnsignedMessage, + // needed to generate message + subnetID ids.ID, + blockchainID ids.ID, + managerAddress common.Address, + validationID ids.ID, + nonce uint64, + weight uint64, +) (*warp.Message, error) { + if unsignedMessage == nil { + addressedCallPayload, err := warpMessage.NewL1ValidatorWeight( + validationID, + nonce, + weight, + ) + if err != nil { + return nil, err + } + addressedCall, err := warpPayload.NewAddressedCall( + managerAddress.Bytes(), + addressedCallPayload.Bytes(), + ) + if err != nil { + return nil, err + } + unsignedMessage, err = warp.NewUnsignedMessage( + network.ID, + blockchainID, + addressedCall.Bytes(), + ) + if err != nil { + return nil, err + } + } + signatureAggregator, err := interchain.NewSignatureAggregator( + ctx, + network, + aggregatorLogger, + subnetID, + aggregatorQuorumPercentage, + aggregatorAllowPrivateIPs, + aggregatorExtraPeerEndpoints, + ) + if err != nil { + return nil, err + } + return signatureAggregator.Sign(unsignedMessage, nil) +} + +func GetPChainL1ValidatorWeightMessage( + ctx context.Context, + network models.Network, + aggregatorLogger logging.Logger, + aggregatorQuorumPercentage uint64, + aggregatorAllowPrivateIPs bool, + aggregatorExtraPeerEndpoints []info.Peer, + subnetID ids.ID, + // message is given + l1SignedMessage *warp.Message, + // needed to generate full message contents + validationID ids.ID, + nonce uint64, + weight uint64, +) (*warp.Message, error) { + if l1SignedMessage != nil { + addressedCall, err := warpPayload.ParseAddressedCall(l1SignedMessage.UnsignedMessage.Payload) + if err != nil { + return nil, err + } + weightMsg, err := warpMessage.ParseL1ValidatorWeight(addressedCall.Payload) + if err != nil { + return nil, err + } + validationID = weightMsg.ValidationID + nonce = weightMsg.Nonce + weight = weightMsg.Weight + } + addressedCallPayload, err := warpMessage.NewL1ValidatorWeight( + validationID, + nonce, + weight, + ) + if err != nil { + return nil, err + } + addressedCall, err := warpPayload.NewAddressedCall( + nil, + addressedCallPayload.Bytes(), + ) + if err != nil { + return nil, err + } + unsignedMessage, err := warp.NewUnsignedMessage( + network.ID, + avagoconstants.PlatformChainID, + addressedCall.Bytes(), + ) + if err != nil { + return nil, err + } + signatureAggregator, err := interchain.NewSignatureAggregator( + ctx, + network, + aggregatorLogger, + subnetID, + aggregatorQuorumPercentage, + aggregatorAllowPrivateIPs, + aggregatorExtraPeerEndpoints, + ) + if err != nil { + return nil, err + } + return signatureAggregator.Sign(unsignedMessage, nil) +} + +func GetL1ValidatorWeightMessageFromTx( + rpcURL string, + validationID ids.ID, + weight uint64, + txHash string, +) (*warp.UnsignedMessage, error) { + client, err := evm.GetClient(rpcURL) + if err != nil { + return nil, err + } + ctx, cancel := utils.GetAPILargeContext() + defer cancel() + receipt, err := client.TransactionReceipt(ctx, common.HexToHash(txHash)) + if err != nil { + return nil, err + } + msgs := GetWarpMessagesFromLogs(receipt.Logs) + for _, msg := range msgs { + payload := msg.Payload + addressedCall, err := warpPayload.ParseAddressedCall(payload) + if err == nil { + weightMsg, err := warpMessage.ParseL1ValidatorWeight(addressedCall.Payload) + if err == nil { + if weightMsg.ValidationID == validationID && weightMsg.Weight == weight { + return msg, nil + } + } + } + } + return nil, fmt.Errorf("weight message not found on tx %s", txHash) +} + +func SearchForL1ValidatorWeightMessage( + rpcURL string, + validationID ids.ID, + weight uint64, +) (*warp.UnsignedMessage, error) { + const maxBlocksToSearch = 500 + client, err := evm.GetClient(rpcURL) + if err != nil { + return nil, err + } + ctx, cancel := utils.GetAPILargeContext() + defer cancel() + height, err := client.BlockNumber(ctx) + if err != nil { + return nil, err + } + maxBlock := int64(height) + minBlock := max(maxBlock-maxBlocksToSearch, 0) + for blockNumber := maxBlock; blockNumber >= minBlock; blockNumber-- { + ctx, cancel := utils.GetAPILargeContext() + defer cancel() + block, err := client.BlockByNumber(ctx, big.NewInt(blockNumber)) + if err != nil { + return nil, err + } + blockHash := block.Hash() + logs, err := client.FilterLogs(ctx, interfaces.FilterQuery{ + BlockHash: &blockHash, + Addresses: []common.Address{subnetEvmWarp.Module.Address}, + }) + if err != nil { + return nil, err + } + msgs := GetWarpMessagesFromLogs(utils.PointersSlice(logs)) + for _, msg := range msgs { + payload := msg.Payload + addressedCall, err := warpPayload.ParseAddressedCall(payload) + if err == nil { + weightMsg, err := warpMessage.ParseL1ValidatorWeight(addressedCall.Payload) + if err == nil { + if weightMsg.ValidationID == validationID && weightMsg.Weight == weight { + return msg, nil + } else { + return nil, nil + } + } + } + } + } + return nil, nil +} diff --git a/pkg/vm/create_evm.go b/pkg/vm/create_evm.go index 14dedfdda..0b42a1433 100644 --- a/pkg/vm/create_evm.go +++ b/pkg/vm/create_evm.go @@ -39,6 +39,7 @@ func CreateEvmSidecar( tokenSymbol string, getRPCVersionFromBinary bool, sovereign bool, + useACP99 bool, ) (*models.Sidecar, error) { var ( err error @@ -73,6 +74,7 @@ func CreateEvmSidecar( sc.TokenSymbol = tokenSymbol sc.TokenName = tokenSymbol + " Token" sc.Sovereign = sovereign + sc.UseACP99 = useACP99 return sc, nil } @@ -82,6 +84,7 @@ func CreateEVMGenesis( addICMRegistryToGenesis bool, proxyOwner string, rewardBasisPoints uint64, + useACP99 bool, ) ([]byte, error) { feeConfig := getFeeConfig(params) @@ -127,11 +130,17 @@ func CreateEVMGenesis( } if params.UsePoAValidatorManager { validatormanager.AddTransparentProxyContractToAllocations(params.initialTokenAllocation, proxyOwner) - validatormanager.AddValidatorMessagesContractToAllocations(params.initialTokenAllocation) - validatormanager.AddPoAValidatorManagerContractToAllocations(params.initialTokenAllocation) + // valid for both ACP99 and v1.0.0 + validatormanager.AddValidatorMessagesACP99ContractToAllocations(params.initialTokenAllocation) + if useACP99 { + validatormanager.AddPoAValidatorManagerACP99ContractToAllocations(params.initialTokenAllocation) + } else { + validatormanager.AddPoAValidatorManagerContractToAllocations(params.initialTokenAllocation) + } } else if params.UsePoSValidatorManager { validatormanager.AddTransparentProxyContractToAllocations(params.initialTokenAllocation, proxyOwner) - validatormanager.AddValidatorMessagesContractToAllocations(params.initialTokenAllocation) + // valid for v1.0.0 + validatormanager.AddValidatorMessagesACP99ContractToAllocations(params.initialTokenAllocation) validatormanager.AddRewardCalculatorToAllocations(params.initialTokenAllocation, rewardBasisPoints) params.enableNativeMinterPrecompile = true } diff --git a/sdk/SDK.md b/sdk/SDK.md index e1678d868..45862bfa5 100644 --- a/sdk/SDK.md +++ b/sdk/SDK.md @@ -467,10 +467,10 @@ func IsValidator(net network.Network, subnetID ids.ID, nodeID ids.NodeID) (bool, ### Functions -#### GetPChainSubnetConversionWarpMessage +#### GetPChainSubnetToL1ConversionMessage ```go -func GetPChainSubnetConversionWarpMessage( +func GetPChainSubnetToL1ConversionMessage( network models.Network, aggregatorLogger logging.Logger, aggregatorQuorumPercentage uint64, diff --git a/sdk/blockchain/blockchain.go b/sdk/blockchain/blockchain.go index f6f5f4592..21557226a 100644 --- a/sdk/blockchain/blockchain.go +++ b/sdk/blockchain/blockchain.go @@ -350,6 +350,7 @@ func (c *Subnet) InitializeProofOfAuthority( aggregatorAllowPrivatePeers bool, aggregatorLogger logging.Logger, validatorManagerAddressStr string, + useACP99 bool, ) error { if c.SubnetID == ids.Empty { return fmt.Errorf("unable to initialize Proof of Authority: %w", errMissingSubnetID) @@ -384,6 +385,7 @@ func (c *Subnet) InitializeProofOfAuthority( privateKey, c.SubnetID, *c.OwnerAddress, + useACP99, ) if err != nil { if !errors.Is(err, validatormanager.ErrAlreadyInitialized) { @@ -392,7 +394,7 @@ func (c *Subnet) InitializeProofOfAuthority( ux.Logger.PrintToUser("Warning: the PoA contract is already initialized.") } - subnetConversionSignedMessage, err := validatormanager.GetPChainSubnetConversionWarpMessage( + subnetConversionSignedMessage, err := validatormanager.GetPChainSubnetToL1ConversionMessage( ctx, network, aggregatorLogger, @@ -454,7 +456,7 @@ func (c *Subnet) InitializeProofOfStake( } ux.Logger.PrintToUser("Warning: the PoS contract is already initialized.") } - subnetConversionSignedMessage, err := validatormanager.GetPChainSubnetConversionWarpMessage( + subnetConversionSignedMessage, err := validatormanager.GetPChainSubnetToL1ConversionMessage( ctx, network, aggregatorLogger, diff --git a/sdk/validatormanager/root.go b/sdk/validatormanager/root.go index a3150b660..9472862c5 100644 --- a/sdk/validatormanager/root.go +++ b/sdk/validatormanager/root.go @@ -23,6 +23,13 @@ import ( "github.com/ethereum/go-ethereum/common" ) +type ACP99ValidatorManagerSettings struct { + Admin common.Address + SubnetID [32]byte + ChurnPeriodSeconds uint64 + MaximumChurnPercentage uint8 +} + type ValidatorManagerSettings struct { SubnetID [32]byte ChurnPeriodSeconds uint64 @@ -174,13 +181,13 @@ func (p PoSParams) Verify() error { return nil } -// GetPChainSubnetConversionWarpMessage constructs p-chain-validated (signed) subnet conversion warp +// GetPChainSubnetToL1ConversionMessage constructs p-chain-validated (signed) subnet conversion warp // message, to be sent to the validators manager when // initializing validators set // the message specifies [subnetID] that is being converted // together with the validator's manager [managerBlockchainID], // [managerAddress], and the initial list of [validators] -func GetPChainSubnetConversionWarpMessage( +func GetPChainSubnetToL1ConversionMessage( ctx context.Context, network models.Network, aggregatorLogger logging.Logger, @@ -283,6 +290,8 @@ func InitializeValidatorsSet( } return contract.TxToMethodWithWarpMessage( rpcURL, + false, + common.Address{}, privateKey, managerAddress, subnetConversionSignedMessage, diff --git a/sdk/validatormanager/validator_manager_poa.go b/sdk/validatormanager/validator_manager_poa.go index a9a5ba952..9cbc8c286 100644 --- a/sdk/validatormanager/validator_manager_poa.go +++ b/sdk/validatormanager/validator_manager_poa.go @@ -23,25 +23,46 @@ func PoAValidatorManagerInitialize( privateKey string, subnetID ids.ID, ownerAddress common.Address, + useACP99 bool, ) (*types.Transaction, *types.Receipt, error) { const ( defaultChurnPeriodSeconds = uint64(0) defaultMaximumChurnPercentage = uint8(20) ) - params := ValidatorManagerSettings{ - SubnetID: subnetID, - ChurnPeriodSeconds: defaultChurnPeriodSeconds, - MaximumChurnPercentage: defaultMaximumChurnPercentage, + if useACP99 { + return contract.TxToMethod( + rpcURL, + false, + common.Address{}, + privateKey, + managerAddress, + nil, + "initialize PoA manager", + ErrorSignatureToError, + "initialize((address, bytes32,uint64,uint8))", + ACP99ValidatorManagerSettings{ + Admin: ownerAddress, + SubnetID: subnetID, + ChurnPeriodSeconds: defaultChurnPeriodSeconds, + MaximumChurnPercentage: defaultMaximumChurnPercentage, + }, + ) } return contract.TxToMethod( rpcURL, + false, + common.Address{}, privateKey, managerAddress, nil, "initialize PoA manager", ErrorSignatureToError, "initialize((bytes32,uint64,uint8),address)", - params, + ValidatorManagerSettings{ + SubnetID: subnetID, + ChurnPeriodSeconds: defaultChurnPeriodSeconds, + MaximumChurnPercentage: defaultMaximumChurnPercentage, + }, ownerAddress, ) } diff --git a/sdk/validatormanager/validator_manager_pos.go b/sdk/validatormanager/validator_manager_pos.go index 4e08fbf0a..1d35546bf 100644 --- a/sdk/validatormanager/validator_manager_pos.go +++ b/sdk/validatormanager/validator_manager_pos.go @@ -46,6 +46,8 @@ func PoSValidatorManagerInitialize( return contract.TxToMethod( rpcURL, + false, + common.Address{}, privateKey, managerAddress, nil, diff --git a/tests/e2e/assets/test_subnet_evm_poa_genesis.json b/tests/e2e/assets/test_subnet_evm_poa_genesis.json index 8a19fb265..8be79a026 100644 --- a/tests/e2e/assets/test_subnet_evm_poa_genesis.json +++ b/tests/e2e/assets/test_subnet_evm_poa_genesis.json @@ -36,11 +36,8 @@ "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "coinbase": "0x0000000000000000000000000000000000000000", "alloc": { - "8db97c7cece249c2b98bdc0226cc4c2a57bf52fc": { - "balance": "0xd3c21bcecceda1000000" - }, "0c0deba5e0000000000000000000000000000000": { - "code": "0x608060405234801561000f575f80fd5b5060043610610132575f3560e01c80639ba96b86116100b4578063c974d1b611610079578063c974d1b6146102a7578063d588c18f146102af578063d5f20ff6146102c2578063df93d8de146102e2578063f2fde38b146102ec578063fd7ac5e7146102ff575f80fd5b80639ba96b861461024c578063a3a65e481461025f578063b771b3bc14610272578063bc5fbfec14610280578063bee0a03f14610294575f80fd5b8063715018a6116100fa578063715018a6146101be578063732214f8146101c65780638280a25a146101db5780638da5cb5b146101f557806397fb70d414610239575f80fd5b80630322ed981461013657806320d91b7a1461014b578063467ef06f1461015e57806360305d621461017157806366435abf14610193575b5f80fd5b610149610144366004612b01565b610312565b005b610149610159366004612b30565b610529565b61014961016c366004612b7e565b610a15565b610179601481565b60405163ffffffff90911681526020015b60405180910390f35b6101a66101a1366004612b01565b610a23565b6040516001600160401b03909116815260200161018a565b610149610a37565b6101cd5f81565b60405190815260200161018a565b6101e3603081565b60405160ff909116815260200161018a565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b03165b6040516001600160a01b03909116815260200161018a565b610149610247366004612b01565b610a4a565b6101cd61025a366004612bad565b610a5f565b61014961026d366004612b7e565b610a7b565b6102216005600160991b0181565b6101cd5f8051602061370d83398151915281565b6101496102a2366004612b01565b610c04565b6101e3601481565b6101496102bd366004612c06565b610d41565b6102d56102d0366004612b01565b610e4f565b60405161018a9190612cc3565b6101a66202a30081565b6101496102fa366004612d43565b610f9e565b6101cd61030d366004612d65565b610fdb565b5f8181525f8051602061372d8339815191526020526040808220815160e0810190925280545f8051602061370d83398151915293929190829060ff16600581111561035f5761035f612c42565b600581111561037057610370612c42565b815260200160018201805461038490612dd0565b80601f01602080910402602001604051908101604052809291908181526020018280546103b090612dd0565b80156103fb5780601f106103d2576101008083540402835291602001916103fb565b820191905f5260205f20905b8154815290600101906020018083116103de57829003601f168201915b505050918352505060028201546001600160401b038082166020840152600160401b820481166040840152600160801b820481166060840152600160c01b909104811660808301526003928301541660a0909101529091508151600581111561046657610466612c42565b146104a2575f8381526007830160205260409081902054905163170cc93360e21b81526104999160ff1690600401612e08565b60405180910390fd5b6005600160991b016001600160a01b031663ee5b48eb6104c78584606001515f611036565b6040518263ffffffff1660e01b81526004016104e39190612e16565b6020604051808303815f875af11580156104ff573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105239190612e28565b50505050565b7fe92546d698950ddd38910d2e15ed1d923cd0a7b3dde9e2a6a3f380565559cb09545f8051602061370d8339815191529060ff161561057b57604051637fab81e560e01b815260040160405180910390fd5b6005600160991b016001600160a01b0316634213cf786040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105be573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105e29190612e28565b83602001351461060b576040516372b0a7e760e11b815260208401356004820152602401610499565b3061061c6060850160408601612d43565b6001600160a01b03161461065f5761063a6060840160408501612d43565b604051632f88120d60e21b81526001600160a01b039091166004820152602401610499565b5f61066d6060850185612e3f565b905090505f805b828163ffffffff161015610955575f6106906060880188612e3f565b8363ffffffff168181106106a6576106a6612e84565b90506020028101906106b89190612e98565b6106c190612fbc565b80516040519192505f9160088801916106d991613035565b9081526020016040518091039020541461070957805160405163a41f772f60e01b81526104999190600401612e16565b5f6002885f01358460405160200161073892919091825260e01b6001600160e01b031916602082015260240190565b60408051601f198184030181529082905261075291613035565b602060405180830381855afa15801561076d573d5f803e3d5ffd5b5050506040513d601f19601f820116820180604052508101906107909190612e28565b90508086600801835f01516040516107a89190613035565b90815260408051602092819003830181209390935560e0830181526002835284518284015284810180516001600160401b03908116858401525f60608601819052915181166080860152421660a085015260c0840181905284815260078a01909252902081518154829060ff1916600183600581111561082a5761082a612c42565b0217905550602082015160018201906108439082613091565b506040828101516002830180546060860151608087015160a08801516001600160401b039586166001600160801b031990941693909317600160401b92861692909202919091176001600160801b0316600160801b918516919091026001600160c01b031617600160c01b9184169190910217905560c0909301516003909201805467ffffffffffffffff1916928416929092179091558301516108e8911685613164565b82516040519195506108f991613035565b60408051918290038220908401516001600160401b031682529082907f9d47fef9da077661546e646d61830bfcbda90506c2e5eed38195e82c4eb1cbdf9060200160405180910390a350508061094e90613177565b9050610674565b50600483018190555f61097361096a86611085565b6040015161119b565b90505f61097f87611328565b90505f6002826040516109929190613035565b602060405180830381855afa1580156109ad573d5f803e3d5ffd5b5050506040513d601f19601f820116820180604052508101906109d09190612e28565b90508281146109fc57604051631872fc8d60e01b81526004810182905260248101849052604401610499565b5050506009909201805460ff1916600117905550505050565b610a1e81611561565b505050565b5f610a2d82610e4f565b6080015192915050565b610a3f61189f565b610a485f6118fa565b565b610a5261189f565b610a5b8161196a565b5050565b5f610a6861189f565b610a728383611c4e565b90505b92915050565b5f8051602061370d8339815191525f80610aa0610a9785611085565b604001516121a1565b9150915080610ac657604051632d07135360e01b81528115156004820152602401610499565b5f82815260068401602052604090208054610ae090612dd0565b90505f03610b045760405163089938b360e11b815260048101839052602401610499565b60015f83815260078501602052604090205460ff166005811115610b2a57610b2a612c42565b14610b5d575f8281526007840160205260409081902054905163170cc93360e21b81526104999160ff1690600401612e08565b5f8281526006840160205260408120610b7591612a75565b5f828152600784016020908152604091829020805460ff1916600290811782550180546001600160401b0342818116600160c01b026001600160c01b0390931692909217928390558451600160801b9093041682529181019190915283917ff8fd1c90fb9cfa2ca2358fdf5806b086ad43315d92b221c929efc7f105ce7568910160405180910390a250505050565b5f8181527fe92546d698950ddd38910d2e15ed1d923cd0a7b3dde9e2a6a3f380565559cb066020526040902080545f8051602061370d8339815191529190610c4b90612dd0565b90505f03610c6f5760405163089938b360e11b815260048101839052602401610499565b60015f83815260078301602052604090205460ff166005811115610c9557610c95612c42565b14610cc8575f8281526007820160205260409081902054905163170cc93360e21b81526104999160ff1690600401612e08565b5f82815260068201602052604090819020905163ee5b48eb60e01b81526005600160991b019163ee5b48eb91610d019190600401613199565b6020604051808303815f875af1158015610d1d573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a1e9190612e28565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff1615906001600160401b03165f81158015610d855750825b90505f826001600160401b03166001148015610da05750303b155b905081158015610dae575080155b15610dcc5760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff191660011785558315610df657845460ff60401b1916600160401b1785555b610e00878761235d565b8315610e4657845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50505050505050565b610e57612aac565b5f8281525f8051602061372d833981519152602052604090819020815160e0810190925280545f8051602061370d833981519152929190829060ff166005811115610ea457610ea4612c42565b6005811115610eb557610eb5612c42565b8152602001600182018054610ec990612dd0565b80601f0160208091040260200160405190810160405280929190818152602001828054610ef590612dd0565b8015610f405780601f10610f1757610100808354040283529160200191610f40565b820191905f5260205f20905b815481529060010190602001808311610f2357829003601f168201915b505050918352505060028201546001600160401b038082166020840152600160401b820481166040840152600160801b820481166060840152600160c01b9091048116608083015260039092015490911660a0909101529392505050565b610fa661189f565b6001600160a01b038116610fcf57604051631e4fbdf760e01b81525f6004820152602401610499565b610fd8816118fa565b50565b6040515f905f8051602061370d833981519152907fe92546d698950ddd38910d2e15ed1d923cd0a7b3dde9e2a6a3f380565559cb089061101e9086908690613223565b90815260200160405180910390205491505092915050565b604080515f6020820152600360e01b602282015260268101949094526001600160c01b031960c093841b811660468601529190921b16604e830152805180830360360181526056909201905290565b60408051606080820183525f8083526020830152918101919091526040516306f8253560e41b815263ffffffff831660048201525f9081906005600160991b0190636f825350906024015f60405180830381865afa1580156110e9573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526111109190810190613241565b915091508061113257604051636b2f19e960e01b815260040160405180910390fd5b815115611158578151604051636ba589a560e01b81526004810191909152602401610499565b60208201516001600160a01b031615611194576020820151604051624de75d60e31b81526001600160a01b039091166004820152602401610499565b5092915050565b5f81516026146111d057815160405163cc92daa160e01b815263ffffffff909116600482015260266024820152604401610499565b5f805b600281101561121f576111e7816001613313565b6111f2906008613326565b61ffff1684828151811061120857611208612e84565b016020015160f81c901b91909117906001016111d3565b5061ffff8116156112495760405163407b587360e01b815261ffff82166004820152602401610499565b5f805b60048110156112a457611260816003613313565b61126b906008613326565b63ffffffff168561127d836002613164565b8151811061128d5761128d612e84565b016020015160f81c901b919091179060010161124c565b5063ffffffff8116156112ca57604051635b60892f60e01b815260040160405180910390fd5b5f805b602081101561131f576112e181601f613313565b6112ec906008613326565b866112f8836006613164565b8151811061130857611308612e84565b016020015160f81c901b91909117906001016112cd565b50949350505050565b60605f8083356020850135601461134487870160408901612d43565b6113516060890189612e3f565b60405160f09790971b6001600160f01b0319166020880152602287019590955250604285019290925260e090811b6001600160e01b0319908116606286015260609290921b6bffffffffffffffffffffffff191660668501529190911b16607a820152607e0160405160208183030381529060405290505f5b6113d76060850185612e3f565b9050811015611194576113ed6060850185612e3f565b828181106113fd576113fd612e84565b905060200281019061140f9190612e98565b61141d90602081019061333d565b905060301461143f5760405163180ffa0d60e01b815260040160405180910390fd5b8161144d6060860186612e3f565b8381811061145d5761145d612e84565b905060200281019061146f9190612e98565b611479908061333d565b90506114886060870187612e3f565b8481811061149857611498612e84565b90506020028101906114aa9190612e98565b6114b4908061333d565b6114c16060890189612e3f565b868181106114d1576114d1612e84565b90506020028101906114e39190612e98565b6114f190602081019061333d565b6114fe60608b018b612e3f565b8881811061150e5761150e612e84565b90506020028101906115209190612e98565b61153190606081019060400161337f565b6040516020016115479796959493929190613398565b60408051601f1981840301815291905291506001016113ca565b5f61156a612aac565b5f8051602061370d8339815191525f80611586610a9787611085565b9150915080156115ad57604051632d07135360e01b81528115156004820152602401610499565b5f828152600784016020526040808220815160e081019092528054829060ff1660058111156115de576115de612c42565b60058111156115ef576115ef612c42565b815260200160018201805461160390612dd0565b80601f016020809104026020016040519081016040528092919081815260200182805461162f90612dd0565b801561167a5780601f106116515761010080835404028352916020019161167a565b820191905f5260205f20905b81548152906001019060200180831161165d57829003601f168201915b505050918352505060028201546001600160401b038082166020840152600160401b820481166040840152600160801b820481166060840152600160c01b909104811660808301526003928301541660a090910152909150815160058111156116e5576116e5612c42565b14158015611706575060018151600581111561170357611703612c42565b14155b1561172757805160405163170cc93360e21b81526104999190600401612e08565b60038151600581111561173c5761173c612c42565b0361174a576004815261174f565b600581525b8360080181602001516040516117659190613035565b90815260408051602092819003830190205f908190558581526007870190925290208151815483929190829060ff191660018360058111156117a9576117a9612c42565b0217905550602082015160018201906117c29082613091565b5060408201516002820180546060850151608086015160a08701516001600160401b039586166001600160801b031990941693909317600160401b92861692909202919091176001600160801b0316600160801b918516919091026001600160c01b031617600160c01b9184169190910217905560c0909201516003909101805467ffffffffffffffff1916919092161790558051600581111561186857611868612c42565b60405184907f1c08e59656f1a18dc2da76826cdc52805c43e897a17c50faefb8ab3c1526cc16905f90a39196919550909350505050565b336118d17f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6001600160a01b031614610a485760405163118cdaa760e01b8152336004820152602401610499565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080546001600160a01b031981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a3505050565b611972612aac565b5f8281525f8051602061372d8339815191526020526040808220815160e0810190925280545f8051602061370d83398151915293929190829060ff1660058111156119bf576119bf612c42565b60058111156119d0576119d0612c42565b81526020016001820180546119e490612dd0565b80601f0160208091040260200160405190810160405280929190818152602001828054611a1090612dd0565b8015611a5b5780601f10611a3257610100808354040283529160200191611a5b565b820191905f5260205f20905b815481529060010190602001808311611a3e57829003601f168201915b50505091835250506002828101546001600160401b038082166020850152600160401b820481166040850152600160801b820481166060850152600160c01b9091048116608084015260039093015490921660a09091015290915081516005811115611ac957611ac9612c42565b14611afc575f8481526007830160205260409081902054905163170cc93360e21b81526104999160ff1690600401612e08565b60038152426001600160401b031660c08201525f84815260078301602052604090208151815483929190829060ff19166001836005811115611b4057611b40612c42565b021790555060208201516001820190611b599082613091565b5060408201516002820180546060850151608086015160a08701516001600160401b039586166001600160801b031990941693909317600160401b92861692909202919091176001600160801b0316600160801b918516919091026001600160c01b031617600160c01b9184169190910217905560c0909201516003909101805467ffffffffffffffff1916919092161790555f611bf78582612377565b6080840151604080516001600160401b03909216825242602083015291935083925087917f13d58394cf269d48bcf927959a29a5ffee7c9924dafff8927ecdf3c48ffa7c67910160405180910390a3509392505050565b7fe92546d698950ddd38910d2e15ed1d923cd0a7b3dde9e2a6a3f380565559cb09545f9060ff16611c9257604051637fab81e560e01b815260040160405180910390fd5b5f8051602061370d83398151915242611cb1606086016040870161337f565b6001600160401b0316111580611ceb5750611ccf6202a30042613164565b611cdf606086016040870161337f565b6001600160401b031610155b15611d2557611d00606085016040860161337f565b604051635879da1360e11b81526001600160401b039091166004820152602401610499565b6030611d34602086018661333d565b905014611d6657611d48602085018561333d565b6040516326475b2f60e11b8152610499925060040190815260200190565b611d70848061333d565b90505f03611d9d57611d82848061333d565b604051633e08a12560e11b8152600401610499929190613401565b5f60088201611dac868061333d565b604051611dba929190613223565b90815260200160405180910390205414611df357611dd8848061333d565b60405163a41f772f60e01b8152600401610499929190613401565b611dfd835f6124ce565b6040805160e08101909152815481525f908190611f099060208101611e22898061333d565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250505090825250602090810190611e6a908a018a61333d565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250505090825250602001611eb360608a0160408b0161337f565b6001600160401b03168152602001611ece60608a018a61342f565b611ed790613443565b8152602001611ee960808a018a61342f565b611ef290613443565b8152602001876001600160401b03168152506126a8565b5f82815260068601602052604090209193509150611f278282613091565b508160088401611f37888061333d565b604051611f45929190613223565b9081526040519081900360200181209190915563ee5b48eb60e01b81525f906005600160991b019063ee5b48eb90611f81908590600401612e16565b6020604051808303815f875af1158015611f9d573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611fc19190612e28565b6040805160e081019091529091508060018152602001611fe1898061333d565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201829052509385525050506001600160401b0389166020808401829052604080850184905260608501929092526080840183905260a0909301829052868252600788019092522081518154829060ff1916600183600581111561207057612070612c42565b0217905550602082015160018201906120899082613091565b5060408201516002820180546060850151608086015160a08701516001600160401b039586166001600160801b031990941693909317600160401b92861692909202919091176001600160801b0316600160801b918516919091026001600160c01b031617600160c01b9184169190910217905560c0909201516003909101805467ffffffffffffffff19169190921617905580612127888061333d565b604051612135929190613223565b6040518091039020847fb77297e3befc691bfc864a81e241f83e2ef722b6e7becaa2ecec250c6d52b430898b6040016020810190612173919061337f565b604080516001600160401b0393841681529290911660208301520160405180910390a4509095945050505050565b5f8082516027146121d757825160405163cc92daa160e01b815263ffffffff909116600482015260276024820152604401610499565b5f805b6002811015612226576121ee816001613313565b6121f9906008613326565b61ffff1685828151811061220f5761220f612e84565b016020015160f81c901b91909117906001016121da565b5061ffff8116156122505760405163407b587360e01b815261ffff82166004820152602401610499565b5f805b60048110156122ab57612267816003613313565b612272906008613326565b63ffffffff1686612284836002613164565b8151811061229457612294612e84565b016020015160f81c901b9190911790600101612253565b5063ffffffff81166002146122d357604051635b60892f60e01b815260040160405180910390fd5b5f805b6020811015612328576122ea81601f613313565b6122f5906008613326565b87612301836006613164565b8151811061231157612311612e84565b016020015160f81c901b91909117906001016122d6565b505f8660268151811061233d5761233d612e84565b016020015191976001600160f81b03199092161515965090945050505050565b612365612895565b61236e826128de565b610a5b816128f7565b5f8281525f8051602061372d833981519152602052604081206002015481905f8051602061370d83398151915290600160801b90046001600160401b03166123bf85826124ce565b5f6123c987612908565b5f8881526007850160205260408120600201805467ffffffffffffffff60801b1916600160801b6001600160401b038b16021790559091506005600160991b0163ee5b48eb6124198a858b611036565b6040518263ffffffff1660e01b81526004016124359190612e16565b6020604051808303815f875af1158015612451573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906124759190612e28565b604080516001600160401b038a811682526020820184905282519394508516928b927f07de5ff35a674a8005e661f3333c907ca6333462808762d19dc7b3abb1a8c1df928290030190a3909450925050505b9250929050565b5f8051602061370d8339815191525f6001600160401b038084169085161115612502576124fb838561350a565b905061250f565b61250c848461350a565b90505b6040805160808101825260028401548082526003850154602083015260048501549282019290925260058401546001600160401b031660608201524291158061257157506001840154815161256d916001600160401b031690613164565b8210155b15612597576001600160401b0383166060820152818152604081015160208201526125b6565b82816060018181516125a9919061352a565b6001600160401b03169052505b60608101516125c690606461354a565b602082015160018601546001600160401b0392909216916125f19190600160401b900460ff16613326565b101561262157606081015160405163dfae880160e01b81526001600160401b039091166004820152602401610499565b856001600160401b03168160400181815161263c9190613164565b9052506040810180516001600160401b038716919061265c908390613313565b905250805160028501556020810151600385015560408101516004850155606001516005909301805467ffffffffffffffff19166001600160401b039094169390931790925550505050565b5f60608260400151516030146126d15760405163180ffa0d60e01b815260040160405180910390fd5b82516020808501518051604080880151606089015160808a01518051908701515193515f98612712988a986001989297929690959094909390929101613575565b60405160208183030381529060405290505f5b846080015160200151518110156127845781856080015160200151828151811061275157612751612e84565b602002602001015160405160200161276a92919061362f565b60408051601f198184030181529190529150600101612725565b5060a08401518051602091820151516040516127a4938593929101613665565b60405160208183030381529060405290505f5b8460a00151602001515181101561281657818560a001516020015182815181106127e3576127e3612e84565b60200260200101516040516020016127fc92919061362f565b60408051601f1981840301815291905291506001016127b7565b5060c084015160405161282d9183916020016136a0565b604051602081830303815290604052905060028160405161284e9190613035565b602060405180830381855afa158015612869573d5f803e3d5ffd5b5050506040513d601f19601f8201168201806040525081019061288c9190612e28565b94909350915050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff16610a4857604051631afcd79f60e31b815260040160405180910390fd5b6128e6612895565b6128ee61297d565b610fd881612985565b6128ff612895565b610fd881612a6d565b5f8181525f8051602061372d8339815191526020526040812060020180545f8051602061370d833981519152919060089061295290600160401b90046001600160401b03166136d1565b91906101000a8154816001600160401b0302191690836001600160401b031602179055915050919050565b610a48612895565b61298d612895565b80355f8051602061370d83398151915290815560146129b260608401604085016136ec565b60ff1611806129d157506129cc60608301604084016136ec565b60ff16155b15612a05576129e660608301604084016136ec565b604051634a59bbff60e11b815260ff9091166004820152602401610499565b612a1560608301604084016136ec565b60018201805460ff92909216600160401b0260ff60401b19909216919091179055612a46604083016020840161337f565b600191909101805467ffffffffffffffff19166001600160401b0390921691909117905550565b610fa6612895565b508054612a8190612dd0565b5f825580601f10612a90575050565b601f0160209004905f5260205f2090810190610fd89190612ae9565b6040805160e08101909152805f81526060602082018190525f604083018190529082018190526080820181905260a0820181905260c09091015290565b5b80821115612afd575f8155600101612aea565b5090565b5f60208284031215612b11575f80fd5b5035919050565b803563ffffffff81168114612b2b575f80fd5b919050565b5f8060408385031215612b41575f80fd5b82356001600160401b03811115612b56575f80fd5b830160808186031215612b67575f80fd5b9150612b7560208401612b18565b90509250929050565b5f60208284031215612b8e575f80fd5b610a7282612b18565b80356001600160401b0381168114612b2b575f80fd5b5f8060408385031215612bbe575f80fd5b82356001600160401b03811115612bd3575f80fd5b830160a08186031215612be4575f80fd5b9150612b7560208401612b97565b6001600160a01b0381168114610fd8575f80fd5b5f808284036080811215612c18575f80fd5b6060811215612c25575f80fd5b508291506060830135612c3781612bf2565b809150509250929050565b634e487b7160e01b5f52602160045260245ffd5b60068110612c7257634e487b7160e01b5f52602160045260245ffd5b9052565b5f5b83811015612c90578181015183820152602001612c78565b50505f910152565b5f8151808452612caf816020860160208601612c76565b601f01601f19169290920160200192915050565b60208152612cd5602082018351612c56565b5f602083015160e06040840152612cf0610100840182612c98565b905060408401516001600160401b0380821660608601528060608701511660808601528060808701511660a08601528060a08701511660c08601528060c08701511660e086015250508091505092915050565b5f60208284031215612d53575f80fd5b8135612d5e81612bf2565b9392505050565b5f8060208385031215612d76575f80fd5b82356001600160401b0380821115612d8c575f80fd5b818501915085601f830112612d9f575f80fd5b813581811115612dad575f80fd5b866020828501011115612dbe575f80fd5b60209290920196919550909350505050565b600181811c90821680612de457607f821691505b602082108103612e0257634e487b7160e01b5f52602260045260245ffd5b50919050565b60208101610a758284612c56565b602081525f610a726020830184612c98565b5f60208284031215612e38575f80fd5b5051919050565b5f808335601e19843603018112612e54575f80fd5b8301803591506001600160401b03821115612e6d575f80fd5b6020019150600581901b36038213156124c7575f80fd5b634e487b7160e01b5f52603260045260245ffd5b5f8235605e19833603018112612eac575f80fd5b9190910192915050565b634e487b7160e01b5f52604160045260245ffd5b604051606081016001600160401b0381118282101715612eec57612eec612eb6565b60405290565b604080519081016001600160401b0381118282101715612eec57612eec612eb6565b604051601f8201601f191681016001600160401b0381118282101715612f3c57612f3c612eb6565b604052919050565b5f6001600160401b03821115612f5c57612f5c612eb6565b50601f01601f191660200190565b5f82601f830112612f79575f80fd5b8135612f8c612f8782612f44565b612f14565b818152846020838601011115612fa0575f80fd5b816020850160208301375f918101602001919091529392505050565b5f60608236031215612fcc575f80fd5b612fd4612eca565b82356001600160401b0380821115612fea575f80fd5b612ff636838701612f6a565b8352602085013591508082111561300b575f80fd5b5061301836828601612f6a565b60208301525061302a60408401612b97565b604082015292915050565b5f8251612eac818460208701612c76565b601f821115610a1e57805f5260205f20601f840160051c8101602085101561306b5750805b601f840160051c820191505b8181101561308a575f8155600101613077565b5050505050565b81516001600160401b038111156130aa576130aa612eb6565b6130be816130b88454612dd0565b84613046565b602080601f8311600181146130f1575f84156130da5750858301515b5f19600386901b1c1916600185901b178555613148565b5f85815260208120601f198616915b8281101561311f57888601518255948401946001909101908401613100565b508582101561313c57878501515f19600388901b60f8161c191681555b505060018460011b0185555b505050505050565b634e487b7160e01b5f52601160045260245ffd5b80820180821115610a7557610a75613150565b5f63ffffffff80831681810361318f5761318f613150565b6001019392505050565b5f60208083525f84546131ab81612dd0565b806020870152604060018084165f81146131cc57600181146131e857613215565b60ff19851660408a0152604084151560051b8a01019550613215565b895f5260205f205f5b8581101561320c5781548b82018601529083019088016131f1565b8a016040019650505b509398975050505050505050565b818382375f9101908152919050565b80518015158114612b2b575f80fd5b5f8060408385031215613252575f80fd5b82516001600160401b0380821115613268575f80fd5b908401906060828703121561327b575f80fd5b613283612eca565b8251815260208084015161329681612bf2565b828201526040840151838111156132ab575f80fd5b80850194505087601f8501126132bf575f80fd5b835192506132cf612f8784612f44565b83815288828587010111156132e2575f80fd5b6132f184838301848801612c76565b80604084015250819550613306818801613232565b9450505050509250929050565b81810381811115610a7557610a75613150565b8082028115828204841417610a7557610a75613150565b5f808335601e19843603018112613352575f80fd5b8301803591506001600160401b0382111561336b575f80fd5b6020019150368190038213156124c7575f80fd5b5f6020828403121561338f575f80fd5b610a7282612b97565b5f88516133a9818460208d01612c76565b60e089901b6001600160e01b031916908301908152868860048301378681019050600481015f8152858782375060c09390931b6001600160c01b0319166004939094019283019390935250600c019695505050505050565b60208152816020820152818360408301375f818301604090810191909152601f909201601f19160101919050565b5f8235603e19833603018112612eac575f80fd5b5f60408236031215613453575f80fd5b61345b612ef2565b61346483612b18565b81526020808401356001600160401b0380821115613480575f80fd5b9085019036601f830112613492575f80fd5b8135818111156134a4576134a4612eb6565b8060051b91506134b5848301612f14565b81815291830184019184810190368411156134ce575f80fd5b938501935b838510156134f857843592506134e883612bf2565b82825293850193908501906134d3565b94860194909452509295945050505050565b6001600160401b0382811682821603908082111561119457611194613150565b6001600160401b0381811683821601908082111561119457611194613150565b6001600160401b0381811683821602808216919082811461356d5761356d613150565b505092915050565b61ffff60f01b8a60f01b1681525f63ffffffff60e01b808b60e01b166002840152896006840152808960e01b1660268401525086516135bb81602a850160208b01612c76565b8651908301906135d281602a840160208b01612c76565b60c087901b6001600160c01b031916602a9290910191820152613604603282018660e01b6001600160e01b0319169052565b61361d603682018560e01b6001600160e01b0319169052565b603a019b9a5050505050505050505050565b5f8351613640818460208801612c76565b60609390931b6bffffffffffffffffffffffff19169190920190815260140192915050565b5f8451613676818460208901612c76565b6001600160e01b031960e095861b8116919093019081529290931b16600482015260080192915050565b5f83516136b1818460208801612c76565b60c09390931b6001600160c01b0319169190920190815260080192915050565b5f6001600160401b0380831681810361318f5761318f613150565b5f602082840312156136fc575f80fd5b813560ff81168114612d5e575f80fdfee92546d698950ddd38910d2e15ed1d923cd0a7b3dde9e2a6a3f380565559cb00e92546d698950ddd38910d2e15ed1d923cd0a7b3dde9e2a6a3f380565559cb07a164736f6c6343000819000a", + "code": "0x608060405234801561000f575f80fd5b5060043610610187575f3560e01c8063a3a65e48116100d9578063c974d1b611610093578063df93d8de1161006e578063df93d8de1461039e578063ed285ae1146103a8578063f2fde38b146103bb578063fd7ac5e7146103ce575f80fd5b8063c974d1b614610346578063ce161f141461034e578063d5f20ff61461037e575f80fd5b8063a3a65e48146102d0578063b6e6a2ca146102e3578063b771b3bc146102f6578063bb0b193814610304578063bc5fbfec1461030c578063bee0a03f14610333575f80fd5b80636610966911610144578063736c87be1161011f578063736c87be1461024c5780638280a25a1461025f5780638da5cb5b146102795780639681d940146102bd575f80fd5b8063661096691461020b578063715018a61461023d578063732214f814610245575f80fd5b80630322ed981461018b57806309c1df66146101a057806320d91b7a146101c55780635dc1f535146101d857806360305d62146101ee57806363e2ca97146101ee575b5f80fd5b61019e610199366004612893565b6103e1565b005b6101a8610674565b6040516001600160401b0390911681526020015b60405180910390f35b61019e6101d33660046128d3565b61068f565b6101e0610c48565b6040519081526020016101bc565b6101f6601481565b60405163ffffffff90911681526020016101bc565b61021e61021936600461293c565b610c57565b604080516001600160401b0390931683526020830191909152016101bc565b61019e610c77565b6101e05f81565b61019e61025a36600461296a565b610c8a565b610267603081565b60405160ff90911681526020016101bc565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b03165b6040516001600160a01b0390911681526020016101bc565b6101e06102cb36600461298b565b610d96565b6101e06102de36600461298b565b61114a565b61019e6102f1366004612893565b611341565b6102a56005600160991b0181565b6101a8611355565b6101e07fe92546d698950ddd38910d2e15ed1d923cd0a7b3dde9e2a6a3f380565559cb0081565b61019e610341366004612893565b611377565b610267601481565b61036161035c36600461298b565b611498565b604080519283526001600160401b039091166020830152016101bc565b61039161038c366004612893565b611623565b6040516101bc9190612a25565b6101a86202a30081565b6101e06103b6366004612cbe565b6117aa565b61019e6103c9366004612d82565b6117cc565b6101e06103dc366004612d9d565b611806565b5f6103ea61183f565b5f838152600580830160205260408083208151610100810190925280549495509293909291839160ff1690811115610424576104246129a4565b6005811115610435576104356129a4565b815260200160018201805461044990612e08565b80601f016020809104026020016040519081016040528092919081815260200182805461047590612e08565b80156104c05780601f10610497576101008083540402835291602001916104c0565b820191905f5260205f20905b8154815290600101906020018083116104a357829003601f168201915b505050918352505060028201546001600160401b038082166020840152600160401b80830482166040850152600160801b830482166060850152600160c01b9092048116608084015260039384015480821660a0850152919091041660c09091015290915081516005811115610538576105386129a4565b14610574575f8381526005830160205260409081902054905163170cc93360e21b815261056b9160ff1690600401612e3a565b60405180910390fd5b606081015160405163854a893f60e01b8152600481018590526001600160401b0390911660248201525f60448201526005600160991b019063ee5b48eb90739c00629ce712b0255b17a4a657171acd15720b8c9063854a893f906064015f60405180830381865af41580156105eb573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526106129190810190612e92565b6040518263ffffffff1660e01b815260040161062e9190612ec3565b6020604051808303815f875af115801561064a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061066e9190612ed5565b50505050565b5f61067d61183f565b600101546001600160401b0316919050565b5f61069861183f565b600781015490915060ff16156106c157604051637fab81e560e01b815260040160405180910390fd5b6005600160991b016001600160a01b0316634213cf786040518163ffffffff1660e01b8152600401602060405180830381865afa158015610704573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107289190612ed5565b836020013514610751576040516372b0a7e760e11b81526020840135600482015260240161056b565b306107626060850160408601612d82565b6001600160a01b0316146107a5576107806060840160408501612d82565b604051632f88120d60e21b81526001600160a01b03909116600482015260240161056b565b5f6107b36060850185612eec565b905090505f805b828163ffffffff161015610a39575f6107d66060880188612eec565b8363ffffffff168181106107ec576107ec612f31565b90506020028101906107fe9190612f45565b61080790612f63565b80516040519192505f91600688019161081f91612fde565b9081526020016040518091039020541461084f57805160405163a41f772f60e01b815261056b9190600401612ec3565b805151601414610875578051604051633e08a12560e11b815261056b9190600401612ec3565b5f6002885f0135846040516020016108a492919091825260e01b6001600160e01b031916602082015260240190565b60408051601f19818403018152908290526108be91612fde565b602060405180830381855afa1580156108d9573d5f803e3d5ffd5b5050506040513d601f19601f820116820180604052508101906108fc9190612ed5565b90508086600601835f01516040516109149190612fde565b90815260408051918290036020908101909220929092555f8381526005890190915220805460ff191660021781558251600190910190610954908261303a565b50604082810180515f84815260058a016020529290922060028101805492516001600160401b0394851667ffffffffffffffff60801b90941693909317600160c01b858516021790556003018054429093166001600160801b0319909316929092179091556109c39085613109565b8251602001519094506bffffffffffffffffffffffff1916817f9d9c026e2cadfec89cccc2cd72705360eca1beba24774f3363f4bb33faabc7d78460400151604051610a1e91906001600160401b0391909116815260200190565b60405180910390a3505080610a3290613129565b90506107ba565b506003830180546fffffffffffffffff00000000000000001916600160401b6001600160401b0384168102919091179091556001840154606491610a81910460ff168361314b565b6001600160401b03161015610ab457604051633e1a785160e01b81526001600160401b038216600482015260240161056b565b5f739c00629ce712b0255b17a4a657171acd15720b8c634d847884610ad887611863565b604001516040518263ffffffff1660e01b8152600401610af89190612ec3565b602060405180830381865af4158015610b13573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b379190612ed5565b90505f739c00629ce712b0255b17a4a657171acd15720b8c6387418b8e886040518263ffffffff1660e01b8152600401610b7191906132a1565b5f60405180830381865af4158015610b8b573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610bb29190810190612e92565b90505f600282604051610bc59190612fde565b602060405180830381855afa158015610be0573d5f803e3d5ffd5b5050506040513d601f19601f82011682018060405250810190610c039190612ed5565b9050828114610c2f5760405163baaea89d60e01b8152600481018290526024810184905260440161056b565b5050506007909201805460ff1916600117905550505050565b5f610c5161183f565b54919050565b5f80610c61611979565b610c6b84846119d4565b915091505b9250929050565b610c7f611979565b610c885f611b9c565b565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff1615906001600160401b03165f81158015610cce5750825b90505f826001600160401b03166001148015610ce95750303b155b905081158015610cf7575080155b15610d155760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff191660011785558315610d3f57845460ff60401b1916600160401b1785555b610d4886611c0c565b8315610d8e57845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b505050505050565b5f610d9f611979565b5f610da861183f565b90505f80739c00629ce712b0255b17a4a657171acd15720b8c63021de88f610dcf87611863565b604001516040518263ffffffff1660e01b8152600401610def9190612ec3565b6040805180830381865af4158015610e09573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e2d9190613344565b915091508015610e5457604051632d07135360e01b8152811515600482015260240161056b565b5f8281526005808501602052604080832081516101008101909252805491929091839160ff90911690811115610e8c57610e8c6129a4565b6005811115610e9d57610e9d6129a4565b8152602001600182018054610eb190612e08565b80601f0160208091040260200160405190810160405280929190818152602001828054610edd90612e08565b8015610f285780601f10610eff57610100808354040283529160200191610f28565b820191905f5260205f20905b815481529060010190602001808311610f0b57829003601f168201915b505050918352505060028201546001600160401b038082166020840152600160401b80830482166040850152600160801b830482166060850152600160c01b9092048116608084015260039384015480821660a0850152919091041660c09091015290915081516005811115610fa057610fa06129a4565b14158015610fc15750600181516005811115610fbe57610fbe6129a4565b14155b15610fe257805160405163170cc93360e21b815261056b9190600401612e3a565b600381516005811115610ff757610ff76129a4565b03611005576004815261100a565b600581525b8360060181602001516040516110209190612fde565b90815260408051602092819003830190205f90819055858152600587810190935220825181548493839160ff1916906001908490811115611063576110636129a4565b02179055506020820151600182019061107c908261303a565b506040828101516002830180546060860151608087015160a08801516001600160401b039586166001600160801b031994851617600160401b9387168402176001600160801b0316600160801b928716929092026001600160c01b031691909117600160c01b918616919091021790925560c08601516003909501805460e09097015195841696909116959095179390911602919091179091555183907fafaccef7080649a725bc30a35359a257a4a27225be352875c80bdf6b5f04080c905f90a25090925050505b919050565b5f611153611979565b5f61115c61183f565b90505f80739c00629ce712b0255b17a4a657171acd15720b8c63021de88f61118387611863565b604001516040518263ffffffff1660e01b81526004016111a39190612ec3565b6040805180830381865af41580156111bd573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111e19190613344565b915091508061120757604051632d07135360e01b8152811515600482015260240161056b565b5f8281526004840160205260409020805461122190612e08565b90505f036112455760405163089938b360e11b81526004810183905260240161056b565b60015f838152600580860160205260409091205460ff169081111561126c5761126c6129a4565b1461129f575f8281526005840160205260409081902054905163170cc93360e21b815261056b9160ff1690600401612e3a565b5f82815260048401602052604081206112b791612849565b5f828152600584016020908152604091829020805460ff1916600290811782556003820180546001600160401b0342811667ffffffffffffffff19909216919091179091559101549251600160c01b90930416825283917f967ae87813a3b5f201dd9bcba778d457176eafe6f41facee1c718091d3952d06910160405180910390a2509392505050565b611349611979565b61135281611c32565b50565b5f61135e61183f565b60030154600160401b90046001600160401b0316919050565b5f61138061183f565b5f838152600482016020526040902080549192509061139e90612e08565b90505f036113c25760405163089938b360e11b81526004810183905260240161056b565b60015f838152600580840160205260409091205460ff16908111156113e9576113e96129a4565b1461141c575f8281526005820160205260409081902054905163170cc93360e21b815261056b9160ff1690600401612e3a565b5f8281526004808301602052604091829020915163ee5b48eb60e01b81526005600160991b019263ee5b48eb926114539201613365565b6020604051808303815f875af115801561146f573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114939190612ed5565b505050565b5f806114a2611979565b5f6114ac84611863565b90505f805f739c00629ce712b0255b17a4a657171acd15720b8c6350782b0f85604001516040518263ffffffff1660e01b81526004016114ec9190612ec3565b606060405180830381865af4158015611507573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061152b91906133ef565b9250925092505f61153a61183f565b5f8581526005820160205260409020600201549091506001600160401b03808516600160401b90920416101561158e57604051632e19bc2d60e11b81526001600160401b038416600482015260240161056b565b5f8481526005820160205260409081902060020180546001600160401b038616600160801b0267ffffffffffffffff60801b199091161790555184907fc917996591802ecedcfced71321d4bb5320f7dfbacf5477dffe1dbf8b8839ff99061160e90869086906001600160401b0392831681529116602082015260400190565b60405180910390a25091945092505050915091565b60408051610100810182525f8082526060602083018190529282018190529181018290526080810182905260a0810182905260c0810182905260e081018290529061166c61183f565b5f84815260058083016020526040918290208251610100810190935280549394509192839160ff909116908111156116a6576116a66129a4565b60058111156116b7576116b76129a4565b81526020016001820180546116cb90612e08565b80601f01602080910402602001604051908101604052809291908181526020018280546116f790612e08565b80156117425780601f1061171957610100808354040283529160200191611742565b820191905f5260205f20905b81548152906001019060200180831161172557829003601f168201915b505050918352505060028201546001600160401b038082166020840152600160401b80830482166040850152600160801b830482166060850152600160c01b9092048116608084015260039093015480841660a08401520490911660c0909101529392505050565b5f6117b3611979565b6117c1878787878787611f1d565b979650505050505050565b6117d4611979565b6001600160a01b0381166117fd57604051631e4fbdf760e01b81525f600482015260240161056b565b61135281611b9c565b5f8061181061183f565b905080600601848460405161182692919061342f565b9081526020016040518091039020549150505b92915050565b7fe92546d698950ddd38910d2e15ed1d923cd0a7b3dde9e2a6a3f380565559cb0090565b60408051606080820183525f8083526020830152918101919091526040516306f8253560e41b815263ffffffff831660048201525f9081906005600160991b0190636f825350906024015f60405180830381865afa1580156118c7573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526118ee919081019061343e565b915091508061191057604051636b2f19e960e01b815260040160405180910390fd5b815115611936578151604051636ba589a560e01b8152600481019190915260240161056b565b60208201516001600160a01b031615611972576020820151604051624de75d60e31b81526001600160a01b03909116600482015260240161056b565b5092915050565b336119ab7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6001600160a01b031614610c885760405163118cdaa760e01b815233600482015260240161056b565b5f805f6119df61183f565b5f868152600582016020526040902060020154909150600160c01b90046001600160401b0316611a0f8582612307565b5f611a1987612574565b5f88815260058501602052604080822060020180546001600160c01b0316600160c01b6001600160401b038c811691820292909217909255915163854a893f60e01b8152600481018c905291841660248301526044820152919250906005600160991b019063ee5b48eb90739c00629ce712b0255b17a4a657171acd15720b8c9063854a893f906064015f60405180830381865af4158015611abd573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052611ae49190810190612e92565b6040518263ffffffff1660e01b8152600401611b009190612ec3565b6020604051808303815f875af1158015611b1c573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611b409190612ed5565b604080516001600160401b038581168252602082018490528a1681830152905191925089917f6e350dd49b060d87f297206fd309234ed43156d890ced0f139ecf704310481d39181900360600190a29097909650945050505050565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080546001600160a01b031981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a3505050565b611c146125dd565b611c29611c246020830183612d82565b612626565b61135281612637565b5f611c3b61183f565b5f838152600580830160205260408083208151610100810190925280549495509293909291839160ff1690811115611c7557611c756129a4565b6005811115611c8657611c866129a4565b8152602001600182018054611c9a90612e08565b80601f0160208091040260200160405190810160405280929190818152602001828054611cc690612e08565b8015611d115780601f10611ce857610100808354040283529160200191611d11565b820191905f5260205f20905b815481529060010190602001808311611cf457829003601f168201915b50505091835250506002828101546001600160401b038082166020850152600160401b80830482166040860152600160801b830482166060860152600160c01b9092048116608085015260039094015480851660a08501520490921660c09091015290915081516005811115611d8957611d896129a4565b14611dbc575f8381526005830160205260409081902054905163170cc93360e21b815261056b9160ff1690600401612e3a565b60038152426001600160401b031660e08201525f83815260058381016020526040909120825181548493839160ff1916906001908490811115611e0157611e016129a4565b021790555060208201516001820190611e1a908261303a565b5060408201516002820180546060850151608086015160a08701516001600160401b039586166001600160801b031994851617600160401b9387168402176001600160801b0316600160801b928716929092026001600160c01b031691909117600160c01b918616919091021790925560c08501516003909401805460e090960151948416959091169490941792909116021790555f611eba84826119d4565b915050837fbae388a94e7f18411fe57098f12f418b8e1a8273e0532a90188a3a059b897273828460a0015142604051611f0f939291909283526001600160401b03918216602084015216604082015260600190565b60405180910390a250505050565b5f611f2661183f565b6007015460ff16611f4a57604051637fab81e560e01b815260040160405180910390fd5b5f611f5361183f565b905042866001600160401b0316111580611f825750611f756202a300426134cb565b866001600160401b031610155b15611fab57604051635879da1360e11b81526001600160401b038716600482015260240161056b565b60038101546001600160401b0390611fce90600160401b900482168583166134cb565b1115611ff857604051633e1a785160e01b81526001600160401b038416600482015260240161056b565b6120018561271e565b61200a8461271e565b86516030146120315786516040516326475b2f60e11b815260040161056b91815260200190565b87516014146120555787604051633e08a12560e11b815260040161056b9190612ec3565b5f801b816006018960405161206a9190612fde565b90815260200160405180910390205414612099578760405163a41f772f60e01b815260040161056b9190612ec3565b6120a3835f612307565b5f80739c00629ce712b0255b17a4a657171acd15720b8c63eb97ce516040518060e00160405280865f015481526020018d81526020018c81526020018b6001600160401b031681526020018a8152602001898152602001886001600160401b03168152506040518263ffffffff1660e01b81526004016121239190613544565b5f60405180830381865af415801561213d573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261216491908101906135fb565b5f82815260048601602052604090209193509150612182828261303a565b5081836006018b6040516121969190612fde565b9081526040519081900360200181209190915563ee5b48eb60e01b81525f906005600160991b019063ee5b48eb906121d2908590600401612ec3565b6020604051808303815f875af11580156121ee573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906122129190612ed5565b5f8481526005860160205260409020805460ff1916600190811782559192500161223c8c8261303a565b505f8381526005850160205260409020600281018054600160c01b6001600160401b038a1690810267ffffffffffffffff60801b9092161717905560030180546001600160801b03191690556122938b6020015190565b6bffffffffffffffffffffffff1916837f5881be437bdcb008bfa5f20e32d3e335ccf8ab90ef2818852a251625260af35d838c8a6040516122f0939291909283526001600160401b03918216602084015216604082015260600190565b60405180910390a350909998505050505050505050565b5f61231061183f565b90505f826001600160401b0316846001600160401b0316111561233e57612337838561363e565b905061234b565b612348848461363e565b90505b60408051608081018252600284015480825260038501546001600160401b038082166020850152600160401b8204811694840194909452600160801b90049092166060820152429115806123b85750600184015481516123b4916001600160401b0316906134cb565b8210155b156123e0576001600160401b03808416606083015282825260408201511660208201526123ff565b82816060018181516123f29190613109565b6001600160401b03169052505b606081015161240f90606461314b565b602082015160018601546001600160401b03929092169161243a9190600160401b900460ff1661314b565b6001600160401b0316101561247357606081015160405163dfae880160e01b81526001600160401b03909116600482015260240161056b565b85816040018181516124859190613109565b6001600160401b03169052506040810180518691906124a590839061363e565b6001600160401b0316905250600184015460408201516064916124d391600160401b90910460ff169061314b565b6001600160401b0316101561250c576040808201519051633e1a785160e01b81526001600160401b03909116600482015260240161056b565b8051600285015560208101516003909401805460408301516060909301516001600160401b03908116600160801b0267ffffffffffffffff60801b19948216600160401b026001600160801b0319909316919097161717919091169390931790925550505050565b5f8061257e61183f565b5f84815260058201602052604090206002018054919250906008906125b290600160401b90046001600160401b031661365e565b91906101000a8154816001600160401b0302191690836001600160401b031602179055915050919050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff16610c8857604051631afcd79f60e31b815260040160405180910390fd5b61262e6125dd565b61135281612841565b61263f6125dd565b5f61264861183f565b60208301358155905060146126636080840160608501613679565b60ff161180612682575061267d6080830160608401613679565b60ff16155b156126b6576126976080830160608401613679565b604051634a59bbff60e11b815260ff909116600482015260240161056b565b6126c66080830160608401613679565b60018201805460ff92909216600160401b0260ff60401b199092169190911790556126f76060830160408401613699565b600191909101805467ffffffffffffffff19166001600160401b0390921691909117905550565b805163ffffffff16158015612737575060208101515115155b1561276b57805160208201515160405163c08a0f1d60e01b815263ffffffff9092166004830152602482015260440161056b565b602081015151815163ffffffff1611156127ae57805160208201515160405163c08a0f1d60e01b815263ffffffff9092166004830152602482015260440161056b565b60015b81602001515181101561283d5760208201516127ce6001836136b4565b815181106127de576127de612f31565b60200260200101516001600160a01b03168260200151828151811061280557612805612f31565b60200260200101516001600160a01b0316101561283557604051630dbc8d5f60e31b815260040160405180910390fd5b6001016127b1565b5050565b6117d46125dd565b50805461285590612e08565b5f825580601f10612864575050565b601f0160209004905f5260205f209081019061135291905b8082111561288f575f815560010161287c565b5090565b5f602082840312156128a3575f80fd5b5035919050565b5f608082840312156128ba575f80fd5b50919050565b803563ffffffff81168114611145575f80fd5b5f80604083850312156128e4575f80fd5b82356001600160401b038111156128f9575f80fd5b612905858286016128aa565b925050612914602084016128c0565b90509250929050565b6001600160401b0381168114611352575f80fd5b80356111458161291d565b5f806040838503121561294d575f80fd5b82359150602083013561295f8161291d565b809150509250929050565b5f6080828403121561297a575f80fd5b61298483836128aa565b9392505050565b5f6020828403121561299b575f80fd5b612984826128c0565b634e487b7160e01b5f52602160045260245ffd5b600681106129d457634e487b7160e01b5f52602160045260245ffd5b9052565b5f5b838110156129f25781810151838201526020016129da565b50505f910152565b5f8151808452612a118160208601602086016129d8565b601f01601f19169290920160200192915050565b60208152612a376020820183516129b8565b5f6020830151610100806040850152612a546101208501836129fa565b915060408501516001600160401b03808216606087015280606088015116608087015250506080850151612a9360a08601826001600160401b03169052565b5060a08501516001600160401b03811660c08601525060c08501516001600160401b03811660e08601525060e08501516001600160401b038116858301525090949350505050565b634e487b7160e01b5f52604160045260245ffd5b604080519081016001600160401b0381118282101715612b1157612b11612adb565b60405290565b604051606081016001600160401b0381118282101715612b1157612b11612adb565b604051601f8201601f191681016001600160401b0381118282101715612b6157612b61612adb565b604052919050565b5f6001600160401b03821115612b8157612b81612adb565b50601f01601f191660200190565b5f82601f830112612b9e575f80fd5b8135612bb1612bac82612b69565b612b39565b818152846020838601011115612bc5575f80fd5b816020850160208301375f918101602001919091529392505050565b6001600160a01b0381168114611352575f80fd5b5f60408284031215612c05575f80fd5b612c0d612aef565b9050612c18826128c0565b81526020808301356001600160401b0380821115612c34575f80fd5b818501915085601f830112612c47575f80fd5b813581811115612c5957612c59612adb565b8060051b9150612c6a848301612b39565b8181529183018401918481019088841115612c83575f80fd5b938501935b83851015612cad5784359250612c9d83612be1565b8282529385019390850190612c88565b808688015250505050505092915050565b5f805f805f8060c08789031215612cd3575f80fd5b86356001600160401b0380821115612ce9575f80fd5b612cf58a838b01612b8f565b97506020890135915080821115612d0a575f80fd5b612d168a838b01612b8f565b9650612d2460408a01612931565b95506060890135915080821115612d39575f80fd5b612d458a838b01612bf5565b94506080890135915080821115612d5a575f80fd5b50612d6789828a01612bf5565b925050612d7660a08801612931565b90509295509295509295565b5f60208284031215612d92575f80fd5b813561298481612be1565b5f8060208385031215612dae575f80fd5b82356001600160401b0380821115612dc4575f80fd5b818501915085601f830112612dd7575f80fd5b813581811115612de5575f80fd5b866020828501011115612df6575f80fd5b60209290920196919550909350505050565b600181811c90821680612e1c57607f821691505b6020821081036128ba57634e487b7160e01b5f52602260045260245ffd5b6020810161183982846129b8565b5f82601f830112612e57575f80fd5b8151612e65612bac82612b69565b818152846020838601011115612e79575f80fd5b612e8a8260208301602087016129d8565b949350505050565b5f60208284031215612ea2575f80fd5b81516001600160401b03811115612eb7575f80fd5b612e8a84828501612e48565b602081525f61298460208301846129fa565b5f60208284031215612ee5575f80fd5b5051919050565b5f808335601e19843603018112612f01575f80fd5b8301803591506001600160401b03821115612f1a575f80fd5b6020019150600581901b3603821315610c70575f80fd5b634e487b7160e01b5f52603260045260245ffd5b5f8235605e19833603018112612f59575f80fd5b9190910192915050565b5f60608236031215612f73575f80fd5b612f7b612b17565b82356001600160401b0380821115612f91575f80fd5b612f9d36838701612b8f565b83526020850135915080821115612fb2575f80fd5b50612fbf36828601612b8f565b6020830152506040830135612fd38161291d565b604082015292915050565b5f8251612f598184602087016129d8565b601f82111561149357805f5260205f20601f840160051c810160208510156130145750805b601f840160051c820191505b81811015613033575f8155600101613020565b5050505050565b81516001600160401b0381111561305357613053612adb565b613067816130618454612e08565b84612fef565b602080601f83116001811461309a575f84156130835750858301515b5f19600386901b1c1916600185901b178555610d8e565b5f85815260208120601f198616915b828110156130c8578886015182559484019460019091019084016130a9565b50858210156130e557878501515f19600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b5f52601160045260245ffd5b6001600160401b03818116838216019080821115611972576119726130f5565b5f63ffffffff808316818103613141576131416130f5565b6001019392505050565b6001600160401b0381811683821602808216919082811461316e5761316e6130f5565b505092915050565b5f808335601e1984360301811261318b575f80fd5b83016020810192503590506001600160401b038111156131a9575f80fd5b803603821315610c70575f80fd5b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b5f8383855260208086019550808560051b830101845f5b8781101561329457848303601f19018952813536889003605e1901811261321b575f80fd5b870160606132298280613176565b82875261323983880182846131b7565b9250505061324986830183613176565b8683038888015261325b8382846131b7565b9250505060408083013592506132708361291d565b6001600160401b0392909216949091019390935297830197908301906001016131f6565b5090979650505050505050565b6020815281356020820152602082013560408201525f60408301356132c581612be1565b6001600160a01b031660608381019190915283013536849003601e190181126132ec575f80fd5b83016020810190356001600160401b03811115613307575f80fd5b8060051b3603821315613318575f80fd5b60808085015261332c60a0850182846131df565b95945050505050565b80518015158114611145575f80fd5b5f8060408385031215613355575f80fd5b8251915061291460208401613335565b5f60208083525f845461337781612e08565b806020870152604060018084165f811461339857600181146133b4576133e1565b60ff19851660408a0152604084151560051b8a010195506133e1565b895f5260205f205f5b858110156133d85781548b82018601529083019088016133bd565b8a016040019650505b509398975050505050505050565b5f805f60608486031215613401575f80fd5b8351925060208401516134138161291d565b60408501519092506134248161291d565b809150509250925092565b818382375f9101908152919050565b5f806040838503121561344f575f80fd5b82516001600160401b0380821115613465575f80fd5b9084019060608287031215613478575f80fd5b613480612b17565b82518152602083015161349281612be1565b60208201526040830151828111156134a8575f80fd5b6134b488828601612e48565b604083015250935061291491505060208401613335565b80820180821115611839576118396130f5565b5f6040830163ffffffff8351168452602080840151604060208701528281518085526060880191506020830194505f92505b808310156135395784516001600160a01b03168252938301936001929092019190830190613510565b509695505050505050565b60208152815160208201525f602083015160e0604084015261356a6101008401826129fa565b90506040840151601f198085840301606086015261358883836129fa565b92506001600160401b03606087015116608086015260808601519150808584030160a08601526135b883836134de565b925060a08601519150808584030160c0860152506135d682826134de565b91505060c08401516135f360e08501826001600160401b03169052565b509392505050565b5f806040838503121561360c575f80fd5b8251915060208301516001600160401b03811115613628575f80fd5b61363485828601612e48565b9150509250929050565b6001600160401b03828116828216039080821115611972576119726130f5565b5f6001600160401b03808316818103613141576131416130f5565b5f60208284031215613689575f80fd5b813560ff81168114612984575f80fd5b5f602082840312156136a9575f80fd5b81356129848161291d565b81810381811115611839576118396130f556fea164736f6c6343000819000a", "balance": "0x0", "nonce": "0x1" }, @@ -53,12 +50,17 @@ "balance": "0x0", "nonce": "0x1" }, - "32aaa04b1c166d02b0ee152dd221367687f72108": { - "balance": "0x2086ac351052600000" - }, "48a90c916ad48a72f49fa72a9f889c1ba9cc9b4b": { "balance": "0x8ac7230489e80000" }, + "8db97c7cece249c2b98bdc0226cc4c2a57bf52fc": { + "balance": "0xd3c21bcecceda1000000" + }, + "9c00629ce712b0255b17a4a657171acd15720b8c": { + "code": "0x73000000000000000000000000000000000000000030146080604052600436106100b1575f3560e01c8063854a893f11610079578063854a893f146101b257806387418b8e1461020f5780639b83546514610222578063a699c13514610242578063e1d68f3014610255578063eb97ce5114610268575f80fd5b8063021de88f146100b5578063088c2463146100e25780634d8478841461011257806350782b0f146101335780637f7c427a1461016b575b5f80fd5b6100c86100c33660046118a9565b610289565b604080519283529015156020830152015b60405180910390f35b6100f56100f03660046118a9565b61044a565b604080519283526001600160401b039091166020830152016100d9565b6101256101203660046118a9565b61063b565b6040519081526020016100d9565b6101466101413660046118a9565b6107c8565b604080519384526001600160401b0392831660208501529116908201526060016100d9565b6101a56101793660046118e2565b604080515f60208201819052602282015260268082019390935281518082039093018352604601905290565b6040516100d99190611946565b6101a56101c036600461197a565b604080515f6020820152600360e01b602282015260268101949094526001600160c01b031960c093841b811660468601529190921b16604e830152805180830360360181526056909201905290565b6101a561021d3660046119eb565b610a1e565b6102356102303660046118a9565b610b60565b6040516100d99190611bb4565b6101a5610250366004611c6b565b6114ab565b6101a5610263366004611c9d565b6114ef565b61027b610276366004611d80565b611525565b6040516100d9929190611e7c565b5f8082516027146102c457825160405163cc92daa160e01b815263ffffffff9091166004820152602760248201526044015b60405180910390fd5b5f805b6002811015610313576102db816001611ea8565b6102e6906008611ebb565b61ffff168582815181106102fc576102fc611ed2565b016020015160f81c901b91909117906001016102c7565b5061ffff81161561033d5760405163407b587360e01b815261ffff821660048201526024016102bb565b5f805b600481101561039857610354816003611ea8565b61035f906008611ebb565b63ffffffff1686610371836002611ee6565b8151811061038157610381611ed2565b016020015160f81c901b9190911790600101610340565b5063ffffffff81166002146103c057604051635b60892f60e01b815260040160405180910390fd5b5f805b6020811015610415576103d781601f611ea8565b6103e2906008611ebb565b876103ee836006611ee6565b815181106103fe576103fe611ed2565b016020015160f81c901b91909117906001016103c3565b505f8660268151811061042a5761042a611ed2565b016020015191976001600160f81b03199092161515965090945050505050565b5f808251602e1461048057825160405163cc92daa160e01b815263ffffffff9091166004820152602e60248201526044016102bb565b5f805b60028110156104cf57610497816001611ea8565b6104a2906008611ebb565b61ffff168582815181106104b8576104b8611ed2565b016020015160f81c901b9190911790600101610483565b5061ffff8116156104f95760405163407b587360e01b815261ffff821660048201526024016102bb565b5f805b600481101561055457610510816003611ea8565b61051b906008611ebb565b63ffffffff168661052d836002611ee6565b8151811061053d5761053d611ed2565b016020015160f81c901b91909117906001016104fc565b5063ffffffff81161561057a57604051635b60892f60e01b815260040160405180910390fd5b5f805b60208110156105cf5761059181601f611ea8565b61059c906008611ebb565b876105a8836006611ee6565b815181106105b8576105b8611ed2565b016020015160f81c901b919091179060010161057d565b505f805b600881101561062e576105e7816007611ea8565b6105f2906008611ebb565b6001600160401b031688610607836026611ee6565b8151811061061757610617611ed2565b016020015160f81c901b91909117906001016105d3565b5090969095509350505050565b5f815160261461067057815160405163cc92daa160e01b815263ffffffff9091166004820152602660248201526044016102bb565b5f805b60028110156106bf57610687816001611ea8565b610692906008611ebb565b61ffff168482815181106106a8576106a8611ed2565b016020015160f81c901b9190911790600101610673565b5061ffff8116156106e95760405163407b587360e01b815261ffff821660048201526024016102bb565b5f805b600481101561074457610700816003611ea8565b61070b906008611ebb565b63ffffffff168561071d836002611ee6565b8151811061072d5761072d611ed2565b016020015160f81c901b91909117906001016106ec565b5063ffffffff81161561076a57604051635b60892f60e01b815260040160405180910390fd5b5f805b60208110156107bf5761078181601f611ea8565b61078c906008611ebb565b86610798836006611ee6565b815181106107a8576107a8611ed2565b016020015160f81c901b919091179060010161076d565b50949350505050565b5f805f83516036146107ff57835160405163cc92daa160e01b815263ffffffff9091166004820152603660248201526044016102bb565b5f805b600281101561084e57610816816001611ea8565b610821906008611ebb565b61ffff1686828151811061083757610837611ed2565b016020015160f81c901b9190911790600101610802565b5061ffff8116156108785760405163407b587360e01b815261ffff821660048201526024016102bb565b5f805b60048110156108d35761088f816003611ea8565b61089a906008611ebb565b63ffffffff16876108ac836002611ee6565b815181106108bc576108bc611ed2565b016020015160f81c901b919091179060010161087b565b5063ffffffff81166003146108fb57604051635b60892f60e01b815260040160405180910390fd5b5f805b60208110156109505761091281601f611ea8565b61091d906008611ebb565b88610929836006611ee6565b8151811061093957610939611ed2565b016020015160f81c901b91909117906001016108fe565b505f805b60088110156109af57610968816007611ea8565b610973906008611ebb565b6001600160401b031689610988836026611ee6565b8151811061099857610998611ed2565b016020015160f81c901b9190911790600101610954565b505f805b6008811015610a0e576109c7816007611ea8565b6109d2906008611ebb565b6001600160401b03168a6109e783602e611ee6565b815181106109f7576109f7611ed2565b016020015160f81c901b91909117906001016109b3565b5091989097509095509350505050565b80516020808301516040808501516060868101515192515f95810186905260228101969096526042860193909352600560e21b60628601526bffffffffffffffffffffffff1990831b16606685015260e01b6001600160e01b031916607a84015291607e0160405160208183030381529060405290505f5b836060015151811015610b59578184606001518281518110610aba57610aba611ed2565b60200260200101515f01515185606001518381518110610adc57610adc611ed2565b60200260200101515f015186606001518481518110610afd57610afd611ed2565b60200260200101516020015187606001518581518110610b1f57610b1f611ed2565b602002602001015160400151604051602001610b3f959493929190611ef9565b60408051601f198184030181529190529150600101610a96565b5092915050565b610b68611712565b5f610b71611712565b5f805b6002811015610bcf57610b88816001611ea8565b610b93906008611ebb565b61ffff1686610ba863ffffffff871684611ee6565b81518110610bb857610bb8611ed2565b016020015160f81c901b9190911790600101610b74565b5061ffff811615610bf95760405163407b587360e01b815261ffff821660048201526024016102bb565b610c04600284611f72565b9250505f805b6004811015610c6957610c1e816003611ea8565b610c29906008611ebb565b63ffffffff16868563ffffffff1683610c429190611ee6565b81518110610c5257610c52611ed2565b016020015160f81c901b9190911790600101610c0a565b5063ffffffff8116600114610c9157604051635b60892f60e01b815260040160405180910390fd5b610c9c600484611f72565b9250505f805b6020811015610cf957610cb681601f611ea8565b610cc1906008611ebb565b86610cd263ffffffff871684611ee6565b81518110610ce257610ce2611ed2565b016020015160f81c901b9190911790600101610ca2565b50808252610d08602084611f72565b9250505f805b6004811015610d6d57610d22816003611ea8565b610d2d906008611ebb565b63ffffffff16868563ffffffff1683610d469190611ee6565b81518110610d5657610d56611ed2565b016020015160f81c901b9190911790600101610d0e565b50610d79600484611f72565b92505f8163ffffffff166001600160401b03811115610d9a57610d9a61176c565b6040519080825280601f01601f191660200182016040528015610dc4576020820181803683370190505b5090505f5b8263ffffffff16811015610e335786610de863ffffffff871683611ee6565b81518110610df857610df8611ed2565b602001015160f81c60f81b828281518110610e1557610e15611ed2565b60200101906001600160f81b03191690815f1a905350600101610dc9565b5060208301819052610e458285611f72565b604080516030808252606082019092529195505f92506020820181803683370190505090505f5b6030811015610ed15786610e8663ffffffff871683611ee6565b81518110610e9657610e96611ed2565b602001015160f81c60f81b828281518110610eb357610eb3611ed2565b60200101906001600160f81b03191690815f1a905350600101610e6c565b5060408301819052610ee4603085611f72565b9350505f805b6008811015610f4a57610efe816007611ea8565b610f09906008611ebb565b6001600160401b031687610f2363ffffffff881684611ee6565b81518110610f3357610f33611ed2565b016020015160f81c901b9190911790600101610eea565b506001600160401b0381166060840152610f65600885611f72565b9350505f805f5b6004811015610fcb57610f80816003611ea8565b610f8b906008611ebb565b63ffffffff16888763ffffffff1683610fa49190611ee6565b81518110610fb457610fb4611ed2565b016020015160f81c901b9190911790600101610f6c565b50610fd7600486611f72565b94505f5b600481101561103a57610fef816003611ea8565b610ffa906008611ebb565b63ffffffff16888763ffffffff16836110139190611ee6565b8151811061102357611023611ed2565b016020015160f81c901b9290921791600101610fdb565b50611046600486611f72565b94505f8263ffffffff166001600160401b038111156110675761106761176c565b604051908082528060200260200182016040528015611090578160200160208202803683370190505b5090505f5b8363ffffffff16811015611178576040805160148082528183019092525f916020820181803683370190505090505f5b601481101561112a578a6110df63ffffffff8b1683611ee6565b815181106110ef576110ef611ed2565b602001015160f81c60f81b82828151811061110c5761110c611ed2565b60200101906001600160f81b03191690815f1a9053506001016110c5565b505f601482015190508084848151811061114657611146611ed2565b6001600160a01b039092166020928302919091019091015261116960148a611f72565b98505050806001019050611095565b506040805180820190915263ffffffff9092168252602082015260808401525f80805b60048110156111fa576111af816003611ea8565b6111ba906008611ebb565b63ffffffff16898863ffffffff16836111d39190611ee6565b815181106111e3576111e3611ed2565b016020015160f81c901b919091179060010161119b565b50611206600487611f72565b95505f5b60048110156112695761121e816003611ea8565b611229906008611ebb565b63ffffffff16898863ffffffff16836112429190611ee6565b8151811061125257611252611ed2565b016020015160f81c901b929092179160010161120a565b50611275600487611f72565b95505f8263ffffffff166001600160401b038111156112965761129661176c565b6040519080825280602002602001820160405280156112bf578160200160208202803683370190505b5090505f5b8363ffffffff168110156113a7576040805160148082528183019092525f916020820181803683370190505090505f5b6014811015611359578b61130e63ffffffff8c1683611ee6565b8151811061131e5761131e611ed2565b602001015160f81c60f81b82828151811061133b5761133b611ed2565b60200101906001600160f81b03191690815f1a9053506001016112f4565b505f601482015190508084848151811061137557611375611ed2565b6001600160a01b039092166020928302919091019091015261139860148b611f72565b995050508060010190506112c4565b506040805180820190915263ffffffff9092168252602082015260a08501525f6113d18284611f72565b6113dc906014611f8f565b6113e785607a611f72565b6113f19190611f72565b90508063ffffffff1688511461142d57875160405163cc92daa160e01b815263ffffffff918216600482015290821660248201526044016102bb565b5f805b600881101561149057611444816007611ea8565b61144f906008611ebb565b6001600160401b03168a61146963ffffffff8b1684611ee6565b8151811061147957611479611ed2565b016020015160f81c901b9190911790600101611430565b506001600160401b031660c086015250929695505050505050565b6040515f6020820152600160e11b60228201526026810183905281151560f81b60468201526060906047015b60405160208183030381529060405290505b92915050565b6040515f602082018190526022820152602681018390526001600160c01b031960c083901b166046820152606090604e016114d7565b5f606082604001515160301461154e5760405163180ffa0d60e01b815260040160405180910390fd5b82516020808501518051604080880151606089015160808a01518051908701515193515f9861158f988a986001989297929690959094909390929101611fb7565b60405160208183030381529060405290505f5b84608001516020015151811015611601578185608001516020015182815181106115ce576115ce611ed2565b60200260200101516040516020016115e7929190612071565b60408051601f1981840301815291905291506001016115a2565b5060a08401518051602091820151516040516116219385939291016120a7565b60405160208183030381529060405290505f5b8460a00151602001515181101561169357818560a0015160200151828151811061166057611660611ed2565b6020026020010151604051602001611679929190612071565b60408051601f198184030181529190529150600101611634565b5060c08401516040516116aa9183916020016120e2565b60405160208183030381529060405290506002816040516116cb9190612113565b602060405180830381855afa1580156116e6573d5f803e3d5ffd5b5050506040513d601f19601f82011682018060405250810190611709919061212e565b94909350915050565b6040805160e0810182525f808252606060208084018290528385018290528184018390528451808601865283815280820183905260808501528451808601909552918452908301529060a082019081525f60209091015290565b634e487b7160e01b5f52604160045260245ffd5b604051608081016001600160401b03811182821017156117a2576117a261176c565b60405290565b604051606081016001600160401b03811182821017156117a2576117a261176c565b604080519081016001600160401b03811182821017156117a2576117a261176c565b60405160e081016001600160401b03811182821017156117a2576117a261176c565b604051601f8201601f191681016001600160401b03811182821017156118365761183661176c565b604052919050565b5f82601f83011261184d575f80fd5b81356001600160401b038111156118665761186661176c565b611879601f8201601f191660200161180e565b81815284602083860101111561188d575f80fd5b816020850160208301375f918101602001919091529392505050565b5f602082840312156118b9575f80fd5b81356001600160401b038111156118ce575f80fd5b6118da8482850161183e565b949350505050565b5f602082840312156118f2575f80fd5b5035919050565b5f5b838110156119135781810151838201526020016118fb565b50505f910152565b5f81518084526119328160208601602086016118f9565b601f01601f19169290920160200192915050565b602081525f611958602083018461191b565b9392505050565b80356001600160401b0381168114611975575f80fd5b919050565b5f805f6060848603121561198c575f80fd5b8335925061199c6020850161195f565b91506119aa6040850161195f565b90509250925092565b80356001600160a01b0381168114611975575f80fd5b5f6001600160401b038211156119e1576119e161176c565b5060051b60200190565b5f60208083850312156119fc575f80fd5b82356001600160401b0380821115611a12575f80fd5b9084019060808287031215611a25575f80fd5b611a2d611780565b823581528383013584820152611a45604084016119b3565b604082015260608084013583811115611a5c575f80fd5b80850194505087601f850112611a70575f80fd5b8335611a83611a7e826119c9565b61180e565b81815260059190911b8501860190868101908a831115611aa1575f80fd5b8787015b83811015611b3a57803587811115611abb575f80fd5b8801808d03601f1901861315611acf575f80fd5b611ad76117a8565b8a82013589811115611ae7575f80fd5b611af58f8d8386010161183e565b825250604082013589811115611b09575f80fd5b611b178f8d8386010161183e565b8c83015250611b2787830161195f565b6040820152845250918801918801611aa5565b506060850152509198975050505050505050565b5f6040830163ffffffff8351168452602080840151604060208701528281518085526060880191506020830194505f92505b80831015611ba95784516001600160a01b03168252938301936001929092019190830190611b80565b509695505050505050565b60208152815160208201525f602083015160e06040840152611bda61010084018261191b565b90506040840151601f1980858403016060860152611bf8838361191b565b92506001600160401b03606087015116608086015260808601519150808584030160a0860152611c288383611b4e565b925060a08601519150808584030160c086015250611c468282611b4e565b91505060c0840151611c6360e08501826001600160401b03169052565b509392505050565b5f8060408385031215611c7c575f80fd5b8235915060208301358015158114611c92575f80fd5b809150509250929050565b5f8060408385031215611cae575f80fd5b82359150611cbe6020840161195f565b90509250929050565b5f60408284031215611cd7575f80fd5b611cdf6117ca565b9050813563ffffffff81168114611cf4575f80fd5b81526020828101356001600160401b03811115611d0f575f80fd5b8301601f81018513611d1f575f80fd5b8035611d2d611a7e826119c9565b81815260059190911b82018301908381019087831115611d4b575f80fd5b928401925b82841015611d7057611d61846119b3565b82529284019290840190611d50565b8085870152505050505092915050565b5f60208284031215611d90575f80fd5b81356001600160401b0380821115611da6575f80fd5b9083019060e08286031215611db9575f80fd5b611dc16117ec565b82358152602083013582811115611dd6575f80fd5b611de28782860161183e565b602083015250604083013582811115611df9575f80fd5b611e058782860161183e565b604083015250611e176060840161195f565b6060820152608083013582811115611e2d575f80fd5b611e3987828601611cc7565b60808301525060a083013582811115611e50575f80fd5b611e5c87828601611cc7565b60a083015250611e6e60c0840161195f565b60c082015295945050505050565b828152604060208201525f6118da604083018461191b565b634e487b7160e01b5f52601160045260245ffd5b818103818111156114e9576114e9611e94565b80820281158282048414176114e9576114e9611e94565b634e487b7160e01b5f52603260045260245ffd5b808201808211156114e9576114e9611e94565b5f8651611f0a818460208b016118f9565b60e087901b6001600160e01b0319169083019081528551611f32816004840160208a016118f9565b8551910190611f488160048401602089016118f9565b60c09490941b6001600160c01b031916600491909401908101939093525050600c01949350505050565b63ffffffff818116838216019080821115610b5957610b59611e94565b63ffffffff818116838216028082169190828114611faf57611faf611e94565b505092915050565b61ffff60f01b8a60f01b1681525f63ffffffff60e01b808b60e01b166002840152896006840152808960e01b166026840152508651611ffd81602a850160208b016118f9565b86519083019061201481602a840160208b016118f9565b60c087901b6001600160c01b031916602a9290910191820152612046603282018660e01b6001600160e01b0319169052565b61205f603682018560e01b6001600160e01b0319169052565b603a019b9a5050505050505050505050565b5f83516120828184602088016118f9565b60609390931b6bffffffffffffffffffffffff19169190920190815260140192915050565b5f84516120b88184602089016118f9565b6001600160e01b031960e095861b8116919093019081529290931b16600482015260080192915050565b5f83516120f38184602088016118f9565b60c09390931b6001600160c01b0319169190920190815260080192915050565b5f82516121248184602087016118f9565b9190910192915050565b5f6020828403121561213e575f80fd5b505191905056fea164736f6c6343000819000a", + "balance": "0x0", + "nonce": "0x1" + }, "c0ffee1234567890abcdef1234567890abcdef34": { "code": "0x60806040526004361061007b5760003560e01c80639623609d1161004e5780639623609d1461011157806399a88ec414610124578063f2fde38b14610144578063f3b7dead1461016457600080fd5b8063204e1c7a14610080578063715018a6146100bc5780637eff275e146100d35780638da5cb5b146100f3575b600080fd5b34801561008c57600080fd5b506100a061009b366004610499565b610184565b6040516001600160a01b03909116815260200160405180910390f35b3480156100c857600080fd5b506100d1610215565b005b3480156100df57600080fd5b506100d16100ee3660046104bd565b610229565b3480156100ff57600080fd5b506000546001600160a01b03166100a0565b6100d161011f36600461050c565b610291565b34801561013057600080fd5b506100d161013f3660046104bd565b610300565b34801561015057600080fd5b506100d161015f366004610499565b610336565b34801561017057600080fd5b506100a061017f366004610499565b6103b4565b6000806000836001600160a01b03166040516101aa90635c60da1b60e01b815260040190565b600060405180830381855afa9150503d80600081146101e5576040519150601f19603f3d011682016040523d82523d6000602084013e6101ea565b606091505b5091509150816101f957600080fd5b8080602001905181019061020d91906105e2565b949350505050565b61021d6103da565b6102276000610434565b565b6102316103da565b6040516308f2839760e41b81526001600160a01b038281166004830152831690638f283970906024015b600060405180830381600087803b15801561027557600080fd5b505af1158015610289573d6000803e3d6000fd5b505050505050565b6102996103da565b60405163278f794360e11b81526001600160a01b03841690634f1ef2869034906102c990869086906004016105ff565b6000604051808303818588803b1580156102e257600080fd5b505af11580156102f6573d6000803e3d6000fd5b5050505050505050565b6103086103da565b604051631b2ce7f360e11b81526001600160a01b038281166004830152831690633659cfe69060240161025b565b61033e6103da565b6001600160a01b0381166103a85760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b6103b181610434565b50565b6000806000836001600160a01b03166040516101aa906303e1469160e61b815260040190565b6000546001600160a01b031633146102275760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161039f565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b03811681146103b157600080fd5b6000602082840312156104ab57600080fd5b81356104b681610484565b9392505050565b600080604083850312156104d057600080fd5b82356104db81610484565b915060208301356104eb81610484565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b60008060006060848603121561052157600080fd5b833561052c81610484565b9250602084013561053c81610484565b9150604084013567ffffffffffffffff8082111561055957600080fd5b818601915086601f83011261056d57600080fd5b81358181111561057f5761057f6104f6565b604051601f8201601f19908116603f011681019083821181831017156105a7576105a76104f6565b816040528281528960208487010111156105c057600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b6000602082840312156105f457600080fd5b81516104b681610484565b60018060a01b03831681526000602060406020840152835180604085015260005b8181101561063c57858101830151858201606001528201610620565b506000606082860101526060601f19601f83011685010192505050939250505056fea264697066735822122019f39983a6fd15f3cffa764efd6fb0234ffe8d71051b3ebddc0b6bd99f87fa9764736f6c63430008190033", "storage": { @@ -66,6 +68,9 @@ }, "balance": "0x0", "nonce": "0x1" + }, + "f34408c05e3b339b1c89d15163d4b9d96845597a": { + "balance": "0x2086ac351052600000" } }, "airdropHash": "0x0000000000000000000000000000000000000000000000000000000000000000", diff --git a/tests/e2e/commands/etna.go b/tests/e2e/commands/etna.go index 13d3e570f..47ab8d9f2 100644 --- a/tests/e2e/commands/etna.go +++ b/tests/e2e/commands/etna.go @@ -31,7 +31,7 @@ func CreateEtnaSubnetEvmConfig( subnetName string, ewoqEVMAddress string, subnetManagementType SubnetManagementType, -) { +) (string, string) { // Check config does not already exist exists, err := utils.SubnetConfigExists(subnetName) gomega.Expect(err).Should(gomega.BeNil()) @@ -77,9 +77,16 @@ func CreateEtnaSubnetEvmConfig( exists, err = utils.SubnetConfigExists(subnetName) gomega.Expect(err).Should(gomega.BeNil()) gomega.Expect(exists).Should(gomega.BeTrue()) + + // return binary versions for this conf + mapper := utils.NewVersionMapper() + mapping, err := utils.GetVersionMapping(mapper) + gomega.Expect(err).Should(gomega.BeNil()) + return mapping[utils.LatestEVM2AvagoKey], mapping[utils.LatestAvago2EVMKey] } func CreateLocalEtnaNode( + avagoVersion string, clusterName string, numNodes int, ) (string, error) { @@ -92,6 +99,8 @@ func CreateLocalEtnaNode( "--local", "--num-nodes", fmt.Sprintf("%d", numNodes), + "--custom-avalanchego-version", + avagoVersion, "--"+constants.SkipUpdateFlag, ) fmt.Println(cmd) diff --git a/tests/e2e/testcases/subnet/sov/addRemoveValidatorPoA/suite.go b/tests/e2e/testcases/subnet/sov/addRemoveValidatorPoA/suite.go index e8b4a548d..64ea7c6b7 100644 --- a/tests/e2e/testcases/subnet/sov/addRemoveValidatorPoA/suite.go +++ b/tests/e2e/testcases/subnet/sov/addRemoveValidatorPoA/suite.go @@ -23,11 +23,12 @@ const ( var ( blockchainID string localClusterUris []string + avagoVersion string ) var _ = ginkgo.Describe("[Etna AddRemove Validator SOV PoA]", func() { ginkgo.It("Create Etna Subnet Config", func() { - commands.CreateEtnaSubnetEvmConfig( + _, avagoVersion = commands.CreateEtnaSubnetEvmConfig( utils.SubnetName, ewoqEVMAddress, commands.PoA, @@ -35,12 +36,13 @@ var _ = ginkgo.Describe("[Etna AddRemove Validator SOV PoA]", func() { }) ginkgo.It("Can create an Etna Local Network", func() { - output := commands.StartNetwork() + output := commands.StartNetworkWithVersion(avagoVersion) fmt.Println(output) }) ginkgo.It("Can create a local node connected to Etna Local Network", func() { output, err := commands.CreateLocalEtnaNode( + avagoVersion, utils.TestLocalNodeName, 7, ) diff --git a/tests/e2e/testcases/subnet/sov/addRemoveValidatorPoS/suite.go b/tests/e2e/testcases/subnet/sov/addRemoveValidatorPoS/suite.go index 792765d15..65bfe412a 100644 --- a/tests/e2e/testcases/subnet/sov/addRemoveValidatorPoS/suite.go +++ b/tests/e2e/testcases/subnet/sov/addRemoveValidatorPoS/suite.go @@ -25,11 +25,12 @@ const ( var ( blockchainID string localClusterUris []string + avagoVersion string ) var _ = ginkgo.Describe("[Etna AddRemove Validator SOV PoS]", func() { ginkgo.It("Create Etna Subnet Config", func() { - commands.CreateEtnaSubnetEvmConfig( + _, avagoVersion = commands.CreateEtnaSubnetEvmConfig( utils.SubnetName, ewoqEVMAddress, commands.PoS, @@ -37,12 +38,13 @@ var _ = ginkgo.Describe("[Etna AddRemove Validator SOV PoS]", func() { }) ginkgo.It("Can create an Etna Local Network", func() { - output := commands.StartNetwork() + output := commands.StartNetworkWithVersion(avagoVersion) fmt.Println(output) }) ginkgo.It("Can create a local node connected to Etna Local Network", func() { output, err := commands.CreateLocalEtnaNode( + avagoVersion, utils.TestLocalNodeName, 7, ) diff --git a/tests/e2e/testcases/subnet/sov/addValidatorLocal/suite.go b/tests/e2e/testcases/subnet/sov/addValidatorLocal/suite.go index 51fc4e43d..c690bed9f 100644 --- a/tests/e2e/testcases/subnet/sov/addValidatorLocal/suite.go +++ b/tests/e2e/testcases/subnet/sov/addValidatorLocal/suite.go @@ -19,16 +19,18 @@ const ( ewoqPChainAddress = "P-custom18jma8ppw3nhx5r4ap8clazz0dps7rv5u9xde7p" ) +var avagoVersion string + var _ = ginkgo.Describe("[Etna Add Validator SOV Local]", func() { ginkgo.It("Create Etna Subnet Config", func() { - commands.CreateEtnaSubnetEvmConfig( + _, avagoVersion = commands.CreateEtnaSubnetEvmConfig( utils.SubnetName, ewoqEVMAddress, commands.PoS, ) }) ginkgo.It("Can deploy blockchain to localhost and upsize it", func() { - output := commands.StartNetwork() + output := commands.StartNetworkWithVersion(avagoVersion) fmt.Println(output) output, err := commands.DeployEtnaBlockchain( utils.SubnetName, diff --git a/tests/e2e/testcases/subnet/sov/etna/suite.go b/tests/e2e/testcases/subnet/sov/etna/suite.go index 02f2c8bd6..ebfed3cea 100644 --- a/tests/e2e/testcases/subnet/sov/etna/suite.go +++ b/tests/e2e/testcases/subnet/sov/etna/suite.go @@ -22,7 +22,7 @@ const ( ewoqPChainAddress = "P-custom18jma8ppw3nhx5r4ap8clazz0dps7rv5u9xde7p" ) -func createEtnaSubnetEvmConfig(poa, pos bool) { +func createEtnaSubnetEvmConfig(poa, pos bool) string { // Check config does not already exist exists, err := utils.SubnetConfigExists(utils.SubnetName) gomega.Expect(err).Should(gomega.BeNil()) @@ -62,6 +62,12 @@ func createEtnaSubnetEvmConfig(poa, pos bool) { exists, err = utils.SubnetConfigExists(utils.SubnetName) gomega.Expect(err).Should(gomega.BeNil()) gomega.Expect(exists).Should(gomega.BeTrue()) + + // return binary versions for this conf + mapper := utils.NewVersionMapper() + mapping, err := utils.GetVersionMapping(mapper) + gomega.Expect(err).Should(gomega.BeNil()) + return mapping[utils.LatestAvago2EVMKey] } func createEtnaSubnetEvmConfigWithoutProxyOwner(poa, pos bool) { @@ -336,6 +342,8 @@ func initValidatorManagerEtnaFlag( return string(output), err } +var avagoVersion string + var _ = ginkgo.Describe("[Etna Subnet SOV]", func() { ginkgo.BeforeEach(func() { // key @@ -377,10 +385,10 @@ var _ = ginkgo.Describe("[Etna Subnet SOV]", func() { }) ginkgo.It("Start Local Node on Etna & Deploy the Subnet To Etna Local Network using cluster flag", func() { - _ = commands.StartNetwork() - _, err := commands.CreateLocalEtnaNode(utils.TestLocalNodeName, 1) + avagoVersion = createEtnaSubnetEvmConfig(true, false) + _ = commands.StartNetworkWithVersion(avagoVersion) + _, err := commands.CreateLocalEtnaNode(avagoVersion, utils.TestLocalNodeName, 1) gomega.Expect(err).Should(gomega.BeNil()) - createEtnaSubnetEvmConfig(true, false) deployEtnaSubnetClusterFlagConvertOnly(utils.TestLocalNodeName) _, err = commands.TrackLocalEtnaSubnet(utils.TestLocalNodeName, utils.SubnetName) gomega.Expect(err).Should(gomega.BeNil()) @@ -389,10 +397,10 @@ var _ = ginkgo.Describe("[Etna Subnet SOV]", func() { }) ginkgo.It("Mix and match network and cluster flags test 1", func() { - _ = commands.StartNetwork() - _, err := commands.CreateLocalEtnaNode(utils.TestLocalNodeName, 1) + avagoVersion = createEtnaSubnetEvmConfig(true, false) + _ = commands.StartNetworkWithVersion(avagoVersion) + _, err := commands.CreateLocalEtnaNode(avagoVersion, utils.TestLocalNodeName, 1) gomega.Expect(err).Should(gomega.BeNil()) - createEtnaSubnetEvmConfig(true, false) deployEtnaSubnetClusterFlagConvertOnly(utils.TestLocalNodeName) _, err = commands.TrackLocalEtnaSubnet(utils.TestLocalNodeName, utils.SubnetName) gomega.Expect(err).Should(gomega.BeNil()) diff --git a/tests/e2e/testcases/validatormanager/suite.go b/tests/e2e/testcases/validatormanager/suite.go index c0208e73c..3e875f078 100644 --- a/tests/e2e/testcases/validatormanager/suite.go +++ b/tests/e2e/testcases/validatormanager/suite.go @@ -215,7 +215,7 @@ var _ = ginkgo.Describe("[Validator Manager POA Set Up]", ginkgo.Ordered, func() ctx, cancel := utils.GetSignatureAggregatorContext() defer cancel() - err = subnetSDK.InitializeProofOfAuthority(ctx, network, k.PrivKeyHex(), extraAggregatorPeers, true, logging.NoLog{}, ProxyContractAddress) + err = subnetSDK.InitializeProofOfAuthority(ctx, network, k.PrivKeyHex(), extraAggregatorPeers, true, logging.NoLog{}, ProxyContractAddress, true) gomega.Expect(err).Should(gomega.BeNil()) }) })