package main import ( "bytes" "encoding/json" "fmt" "io/ioutil" "math/big" "net/http" "os" "path" "strconv" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/rlp" "github.com/harmony-one/bls/ffi/go/bls" "github.com/harmony-one/harmony/accounts" "github.com/harmony-one/harmony/accounts/keystore" common2 "github.com/harmony-one/harmony/internal/common" "github.com/harmony-one/harmony/numeric" "github.com/harmony-one/harmony/shard" staking "github.com/harmony-one/harmony/staking/types" "github.com/spf13/cobra" ) const ( keystoreDir = ".hmy/keystore" stakingRPC = "hmy_sendRawStakingTransaction" ) type staker struct{} var ( queryID = 0 s = &staker{} localNetChain = big.NewInt(2) dAddr, _ = common2.Bech32ToAddress(testAccount) ) const ( // Harmony protocol assume beacon chain shard is only place to send // staking, later need to consider logic when beacon chain shard rotates stakingShard = 0 testAccount = "one1a0x3d6xpmr6f8wsyaxd9v36pytvp48zckswvv9" testBLSPubKey = "b9486167ab9087ab818dc4ce026edb5bf216863364c32e42df2af03c5ced1ad181e7d12f0e6dd5307a73b62247608611" testAccountPassword = "" ) func (s *staker) run(cmd *cobra.Command, args []string) error { scryptN := keystore.StandardScryptN scryptP := keystore.StandardScryptP ks := keystore.NewKeyStore(keystoreDir, scryptN, scryptP) account := accounts.Account{Address: dAddr} ks.Unlock(account, testAccountPassword) gasPrice := big.NewInt(0) stakePayloadMaker := func() (staking.Directive, interface{}) { p := &bls.PublicKey{} p.DeserializeHexStr(testBLSPubKey) pub := shard.BlsPublicKey{} pub.FromLibBLSPublicKey(p) return staking.DirectiveCreateValidator, staking.CreateValidator{ Description: &staking.Description{ Name: "SuperHero", Identity: "YouWouldNotKnow", Website: "Secret Website", SecurityContact: "Mr.DoubleZeroSeven", Details: "blah blah blah", }, CommissionRates: staking.CommissionRates{ Rate: numeric.NewDec(100), MaxRate: numeric.NewDec(150), MaxChangeRate: numeric.NewDec(5), }, MinSelfDelegation: big.NewInt(10), MaxTotalDelegation: big.NewInt(3000), ValidatorAddress: common.Address(dAddr), SlotPubKeys: []shard.BlsPublicKey{pub}, Amount: big.NewInt(100), } // return staking.DirectiveDelegate, staking.Delegate{ // common.Address(dAddr), // common.Address(dAddr), // big.NewInt(10), // } } stakingTx, err := staking.NewStakingTransaction(2, 100, gasPrice, stakePayloadMaker) if err != nil { return err } signed, oops := ks.SignStakingTx(account, stakingTx, localNetChain) if oops != nil { return oops } enc, oops1 := rlp.EncodeToBytes(signed) if oops1 != nil { return oops1 } tx := new(staking.StakingTransaction) if err := rlp.DecodeBytes(enc, tx); err != nil { return err } payload, err := tx.RLPEncodeStakeMsg() restored, errRestor := staking.RLPDecodeStakeMsg( payload, staking.DirectiveCreateValidator, ) fmt.Printf("In Client side: %+v\n", restored) fmt.Println(errRestor) rlp.DecodeBytes(enc, tx) hexSignature := hexutil.Encode(enc) param := []interface{}{hexSignature} result, reqOops := baseRequest(stakingRPC, "http://localhost:9500", param) fmt.Println(string(result)) return reqOops } func versionS() string { return fmt.Sprintf( "Harmony (C) 2019. %v, version %v-%v (%v %v)", path.Base(os.Args[0]), version, commit, builtBy, builtAt, ) } func (s *staker) preRunInit(cmd *cobra.Command, args []string) error { // Just in case need to do some kind of setup that needs to propagate downward return nil } func baseRequest(method, node string, params interface{}) ([]byte, error) { requestBody, _ := json.Marshal(map[string]interface{}{ "jsonrpc": "2.0", "id": strconv.Itoa(queryID), "method": method, "params": params, }) resp, err := http.Post(node, "application/json", bytes.NewBuffer(requestBody)) fmt.Printf("URL: %s, Request Body: %s\n\n", node, string(requestBody)) if err != nil { return nil, err } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { return nil, err } queryID++ fmt.Printf("URL: %s, Response Body: %s\n\n", node, string(body)) return body, err } func init() { rootCmd.AddCommand(&cobra.Command{ Use: "staking-iterate", Short: "run through staking process", PersistentPreRunE: s.preRunInit, RunE: s.run, }) rootCmd.AddCommand(&cobra.Command{ Use: "version", Short: "Show version", Run: func(cmd *cobra.Command, args []string) { fmt.Fprintf(os.Stderr, versionS()+"\n") os.Exit(0) }, }) } var ( rootCmd = &cobra.Command{ Use: "staking-standalone", SilenceUsage: true, Long: "testing staking quickly", Run: func(cmd *cobra.Command, args []string) { cmd.Help() }, } )