update app

This commit is contained in:
Anton Kaliaev
2020-11-04 12:46:59 +04:00
parent 28fec3ce2b
commit 013c59b17e

View File

@@ -9,7 +9,6 @@ import (
"github.com/cosmos/iavl"
dbm "github.com/tendermint/tm-db"
"github.com/tendermint/tmlibs/merkle"
"github.com/tendermint/tendermint/abci/example/code"
abci "github.com/tendermint/tendermint/abci/types"
@@ -28,6 +27,12 @@ const (
TxTypeValSetCAS byte = 0x07
NonceLength = 12
// Additional codes.
CodeType_UnknownRequest = 2
CodeType_EncodingError = 3
CodeType_BadNonce = 4
CodeType_ErrUnknownRequest = 5
)
// Database key for merkle tree save value db values
@@ -63,7 +68,7 @@ type ValidatorSetState struct {
// Validator represents a single validator.
type Validator struct {
PubKey crypto.PubKey `json:"pub_key"`
Power uint64 `json:"power"`
Power int64 `json:"power"`
}
// Has returns true if v is present in the validator set.
@@ -158,7 +163,7 @@ func NewMerkleEyesApp(dbName string, cacheSize int) *MerkleEyesApp {
panic(err)
}
var eyesState MerkleEyesState
err := json.Unmarshal(eyesStateBytes, &eyesState)
err = json.Unmarshal(eyesStateBytes, &eyesState)
if err != nil {
fmt.Println("error reading MerkleEyesState")
panic(err)
@@ -184,18 +189,20 @@ func (app *MerkleEyesApp) CloseDB() {
}
}
func (app *MerkleEyesApp) Info() abci.ResponseInfo {
// Info implements ABCI.
func (app *MerkleEyesApp) Info(req abci.RequestInfo) abci.ResponseInfo {
return abci.ResponseInfo{
Version: version.ABCIVersion,
AppVersion: 1,
LastBlockHeight: int64(app.state.Height),
LastBlockAppHash: app.state.Hash,
LastBlockHeight: int64(app.height),
LastBlockAppHash: app.state.Deliver().Hash(),
}
}
// InitChain implements ABCI.
func (app *MerkleEyesApp) InitChain(req abci.RequestInitChain) abci.ResponseInitChain {
for _, v := range req.Validators {
app.validators.Set(&Validator{v.PubKey, v.Power})
app.validators.Set(&Validator{PubKey: v.PubKey, Power: v.Power})
}
return abci.ResponseInitChain{
@@ -257,43 +264,43 @@ func (app *MerkleEyesApp) Commit() abci.ResponseCommit {
return abci.ResponseCommit{Data: hash}
}
// Query implements abci.Application
func (app *MerkleEyesApp) Query(req abci.RequestQuery) abci.ResponseQuery {
if len(reqQuery.Data) == 0 {
// Query implements ABCI.
func (app *MerkleEyesApp) Query(req abci.RequestQuery) (res abci.ResponseQuery) {
if len(req.Data) == 0 {
return
}
tree := app.state.Committed()
if reqQuery.Height != 0 {
if req.Height != 0 {
// TODO: support older commits
resQuery.Code = abci.CodeType_InternalError
resQuery.Log = "merkleeyes only supports queries on latest commit"
res.Code = abci.CodeType_InternalError
res.Log = "merkleeyes only supports queries on latest commit"
return
}
// set the query response height
resQuery.Height = app.height
res.Height = app.height
switch reqQuery.Path {
switch req.Path {
case "/store", "/key": // Get by key
key := reqQuery.Data // Data holds the key bytes
resQuery.Key = key
if reqQuery.Prove {
key := req.Data // Data holds the key bytes
res.Key = key
if req.Prove {
value, proof, exists := tree.Proof(storeKey(key))
if !exists {
resQuery.Log = "Key not found"
res.Log = "Key not found"
}
resQuery.Value = value
resQuery.Proof = proof
res.Value = value
res.Proof = proof
// TODO: return index too?
} else {
index, value, _ := tree.Get(storeKey(key))
resQuery.Value = value
resQuery.Index = int64(index)
res.Value = value
res.Index = int64(index)
}
case "/index": // Get by Index
index := wire.GetInt64(reqQuery.Data)
index := wire.GetInt64(req.Data)
key, value := tree.GetByIndex(int(index))
resQuery.Key = key
resQuery.Index = int64(index)
@@ -305,8 +312,8 @@ func (app *MerkleEyesApp) Query(req abci.RequestQuery) abci.ResponseQuery {
resQuery.Value = sizeBytes
default:
resQuery.Code = abci.CodeType_UnknownRequest
resQuery.Log = cmn.Fmt("Unexpected Query path: %v", reqQuery.Path)
resQuery.Code = CodeType_UnknownRequest
resQuery.Log = fmt.Sprintf("Unexpected Query path: %v", reqQuery.Path)
}
return
}
@@ -319,11 +326,11 @@ func storeKey(key []byte) []byte {
return append([]byte("/key/"), key...)
}
func (app *MerkleEyesApp) doTx(tree merkle.Tree, tx []byte) abci.Result {
func (app *MerkleEyesApp) doTx(tree *iavl.MutableTree, tx []byte) abci.ResponseDeliverTx {
// minimum length is 12 (nonce) + 1 (type byte) = 13
minTxLen := NonceLength + 1
if len(tx) < minTxLen {
return abci.ErrEncodingError.SetLog(fmt.Sprintf("Tx length must be at least %d", minTxLen))
return abci.ResponseDeliverTx{Code: CodeType_EncodingError, Log: fmt.Sprintf("Tx length must be at least %d", minTxLen)}
}
nonce := tx[:12]
@@ -332,7 +339,7 @@ func (app *MerkleEyesApp) doTx(tree merkle.Tree, tx []byte) abci.Result {
// check nonce
_, _, exists := tree.Get(nonceKey(nonce))
if exists {
return abci.ErrBadNonce.AppendLog(fmt.Sprintf("Nonce %X already exists", nonce))
return abci.ResponseDeliverTx{Code: CodeType_BadNonce, Log: fmt.Sprintf("Nonce %X already exists", nonce)}
}
// set nonce
@@ -344,70 +351,70 @@ func (app *MerkleEyesApp) doTx(tree merkle.Tree, tx []byte) abci.Result {
case TxTypeSet: // Set
key, n, err := wire.GetByteSlice(tx)
if err != nil {
return abci.ErrEncodingError.SetLog(cmn.Fmt("Error reading key: %v", err.Error()))
return abci.ResponseDeliverTx{Code: CodeType_EncodingError, Log: fmt.Sprintf("Error reading key: %v", err)}
}
tx = tx[n:]
value, n, err := wire.GetByteSlice(tx)
if err != nil {
return abci.ErrEncodingError.SetLog(cmn.Fmt("Error reading value: %v", err.Error()))
return abci.ResponseDeliverTx{Code: CodeType_EncodingError, Log: fmt.Sprintf("Error reading value: %v", err)}
}
tx = tx[n:]
if len(tx) != 0 {
return abci.ErrEncodingError.SetLog(cmn.Fmt("Got bytes left over"))
return abci.ResponseDeliverTx{Code: CodeType_EncodingError, Log: "Got bytes left over"}
}
tree.Set(storeKey(key), value)
fmt.Println("SET", cmn.Fmt("%X", key), cmn.Fmt("%X", value))
fmt.Println("SET", fmt.Sprintf("%X", key), fmt.Sprintf("%X", value))
case TxTypeRm: // Remove
key, n, err := wire.GetByteSlice(tx)
if err != nil {
return abci.ErrEncodingError.SetLog(cmn.Fmt("Error reading key: %v", err.Error()))
return abci.ResponseDeliverTx{Code: CodeType_EncodingError, Log: fmt.Sprintf("Error reading key: %v", err)}
}
tx = tx[n:]
if len(tx) != 0 {
return abci.ErrEncodingError.SetLog(cmn.Fmt("Got bytes left over"))
return abci.ResponseDeliverTx{Code: CodeType_EncodingError, Log: fmt.Sprintf("Got bytes left over")}
}
tree.Remove(storeKey(key))
fmt.Println("RM", cmn.Fmt("%X", key))
fmt.Println("RM", fmt.Sprintf("%X", key))
case TxTypeGet: // Get
key, n, err := wire.GetByteSlice(tx)
if err != nil {
return abci.ErrEncodingError.SetLog(cmn.Fmt("Error reading key: %v", err.Error()))
return abci.ResponseDeliverTx{Code: CodeType_EncodingError, Log: fmt.Sprintf("Error reading key: %v", err)}
}
tx = tx[n:]
if len(tx) != 0 {
return abci.ErrEncodingError.SetLog(cmn.Fmt("Got bytes left over"))
return abci.ResponseDeliverTx{Code: CodeType_EncodingError, Log: "Got bytes left over"}
}
_, value, exists := tree.Get(storeKey(key))
if exists {
fmt.Println("GET", cmn.Fmt("%X", key), cmn.Fmt("%X", value))
return abci.OK.SetData(value)
fmt.Println("GET", fmt.Sprintf("%X", key), fmt.Sprintf("%X", value))
return abci.ResponseDeliverTx{Code: abci.CodeTypeOK, Data: value}
} else {
return abci.ErrBaseUnknownAddress.AppendLog(fmt.Sprintf("Cannot find key: %X", key))
}
case TxTypeCompareAndSet: // Compare and Set
key, n, err := wire.GetByteSlice(tx)
if err != nil {
return abci.ErrEncodingError.SetLog(cmn.Fmt("Error reading key: %v", err.Error()))
return abci.ResponseDeliverTx{Code: CodeType_EncodingError, Log: fmt.Sprintf("Error reading key: %v", err)}
}
tx = tx[n:]
compareValue, n, err := wire.GetByteSlice(tx)
if err != nil {
return abci.ErrEncodingError.SetLog(cmn.Fmt("Error reading compare value: %v", err.Error()))
return abci.ResponseDeliverTx{Code: CodeType_EncodingError, Log: fmt.Sprintf("Error reading compare value: %v", err)}
}
tx = tx[n:]
setValue, n, err := wire.GetByteSlice(tx)
if err != nil {
return abci.ErrEncodingError.SetLog(cmn.Fmt("Error reading set value: %v", err.Error()))
return abci.ResponseDeliverTx{Code: CodeType_EncodingError, Log: fmt.Sprintf("Error reading set value: %v", err)}
}
tx = tx[n:]
if len(tx) != 0 {
return abci.ErrEncodingError.SetLog(cmn.Fmt("Got bytes left over"))
return abci.ResponseDeliverTx{Code: CodeType_EncodingError, Log: "Got bytes left over"}
}
_, value, exists := tree.Get(storeKey(key))
@@ -419,18 +426,20 @@ func (app *MerkleEyesApp) doTx(tree merkle.Tree, tx []byte) abci.Result {
}
tree.Set(storeKey(key), setValue)
fmt.Println("CAS-SET", cmn.Fmt("%X", key), cmn.Fmt("%X", compareValue), cmn.Fmt("%X", setValue))
fmt.Println("CAS-SET", fmt.Sprintf("%X", key), fmt.Sprintf("%X", compareValue), fmt.Sprintf("%X", setValue))
case TxTypeValSetChange:
pubKey, n, err := wire.GetByteSlice(tx)
if err != nil {
return abci.ErrEncodingError.SetLog(cmn.Fmt("Error reading pubkey: %v", err.Error()))
return abci.ResponseDeliverTx{Code: CodeType_EncodingError, Log: fmt.Sprintf("Error reading pubkey: %v", err)}
}
if len(pubKey) != 32 {
return abci.ErrEncodingError.SetLog(cmn.Fmt("Pubkey must be 32 bytes: %X is %d bytes", pubKey, len(pubKey)))
return abci.ResponseDeliverTx{Code: CodeType_EncodingError,
Log: fmt.Sprintf("Pubkey must be 32 bytes: %X is %d bytes", pubKey, len(pubKey))}
}
tx = tx[n:]
if len(tx) != 8 {
return abci.ErrEncodingError.SetLog(cmn.Fmt("Power must be 8 bytes: %X is %d bytes", tx, len(tx)))
return abci.ResponseDeliverTx{Code: CodeType_EncodingError,
Log: fmt.Sprintf("Power must be 8 bytes: %X is %d bytes", tx, len(tx))}
}
power := wire.GetUint64(tx)
@@ -439,13 +448,14 @@ func (app *MerkleEyesApp) doTx(tree merkle.Tree, tx []byte) abci.Result {
case TxTypeValSetRead:
b, err := json.Marshal(app.validators)
if err != nil {
return abci.ErrInternalError.SetLog(cmn.Fmt("Error marshalling validator info: %v", err))
return abci.ErrInternalError.SetLog(fmt.Sprintf("Error marshalling validator info: %v", err))
}
return abci.OK.SetData(b).SetLog(string(b))
return abci.ResponseDeliverTx{Code: abci.CodeTypeOK, Data: b, Log: string(b)}
case TxTypeValSetCAS:
if len(tx) < 8 {
return abci.ErrEncodingError.SetLog(cmn.Fmt("Version number must be 8 bytes: remaining tx (%X) is %d bytes", tx, len(tx)))
return abci.ResponseDeliverTx{Code: CodeType_EncodingError,
Log: fmt.Sprintf("Version number must be 8 bytes: remaining tx (%X) is %d bytes", tx, len(tx))}
}
version := wire.GetUint64(tx)
if app.validators.Version != version {
@@ -455,21 +465,24 @@ func (app *MerkleEyesApp) doTx(tree merkle.Tree, tx []byte) abci.Result {
pubKey, n, err := wire.GetByteSlice(tx)
if err != nil {
return abci.ErrEncodingError.SetLog(cmn.Fmt("Error reading pubkey: %v", err.Error()))
return abci.ResponseDeliverTx{Code: CodeType_EncodingError,
Log: fmt.Sprintf("Error reading pubkey: %v", err)}
}
if len(pubKey) != 32 {
return abci.ErrEncodingError.SetLog(cmn.Fmt("Pubkey must be 32 bytes: %X is %d bytes", pubKey, len(pubKey)))
return abci.ResponseDeliverTx{Code: CodeType_EncodingError,
Log: fmt.Sprintf("Pubkey must be 32 bytes: %X is %d bytes", pubKey, len(pubKey))}
}
tx = tx[n:]
if len(tx) != 8 {
return abci.ErrEncodingError.SetLog(cmn.Fmt("Power must be 8 bytes: %X is %d bytes", tx, len(tx)))
return abci.ResponseDeliverTx{Code: CodeType_EncodingError,
Log: fmt.Sprintf("Power must be 8 bytes: %X is %d bytes", tx, len(tx))}
}
power := wire.GetUint64(tx)
return app.updateValidator(pubKey, power)
default:
return abci.ErrUnknownRequest.SetLog(cmn.Fmt("Unexpected Tx type byte %X", typeByte))
return abci.ErrUnknownRequest.SetLog(fmt.Sprintf("Unexpected Tx type byte %X", typeByte))
}
return abci.OK
}
@@ -479,7 +492,7 @@ func (app *MerkleEyesApp) updateValidator(pubKey []byte, power uint64) abci.Resu
if v.Power == 0 {
// remove validator
if !app.validators.Has(v) {
return abci.ErrUnauthorized.SetLog(cmn.Fmt("Cannot remove non-existent validator %v", v))
return abci.ErrUnauthorized.SetLog(fmt.Sprintf("Cannot remove non-existent validator %v", v))
}
app.validators.Remove(v)
} else {
@@ -492,5 +505,5 @@ func (app *MerkleEyesApp) updateValidator(pubKey []byte, power uint64) abci.Resu
copy(pubKeyEd[:], pubKey)
app.changes = append(app.changes, &abci.Validator{pubKeyEd.Bytes(), power})
return abci.OK
return abci.ResponseDeliverTx{Code: abci.CodeTypeOK}
}