-
Notifications
You must be signed in to change notification settings - Fork 0
/
deposit_stake.go
152 lines (133 loc) · 4.83 KB
/
deposit_stake.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
package tx
import (
"encoding/hex"
"fmt"
"math/big"
"strings"
"github.com/dnerochain/dnero/crypto"
"github.com/dnerochain/dnero/crypto/bls"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/dnerochain/dnero/cmd/dnerocli/cmd/utils"
"github.com/dnerochain/dnero/common"
"github.com/dnerochain/dnero/core"
"github.com/dnerochain/dnero/ledger/types"
"github.com/dnerochain/dnero/rpc"
rpcc "github.com/ybbus/jsonrpc"
)
// depositStakeCmd represents the deposit stake command
// Example:
// dnerocli tx deposit --chain="privatenet" --source=2E833968E5bB786Ae419c4d13189fB081Cc43bab --holder=2E833968E5bB786Ae419c4d13189fB081Cc43bab --stake=6000000 --purpose=0 --seq=7
var depositStakeCmd = &cobra.Command{
Use: "deposit",
Short: "Deposit stake to a validator or sentry",
Example: `dnerocli tx deposit --chain="privatenet" --source=2E833968E5bB786Ae419c4d13189fB081Cc43bab --holder=2E833968E5bB786Ae419c4d13189fB081Cc43bab --stake=6000000 --purpose=0 --seq=7`,
Run: doDepositStakeCmd,
}
func doDepositStakeCmd(cmd *cobra.Command, args []string) {
wallet, sourceAddress, err := walletUnlockWithPath(cmd, sourceFlag, pathFlag)
if err != nil {
return
}
defer wallet.Lock(sourceAddress)
fee, ok := types.ParseCoinAmount(feeFlag)
if !ok {
utils.Error("Failed to parse fee")
}
stake, ok := types.ParseCoinAmount(stakeInDneroFlag)
if !ok {
utils.Error("Failed to parse stake")
}
if stake.Cmp(core.Zero) < 0 {
utils.Error("Invalid input: stake must be positive\n")
}
source := types.TxInput{
Address: sourceAddress,
Coins: types.Coins{
DneroWei: stake,
DTokenWei: new(big.Int).SetUint64(0),
},
Sequence: uint64(seqFlag),
}
depositStakeTx := &types.DepositStakeTxV1{
Fee: types.Coins{
DneroWei: new(big.Int).SetUint64(0),
DTokenWei: fee,
},
Source: source,
Purpose: purposeFlag,
}
// Parse holder flag.
var holderAddress common.Address
if purposeFlag == core.StakeForValidator {
if len(holderFlag) != 40 && len(holderFlag) != 42 {
utils.Error("holder must be a valid address")
}
holderAddress = common.HexToAddress(holderFlag)
} else {
if strings.HasPrefix(holderFlag, "0x") {
holderFlag = holderFlag[2:]
}
if len(holderFlag) != 458 {
utils.Error("Holder must be a valid sentry address")
}
sentryKeyBytes, err := hex.DecodeString(holderFlag)
if err != nil {
utils.Error("Failed to decode sentry address: %v\n", err)
}
holderAddress = common.BytesToAddress(sentryKeyBytes[:20])
blsPubkey, err := bls.PublicKeyFromBytes(sentryKeyBytes[20:68])
if err != nil {
utils.Error("Failed to decode bls Pubkey: %v\n", err)
}
blsPop, err := bls.SignatureFromBytes(sentryKeyBytes[68:164])
if err != nil {
utils.Error("Failed to decode bls POP: %v\n", err)
}
holderSig, err := crypto.SignatureFromBytes(sentryKeyBytes[164:])
if err != nil {
utils.Error("Failed to decode signature: %v\n", err)
}
depositStakeTx.BlsPubkey = blsPubkey
depositStakeTx.BlsPop = blsPop
depositStakeTx.HolderSig = holderSig
}
depositStakeTx.Holder = types.TxOutput{
Address: holderAddress,
}
sig, err := wallet.Sign(sourceAddress, depositStakeTx.SignBytes(chainIDFlag))
if err != nil {
utils.Error("Failed to sign transaction: %v\n", err)
}
depositStakeTx.SetSignature(sourceAddress, sig)
raw, err := types.TxToBytes(depositStakeTx)
if err != nil {
utils.Error("Failed to encode transaction: %v\n", err)
}
signedTx := hex.EncodeToString(raw)
client := rpcc.NewRPCClient(viper.GetString(utils.CfgRemoteRPCEndpoint))
res, err := client.Call("dnero.BroadcastRawTransaction", rpc.BroadcastRawTransactionArgs{TxBytes: signedTx})
if err != nil {
utils.Error("Failed to broadcast transaction: %v\n", err)
}
if res.Error != nil {
utils.Error("Server returned error: %v\n", res.Error)
}
fmt.Printf("Successfully broadcasted transaction.\n")
}
func init() {
depositStakeCmd.Flags().StringVar(&chainIDFlag, "chain", "", "Chain ID")
depositStakeCmd.Flags().StringVar(&sourceFlag, "source", "", "Source of the stake")
depositStakeCmd.Flags().StringVar(&holderFlag, "holder", "", "Holder of the stake")
depositStakeCmd.Flags().StringVar(&pathFlag, "path", "", "Wallet derivation path")
depositStakeCmd.Flags().StringVar(&feeFlag, "fee", fmt.Sprintf("%dwei", types.MinimumTransactionFeeDTokenWeiJune2021), "Fee")
depositStakeCmd.Flags().Uint64Var(&seqFlag, "seq", 0, "Sequence number of the transaction")
depositStakeCmd.Flags().StringVar(&stakeInDneroFlag, "stake", "5000000", "Dnero amount to stake")
depositStakeCmd.Flags().Uint8Var(&purposeFlag, "purpose", 0, "Purpose of staking")
depositStakeCmd.Flags().StringVar(&walletFlag, "wallet", "soft", "Wallet type (soft|nano)")
depositStakeCmd.MarkFlagRequired("chain")
depositStakeCmd.MarkFlagRequired("source")
depositStakeCmd.MarkFlagRequired("holder")
depositStakeCmd.MarkFlagRequired("seq")
depositStakeCmd.MarkFlagRequired("stake")
}