package services import ( "bytes" "crypto/ecdsa" "encoding/json" "fmt" "math/big" "strings" "testing" common2 "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/harmony-one/harmony/crypto/bls" "github.com/harmony-one/harmony/internal/common" "github.com/harmony-one/harmony/numeric" "github.com/coinbase/rosetta-sdk-go/types" "github.com/ethereum/go-ethereum/crypto" hmytypes "github.com/harmony-one/harmony/core/types" stakingTypes "github.com/harmony-one/harmony/staking/types" "github.com/harmony-one/harmony/test/helpers" ) func TestUnpackWrappedTransactionFromString(t *testing.T) { refKey, err := crypto.GenerateKey() if err != nil { t.Fatal(err) } refAddr := crypto.PubkeyToAddress(refKey.PublicKey) refAddrID, rosettaError := newAccountIdentifier(refAddr) if rosettaError != nil { t.Fatal(rosettaError) } refEstGasUsed := big.NewInt(100000) signer := hmytypes.NewEIP155Signer(big.NewInt(0)) // Test plain transactions tx, err := helpers.CreateTestTransaction( signer, 0, 1, 2, refEstGasUsed.Uint64(), gasPrice, big.NewInt(1e10), []byte{0x01, 0x02}, ) if err != nil { t.Fatal(err) } buf := &bytes.Buffer{} if err := tx.EncodeRLP(buf); err != nil { t.Fatal(err) } wrappedTransaction := WrappedTransaction{ RLPBytes: buf.Bytes(), From: refAddrID, IsStaking: false, } marshalledBytes, err := json.Marshal(wrappedTransaction) if err != nil { t.Fatal(err) } testWrappedTx, testTx, rosettaError := unpackWrappedTransactionFromString(string(marshalledBytes), true) if rosettaError != nil { t.Fatal(rosettaError) } if types.Hash(tx) != types.Hash(testTx) { t.Error("unwrapped tx does not match reference tx") } if types.Hash(testWrappedTx) != types.Hash(wrappedTransaction) { t.Error("unwrapped tx struct does not matched reference tx struct") } // Test staking transactions receiverKey, err := crypto.GenerateKey() if err != nil { t.Fatalf(err.Error()) } stx, err := helpers.CreateTestStakingTransaction(func() (stakingTypes.Directive, interface{}) { return stakingTypes.DirectiveDelegate, stakingTypes.Delegate{ DelegatorAddress: refAddr, ValidatorAddress: crypto.PubkeyToAddress(receiverKey.PublicKey), Amount: tenOnes, } }, refKey, 10, refEstGasUsed.Uint64(), gasPrice) if err != nil { t.Fatal(err) } buf = &bytes.Buffer{} if err := stx.EncodeRLP(buf); err != nil { t.Fatal(err) } wrappedTransaction.RLPBytes = buf.Bytes() wrappedTransaction.IsStaking = true marshalledBytes, err = json.Marshal(wrappedTransaction) if err != nil { t.Fatal(err) } testWrappedTx, testStx, rosettaError := unpackWrappedTransactionFromString(string(marshalledBytes), true) if rosettaError != nil { t.Fatal(rosettaError) } if types.Hash(testStx) != types.Hash(stx) { t.Error("unwrapped tx does not match reference tx") } if types.Hash(testWrappedTx) != types.Hash(wrappedTransaction) { t.Error("unwrapped tx struct does not matched reference tx struct") } // Test invalid marshall marshalledBytesFail := marshalledBytes[:] marshalledBytesFail[0] = 0x0 _, _, rosettaError = unpackWrappedTransactionFromString(string(marshalledBytesFail), true) if rosettaError == nil { t.Fatal("expected error") } // test invalid RLP encoding for staking wrappedTransaction.RLPBytes = []byte{0x0} marshalledBytesFail, err = json.Marshal(wrappedTransaction) if err != nil { t.Fatal(err) } _, _, rosettaError = unpackWrappedTransactionFromString(string(marshalledBytesFail), true) if rosettaError == nil { t.Fatal("expected error") } // test invalid RLP encoding for plain wrappedTransaction.IsStaking = false marshalledBytesFail, err = json.Marshal(wrappedTransaction) if err != nil { t.Fatal(err) } _, _, rosettaError = unpackWrappedTransactionFromString(string(marshalledBytesFail), true) if rosettaError == nil { t.Fatal("expected error") } // test invalid nil RLP wrappedTransaction.RLPBytes = nil marshalledBytesFail, err = json.Marshal(wrappedTransaction) if err != nil { t.Fatal(err) } _, _, rosettaError = unpackWrappedTransactionFromString(string(marshalledBytesFail), true) if rosettaError == nil { t.Fatal("expected error") } // test invalid from address wrappedTransaction.RLPBytes = buf.Bytes() wrappedTransaction.From = nil marshalledBytesFail, err = json.Marshal(wrappedTransaction) if err != nil { t.Fatal(err) } _, _, rosettaError = unpackWrappedTransactionFromString(string(marshalledBytesFail), true) if rosettaError == nil { t.Fatal("expected error") } } func TestRecoverSenderAddressFromCreateValidatorString(t *testing.T) { key, err := crypto.HexToECDSA("4edef2c24995d15b0e25cbd152fb0e2c05d3b79b9c2afd134e6f59f91bf99e48") if err != nil { t.Fatal(err.Error()) } stakingTransaction, expectedPayload, err := stakingCreateValidatorTransaction(key) if err != nil { t.Fatal(err.Error()) } address, err := stakingTransaction.SenderAddress() if err != nil { t.Fatal(err.Error()) } if strings.ToLower(hexutil.Encode(address[:])) != "0xebcd16e8c1d8f493ba04e99a56474122d81a9c58" { t.Fatal("address error") } _, tx, rosettaError := unpackWrappedTransactionFromString("{\"rlp_bytes\":\"+QExgPkBIJQLWF+NrvvGijEfvUyyDZF0rRdAFvg4hUFsaWNlhWFsaWNlkWFsaWNlLmhhcm1vbnkub25lg0JvYpVEb24ndCBtZXNzIHdpdGggbWUhISHdyYgBY0V4XYoAAMmIDH1xO0naAADIh7GivC7FAACIiscjBInoAACJoqFdCVGb4AAA8bAwssOLExbakeBorDvYdRwJAe9sAqHVi8cSEEkYMCxu0D1YlGcdDIFtrStNMDMg8gL4YrhgaPgAtq32V7Z0kD4EcIBgkSuJO3x7UAeIgIJHVQqz4YblakTr88pIj47RpC9s7zoEvV0rK361p2eEjTE1s2LmaM5rukLHudVmbY46g75we1cI5yLFiTn+mwfBcPO3BiQUiQVrx14tYxAAAICEdzWUAIOhvkCAgIA=\",\"is_staking\":true,\"contract_code\":\"0x\",\"from\":{\"address\":\"one1a0x3d6xpmr6f8wsyaxd9v36pytvp48zckswvv9\",\"metadata\":{\"hex_address\":\"0xeBCD16e8c1D8f493bA04E99a56474122D81A9c58\"}}}", false) if rosettaError != nil { t.Fatal(rosettaError) } signer := stakingTypes.NewEIP155Signer(new(big.Int).SetUint64(1)) stakingTx, ok := tx.(*stakingTypes.StakingTransaction) if !ok { t.Fatal() } sig, err := hexutil.Decode("0x5ee37d4f19016a7ba6eef5dad74f0214ecfb73feda46dd263c3dd0ed54f9d4f60d78033196f148b2a005fe0c1af9afbb0e6f087075f1c9addb3ec8d7d2b6b16600") if err != nil { t.Fatal(err) } stakingTx, err = stakingTx.WithSignature(signer, sig) if err != nil { t.Fatal(err) } v, r, s := stakingTransaction.RawSignatureValues() v1, r1, s1 := stakingTx.RawSignatureValues() if v.String() != v1.String() || r.String() != r1.String() || s.String() != s1.String() { t.Log(stakingTransaction.RawSignatureValues()) t.Log(stakingTx.RawSignatureValues()) t.Fatal("signature error") } if expectedPayload != signer.Hash(stakingTx) { t.Error("payload error") } address, err = stakingTx.SenderAddress() if err != nil { t.Fatal(err.Error()) } if strings.ToLower(hexutil.Encode(address[:])) != "0xebcd16e8c1d8f493ba04e99a56474122d81a9c58" { t.Fatal("address error") } } func TestRecoverSenderAddressFromEditValidatorString(t *testing.T) { key, err := crypto.HexToECDSA("4edef2c24995d15b0e25cbd152fb0e2c05d3b79b9c2afd134e6f59f91bf99e48") if err != nil { t.Fatal(err.Error()) } stakingTransaction, expectedPayload, err := stakingEditValidatorTransaction(key) if err != nil { t.Fatal(err.Error()) } address, err := stakingTransaction.SenderAddress() if err != nil { t.Fatal(err.Error()) } if strings.ToLower(hexutil.Encode(address[:])) != "0xebcd16e8c1d8f493ba04e99a56474122d81a9c58" { t.Fatal("address error") } // todo to correct rlp bytes _, tx, rosettaError := unpackWrappedTransactionFromString("{\"rlp_bytes\":\"+QFBAfkBMZTrzRbowdj0k7oE6ZpWR0Ei2BqcWPg4hUFsaWNlhWFsaWNlkWFsaWNlLmhhcm1vbnkub25lg0JvYpVEb24ndCBtZXNzIHdpdGggbWUhISHJiAFjRXhdigAAiIrHIwSJ6AAAiaKhXQlRm+AAALAwssOLExbakeBorDvYdRwJAe9sAqHVi8cSEEkYMCxu0D1YlGcdDIFtrStNMDMg8gKwMLLDixMW2pHgaKw72HUcCQHvbAKh1YvHEhBJGDAsbtA9WJRnHQyBba0rTTAzIPICuGBo+AC2rfZXtnSQPgRwgGCRK4k7fHtQB4iAgkdVCrPhhuVqROvzykiPjtGkL2zvOgS9XSsrfrWnZ4SNMTWzYuZozmu6Qse51WZtjjqDvnB7VwjnIsWJOf6bB8Fw87cGJBSAgIR3NZQAgqQQgICA\",\"is_staking\":true,\"contract_code\":\"0x\",\"from\":{\"address\":\"one1a0x3d6xpmr6f8wsyaxd9v36pytvp48zckswvv9\",\"metadata\":{\"hex_address\":\"0xeBCD16e8c1D8f493bA04E99a56474122D81A9c58\"}}}", false) if rosettaError != nil { t.Fatal(rosettaError) } signer := stakingTypes.NewEIP155Signer(new(big.Int).SetUint64(1)) stakingTx, ok := tx.(*stakingTypes.StakingTransaction) if !ok { t.Fatal() } sig, err := hexutil.Decode("0xe7d6edf1fc99806533bb2c5c5ece5873ddbf391c58ab2b839afb0770d86d70df6ccb4727afa97b0f26bec18dbb6bf287ef93867b2129af2d2a9bcced735d79f400") if err != nil { t.Fatal(err) } stakingTx, err = stakingTx.WithSignature(signer, sig) if err != nil { t.Fatal(err) } v, r, s := stakingTransaction.RawSignatureValues() v1, r1, s1 := stakingTx.RawSignatureValues() if v.String() != v1.String() || r.String() != r1.String() || s.String() != s1.String() { t.Log(stakingTransaction.RawSignatureValues()) t.Log(stakingTx.RawSignatureValues()) t.Fatal("signature error") } if expectedPayload != signer.Hash(stakingTx) { t.Error("payload error") } address, err = stakingTx.SenderAddress() if err != nil { t.Fatal(err.Error()) } if strings.ToLower(hexutil.Encode(address[:])) != "0xebcd16e8c1d8f493ba04e99a56474122d81a9c58" { t.Fatal("address error") } } func TestRecoverSenderAddressFromDelegateString(t *testing.T) { key, err := crypto.HexToECDSA("4edef2c24995d15b0e25cbd152fb0e2c05d3b79b9c2afd134e6f59f91bf99e48") if err != nil { t.Fatal(err.Error()) } stakingTransaction, expectedPayload, err := stakingDelegateTransaction(key) if err != nil { t.Fatal(err.Error()) } address, err := stakingTransaction.SenderAddress() if err != nil { t.Fatal(err.Error()) } if strings.ToLower(hexutil.Encode(address[:])) != "0xebcd16e8c1d8f493ba04e99a56474122d81a9c58" { t.Fatal("address error") } _, tx, rosettaError := unpackWrappedTransactionFromString("{\"rlp_bytes\":\"+EEC85TrzRbowdj0k7oE6ZpWR0Ei2BqcWJTrzRbowdj0k7oE6ZpWR0Ei2BqcWIiKxyMEiegAAICEdzWUAIKkEICAgA==\",\"is_staking\":true,\"contract_code\":\"0x\",\"from\":{\"address\":\"one1a0x3d6xpmr6f8wsyaxd9v36pytvp48zckswvv9\",\"metadata\":{\"hex_address\":\"0xeBCD16e8c1D8f493bA04E99a56474122D81A9c58\"}}}", false) if rosettaError != nil { t.Fatal(rosettaError) } signer := stakingTypes.NewEIP155Signer(new(big.Int).SetUint64(1)) stakingTx, ok := tx.(*stakingTypes.StakingTransaction) if !ok { t.Fatal() } sig, err := hexutil.Decode("0xfcfdda6ac52e81c5a4f53628588cd7fb2b0da40fb42f26472329698522230ca759fd3ba51b4078cc2b2370253688f1cc7f16706e897bf9fee0c1e7369f22dbf500") if err != nil { t.Fatal(err) } stakingTx, err = stakingTx.WithSignature(signer, sig) if err != nil { t.Fatal(err) } v, r, s := stakingTransaction.RawSignatureValues() v1, r1, s1 := stakingTx.RawSignatureValues() if v.String() != v1.String() || r.String() != r1.String() || s.String() != s1.String() { t.Log(stakingTransaction.RawSignatureValues()) t.Log(stakingTx.RawSignatureValues()) t.Fatal("signature error") } if expectedPayload != signer.Hash(stakingTx) { t.Error("payload error") } address, err = stakingTx.SenderAddress() if err != nil { t.Fatal(err.Error()) } if strings.ToLower(hexutil.Encode(address[:])) != "0xebcd16e8c1d8f493ba04e99a56474122d81a9c58" { t.Fatal("address error") } } func TestRecoverSenderAddressFromUndelegateString(t *testing.T) { key, err := crypto.HexToECDSA("4edef2c24995d15b0e25cbd152fb0e2c05d3b79b9c2afd134e6f59f91bf99e48") if err != nil { t.Fatal(err.Error()) } stakingTransaction, expectedPayload, err := stakingUndelegateTransaction(key) if err != nil { t.Fatal(err.Error()) } address, err := stakingTransaction.SenderAddress() if err != nil { t.Fatal(err.Error()) } if strings.ToLower(hexutil.Encode(address[:])) != "0xebcd16e8c1d8f493ba04e99a56474122d81a9c58" { t.Fatal("address error") } _, tx, rosettaError := unpackWrappedTransactionFromString("{\"rlp_bytes\":\"+EED85TrzRbowdj0k7oE6ZpWR0Ei2BqcWJTrzRbowdj0k7oE6ZpWR0Ei2BqcWIiKxyMEiegAAICEdzWUAIJSCICAgA==\",\"is_staking\":true,\"contract_code\":\"0x\",\"from\":{\"address\":\"one1a0x3d6xpmr6f8wsyaxd9v36pytvp48zckswvv9\",\"metadata\":{\"hex_address\":\"0xeBCD16e8c1D8f493bA04E99a56474122D81A9c58\"}}}", false) if rosettaError != nil { t.Fatal(rosettaError) } signer := stakingTypes.NewEIP155Signer(new(big.Int).SetUint64(1)) stakingTx, ok := tx.(*stakingTypes.StakingTransaction) if !ok { t.Fatal() } sig, err := hexutil.Decode("0xb24e011d4013f0101a68ee0a6181e311fab6f65b768623f4ef8c6d5e429b507e3ce5dd52f3e85ae969854f7ac36a2ac74fe2d779ac9a9d8f38a64f683565980e00") if err != nil { t.Fatal(err) } stakingTx, err = stakingTx.WithSignature(signer, sig) if err != nil { t.Fatal(err) } v, r, s := stakingTransaction.RawSignatureValues() v1, r1, s1 := stakingTx.RawSignatureValues() if v.String() != v1.String() || r.String() != r1.String() || s.String() != s1.String() { t.Log(stakingTransaction.RawSignatureValues()) t.Log(stakingTx.RawSignatureValues()) t.Fatal("signature error") } if expectedPayload != signer.Hash(stakingTx) { t.Error("payload error") } address, err = stakingTx.SenderAddress() if err != nil { t.Fatal(err.Error()) } if strings.ToLower(hexutil.Encode(address[:])) != "0xebcd16e8c1d8f493ba04e99a56474122d81a9c58" { t.Fatal("address error") } } func TestRecoverSenderAddressFromCollectRewardsString(t *testing.T) { key, err := crypto.HexToECDSA("4edef2c24995d15b0e25cbd152fb0e2c05d3b79b9c2afd134e6f59f91bf99e48") if err != nil { t.Fatal(err.Error()) } stakingTransaction, expectedPayload, err := stakingCollectRewardsTransaction(key) if err != nil { t.Fatal(err.Error()) } address, err := stakingTransaction.SenderAddress() if err != nil { t.Fatal(err.Error()) } if strings.ToLower(hexutil.Encode(address[:])) != "0xebcd16e8c1d8f493ba04e99a56474122d81a9c58" { t.Fatal("address error") } _, tx, rosettaError := unpackWrappedTransactionFromString("{\"rlp_bytes\":\"4wTVlOvNFujB2PSTugTpmlZHQSLYGpxYgIR3NZQAglIIgICA\",\"is_staking\":true,\"contract_code\":\"0x\",\"from\":{\"address\":\"one13lx3exmpfc446vsguc5d0mtgha2ff7h5uz85pk\",\"metadata\":{\"hex_address\":\"0x8fCD1C9B614E2b5D3208E628d7eD68bF5494faF4\"}}}", false) if rosettaError != nil { a, _ := json.Marshal(rosettaError) fmt.Println(string(a)) t.Fatal(rosettaError) } signer := stakingTypes.NewEIP155Signer(new(big.Int).SetUint64(1)) stakingTx, ok := tx.(*stakingTypes.StakingTransaction) if !ok { t.Fatal() } sig, err := hexutil.Decode("0x13f25e40cf5cadf9ae68a318b216de52dc97ec423f581a36defccbdd31870cc26c66872f9f543246d0da7ee6b48d7e11e5034227795e80a5c1e95ac68a2a024500") if err != nil { t.Fatal(err) } stakingTx, err = stakingTx.WithSignature(signer, sig) if err != nil { t.Fatal(err) } v, r, s := stakingTransaction.RawSignatureValues() v1, r1, s1 := stakingTx.RawSignatureValues() if v.String() != v1.String() || r.String() != r1.String() || s.String() != s1.String() { t.Log(stakingTransaction.RawSignatureValues()) t.Log(stakingTx.RawSignatureValues()) t.Fatal("signature error") } if expectedPayload != signer.Hash(stakingTx) { t.Error("payload error") } address, err = stakingTx.SenderAddress() if err != nil { t.Fatal(err.Error()) } if strings.ToLower(hexutil.Encode(address[:])) != "0xebcd16e8c1d8f493ba04e99a56474122d81a9c58" { t.Fatal("address error") } } func stakingCreateValidatorTransaction(key *ecdsa.PrivateKey) (*stakingTypes.StakingTransaction, common2.Hash, error) { var pub bls.SerializedPublicKey pubb, err := hexutil.Decode("0x30b2c38b1316da91e068ac3bd8751c0901ef6c02a1d58bc712104918302c6ed03d5894671d0c816dad2b4d303320f202") if err != nil { return nil, common2.Hash{}, err } copy(pub[:], pubb) var sig bls.SerializedSignature sigg, err := hexutil.Decode("0x68f800b6adf657b674903e04708060912b893b7c7b500788808247550ab3e186e56a44ebf3ca488f8ed1a42f6cef3a04bd5d2b2b7eb5a767848d3135b362e668ce6bba42c7b9d5666d8e3a83be707b5708e722c58939fe9b07c170f3b7062414") if err != nil { return nil, common2.Hash{}, err } copy(sig[:], sigg) validator, _ := common.Bech32ToAddress("one1pdv9lrdwl0rg5vglh4xtyrv3wjk3wsqket7zxy") stakePayloadMaker := func() (stakingTypes.Directive, interface{}) { return stakingTypes.DirectiveCreateValidator, stakingTypes.CreateValidator{ Description: stakingTypes.Description{ Name: "Alice", Identity: "alice", Website: "alice.harmony.one", SecurityContact: "Bob", Details: "Don't mess with me!!!", }, CommissionRates: stakingTypes.CommissionRates{ Rate: numeric.Dec{new(big.Int).SetUint64(100000000000000000)}, MaxRate: numeric.Dec{new(big.Int).SetUint64(900000000000000000)}, MaxChangeRate: numeric.Dec{new(big.Int).SetUint64(50000000000000000)}, }, MinSelfDelegation: new(big.Int).Mul(new(big.Int).SetInt64(10), big.NewInt(1e18)), MaxTotalDelegation: new(big.Int).Mul(new(big.Int).SetInt64(3000), big.NewInt(1e18)), ValidatorAddress: validator, SlotPubKeys: []bls.SerializedPublicKey{pub}, SlotKeySigs: []bls.SerializedSignature{sig}, Amount: new(big.Int).Mul(new(big.Int).SetInt64(100), big.NewInt(1e18)), } } gasPrice := big.NewInt(2000000000) tx, _ := stakingTypes.NewStakingTransaction(0, 10600000, gasPrice, stakePayloadMaker) signer := stakingTypes.NewEIP155Signer(new(big.Int).SetUint64(1)) signingPayload := signer.Hash(tx) stakingTransaction, err := stakingTypes.Sign(tx, signer, key) if err != nil { return nil, common2.Hash{}, err } return stakingTransaction, signingPayload, nil } func stakingEditValidatorTransaction(key *ecdsa.PrivateKey) (*stakingTypes.StakingTransaction, common2.Hash, error) { stakePayloadMaker := func() (stakingTypes.Directive, interface{}) { var slotKeyToRemove bls.SerializedPublicKey removeBytes, _ := hexutil.Decode("0x30b2c38b1316da91e068ac3bd8751c0901ef6c02a1d58bc712104918302c6ed03d5894671d0c816dad2b4d303320f202") copy(slotKeyToRemove[:], removeBytes) var slotKeyToAdd bls.SerializedPublicKey addBytes, _ := hexutil.Decode("0x30b2c38b1316da91e068ac3bd8751c0901ef6c02a1d58bc712104918302c6ed03d5894671d0c816dad2b4d303320f202") copy(slotKeyToAdd[:], addBytes) var slotKeyToAddSig bls.SerializedSignature sigBytes, _ := hexutil.Decode("0x68f800b6adf657b674903e04708060912b893b7c7b500788808247550ab3e186e56a44ebf3ca488f8ed1a42f6cef3a04bd5d2b2b7eb5a767848d3135b362e668ce6bba42c7b9d5666d8e3a83be707b5708e722c58939fe9b07c170f3b7062414") copy(slotKeyToAddSig[:], sigBytes) validator, _ := common.Bech32ToAddress("one1a0x3d6xpmr6f8wsyaxd9v36pytvp48zckswvv9") return stakingTypes.DirectiveEditValidator, stakingTypes.EditValidator{ Description: stakingTypes.Description{ Name: "Alice", Identity: "alice", Website: "alice.harmony.one", SecurityContact: "Bob", Details: "Don't mess with me!!!", }, CommissionRate: &numeric.Dec{new(big.Int).SetUint64(100000000000000000)}, MinSelfDelegation: new(big.Int).Mul(new(big.Int).SetInt64(10), big.NewInt(1e18)), MaxTotalDelegation: new(big.Int).Mul(new(big.Int).SetInt64(3000), big.NewInt(1e18)), SlotKeyToRemove: &slotKeyToRemove, SlotKeyToAdd: &slotKeyToAdd, SlotKeyToAddSig: &slotKeyToAddSig, ValidatorAddress: validator, } } gasPrice := big.NewInt(2000000000) tx, _ := stakingTypes.NewStakingTransaction(0, 42000, gasPrice, stakePayloadMaker) signer := stakingTypes.NewEIP155Signer(new(big.Int).SetUint64(1)) signingPayload := signer.Hash(tx) stakingTransaction, err := stakingTypes.Sign(tx, signer, key) if err != nil { return nil, common2.Hash{}, err } return stakingTransaction, signingPayload, nil } func stakingDelegateTransaction(key *ecdsa.PrivateKey) (*stakingTypes.StakingTransaction, common2.Hash, error) { stakePayloadMaker := func() (stakingTypes.Directive, interface{}) { validator, _ := common.Bech32ToAddress("one1a0x3d6xpmr6f8wsyaxd9v36pytvp48zckswvv9") delegator, _ := common.Bech32ToAddress("one1a0x3d6xpmr6f8wsyaxd9v36pytvp48zckswvv9") return stakingTypes.DirectiveDelegate, stakingTypes.Delegate{ ValidatorAddress: validator, DelegatorAddress: delegator, Amount: new(big.Int).Mul(new(big.Int).SetInt64(10), big.NewInt(1e18)), } } gasPrice := big.NewInt(2000000000) tx, _ := stakingTypes.NewStakingTransaction(0, 42000, gasPrice, stakePayloadMaker) signer := stakingTypes.NewEIP155Signer(new(big.Int).SetUint64(1)) signingPayload := signer.Hash(tx) stakingTransaction, err := stakingTypes.Sign(tx, signer, key) if err != nil { return nil, common2.Hash{}, err } return stakingTransaction, signingPayload, nil } func stakingUndelegateTransaction(key *ecdsa.PrivateKey) (*stakingTypes.StakingTransaction, common2.Hash, error) { stakePayloadMaker := func() (stakingTypes.Directive, interface{}) { validator, _ := common.Bech32ToAddress("one1a0x3d6xpmr6f8wsyaxd9v36pytvp48zckswvv9") delegator, _ := common.Bech32ToAddress("one1a0x3d6xpmr6f8wsyaxd9v36pytvp48zckswvv9") return stakingTypes.DirectiveUndelegate, stakingTypes.Undelegate{ ValidatorAddress: validator, DelegatorAddress: delegator, Amount: new(big.Int).Mul(new(big.Int).SetInt64(10), big.NewInt(1e18)), } } gasPrice := big.NewInt(2000000000) tx, _ := stakingTypes.NewStakingTransaction(0, 21000, gasPrice, stakePayloadMaker) signer := stakingTypes.NewEIP155Signer(new(big.Int).SetUint64(1)) signingPayload := signer.Hash(tx) stakingTransaction, err := stakingTypes.Sign(tx, signer, key) if err != nil { return nil, common2.Hash{}, err } return stakingTransaction, signingPayload, nil } func stakingCollectRewardsTransaction(key *ecdsa.PrivateKey) (*stakingTypes.StakingTransaction, common2.Hash, error) { stakePayloadMaker := func() (stakingTypes.Directive, interface{}) { delegator, _ := common.Bech32ToAddress("one1a0x3d6xpmr6f8wsyaxd9v36pytvp48zckswvv9") return stakingTypes.DirectiveCollectRewards, stakingTypes.CollectRewards{ DelegatorAddress: delegator, } } gasPrice := big.NewInt(2000000000) tx, _ := stakingTypes.NewStakingTransaction(0, 21000, gasPrice, stakePayloadMaker) signer := stakingTypes.NewEIP155Signer(new(big.Int).SetUint64(1)) signingPayload := signer.Hash(tx) stakingTransaction, err := stakingTypes.Sign(tx, signer, key) if err != nil { return nil, common2.Hash{}, err } return stakingTransaction, signingPayload, nil }