Skip to content

Commit

Permalink
abci
Browse files Browse the repository at this point in the history
  • Loading branch information
tnasu committed Oct 13, 2021
1 parent d7c00ce commit 3e399f9
Show file tree
Hide file tree
Showing 5 changed files with 193 additions and 13 deletions.
81 changes: 76 additions & 5 deletions abci/cmd/abci-cli/abci-cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ package main

import (
"bufio"
"bytes"
"encoding/hex"
"errors"
"fmt"
"github.com/line/ostracon/config"
"io"
"os"
"strings"
Expand All @@ -22,6 +24,7 @@ import (
servertest "github.com/line/ostracon/abci/tests/server"
"github.com/line/ostracon/abci/types"
"github.com/line/ostracon/abci/version"
"github.com/line/ostracon/crypto/encoding"
"github.com/line/ostracon/proto/ostracon/crypto"
)

Expand Down Expand Up @@ -49,6 +52,9 @@ var (

// kvstore
flagPersist string

// staking power for make validator_tx
flagStakingPower int64
)

var RootCmd = &cobra.Command{
Expand Down Expand Up @@ -143,6 +149,10 @@ func addKVStoreFlags() {
kvstoreCmd.PersistentFlags().StringVarP(&flagPersist, "persist", "", "", "directory to use for a database")
}

func addPersistKVStoreMakeValSetChangeTxFlags() {
kvstoreCmd.PersistentFlags().Int64VarP(&flagStakingPower, "staking_power", "p", int64(10), "stakin power for ValSetChangeTx")
}

func addCommands() {
RootCmd.AddCommand(batchCmd)
RootCmd.AddCommand(consoleCmd)
Expand All @@ -162,6 +172,10 @@ func addCommands() {
RootCmd.AddCommand(counterCmd)
addKVStoreFlags()
RootCmd.AddCommand(kvstoreCmd)

// for examples of persist_kvstore
addPersistKVStoreMakeValSetChangeTxFlags()
RootCmd.AddCommand(persistKvstoreMakeValSetChangeTxCmd)
}

var batchCmd = &cobra.Command{
Expand Down Expand Up @@ -269,20 +283,28 @@ var queryCmd = &cobra.Command{

var counterCmd = &cobra.Command{
Use: "counter",
Short: "ABCI demo example",
Long: "ABCI demo example",
Short: "ABCI demo example - counter",
Long: "ABCI demo example - counter",
Args: cobra.ExactArgs(0),
RunE: cmdCounter,
}

var kvstoreCmd = &cobra.Command{
Use: "kvstore",
Short: "ABCI demo example",
Long: "ABCI demo example",
Short: "ABCI demo example - kvstore",
Long: "ABCI demo example - kvstore",
Args: cobra.ExactArgs(0),
RunE: cmdKVStore,
}

var persistKvstoreMakeValSetChangeTxCmd = &cobra.Command{
Use: "valset_change_tx",
Short: "persist_kvstore - make ValSetChangeTx",
Long: "persist_kvstore - make ValSetChangeTx",
Args: cobra.ExactArgs(0),
RunE: cmdPersistKVStoreMakeValSetChangeTx,
}

var testCmd = &cobra.Command{
Use: "test",
Short: "run integration tests",
Expand Down Expand Up @@ -685,6 +707,55 @@ func cmdKVStore(cmd *cobra.Command, args []string) error {
select {}
}

func cmdPersistKVStoreMakeValSetChangeTx(cmd *cobra.Command, args []string) error {
c := config.DefaultConfig()
c.SetRoot(os.Getenv("HOME") + "/" + config.DefaultOstraconDir)
keyFilePath := c.PrivValidatorKeyFile()
if !tmos.FileExists(keyFilePath) {
return fmt.Errorf("private validator file %s does not exist", keyFilePath)
}
keyFile, err := kvstore.LoadPrivValidatorKeyFile(keyFilePath)
if err != nil {
panic(err)
}
publicKey, err := encoding.PubKeyToProto(keyFile.PubKey)
if err != nil {
panic(err)
}
pubStr, tx := kvstore.MakeValSetChangeTxAndMore(publicKey, flagStakingPower)
{
fmt.Println(fmt.Sprintf("DeliverTxSync: data=%s, tx=%s", pubStr, tx))
res, err := client.DeliverTxSync(types.RequestDeliverTx{Tx: []byte(tx)})
if err != nil {
return err
}
printResponse(cmd, args, response{
Code: res.Code,
Data: res.Data,
Info: res.Info,
Log: res.Log,
})
}
{
fmt.Println(fmt.Sprintf("QuerySync: data=%s", pubStr))
res, err := client.QuerySync(types.RequestQuery{Path: "/val", Data: []byte(pubStr)})
if err != nil {
return err
}
printResponse(cmd, args, response{
Code: res.Code,
Info: res.Info,
Log: res.Log,
})
fmt.Println(fmt.Sprintf("original:publicKey:%s", publicKey))
validatorUpdate := types.ValidatorUpdate{}
validatorUpdate.Unmarshal(res.Value)
types.ReadMessage(bytes.NewReader(res.Value), &validatorUpdate)
fmt.Println(fmt.Sprintf("saved :publicKey:%s", validatorUpdate.PubKey))
}
return nil
}

//--------------------------------------------------------------------------------

func printResponse(cmd *cobra.Command, args []string, rsp response) {
Expand All @@ -702,7 +773,7 @@ func printResponse(cmd *cobra.Command, args []string, rsp response) {
}

if len(rsp.Data) != 0 {
// Do no print this line when using the commit command
// Do not print this line when using the commit command
// because the string comes out as gibberish
if cmd.Use != "commit" {
fmt.Printf("-> data: %s\n", rsp.Data)
Expand Down
24 changes: 23 additions & 1 deletion abci/example/kvstore/helpers.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,35 @@
package kvstore

import (
"fmt"
"github.com/line/ostracon/abci/types"
"github.com/line/ostracon/crypto"
"github.com/line/ostracon/crypto/composite"
tmjson "github.com/line/ostracon/libs/json"
tmos "github.com/line/ostracon/libs/os"
tmrand "github.com/line/ostracon/libs/rand"
"github.com/line/ostracon/privval"
"io/ioutil"
)

// Generates a default private key for use in an example or test.
// LoadPrivValidatorKeyFile Load private key for use in an example or test.
func LoadPrivValidatorKeyFile(keyFilePath string) (*privval.FilePVKey, error) {
if !tmos.FileExists(keyFilePath) {
return nil, fmt.Errorf("private validator file %s does not exist\n", keyFilePath)
}
keyJSONBytes, err := ioutil.ReadFile(keyFilePath)
if err != nil {
return nil, fmt.Errorf("private validator file %s does not read\n", keyFilePath)
}
pvKey := privval.FilePVKey{}
err = tmjson.Unmarshal(keyJSONBytes, &pvKey)
if err != nil {
return nil, fmt.Errorf("Error reading PrivValidator key from %v: %v\n", keyFilePath, err)
}
return &pvKey, nil
}

// GenDefaultPrivKey Generates a default private key for use in an example or test.
func GenDefaultPrivKey() crypto.PrivKey {
return composite.GenPrivKey()
}
Expand Down
30 changes: 23 additions & 7 deletions abci/example/kvstore/persistent_kvstore.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,15 @@ func (app *PersistentKVStoreApplication) Query(reqQuery types.RequestQuery) (res

resQuery.Key = reqQuery.Data
resQuery.Value = value
validatorUpdate := types.ValidatorUpdate{}
validatorUpdate.Unmarshal(resQuery.Value)
types.ReadMessage(bytes.NewReader(resQuery.Value), &validatorUpdate)
pubKey, err := cryptoenc.PubKeyFromProto(&validatorUpdate.PubKey)
if err != nil {
panic(err)
}
resQuery.Log = fmt.Sprintf("key=%s, validatorUpdate.PubKey=%v, validatorUpdate.Power=%d",
resQuery.Key, pubKey, validatorUpdate.Power)
return
default:
return app.app.Query(reqQuery)
Expand Down Expand Up @@ -206,20 +215,26 @@ func (app *PersistentKVStoreApplication) Validators() (validators []types.Valida
}

func MakeValSetChangeTx(pubkey pc.PublicKey, power int64) []byte {
_, tx:= MakeValSetChangeTxAndMore(pubkey, power)
return []byte(tx)
}

func MakeValSetChangeTxAndMore(pubkey pc.PublicKey, power int64) (string, string) {
pkBytes, err := pubkey.Marshal()
if err != nil {
panic(err)
}
pubStr := base64.StdEncoding.EncodeToString(pkBytes)
return []byte(fmt.Sprintf("val:%s!%d", pubStr, power))
return pubStr, fmt.Sprintf("val:%s!%d", pubStr, power)
}

func isValidatorTx(tx []byte) bool {
return strings.HasPrefix(string(tx), ValidatorSetChangePrefix)
}

// format is "val:pubkey!power"
// pubkey is a base64-encoded 32-byte ed25519 key
// pubkey is a base64-encoded crypto.PubKey.Bytes
// See MakeValSetChangeTx
func (app *PersistentKVStoreApplication) execValidatorTx(tx []byte) types.ResponseDeliverTx {
tx = tx[len(ValidatorSetChangePrefix):]

Expand All @@ -237,20 +252,20 @@ func (app *PersistentKVStoreApplication) execValidatorTx(tx []byte) types.Respon
if err != nil {
return types.ResponseDeliverTx{
Code: code.CodeTypeEncodingError,
Log: fmt.Sprintf("Pubkey (%s) is invalid base64", pubkeyS)}
Log: fmt.Sprintf("pubkeyS (%s) is invalid base64", pubkeyS)}
}
var pkProto pc.PublicKey
err = pkProto.Unmarshal(pkBytes)
if err != nil {
return types.ResponseDeliverTx{
Code: code.CodeTypeEncodingError,
Log: fmt.Sprintf("Pubkey (%s) is invalid binary", pubkeyS)}
Log: fmt.Sprintf("pkBytes (%x) is invalid binary", pkBytes)}
}
pubkey, err := cryptoenc.PubKeyFromProto(&pkProto)
if err != nil {
return types.ResponseDeliverTx{
Code: code.CodeTypeEncodingError,
Log: fmt.Sprintf("Pubkey (%s) is invalid binary", pubkeyS)}
Log: fmt.Sprintf("pkProto (%s) is invalid binary", pkProto)}
}

// decode the power
Expand All @@ -266,14 +281,16 @@ func (app *PersistentKVStoreApplication) execValidatorTx(tx []byte) types.Respon
}

// add, update, or remove a validator
// See MakeValSetChangeTx
func (app *PersistentKVStoreApplication) updateValidator(v types.ValidatorUpdate) types.ResponseDeliverTx {
pubkey, err := cryptoenc.PubKeyFromProto(&v.PubKey)
if err != nil {
return types.ResponseDeliverTx{
Code: code.CodeTypeEncodingError,
Log: fmt.Sprintf("Error encoding Public Key: %s", err)}
}
key := []byte("val:" + string(pubkey.Bytes()))
pubStr, _ := MakeValSetChangeTxAndMore(v.PubKey, v.Power)
key := []byte("val:" + pubStr)

if v.Power == 0 {
// remove validator
Expand All @@ -282,7 +299,6 @@ func (app *PersistentKVStoreApplication) updateValidator(v types.ValidatorUpdate
panic(err)
}
if !hasKey {
pubStr := base64.StdEncoding.EncodeToString(pubkey.Bytes())
return types.ResponseDeliverTx{
Code: code.CodeTypeUnauthorized,
Log: fmt.Sprintf("Cannot remove non-existent validator %s", pubStr)}
Expand Down
44 changes: 44 additions & 0 deletions abci/example/kvstore/tool/make_val_set_change_tx.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package main

import (
"flag"
"fmt"
"github.com/line/ostracon/abci/example/kvstore"
"github.com/line/ostracon/config"
"github.com/line/ostracon/crypto/encoding"
"net/url"
"os"
)

func main() {
c := config.DefaultConfig()
c.SetRoot(os.Getenv("HOME") + "/" + config.DefaultOstraconDir)
keyFilePath := c.PrivValidatorKeyFile()
var flagKeyFilePath = flag.String("priv-key", keyFilePath, "priv val key file path")
var flagStakingPower = flag.Int64("staking", 10, "staking power for priv valedator")
flag.Parse()
keyFile, err := kvstore.LoadPrivValidatorKeyFile(*flagKeyFilePath)
if err != nil {
panic(err)
}
publicKey, err := encoding.PubKeyToProto(keyFile.PubKey)
if err != nil {
panic(err)
}
pubStr, tx := kvstore.MakeValSetChangeTxAndMore(publicKey, *flagStakingPower)
{
fmt.Println("\n# Send tx of ValSetChangeTx for persist_kvstore")
fmt.Println("# See: persist_kvstore.go#DeliveredTx")
broadcastTxCommit := fmt.Sprintf("curl -s 'localhost:26657/broadcast_tx_commit?tx=\"%s\"'",
url.QueryEscape(tx))
fmt.Println(broadcastTxCommit)
}
{
fmt.Println("\n# Query tx of ValSetChangeTx for persist_kvstore")
fmt.Println("# See: persist_kvstore.go#Query")
query := fmt.Sprintf("curl -s 'localhost:26657/abci_query?path=\"%s\"&data=\"%s\"'",
url.QueryEscape("/val"),
url.QueryEscape(pubStr))
fmt.Println(query)
}
}
27 changes: 27 additions & 0 deletions abci/example/kvstore/tool/make_val_set_change_tx.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#!/bin/bash

IFS_BACK=$IFS
IFS=$'\r\n'

# updator validator with default parameter
commands=`go run make_val_set_change_tx.go --staking=10 --priv-key=${HOME}/.ostracon/config/priv_validator_key.json`
# remove validator tx
commands=`go run make_val_set_change_tx.go --staking=0`
# update validator tx
commands=`go run make_val_set_change_tx.go`
for command in ${commands[@]}; do
if [[ "$command" =~ \# ]]; then
echo $command
else
echo $command
eval $command
RET=$?
echo ""
if [ ${RET} -ne 0 ]; then
echo "ERROR: Result Code of calling RPC: ${RET}"
exit ${RET}
fi
fi
done

IFS=$IFS_BACK

0 comments on commit 3e399f9

Please sign in to comment.