Skip to content

Commit 2446c1c

Browse files
committed
address comments
1 parent 5290d43 commit 2446c1c

24 files changed

+507
-1038
lines changed

app/cmd/cli/node.go

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,8 +118,10 @@ Will prompt the user for the <fromAddr> account passphrase.`,
118118
},
119119
}
120120

121+
// stakeNewCmd is an upgraded version of `nodesCmd` that captures newer
122+
// on-chain functionality in a cleaner way
121123
var stakeNewCmd = &cobra.Command{
122-
Use: `stakeNew <OperatorPublicKey> <OutputAddress> <SignerAddress> <Stake> <ChainIDs> <ServiceURL> <Delegators> <NetworkID> <Fee> [Memo]`,
124+
Use: "stakeNew <OperatorPublicKey> <OutputAddress> <SignerAddress> <Stake> <ChainIDs> <ServiceURL> <Delegators> <NetworkID> <Fee> [Memo]",
123125
Short: "Stake a node in the network",
124126
Long: `Stake a node in the network, promoting it to a servicer or a validator.
125127
@@ -134,7 +136,20 @@ The command takes the following parameters.
134136
Delegators Delegator addresses to share rewards
135137
NetworkID Network ID to submit a transaction to e.g. mainnet or testnet
136138
Fee Transaction fee in uPOKT
137-
Memo Text to include in the transaction. No functional effect.
139+
Memo Optional. Text to include in the transaction. No functional effect.
140+
141+
Example:
142+
$ pocket nodes stakeNew \
143+
e237efc54a93ed61689959e9afa0d4bd49fa11c0b946c35e6bebaccb052ce3fc \
144+
fe818527cd743866c1db6bdeb18731d04891df78 \
145+
1164b9c95638fc201f35eca2af4c35fe0a81b6cf \
146+
8000000000000 \
147+
DEAD,BEEF \
148+
https://x.com:443 \
149+
'{"1000000000000000000000000000000000000000":1,"2000000000000000000000000000000000000000":2}' \
150+
mainnet \
151+
10000 \
152+
"new stake with delegators!"
138153
`,
139154
Args: cobra.MinimumNArgs(9),
140155
Run: func(cmd *cobra.Command, args []string) {

app/cmd/rpc/rpc_test.go

Lines changed: 59 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@ package rpc
22

33
import (
44
"bytes"
5+
"encoding/base64"
56
"encoding/hex"
67
"encoding/json"
78
"fmt"
89
"io"
9-
"io/ioutil"
1010
"math/rand"
1111
"net/http"
1212
"net/http/httptest"
@@ -1471,7 +1471,7 @@ func newQueryRequest(query string, body io.Reader) *http.Request {
14711471
func getResponse(rec *httptest.ResponseRecorder) string {
14721472
res := rec.Result()
14731473
defer res.Body.Close()
1474-
b, err := ioutil.ReadAll(res.Body)
1474+
b, err := io.ReadAll(res.Body)
14751475
if err != nil {
14761476
fmt.Println("could not read response: " + err.Error())
14771477
return ""
@@ -1491,7 +1491,7 @@ func getResponse(rec *httptest.ResponseRecorder) string {
14911491
func getJSONResponse(rec *httptest.ResponseRecorder) []byte {
14921492
res := rec.Result()
14931493
defer res.Body.Close()
1494-
b, err := ioutil.ReadAll(res.Body)
1494+
b, err := io.ReadAll(res.Body)
14951495
if err != nil {
14961496
panic("could not read response: " + err.Error())
14971497
}
@@ -1635,8 +1635,52 @@ func NewValidChallengeProof(t *testing.T, privateKeys []crypto.PrivateKey) (chal
16351635
return proof
16361636
}
16371637

1638+
func generateTestTx() (string, error) {
1639+
app.Codec()
1640+
privKey, err := crypto.NewPrivateKey("5d86a93dee1ef5f950ccfaafd09d9c812f790c3b2c07945501f68b339118aca0e237efc54a93ed61689959e9afa0d4bd49fa11c0b946c35e6bebaccb052ce3fc")
1641+
if err != nil {
1642+
return "", err
1643+
}
1644+
outputAddr, err := types.AddressFromHex("fe818527cd743866c1db6bdeb18731d04891df78")
1645+
if err != nil {
1646+
return "", err
1647+
}
1648+
msg := &types2.MsgStake{
1649+
PublicKey: privKey.PublicKey(),
1650+
Chains: []string{"DEAD", "BEEF"},
1651+
Value: types.NewInt(8000000000000),
1652+
ServiceUrl: "https://x.com:443",
1653+
Output: outputAddr,
1654+
Delegators: map[string]uint32{
1655+
"1000000000000000000000000000000000000000": 1,
1656+
"2000000000000000000000000000000000000000": 2,
1657+
},
1658+
}
1659+
builder := authTypes.NewTxBuilder(
1660+
auth.DefaultTxEncoder(app.Codec()),
1661+
auth.DefaultTxDecoder(app.Codec()),
1662+
"mainnet",
1663+
"memo",
1664+
types.NewCoins(types.NewCoin(types.DefaultStakeDenom, types.NewInt(10000))),
1665+
)
1666+
entropy := int64(42)
1667+
txBytes, err := builder.BuildAndSignWithEntropyForTesting(privKey, msg, entropy)
1668+
if err != nil {
1669+
return "", err
1670+
}
1671+
return base64.StdEncoding.EncodeToString(txBytes), nil
1672+
}
1673+
1674+
// TestMsgStake_Marshaling_BackwardCompatibility verifies MsgStake
1675+
// has backward compatibility before/after the Delegators upgrade,
1676+
// meaning this test passes without the Delegators patch.
16381677
func TestMsgStake_Marshaling_BackwardCompatibility(t *testing.T) {
1639-
// Tx 3640B15041998FE800C2F61FC033CBF295D9282B5E7045A16F754ED9D8A54AFF in Mainnet
1678+
// StakeTxBeforeDelegatorsUpgrade is a transaction in Pocket Mainnet.
1679+
// You can get this with the following command.
1680+
//
1681+
// $ curl -s -X POST -H "Content-Type: application/json" \
1682+
// -d '{"hash":"3640B15041998FE800C2F61FC033CBF295D9282B5E7045A16F754ED9D8A54AFF"}' \
1683+
// <Pocket Mainnet Endpoint>/v1/query/tx | jq '.tx'
16401684
StakeTxBeforeDelegatorsUpgrade :=
16411685
"/wIK4QEKFy94Lm5vZGVzLk1zZ1Byb3RvU3Rha2U4EsUBCiBzfNC5BqUX6Aow9768" +
16421686
"QTKyYiRdhqrGqeqTIMVSckAe8RIEMDAwMxIEMDAwNBIEMDAwNRIEMDAwORIEMDAy" +
@@ -1647,16 +1691,19 @@ func TestMsgStake_Marshaling_BackwardCompatibility(t *testing.T) {
16471691
"w68+vl2z9nC+zYz3u4J7Oe3ntBOVP+cYHO5+lLuc8nH0OaG6pujXEPo19F5qW4Zh" +
16481692
"NBEgtChJp+QhYVgIIiBDdXN0b2RpYWwgdG8gTm9uLUN1c3RvZGlhbCBhZ2FpbijS" +
16491693
"CQ=="
1650-
1694+
// StakeTxBeforeDelegatorsUpgrade is a transaction with the Delegators field.
1695+
// You can generate this transaction by uncommenting the following two lines.
1696+
// StakeTxAfterDelegatorsUpgrade, err := generateTestTx()
1697+
// assert.Nil(t, err)
16511698
StakeTxAfterDelegatorsUpgrade :=
1652-
"5wIK3gEKFy94Lm5vZGVzLk1zZ1Byb3RvU3Rha2U4EsIBCiDiN+/FSpPtYWiZWemv" +
1653-
"oNS9SfoRwLlGw15r66zLBSzj/BIEMDAwMRIEQkVFRhoNODAwMDAwMDAwMDAwMCIR" +
1699+
"3wIK3gEKFy94Lm5vZGVzLk1zZ1Byb3RvU3Rha2U4EsIBCiDiN+/FSpPtYWiZWemv" +
1700+
"oNS9SfoRwLlGw15r66zLBSzj/BIEREVBRBIEQkVFRhoNODAwMDAwMDAwMDAwMCIR" +
16541701
"aHR0cHM6Ly94LmNvbTo0NDMqFP6BhSfNdDhmwdtr3rGHMdBIkd94MiwKKDIwMDAw" +
16551702
"MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAQAjIsCigxMDAwMDAw" +
16561703
"MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwEAESDgoFdXBva3QSBTEw" +
1657-
"MDAwGmQKICMRMWDdwHGZU6kMUecdxLF6UgHw0L1Vcc8lzz8Ynz0ZEkA+A9PANYsP" +
1658-
"+z7TduPuM7iM6jRILBJsdz0OMiGFrpGgJAsw7YrzXloJE4hyI921HoQ/bRFdw3/N" +
1659-
"Nea33C6VZqUGIgRtZW1vKKCQ7dyJ3LatFw=="
1704+
"MDAwGmQKIOI378VKk+1haJlZ6a+g1L1J+hHAuUbDXmvrrMsFLOP8EkDKz4AcELVB" +
1705+
"8Lyzi0+MVD/KXDIlTqjNLlBvFzOen7kZpR1it6gD79SLJXfWhB0qeu7Bux2VWQyf" +
1706+
"2wBBckGpIesBIgRtZW1vKCo="
16601707

16611708
originalNCUST := codec.UpgradeFeatureMap[codec.NonCustodialUpdateKey]
16621709
t.Cleanup(func() {
@@ -1670,13 +1717,15 @@ func TestMsgStake_Marshaling_BackwardCompatibility(t *testing.T) {
16701717
// Initialize app.cdc
16711718
app.Codec()
16721719

1720+
// Validate that an old stake messages DOES NOT have delegators
16731721
stdTx, err := app.UnmarshalTxStr(StakeTxBeforeDelegatorsUpgrade, heightForProto)
16741722
assert.Nil(t, err)
16751723
msgStake, ok := stdTx.Msg.(*types2.MsgStake)
16761724
assert.True(t, ok)
16771725
assert.Nil(t, msgStake.Delegators)
16781726
assert.Nil(t, msgStake.ValidateBasic())
16791727

1728+
// Validate that an old stake messages DOES have delegators
16801729
stdTx, err = app.UnmarshalTxStr(StakeTxAfterDelegatorsUpgrade, heightForProto)
16811730
assert.Nil(t, err)
16821731
msgStake, ok = stdTx.Msg.(*types2.MsgStake)

proto/x/nodes/msg.proto

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ message MsgProtoStake {
2323
(gogoproto.jsontag) = "output_address,omitempty",
2424
(gogoproto.moretags) = "yaml:\"output_address\""
2525
];
26+
// Mapping from delegated-to addresses to a percentage of rewards.
2627
map<string, uint32> Delegators = 6 [
2728
(gogoproto.jsontag) = "delegators,omitempty",
2829
(gogoproto.moretags) = "yaml:\"delegators\""

proto/x/nodes/nodes.proto

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -23,22 +23,6 @@ message ProtoValidator {
2323
map<string, uint32> Delegators = 10 [(gogoproto.jsontag) = "delegators,omitempty", (gogoproto.moretags) = "yaml:\"delegators\""];
2424
}
2525

26-
message ProtoValidatorV8 {
27-
option (gogoproto.equal) = true;
28-
option (gogoproto.goproto_stringer) = true;
29-
option (gogoproto.goproto_getters) = false;
30-
31-
bytes Address = 1 [(gogoproto.casttype) = "github.com/pokt-network/pocket-core/types.Address", (gogoproto.moretags) = "yaml:\"address\"", (gogoproto.jsontag) = "address"];
32-
bytes PublicKey = 2 [(gogoproto.moretags) = "yaml:\"public_key\"", (gogoproto.jsontag) = "public_key"];
33-
bool jailed = 3 [(gogoproto.jsontag) = "jailed"];
34-
int32 status = 4 [(gogoproto.jsontag) = "status"];
35-
repeated string Chains = 5 [(gogoproto.jsontag) = "chains"];
36-
string ServiceURL = 6 [(gogoproto.jsontag) = "service_url"];
37-
string StakedTokens = 7 [(gogoproto.customtype) = "github.com/pokt-network/pocket-core/types.BigInt", (gogoproto.jsontag) = "tokens", (gogoproto.nullable) = false];
38-
google.protobuf.Timestamp UnstakingCompletionTime = 8 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true, (gogoproto.jsontag) = "unstaking_time", (gogoproto.moretags) = "yaml:\"unstaking_time\""];
39-
bytes OutputAddress = 9 [(gogoproto.casttype) = "github.com/pokt-network/pocket-core/types.Address", (gogoproto.jsontag) = "output_address,omitempty", (gogoproto.moretags) = "yaml:\"output_address\""];
40-
}
41-
4226
message LegacyProtoValidator {
4327
option (gogoproto.equal) = true;
4428
option (gogoproto.goproto_stringer) = true;

types/config.go

Lines changed: 32 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -19,38 +19,38 @@ type SDKConfig struct {
1919
}
2020

2121
type PocketConfig struct {
22-
DataDir string `json:"data_dir"`
23-
GenesisName string `json:"genesis_file"`
24-
ChainsName string `json:"chains_name"`
25-
EvidenceDBName string `json:"evidence_db_name"`
26-
TendermintURI string `json:"tendermint_uri"`
27-
KeybaseName string `json:"keybase_name"`
28-
RPCPort string `json:"rpc_port"`
29-
ClientBlockSyncAllowance int `json:"client_block_sync_allowance"`
30-
ClientSessionSyncAllowance int64 `json:"client_session_sync_allowance"`
31-
MaxEvidenceCacheEntires int `json:"max_evidence_cache_entries"`
32-
MaxSessionCacheEntries int `json:"max_session_cache_entries"`
33-
JSONSortRelayResponses bool `json:"json_sort_relay_responses"`
34-
RemoteCLIURL string `json:"remote_cli_url"`
35-
UserAgent string `json:"user_agent"`
36-
ValidatorCacheSize int64 `json:"validator_cache_size"`
37-
ApplicationCacheSize int64 `json:"application_cache_size"`
38-
RPCTimeout int64 `json:"rpc_timeout"`
39-
PrometheusAddr string `json:"pocket_prometheus_port"`
40-
PrometheusMaxOpenfiles int `json:"prometheus_max_open_files"`
41-
MaxClaimAgeForProofRetry int `json:"max_claim_age_for_proof_retry"`
42-
ProofPrevalidation bool `json:"proof_prevalidation"`
43-
CtxCacheSize int `json:"ctx_cache_size"`
44-
ABCILogging bool `json:"abci_logging"`
45-
RelayErrors bool `json:"show_relay_errors"`
46-
DisableTxEvents bool `json:"disable_tx_events"`
47-
Cache bool `json:"-"`
48-
IavlCacheSize int64 `json:"iavl_cache_size"`
49-
ChainsHotReload bool `json:"chains_hot_reload"`
50-
GenerateTokenOnStart bool `json:"generate_token_on_start"`
51-
LeanPocket bool `json:"lean_pocket"`
52-
LeanPocketUserKeyFileName string `json:"lean_pocket_user_key_file"`
53-
NotClaimPossiblyNegativeRewards bool `json:"not_claim_possibly_negative_rewards"`
22+
DataDir string `json:"data_dir"`
23+
GenesisName string `json:"genesis_file"`
24+
ChainsName string `json:"chains_name"`
25+
EvidenceDBName string `json:"evidence_db_name"`
26+
TendermintURI string `json:"tendermint_uri"`
27+
KeybaseName string `json:"keybase_name"`
28+
RPCPort string `json:"rpc_port"`
29+
ClientBlockSyncAllowance int `json:"client_block_sync_allowance"`
30+
ClientSessionSyncAllowance int64 `json:"client_session_sync_allowance"`
31+
MaxEvidenceCacheEntires int `json:"max_evidence_cache_entries"`
32+
MaxSessionCacheEntries int `json:"max_session_cache_entries"`
33+
JSONSortRelayResponses bool `json:"json_sort_relay_responses"`
34+
RemoteCLIURL string `json:"remote_cli_url"`
35+
UserAgent string `json:"user_agent"`
36+
ValidatorCacheSize int64 `json:"validator_cache_size"`
37+
ApplicationCacheSize int64 `json:"application_cache_size"`
38+
RPCTimeout int64 `json:"rpc_timeout"`
39+
PrometheusAddr string `json:"pocket_prometheus_port"`
40+
PrometheusMaxOpenfiles int `json:"prometheus_max_open_files"`
41+
MaxClaimAgeForProofRetry int `json:"max_claim_age_for_proof_retry"`
42+
ProofPrevalidation bool `json:"proof_prevalidation"`
43+
CtxCacheSize int `json:"ctx_cache_size"`
44+
ABCILogging bool `json:"abci_logging"`
45+
RelayErrors bool `json:"show_relay_errors"`
46+
DisableTxEvents bool `json:"disable_tx_events"`
47+
Cache bool `json:"-"`
48+
IavlCacheSize int64 `json:"iavl_cache_size"`
49+
ChainsHotReload bool `json:"chains_hot_reload"`
50+
GenerateTokenOnStart bool `json:"generate_token_on_start"`
51+
LeanPocket bool `json:"lean_pocket"`
52+
LeanPocketUserKeyFileName string `json:"lean_pocket_user_key_file"`
53+
PreventNegativeRewardClaim bool `json:"prevent_negative_reward_claim"`
5454
}
5555

5656
func (c PocketConfig) GetLeanPocketUserKeyFilePath() string {

x/auth/types/txbuilder.go

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,12 @@ package types
33
import (
44
"errors"
55
"fmt"
6-
"github.com/tendermint/tendermint/libs/rand"
76
"strings"
87

98
"github.com/pokt-network/pocket-core/crypto"
10-
119
crkeys "github.com/pokt-network/pocket-core/crypto/keys"
1210
sdk "github.com/pokt-network/pocket-core/types"
11+
"github.com/tendermint/tendermint/libs/rand"
1312
)
1413

1514
// TxBuilder implements a transaction context created in SDK modules.
@@ -113,6 +112,32 @@ func (bldr TxBuilder) BuildAndSign(address sdk.Address, privateKey crypto.Privat
113112
return bldr.txEncoder(NewTx(msg, bldr.fees, sig, bldr.memo, entropy), -1)
114113
}
115114

115+
// BuildAndSignWithEntropyForTesting signs a given message with a given
116+
// private key and entropy.
117+
// This is for testing use only. Use BuildAndSign for production use.
118+
func (bldr TxBuilder) BuildAndSignWithEntropyForTesting(
119+
privateKey crypto.PrivateKey,
120+
msg sdk.ProtoMsg,
121+
entropy int64,
122+
) ([]byte, error) {
123+
if bldr.chainID == "" {
124+
return nil, errors.New("cant build and sign transaciton: the chainID is empty")
125+
}
126+
bytesToSign, err := StdSignBytes(bldr.chainID, entropy, bldr.fees, msg, bldr.memo)
127+
if err != nil {
128+
return nil, err
129+
}
130+
sigBytes, err := privateKey.Sign(bytesToSign)
131+
if err != nil {
132+
return nil, err
133+
}
134+
sig := StdSignature{
135+
Signature: sigBytes,
136+
PublicKey: privateKey.PublicKey(),
137+
}
138+
return bldr.txEncoder(NewTx(msg, bldr.fees, sig, bldr.memo, entropy), -1)
139+
}
140+
116141
// BuildAndSignWithKeyBase builds a single message to be signed, and signs a transaction
117142
// with the built message given a address, passphrase, and a set of messages.
118143
func (bldr TxBuilder) BuildAndSignWithKeyBase(address sdk.Address, passphrase string, msg sdk.ProtoMsg, legacyCodec bool) ([]byte, error) {

x/nodes/handler.go

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,13 +60,19 @@ func handleStake(ctx sdk.Ctx, msg types.MsgStake, k keeper.Keeper, signer crypto
6060
}
6161
}
6262

63-
if !k.Cdc.IsAfterDelegatorUpgrade(ctx.BlockHeight()) &&
64-
msg.Delegators != nil {
63+
if k.Cdc.IsAfterDelegatorUpgrade(ctx.BlockHeight()) {
64+
if err := msg.CheckDelegators(); err != nil {
65+
return err.Result()
66+
}
67+
} else if msg.Delegators != nil {
68+
// Ignore the delegators field before the upgrade
6569
msg.Delegators = nil
6670
}
6771

6872
validator := types.NewValidatorFromMsg(msg)
69-
// StakedTokens is set through StakeValidator. Resetting to 0 for now.
73+
// We used to use NewValidator here to initialize the `validator`, and
74+
// it does not set the field StakedTokens. To keep the same behavior,
75+
// we reset this field to 0. StakedTokens is set through StakeValidator.
7076
validator.StakedTokens = sdk.ZeroInt()
7177
// check if they can stake
7278
if err := k.ValidateValidatorStaking(ctx, validator, msg.Value, sdk.Address(signer.Address())); err != nil {

x/nodes/keeper/params.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ func (k Keeper) ServicerStakeFloorMultiplierExponent(ctx sdk.Ctx) (res sdk.BigDe
144144
return
145145
}
146146

147-
// Split rewards into node's cut and feeCollector's cut (= DAO + Proposer)
147+
// Split block rewards into the node's cut and the feeCollector's (DAO + Proposer) cut
148148
func (k Keeper) splitRewards(
149149
ctx sdk.Ctx,
150150
reward sdk.BigInt,
@@ -164,7 +164,7 @@ func (k Keeper) splitRewards(
164164
return
165165
}
166166

167-
// Split feeCollector's cut into DAO and Propower
167+
// Split feeCollector's cut into the DAO's cut and the Proposer's cut
168168
func (k Keeper) splitFeesCollected(
169169
ctx sdk.Ctx,
170170
feesCollected sdk.BigInt,
@@ -178,7 +178,7 @@ func (k Keeper) splitFeesCollected(
178178
// dao cut calculation truncates int ex: 1.99uPOKT = 1uPOKT
179179
daoCut = feesCollected.ToDec().Mul(daoAllocation).TruncateInt()
180180

181-
// proposer is whatever is left
181+
// proposer gets whatever is left after the DAO's truncated rewards are taken out
182182
proposerCut = feesCollected.Sub(daoCut)
183183
return
184184
}

0 commit comments

Comments
 (0)