Browse Source

abci/examples: switch from hex to base64 pubkey in kvstore (#3641)

* abci/example: use base64 for update validator set

* update kvstore/README.md

* update CHANGELOG_PENDING.md and abci/example/kvstore/README.md
pull/3743/head
needkane 5 years ago
committed by Anton Kaliaev
parent
commit
2e5b2a9537
3 changed files with 17 additions and 14 deletions
  1. +1
    -0
      CHANGELOG_PENDING.md
  2. +3
    -3
      abci/example/kvstore/README.md
  3. +13
    -11
      abci/example/kvstore/persistent_kvstore.go

+ 1
- 0
CHANGELOG_PENDING.md View File

@ -34,6 +34,7 @@
### IMPROVEMENTS: ### IMPROVEMENTS:
- [p2p] \#3666 Add per channel telemetry to improve reactor observability - [p2p] \#3666 Add per channel telemetry to improve reactor observability
- [rpc] [\#3686](https://github.com/tendermint/tendermint/pull/3686) `HTTPClient#Call` returns wrapped errors, so a caller could use `errors.Cause` to retrieve an error code. (@wooparadog) - [rpc] [\#3686](https://github.com/tendermint/tendermint/pull/3686) `HTTPClient#Call` returns wrapped errors, so a caller could use `errors.Cause` to retrieve an error code. (@wooparadog)
- [abci/examples] \#3659 Change validator update tx format (incl. expected pubkey format, which is base64 now) (@needkane)
### BUG FIXES: ### BUG FIXES:
- [libs/db] \#3717 Fixed the BoltDB backend's Batch.Delete implementation (@Yawning) - [libs/db] \#3717 Fixed the BoltDB backend's Batch.Delete implementation (@Yawning)


+ 3
- 3
abci/example/kvstore/README.md View File

@ -22,10 +22,10 @@ and the Handshake allows any necessary blocks to be replayed.
Validator set changes are effected using the following transaction format: Validator set changes are effected using the following transaction format:
``` ```
val:pubkey1/power1,addr2/power2,addr3/power3"
"val:pubkey1!power1,pubkey2!power2,pubkey3!power3"
``` ```
where `power1` is the new voting power for the validator with `pubkey1` (possibly a new one).
where `pubkeyN` is a base64-encoded 32-byte ed25519 key and `powerN` is a new voting power for the validator with `pubkeyN` (possibly a new one).
To remove a validator from the validator set, set power to `0`.
There is no sybil protection against new validators joining. There is no sybil protection against new validators joining.
Validators can be removed by setting their power to `0`.

+ 13
- 11
abci/example/kvstore/persistent_kvstore.go View File

@ -2,7 +2,7 @@ package kvstore
import ( import (
"bytes" "bytes"
"encoding/hex"
"encoding/base64"
"fmt" "fmt"
"strconv" "strconv"
"strings" "strings"
@ -60,10 +60,10 @@ func (app *PersistentKVStoreApplication) SetOption(req types.RequestSetOption) t
return app.app.SetOption(req) return app.app.SetOption(req)
} }
// tx is either "val:pubkey/power" or "key=value" or just arbitrary bytes
// tx is either "val:pubkey!power" or "key=value" or just arbitrary bytes
func (app *PersistentKVStoreApplication) DeliverTx(req types.RequestDeliverTx) types.ResponseDeliverTx { func (app *PersistentKVStoreApplication) DeliverTx(req types.RequestDeliverTx) types.ResponseDeliverTx {
// if it starts with "val:", update the validator set // if it starts with "val:", update the validator set
// format is "val:pubkey/power"
// format is "val:pubkey!power"
if isValidatorTx(req.Tx) { if isValidatorTx(req.Tx) {
// update validators in the merkle tree // update validators in the merkle tree
// and in app.ValUpdates // and in app.ValUpdates
@ -129,33 +129,34 @@ func (app *PersistentKVStoreApplication) Validators() (validators []types.Valida
} }
func MakeValSetChangeTx(pubkey types.PubKey, power int64) []byte { func MakeValSetChangeTx(pubkey types.PubKey, power int64) []byte {
return []byte(fmt.Sprintf("val:%X/%d", pubkey.Data, power))
pubStr := base64.StdEncoding.EncodeToString(pubkey.Data)
return []byte(fmt.Sprintf("val:%s!%d", pubStr, power))
} }
func isValidatorTx(tx []byte) bool { func isValidatorTx(tx []byte) bool {
return strings.HasPrefix(string(tx), ValidatorSetChangePrefix) return strings.HasPrefix(string(tx), ValidatorSetChangePrefix)
} }
// format is "val:pubkey/power"
// pubkey is raw 32-byte ed25519 key
// format is "val:pubkey!power"
// pubkey is a base64-encoded 32-byte ed25519 key
func (app *PersistentKVStoreApplication) execValidatorTx(tx []byte) types.ResponseDeliverTx { func (app *PersistentKVStoreApplication) execValidatorTx(tx []byte) types.ResponseDeliverTx {
tx = tx[len(ValidatorSetChangePrefix):] tx = tx[len(ValidatorSetChangePrefix):]
//get the pubkey and power //get the pubkey and power
pubKeyAndPower := strings.Split(string(tx), "/")
pubKeyAndPower := strings.Split(string(tx), "!")
if len(pubKeyAndPower) != 2 { if len(pubKeyAndPower) != 2 {
return types.ResponseDeliverTx{ return types.ResponseDeliverTx{
Code: code.CodeTypeEncodingError, Code: code.CodeTypeEncodingError,
Log: fmt.Sprintf("Expected 'pubkey/power'. Got %v", pubKeyAndPower)}
Log: fmt.Sprintf("Expected 'pubkey!power'. Got %v", pubKeyAndPower)}
} }
pubkeyS, powerS := pubKeyAndPower[0], pubKeyAndPower[1] pubkeyS, powerS := pubKeyAndPower[0], pubKeyAndPower[1]
// decode the pubkey // decode the pubkey
pubkey, err := hex.DecodeString(pubkeyS)
pubkey, err := base64.StdEncoding.DecodeString(pubkeyS)
if err != nil { if err != nil {
return types.ResponseDeliverTx{ return types.ResponseDeliverTx{
Code: code.CodeTypeEncodingError, Code: code.CodeTypeEncodingError,
Log: fmt.Sprintf("Pubkey (%s) is invalid hex", pubkeyS)}
Log: fmt.Sprintf("Pubkey (%s) is invalid base64", pubkeyS)}
} }
// decode the power // decode the power
@ -176,9 +177,10 @@ func (app *PersistentKVStoreApplication) updateValidator(v types.ValidatorUpdate
if v.Power == 0 { if v.Power == 0 {
// remove validator // remove validator
if !app.app.state.db.Has(key) { if !app.app.state.db.Has(key) {
pubStr := base64.StdEncoding.EncodeToString(v.PubKey.Data)
return types.ResponseDeliverTx{ return types.ResponseDeliverTx{
Code: code.CodeTypeUnauthorized, Code: code.CodeTypeUnauthorized,
Log: fmt.Sprintf("Cannot remove non-existent validator %X", key)}
Log: fmt.Sprintf("Cannot remove non-existent validator %s", pubStr)}
} }
app.app.state.db.Delete(key) app.app.state.db.Delete(key)
} else { } else {


Loading…
Cancel
Save