mirror of
https://github.com/fluencelabs/tendermint
synced 2025-06-15 06:11:20 +00:00
Fixed tests
This commit is contained in:
@ -1,9 +1,8 @@
|
|||||||
package wallet
|
package account
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/tendermint/go-ed25519"
|
"github.com/tendermint/go-ed25519"
|
||||||
|
|
||||||
. "github.com/tendermint/tendermint/account"
|
|
||||||
. "github.com/tendermint/tendermint/common"
|
. "github.com/tendermint/tendermint/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -26,3 +25,7 @@ func GenPrivAccount() *PrivAccount {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (privAccount *PrivAccount) Sign(o Signable) Signature {
|
||||||
|
return privAccount.PrivKey.Sign(SignBytes(o))
|
||||||
|
}
|
@ -8,21 +8,22 @@ import (
|
|||||||
func TestSignAndValidate(t *testing.T) {
|
func TestSignAndValidate(t *testing.T) {
|
||||||
|
|
||||||
privAccount := GenPrivAccount()
|
privAccount := GenPrivAccount()
|
||||||
account := &privAccount.Account
|
pubKey := privAccount.PubKey
|
||||||
|
privKey := privAccount.PrivKey
|
||||||
|
|
||||||
msg := CRandBytes(128)
|
msg := CRandBytes(128)
|
||||||
sig := privAccount.SignBytes(msg)
|
sig := privKey.Sign(msg)
|
||||||
t.Logf("msg: %X, sig: %X", msg, sig)
|
t.Logf("msg: %X, sig: %X", msg, sig)
|
||||||
|
|
||||||
// Test the signature
|
// Test the signature
|
||||||
if !account.VerifyBytes(msg, sig) {
|
if !pubKey.VerifyBytes(msg, sig) {
|
||||||
t.Errorf("Account message signature verification failed")
|
t.Errorf("Account message signature verification failed")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mutate the signature, just one bit.
|
// Mutate the signature, just one bit.
|
||||||
sig.Bytes[0] ^= byte(0x01)
|
sig.(SignatureEd25519).Bytes[0] ^= byte(0x01)
|
||||||
|
|
||||||
if account.VerifyBytes(msg, sig) {
|
if pubKey.VerifyBytes(msg, sig) {
|
||||||
t.Errorf("Account message signature verification should have failed but passed instead")
|
t.Errorf("Account message signature verification should have failed but passed instead")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ func ReadBinary(o interface{}, r io.Reader, n *int64, err *error) interface{} {
|
|||||||
} else {
|
} else {
|
||||||
ptrRv := reflect.New(rt)
|
ptrRv := reflect.New(rt)
|
||||||
readReflect(ptrRv.Elem(), rt, r, n, err)
|
readReflect(ptrRv.Elem(), rt, r, n, err)
|
||||||
return ptrRv.Elem()
|
return ptrRv.Elem().Interface()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,9 @@ package binary
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"reflect"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -80,7 +82,7 @@ func BasicCodecEncoder(o interface{}, w io.Writer, n *int64, err *error) {
|
|||||||
WriteByte(typeTime, w, n, err)
|
WriteByte(typeTime, w, n, err)
|
||||||
WriteTime(o.(time.Time), w, n, err)
|
WriteTime(o.(time.Time), w, n, err)
|
||||||
default:
|
default:
|
||||||
panic("Unsupported type")
|
panic(fmt.Sprintf("Unsupported type: %v", reflect.TypeOf(o)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,7 +118,11 @@ func BasicCodecDecoder(r io.Reader, n *int64, err *error) (o interface{}) {
|
|||||||
case typeTime:
|
case typeTime:
|
||||||
o = ReadTime(r, n, err)
|
o = ReadTime(r, n, err)
|
||||||
default:
|
default:
|
||||||
panic("Unsupported type")
|
if *err != nil {
|
||||||
|
panic(err)
|
||||||
|
} else {
|
||||||
|
panic(fmt.Sprintf("Unsupported type byte: %X", type_))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return o
|
return o
|
||||||
}
|
}
|
||||||
@ -151,7 +157,7 @@ func BasicCodecComparator(o1 interface{}, o2 interface{}) int {
|
|||||||
case time.Time:
|
case time.Time:
|
||||||
return int(o1.(time.Time).UnixNano() - o2.(time.Time).UnixNano())
|
return int(o1.(time.Time).UnixNano() - o2.(time.Time).UnixNano())
|
||||||
default:
|
default:
|
||||||
panic("Unsupported type")
|
panic(fmt.Sprintf("Unsupported type: %v", reflect.TypeOf(o1)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package binary
|
package binary
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"reflect"
|
"reflect"
|
||||||
@ -10,6 +11,9 @@ type TypeInfo struct {
|
|||||||
Type reflect.Type // The type
|
Type reflect.Type // The type
|
||||||
Encoder Encoder // Optional custom encoder function
|
Encoder Encoder // Optional custom encoder function
|
||||||
Decoder Decoder // Optional custom decoder function
|
Decoder Decoder // Optional custom decoder function
|
||||||
|
|
||||||
|
HasTypeByte bool
|
||||||
|
TypeByte byte
|
||||||
}
|
}
|
||||||
|
|
||||||
// If a type implements TypeByte, the byte is included
|
// If a type implements TypeByte, the byte is included
|
||||||
@ -25,18 +29,33 @@ type HasTypeByte interface {
|
|||||||
|
|
||||||
var typeInfos = map[reflect.Type]*TypeInfo{}
|
var typeInfos = map[reflect.Type]*TypeInfo{}
|
||||||
|
|
||||||
func RegisterType(info *TypeInfo) bool {
|
func RegisterType(info *TypeInfo) *TypeInfo {
|
||||||
|
|
||||||
// Register the type info
|
// Register the type info
|
||||||
typeInfos[info.Type] = info
|
typeInfos[info.Type] = info
|
||||||
|
|
||||||
// Also register the underlying struct's info, if info.Type is a pointer.
|
// Also register the underlying struct's info, if info.Type is a pointer.
|
||||||
|
// Or, if info.Type is not a pointer, register the pointer.
|
||||||
if info.Type.Kind() == reflect.Ptr {
|
if info.Type.Kind() == reflect.Ptr {
|
||||||
rt := info.Type.Elem()
|
rt := info.Type.Elem()
|
||||||
typeInfos[rt] = info
|
typeInfos[rt] = info
|
||||||
|
} else {
|
||||||
|
ptrRt := reflect.PtrTo(info.Type)
|
||||||
|
typeInfos[ptrRt] = info
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
// See if the type implements HasTypeByte
|
||||||
|
if info.Type.Implements(reflect.TypeOf((*HasTypeByte)(nil)).Elem()) {
|
||||||
|
zero := reflect.Zero(info.Type)
|
||||||
|
typeByte := zero.Interface().(HasTypeByte).TypeByte()
|
||||||
|
if info.HasTypeByte && info.TypeByte != typeByte {
|
||||||
|
panic(fmt.Sprintf("Type %v expected TypeByte of %X", info.Type, typeByte))
|
||||||
|
}
|
||||||
|
info.HasTypeByte = true
|
||||||
|
info.TypeByte = typeByte
|
||||||
|
}
|
||||||
|
|
||||||
|
return info
|
||||||
}
|
}
|
||||||
|
|
||||||
func readReflect(rv reflect.Value, rt reflect.Type, r io.Reader, n *int64, err *error) {
|
func readReflect(rv reflect.Value, rt reflect.Type, r io.Reader, n *int64, err *error) {
|
||||||
@ -54,15 +73,29 @@ func readReflect(rv reflect.Value, rt reflect.Type, r io.Reader, n *int64, err *
|
|||||||
rv, rt = rv.Elem(), rt.Elem()
|
rv, rt = rv.Elem(), rt.Elem()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Custom decoder
|
// Get typeInfo
|
||||||
typeInfo := typeInfos[rt]
|
typeInfo := typeInfos[rt]
|
||||||
if typeInfo != nil && typeInfo.Decoder != nil {
|
if typeInfo == nil {
|
||||||
|
typeInfo = RegisterType(&TypeInfo{Type: rt})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Custom decoder
|
||||||
|
if typeInfo.Decoder != nil {
|
||||||
decoded := typeInfo.Decoder(r, n, err)
|
decoded := typeInfo.Decoder(r, n, err)
|
||||||
decodedRv := reflect.Indirect(reflect.ValueOf(decoded))
|
decodedRv := reflect.Indirect(reflect.ValueOf(decoded))
|
||||||
rv.Set(decodedRv)
|
rv.Set(decodedRv)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Read TypeByte prefix
|
||||||
|
if typeInfo.HasTypeByte {
|
||||||
|
typeByte := ReadByte(r, n, err)
|
||||||
|
if typeByte != typeInfo.TypeByte {
|
||||||
|
*err = errors.New(fmt.Sprintf("Expected TypeByte of %X but got %X", typeInfo.TypeByte, typeByte))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch rt.Kind() {
|
switch rt.Kind() {
|
||||||
case reflect.Slice:
|
case reflect.Slice:
|
||||||
elemRt := rt.Elem()
|
elemRt := rt.Elem()
|
||||||
@ -86,7 +119,7 @@ func readReflect(rv reflect.Value, rt reflect.Type, r io.Reader, n *int64, err *
|
|||||||
numFields := rt.NumField()
|
numFields := rt.NumField()
|
||||||
for i := 0; i < numFields; i++ {
|
for i := 0; i < numFields; i++ {
|
||||||
field := rt.Field(i)
|
field := rt.Field(i)
|
||||||
if field.Anonymous {
|
if field.PkgPath != "" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
fieldRv := rv.Field(i)
|
fieldRv := rv.Field(i)
|
||||||
@ -97,6 +130,26 @@ func readReflect(rv reflect.Value, rt reflect.Type, r io.Reader, n *int64, err *
|
|||||||
str := ReadString(r, n, err)
|
str := ReadString(r, n, err)
|
||||||
rv.SetString(str)
|
rv.SetString(str)
|
||||||
|
|
||||||
|
case reflect.Int64:
|
||||||
|
num := ReadUInt64(r, n, err)
|
||||||
|
rv.SetInt(int64(num))
|
||||||
|
|
||||||
|
case reflect.Int32:
|
||||||
|
num := ReadUInt32(r, n, err)
|
||||||
|
rv.SetInt(int64(num))
|
||||||
|
|
||||||
|
case reflect.Int16:
|
||||||
|
num := ReadUInt16(r, n, err)
|
||||||
|
rv.SetInt(int64(num))
|
||||||
|
|
||||||
|
case reflect.Int8:
|
||||||
|
num := ReadUInt8(r, n, err)
|
||||||
|
rv.SetInt(int64(num))
|
||||||
|
|
||||||
|
case reflect.Int:
|
||||||
|
num := ReadUVarInt(r, n, err)
|
||||||
|
rv.SetInt(int64(num))
|
||||||
|
|
||||||
case reflect.Uint64:
|
case reflect.Uint64:
|
||||||
num := ReadUInt64(r, n, err)
|
num := ReadUInt64(r, n, err)
|
||||||
rv.SetUint(uint64(num))
|
rv.SetUint(uint64(num))
|
||||||
@ -124,9 +177,14 @@ func readReflect(rv reflect.Value, rt reflect.Type, r io.Reader, n *int64, err *
|
|||||||
|
|
||||||
func writeReflect(rv reflect.Value, rt reflect.Type, w io.Writer, n *int64, err *error) {
|
func writeReflect(rv reflect.Value, rt reflect.Type, w io.Writer, n *int64, err *error) {
|
||||||
|
|
||||||
// Custom encoder
|
// Get typeInfo
|
||||||
typeInfo := typeInfos[rt]
|
typeInfo := typeInfos[rt]
|
||||||
if typeInfo != nil && typeInfo.Encoder != nil {
|
if typeInfo == nil {
|
||||||
|
typeInfo = RegisterType(&TypeInfo{Type: rt})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Custom encoder, say for an interface type rt.
|
||||||
|
if typeInfo.Encoder != nil {
|
||||||
typeInfo.Encoder(rv.Interface(), w, n, err)
|
typeInfo.Encoder(rv.Interface(), w, n, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -135,14 +193,21 @@ func writeReflect(rv reflect.Value, rt reflect.Type, w io.Writer, n *int64, err
|
|||||||
if rt.Kind() == reflect.Ptr {
|
if rt.Kind() == reflect.Ptr {
|
||||||
rt = rt.Elem()
|
rt = rt.Elem()
|
||||||
rv = rv.Elem()
|
rv = rv.Elem()
|
||||||
|
// RegisterType registers the ptr type,
|
||||||
|
// so typeInfo is already for the ptr.
|
||||||
} else if rt.Kind() == reflect.Interface {
|
} else if rt.Kind() == reflect.Interface {
|
||||||
rv = rv.Elem()
|
rv = rv.Elem()
|
||||||
rt = rv.Type()
|
rt = rv.Type()
|
||||||
|
typeInfo = typeInfos[rt]
|
||||||
|
// If interface type, get typeInfo of underlying type.
|
||||||
|
if typeInfo == nil {
|
||||||
|
typeInfo = RegisterType(&TypeInfo{Type: rt})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write TypeByte prefix
|
// Write TypeByte prefix
|
||||||
if rt.Implements(reflect.TypeOf((*HasTypeByte)(nil)).Elem()) {
|
if typeInfo.HasTypeByte {
|
||||||
WriteByte(rv.Interface().(HasTypeByte).TypeByte(), w, n, err)
|
WriteByte(typeInfo.TypeByte, w, n, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
switch rt.Kind() {
|
switch rt.Kind() {
|
||||||
@ -167,7 +232,7 @@ func writeReflect(rv reflect.Value, rt reflect.Type, w io.Writer, n *int64, err
|
|||||||
numFields := rt.NumField()
|
numFields := rt.NumField()
|
||||||
for i := 0; i < numFields; i++ {
|
for i := 0; i < numFields; i++ {
|
||||||
field := rt.Field(i)
|
field := rt.Field(i)
|
||||||
if field.Anonymous {
|
if field.PkgPath != "" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
fieldRv := rv.Field(i)
|
fieldRv := rv.Field(i)
|
||||||
@ -177,6 +242,21 @@ func writeReflect(rv reflect.Value, rt reflect.Type, w io.Writer, n *int64, err
|
|||||||
case reflect.String:
|
case reflect.String:
|
||||||
WriteString(rv.String(), w, n, err)
|
WriteString(rv.String(), w, n, err)
|
||||||
|
|
||||||
|
case reflect.Int64:
|
||||||
|
WriteInt64(rv.Int(), w, n, err)
|
||||||
|
|
||||||
|
case reflect.Int32:
|
||||||
|
WriteInt32(int32(rv.Int()), w, n, err)
|
||||||
|
|
||||||
|
case reflect.Int16:
|
||||||
|
WriteInt16(int16(rv.Int()), w, n, err)
|
||||||
|
|
||||||
|
case reflect.Int8:
|
||||||
|
WriteInt8(int8(rv.Int()), w, n, err)
|
||||||
|
|
||||||
|
case reflect.Int:
|
||||||
|
WriteVarInt(int(rv.Int()), w, n, err)
|
||||||
|
|
||||||
case reflect.Uint64:
|
case reflect.Uint64:
|
||||||
WriteUInt64(rv.Uint(), w, n, err)
|
WriteUInt64(rv.Uint(), w, n, err)
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package blocks
|
package block
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
@ -42,9 +42,11 @@ func (b *Block) ValidateBasic(lastBlockHeight uint, lastBlockHash []byte,
|
|||||||
if !b.Time.After(lastBlockTime) {
|
if !b.Time.After(lastBlockTime) {
|
||||||
return errors.New("Invalid block time")
|
return errors.New("Invalid block time")
|
||||||
}
|
}
|
||||||
|
if b.Header.Height != 1 {
|
||||||
if err := b.Validation.ValidateBasic(); err != nil {
|
if err := b.Validation.ValidateBasic(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// XXX more validation
|
// XXX more validation
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package blocks
|
package block
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
@ -1,4 +1,4 @@
|
|||||||
package blocks
|
package block
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
@ -1,4 +1,4 @@
|
|||||||
package blocks
|
package block
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
@ -1,4 +1,4 @@
|
|||||||
package blocks
|
package block
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
@ -1,4 +1,4 @@
|
|||||||
package blocks
|
package block
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
@ -1,15 +0,0 @@
|
|||||||
package blocks
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/op/go-logging"
|
|
||||||
)
|
|
||||||
|
|
||||||
var log = logging.MustGetLogger("block")
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
logging.SetFormatter(logging.MustStringFormatter("[%{level:.1s}] %{message}"))
|
|
||||||
}
|
|
||||||
|
|
||||||
func SetBlocksLogger(l *logging.Logger) {
|
|
||||||
log = l
|
|
||||||
}
|
|
@ -4,7 +4,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
|
|
||||||
"github.com/tendermint/tendermint/blocks"
|
"github.com/tendermint/tendermint/block"
|
||||||
"github.com/tendermint/tendermint/config"
|
"github.com/tendermint/tendermint/config"
|
||||||
"github.com/tendermint/tendermint/consensus"
|
"github.com/tendermint/tendermint/consensus"
|
||||||
db_ "github.com/tendermint/tendermint/db"
|
db_ "github.com/tendermint/tendermint/db"
|
||||||
@ -21,13 +21,13 @@ type Node struct {
|
|||||||
pexReactor *p2p.PEXReactor
|
pexReactor *p2p.PEXReactor
|
||||||
mempoolReactor *mempool_.MempoolReactor
|
mempoolReactor *mempool_.MempoolReactor
|
||||||
consensusReactor *consensus.ConsensusReactor
|
consensusReactor *consensus.ConsensusReactor
|
||||||
privValidator *consensus.PrivValidator
|
privValidator *state_.PrivValidator
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewNode() *Node {
|
func NewNode() *Node {
|
||||||
// Get BlockStore
|
// Get BlockStore
|
||||||
blockStoreDB := db_.NewMemDB() // TODO configurable db.
|
blockStoreDB := db_.NewMemDB() // TODO configurable db.
|
||||||
blockStore := blocks.NewBlockStore(blockStoreDB)
|
blockStore := block.NewBlockStore(blockStoreDB)
|
||||||
|
|
||||||
// Get State
|
// Get State
|
||||||
stateDB := db_.NewMemDB() // TODO configurable db.
|
stateDB := db_.NewMemDB() // TODO configurable db.
|
||||||
@ -38,9 +38,9 @@ func NewNode() *Node {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get PrivValidator
|
// Get PrivValidator
|
||||||
var privValidator *consensus.PrivValidator
|
var privValidator *state_.PrivValidator
|
||||||
if _, err := os.Stat(config.PrivValidatorFile()); err == nil {
|
if _, err := os.Stat(config.PrivValidatorFile()); err == nil {
|
||||||
privValidator = consensus.LoadPrivValidator()
|
privValidator = state_.LoadPrivValidator()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get PEXReactor
|
// Get PEXReactor
|
||||||
|
@ -4,15 +4,15 @@ import (
|
|||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
. "github.com/tendermint/tendermint/account"
|
||||||
. "github.com/tendermint/tendermint/binary"
|
. "github.com/tendermint/tendermint/binary"
|
||||||
"github.com/tendermint/tendermint/wallet"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func gen_account() {
|
func gen_account() {
|
||||||
|
|
||||||
// TODO: uh, write better logic.
|
// TODO: uh, write better logic.
|
||||||
// Generate private account
|
// Generate private account
|
||||||
privAccount := wallet.GenPrivAccount()
|
privAccount := GenPrivAccount()
|
||||||
|
|
||||||
fmt.Printf(`Generated account:
|
fmt.Printf(`Generated account:
|
||||||
Account Public Key: %X
|
Account Public Key: %X
|
||||||
|
@ -5,7 +5,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/tendermint/tendermint/config"
|
"github.com/tendermint/tendermint/config"
|
||||||
"github.com/tendermint/tendermint/consensus"
|
"github.com/tendermint/tendermint/state"
|
||||||
)
|
)
|
||||||
|
|
||||||
func gen_validator() {
|
func gen_validator() {
|
||||||
@ -17,7 +17,7 @@ func gen_validator() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Generate private validator
|
// Generate private validator
|
||||||
privValidator := consensus.GenPrivValidator()
|
privValidator := state.GenPrivValidator()
|
||||||
privValidator.Save()
|
privValidator.Save()
|
||||||
fmt.Printf("Generated a new validator at %v\n", filename)
|
fmt.Printf("Generated a new validator at %v\n", filename)
|
||||||
}
|
}
|
||||||
|
@ -8,8 +8,8 @@ import (
|
|||||||
|
|
||||||
// Not goroutine safe
|
// Not goroutine safe
|
||||||
type BitArray struct {
|
type BitArray struct {
|
||||||
bits uint
|
Bits uint // NOTE: persisted via reflect, must be exported
|
||||||
elems []uint64
|
Elems []uint64 // NOTE: persisted via reflect, must be exported
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewBitArray(bits uint) BitArray {
|
func NewBitArray(bits uint) BitArray {
|
||||||
@ -17,81 +17,81 @@ func NewBitArray(bits uint) BitArray {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (bA BitArray) Size() uint {
|
func (bA BitArray) Size() uint {
|
||||||
return bA.bits
|
return bA.Bits
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bA BitArray) IsZero() bool {
|
func (bA BitArray) IsZero() bool {
|
||||||
return bA.bits == 0
|
return bA.Bits == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: behavior is undefined if i >= bA.bits
|
// NOTE: behavior is undefined if i >= bA.Bits
|
||||||
func (bA BitArray) GetIndex(i uint) bool {
|
func (bA BitArray) GetIndex(i uint) bool {
|
||||||
if i >= bA.bits {
|
if i >= bA.Bits {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return bA.elems[i/64]&uint64(1<<(i%64)) > 0
|
return bA.Elems[i/64]&uint64(1<<(i%64)) > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: behavior is undefined if i >= bA.bits
|
// NOTE: behavior is undefined if i >= bA.Bits
|
||||||
func (bA BitArray) SetIndex(i uint, v bool) bool {
|
func (bA BitArray) SetIndex(i uint, v bool) bool {
|
||||||
if i >= bA.bits {
|
if i >= bA.Bits {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if v {
|
if v {
|
||||||
bA.elems[i/64] |= uint64(1 << (i % 64))
|
bA.Elems[i/64] |= uint64(1 << (i % 64))
|
||||||
} else {
|
} else {
|
||||||
bA.elems[i/64] &= ^uint64(1 << (i % 64))
|
bA.Elems[i/64] &= ^uint64(1 << (i % 64))
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bA BitArray) Copy() BitArray {
|
func (bA BitArray) Copy() BitArray {
|
||||||
c := make([]uint64, len(bA.elems))
|
c := make([]uint64, len(bA.Elems))
|
||||||
copy(c, bA.elems)
|
copy(c, bA.Elems)
|
||||||
return BitArray{bA.bits, c}
|
return BitArray{bA.Bits, c}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bA BitArray) copyBits(bits uint) BitArray {
|
func (bA BitArray) copyBits(bits uint) BitArray {
|
||||||
c := make([]uint64, (bits+63)/64)
|
c := make([]uint64, (bits+63)/64)
|
||||||
copy(c, bA.elems)
|
copy(c, bA.Elems)
|
||||||
return BitArray{bits, c}
|
return BitArray{bits, c}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns a BitArray of larger bits size.
|
// Returns a BitArray of larger bits size.
|
||||||
func (bA BitArray) Or(o BitArray) BitArray {
|
func (bA BitArray) Or(o BitArray) BitArray {
|
||||||
c := bA.copyBits(MaxUint(bA.bits, o.bits))
|
c := bA.copyBits(MaxUint(bA.Bits, o.Bits))
|
||||||
for i := 0; i < len(c.elems); i++ {
|
for i := 0; i < len(c.Elems); i++ {
|
||||||
c.elems[i] |= o.elems[i]
|
c.Elems[i] |= o.Elems[i]
|
||||||
}
|
}
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns a BitArray of smaller bit size.
|
// Returns a BitArray of smaller bit size.
|
||||||
func (bA BitArray) And(o BitArray) BitArray {
|
func (bA BitArray) And(o BitArray) BitArray {
|
||||||
c := bA.copyBits(MinUint(bA.bits, o.bits))
|
c := bA.copyBits(MinUint(bA.Bits, o.Bits))
|
||||||
for i := 0; i < len(c.elems); i++ {
|
for i := 0; i < len(c.Elems); i++ {
|
||||||
c.elems[i] &= o.elems[i]
|
c.Elems[i] &= o.Elems[i]
|
||||||
}
|
}
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bA BitArray) Not() BitArray {
|
func (bA BitArray) Not() BitArray {
|
||||||
c := bA.Copy()
|
c := bA.Copy()
|
||||||
for i := 0; i < len(c.elems); i++ {
|
for i := 0; i < len(c.Elems); i++ {
|
||||||
c.elems[i] = ^c.elems[i]
|
c.Elems[i] = ^c.Elems[i]
|
||||||
}
|
}
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bA BitArray) Sub(o BitArray) BitArray {
|
func (bA BitArray) Sub(o BitArray) BitArray {
|
||||||
if bA.bits > o.bits {
|
if bA.Bits > o.Bits {
|
||||||
c := bA.Copy()
|
c := bA.Copy()
|
||||||
for i := 0; i < len(o.elems)-1; i++ {
|
for i := 0; i < len(o.Elems)-1; i++ {
|
||||||
c.elems[i] &= ^c.elems[i]
|
c.Elems[i] &= ^c.Elems[i]
|
||||||
}
|
}
|
||||||
i := uint(len(o.elems) - 1)
|
i := uint(len(o.Elems) - 1)
|
||||||
if i >= 0 {
|
if i >= 0 {
|
||||||
for idx := i * 64; idx < o.bits; idx++ {
|
for idx := i * 64; idx < o.Bits; idx++ {
|
||||||
c.SetIndex(idx, c.GetIndex(idx) && !o.GetIndex(idx))
|
c.SetIndex(idx, c.GetIndex(idx) && !o.GetIndex(idx))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -102,7 +102,7 @@ func (bA BitArray) Sub(o BitArray) BitArray {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (bA BitArray) PickRandom() (uint, bool) {
|
func (bA BitArray) PickRandom() (uint, bool) {
|
||||||
length := len(bA.elems)
|
length := len(bA.Elems)
|
||||||
if length == 0 {
|
if length == 0 {
|
||||||
return 0, false
|
return 0, false
|
||||||
}
|
}
|
||||||
@ -110,11 +110,11 @@ func (bA BitArray) PickRandom() (uint, bool) {
|
|||||||
for i := 0; i < length; i++ {
|
for i := 0; i < length; i++ {
|
||||||
elemIdx := ((i + randElemStart) % length)
|
elemIdx := ((i + randElemStart) % length)
|
||||||
if elemIdx < length-1 {
|
if elemIdx < length-1 {
|
||||||
if bA.elems[elemIdx] > 0 {
|
if bA.Elems[elemIdx] > 0 {
|
||||||
randBitStart := rand.Intn(64)
|
randBitStart := rand.Intn(64)
|
||||||
for j := 0; j < 64; j++ {
|
for j := 0; j < 64; j++ {
|
||||||
bitIdx := ((j + randBitStart) % 64)
|
bitIdx := ((j + randBitStart) % 64)
|
||||||
if (bA.elems[elemIdx] & (1 << uint(bitIdx))) > 0 {
|
if (bA.Elems[elemIdx] & (1 << uint(bitIdx))) > 0 {
|
||||||
return 64*uint(elemIdx) + uint(bitIdx), true
|
return 64*uint(elemIdx) + uint(bitIdx), true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -122,14 +122,14 @@ func (bA BitArray) PickRandom() (uint, bool) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Special case for last elem, to ignore straggler bits
|
// Special case for last elem, to ignore straggler bits
|
||||||
elemBits := int(bA.bits) % 64
|
elemBits := int(bA.Bits) % 64
|
||||||
if elemBits == 0 {
|
if elemBits == 0 {
|
||||||
elemBits = 64
|
elemBits = 64
|
||||||
}
|
}
|
||||||
randBitStart := rand.Intn(elemBits)
|
randBitStart := rand.Intn(elemBits)
|
||||||
for j := 0; j < elemBits; j++ {
|
for j := 0; j < elemBits; j++ {
|
||||||
bitIdx := ((j + randBitStart) % elemBits)
|
bitIdx := ((j + randBitStart) % elemBits)
|
||||||
if (bA.elems[elemIdx] & (1 << uint(bitIdx))) > 0 {
|
if (bA.Elems[elemIdx] & (1 << uint(bitIdx))) > 0 {
|
||||||
return 64*uint(elemIdx) + uint(bitIdx), true
|
return 64*uint(elemIdx) + uint(bitIdx), true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -145,7 +145,7 @@ func (bA BitArray) String() string {
|
|||||||
func (bA BitArray) StringWithIndent(indent string) string {
|
func (bA BitArray) StringWithIndent(indent string) string {
|
||||||
lines := []string{}
|
lines := []string{}
|
||||||
bits := ""
|
bits := ""
|
||||||
for i := uint(0); i < bA.bits; i++ {
|
for i := uint(0); i < bA.Bits; i++ {
|
||||||
if bA.GetIndex(i) {
|
if bA.GetIndex(i) {
|
||||||
bits += "X"
|
bits += "X"
|
||||||
} else {
|
} else {
|
||||||
@ -165,5 +165,5 @@ func (bA BitArray) StringWithIndent(indent string) string {
|
|||||||
if len(bits) > 0 {
|
if len(bits) > 0 {
|
||||||
lines = append(lines, bits)
|
lines = append(lines, bits)
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("BA{%v:%v}", bA.bits, strings.Join(lines, indent))
|
return fmt.Sprintf("BA{%v:%v}", bA.Bits, strings.Join(lines, indent))
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,10 @@ package common
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
. "github.com/tendermint/tendermint/binary"
|
||||||
)
|
)
|
||||||
|
|
||||||
func randBitArray(bits uint) (BitArray, []byte) {
|
func randBitArray(bits uint) (BitArray, []byte) {
|
||||||
@ -22,19 +25,18 @@ func randBitArray(bits uint) (BitArray, []byte) {
|
|||||||
|
|
||||||
func TestReadWriteEmptyBitarray(t *testing.T) {
|
func TestReadWriteEmptyBitarray(t *testing.T) {
|
||||||
bA1 := BitArray{}
|
bA1 := BitArray{}
|
||||||
buf := new(bytes.Buffer)
|
buf, n, err := new(bytes.Buffer), new(int64), new(error)
|
||||||
_, err := bA1.WriteTo(buf)
|
WriteBinary(bA1, buf, n, err)
|
||||||
if err != nil {
|
if *err != nil {
|
||||||
t.Error("Failed to write empty bitarray")
|
t.Error("Failed to write empty bitarray")
|
||||||
}
|
}
|
||||||
|
|
||||||
var n int64
|
bA2 := ReadBinary(BitArray{}, buf, n, err).(BitArray)
|
||||||
bA2 := ReadBitArray(buf, &n, &err)
|
if *err != nil {
|
||||||
if err != nil {
|
|
||||||
t.Error("Failed to read empty bitarray")
|
t.Error("Failed to read empty bitarray")
|
||||||
}
|
}
|
||||||
if bA2.bits != 0 {
|
if bA2.Bits != 0 {
|
||||||
t.Error("Expected to get bA2.bits 0")
|
t.Error("Expected to get bA2.Bits 0")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,16 +46,17 @@ func TestReadWriteBitarray(t *testing.T) {
|
|||||||
bA1, testData := randBitArray(64*10 + 8) // not divisible by 64
|
bA1, testData := randBitArray(64*10 + 8) // not divisible by 64
|
||||||
|
|
||||||
// Write it
|
// Write it
|
||||||
buf := new(bytes.Buffer)
|
buf, n, err := new(bytes.Buffer), new(int64), new(error)
|
||||||
_, err := bA1.WriteTo(buf)
|
WriteBinary(bA1, buf, n, err)
|
||||||
if err != nil {
|
if *err != nil {
|
||||||
t.Error("Failed to write bitarray")
|
t.Error("Failed to write bitarray")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fmt.Printf("Bytes: %X", buf.Bytes())
|
||||||
|
|
||||||
// Read it
|
// Read it
|
||||||
var n int64
|
bA2 := ReadBinary(BitArray{}, buf, n, err).(BitArray)
|
||||||
bA2 := ReadBitArray(buf, &n, &err)
|
if *err != nil {
|
||||||
if err != nil {
|
|
||||||
t.Error("Failed to read bitarray")
|
t.Error("Failed to read bitarray")
|
||||||
}
|
}
|
||||||
testData2 := make([]byte, len(testData))
|
testData2 := make([]byte, len(testData))
|
||||||
@ -77,13 +80,13 @@ func TestAnd(t *testing.T) {
|
|||||||
bA2, _ := randBitArray(31)
|
bA2, _ := randBitArray(31)
|
||||||
bA3 := bA1.And(bA2)
|
bA3 := bA1.And(bA2)
|
||||||
|
|
||||||
if bA3.bits != 31 {
|
if bA3.Bits != 31 {
|
||||||
t.Error("Expected min bits", bA3.bits)
|
t.Error("Expected min bits", bA3.Bits)
|
||||||
}
|
}
|
||||||
if len(bA3.elems) != len(bA2.elems) {
|
if len(bA3.Elems) != len(bA2.Elems) {
|
||||||
t.Error("Expected min elems length")
|
t.Error("Expected min elems length")
|
||||||
}
|
}
|
||||||
for i := uint(0); i < bA3.bits; i++ {
|
for i := uint(0); i < bA3.Bits; i++ {
|
||||||
expected := bA1.GetIndex(i) && bA2.GetIndex(i)
|
expected := bA1.GetIndex(i) && bA2.GetIndex(i)
|
||||||
if bA3.GetIndex(i) != expected {
|
if bA3.GetIndex(i) != expected {
|
||||||
t.Error("Wrong bit from bA3", i, bA1.GetIndex(i), bA2.GetIndex(i), bA3.GetIndex(i))
|
t.Error("Wrong bit from bA3", i, bA1.GetIndex(i), bA2.GetIndex(i), bA3.GetIndex(i))
|
||||||
@ -97,13 +100,13 @@ func TestOr(t *testing.T) {
|
|||||||
bA2, _ := randBitArray(31)
|
bA2, _ := randBitArray(31)
|
||||||
bA3 := bA1.Or(bA2)
|
bA3 := bA1.Or(bA2)
|
||||||
|
|
||||||
if bA3.bits != 51 {
|
if bA3.Bits != 51 {
|
||||||
t.Error("Expected max bits")
|
t.Error("Expected max bits")
|
||||||
}
|
}
|
||||||
if len(bA3.elems) != len(bA1.elems) {
|
if len(bA3.Elems) != len(bA1.Elems) {
|
||||||
t.Error("Expected max elems length")
|
t.Error("Expected max elems length")
|
||||||
}
|
}
|
||||||
for i := uint(0); i < bA3.bits; i++ {
|
for i := uint(0); i < bA3.Bits; i++ {
|
||||||
expected := bA1.GetIndex(i) || bA2.GetIndex(i)
|
expected := bA1.GetIndex(i) || bA2.GetIndex(i)
|
||||||
if bA3.GetIndex(i) != expected {
|
if bA3.GetIndex(i) != expected {
|
||||||
t.Error("Wrong bit from bA3", i, bA1.GetIndex(i), bA2.GetIndex(i), bA3.GetIndex(i))
|
t.Error("Wrong bit from bA3", i, bA1.GetIndex(i), bA2.GetIndex(i), bA3.GetIndex(i))
|
||||||
@ -117,13 +120,13 @@ func TestSub1(t *testing.T) {
|
|||||||
bA2, _ := randBitArray(51)
|
bA2, _ := randBitArray(51)
|
||||||
bA3 := bA1.Sub(bA2)
|
bA3 := bA1.Sub(bA2)
|
||||||
|
|
||||||
if bA3.bits != bA1.bits {
|
if bA3.Bits != bA1.Bits {
|
||||||
t.Error("Expected bA1 bits")
|
t.Error("Expected bA1 bits")
|
||||||
}
|
}
|
||||||
if len(bA3.elems) != len(bA1.elems) {
|
if len(bA3.Elems) != len(bA1.Elems) {
|
||||||
t.Error("Expected bA1 elems length")
|
t.Error("Expected bA1 elems length")
|
||||||
}
|
}
|
||||||
for i := uint(0); i < bA3.bits; i++ {
|
for i := uint(0); i < bA3.Bits; i++ {
|
||||||
expected := bA1.GetIndex(i)
|
expected := bA1.GetIndex(i)
|
||||||
if bA2.GetIndex(i) {
|
if bA2.GetIndex(i) {
|
||||||
expected = false
|
expected = false
|
||||||
@ -140,15 +143,15 @@ func TestSub2(t *testing.T) {
|
|||||||
bA2, _ := randBitArray(31)
|
bA2, _ := randBitArray(31)
|
||||||
bA3 := bA1.Sub(bA2)
|
bA3 := bA1.Sub(bA2)
|
||||||
|
|
||||||
if bA3.bits != bA1.bits {
|
if bA3.Bits != bA1.Bits {
|
||||||
t.Error("Expected bA1 bits")
|
t.Error("Expected bA1 bits")
|
||||||
}
|
}
|
||||||
if len(bA3.elems) != len(bA1.elems) {
|
if len(bA3.Elems) != len(bA1.Elems) {
|
||||||
t.Error("Expected bA1 elems length")
|
t.Error("Expected bA1 elems length")
|
||||||
}
|
}
|
||||||
for i := uint(0); i < bA3.bits; i++ {
|
for i := uint(0); i < bA3.Bits; i++ {
|
||||||
expected := bA1.GetIndex(i)
|
expected := bA1.GetIndex(i)
|
||||||
if i < bA2.bits && bA2.GetIndex(i) {
|
if i < bA2.Bits && bA2.GetIndex(i) {
|
||||||
expected = false
|
expected = false
|
||||||
}
|
}
|
||||||
if bA3.GetIndex(i) != expected {
|
if bA3.GetIndex(i) != expected {
|
||||||
|
@ -4,7 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
. "github.com/tendermint/tendermint/account"
|
. "github.com/tendermint/tendermint/account"
|
||||||
. "github.com/tendermint/tendermint/blocks"
|
. "github.com/tendermint/tendermint/block"
|
||||||
. "github.com/tendermint/tendermint/common"
|
. "github.com/tendermint/tendermint/common"
|
||||||
"github.com/tendermint/tendermint/state"
|
"github.com/tendermint/tendermint/state"
|
||||||
)
|
)
|
||||||
@ -28,7 +28,7 @@ type POL struct {
|
|||||||
Votes []POLVoteSignature // Prevote and commit signatures in ValidatorSet order.
|
Votes []POLVoteSignature // Prevote and commit signatures in ValidatorSet order.
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns whether +2/3 have voted/committed for BlockHash.
|
// Returns whether +2/3 have prevoted/committed for BlockHash.
|
||||||
func (pol *POL) Verify(valSet *state.ValidatorSet) error {
|
func (pol *POL) Verify(valSet *state.ValidatorSet) error {
|
||||||
|
|
||||||
if uint(len(pol.Votes)) != valSet.Size() {
|
if uint(len(pol.Votes)) != valSet.Size() {
|
||||||
@ -44,27 +44,32 @@ func (pol *POL) Verify(valSet *state.ValidatorSet) error {
|
|||||||
})
|
})
|
||||||
seenValidators := map[string]struct{}{}
|
seenValidators := map[string]struct{}{}
|
||||||
|
|
||||||
for idx, sig := range pol.Votes {
|
for idx, vote := range pol.Votes {
|
||||||
|
// vote may be zero, in which case skip.
|
||||||
|
if vote.Signature.IsZero() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
voteDoc := prevoteDoc
|
voteDoc := prevoteDoc
|
||||||
_, val := valSet.GetByIndex(uint(idx))
|
_, val := valSet.GetByIndex(uint(idx))
|
||||||
|
|
||||||
// Commit signature?
|
// Commit vote?
|
||||||
if sig.Round < pol.Round {
|
if vote.Round < pol.Round {
|
||||||
voteDoc = SignBytes(&Vote{
|
voteDoc = SignBytes(&Vote{
|
||||||
Height: pol.Height, Round: sig.Round, Type: VoteTypeCommit,
|
Height: pol.Height, Round: vote.Round, Type: VoteTypeCommit,
|
||||||
BlockHash: pol.BlockHash,
|
BlockHash: pol.BlockHash,
|
||||||
BlockParts: pol.BlockParts,
|
BlockParts: pol.BlockParts,
|
||||||
})
|
})
|
||||||
} else if sig.Round > pol.Round {
|
} else if vote.Round > pol.Round {
|
||||||
return Errorf("Invalid commit round %v for POL %v", sig.Round, pol)
|
return Errorf("Invalid commit round %v for POL %v", vote.Round, pol)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate
|
// Validate
|
||||||
if _, seen := seenValidators[string(val.Address)]; seen {
|
if _, seen := seenValidators[string(val.Address)]; seen {
|
||||||
return Errorf("Duplicate validator for vote %v for POL %v", sig, pol)
|
return Errorf("Duplicate validator for vote %v for POL %v", vote, pol)
|
||||||
}
|
}
|
||||||
if !val.PubKey.VerifyBytes(voteDoc, sig.Signature.Bytes) {
|
|
||||||
return Errorf("Invalid signature for vote %v for POL %v", sig, pol)
|
if !val.PubKey.VerifyBytes(voteDoc, vote.Signature) {
|
||||||
|
return Errorf("Invalid signature for vote %v for POL %v", vote, pol)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tally
|
// Tally
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
package consensus
|
package consensus
|
||||||
|
|
||||||
import (
|
import (
|
||||||
. "github.com/tendermint/tendermint/blocks"
|
. "github.com/tendermint/tendermint/binary"
|
||||||
|
. "github.com/tendermint/tendermint/block"
|
||||||
. "github.com/tendermint/tendermint/common"
|
. "github.com/tendermint/tendermint/common"
|
||||||
|
state "github.com/tendermint/tendermint/state"
|
||||||
|
|
||||||
"bytes"
|
"bytes"
|
||||||
"testing"
|
"testing"
|
||||||
@ -10,22 +12,30 @@ import (
|
|||||||
|
|
||||||
// NOTE: see consensus/test.go for common test methods.
|
// NOTE: see consensus/test.go for common test methods.
|
||||||
|
|
||||||
|
// Convenience method.
|
||||||
|
// Signs the vote and sets the POL's vote at the desired index
|
||||||
|
// Returns the POLVoteSignature pointer, so you can modify it afterwards.
|
||||||
|
func signAddPOLVoteSignature(val *state.PrivValidator, valSet *state.ValidatorSet, vote *Vote, pol *POL) *POLVoteSignature {
|
||||||
|
idx, _ := valSet.GetByAddress(val.Address) // now we have the index
|
||||||
|
pol.Votes[idx] = POLVoteSignature{vote.Round, val.SignVote(vote)}
|
||||||
|
return &pol.Votes[idx]
|
||||||
|
}
|
||||||
|
|
||||||
func TestVerifyVotes(t *testing.T) {
|
func TestVerifyVotes(t *testing.T) {
|
||||||
height, round := uint32(1), uint16(0)
|
height, round := uint(1), uint(0)
|
||||||
_, valSet, privAccounts := makeVoteSet(height, round, VoteTypePrevote, 10, 1)
|
_, valSet, privValidators := makeVoteSet(height, round, VoteTypePrevote, 10, 1)
|
||||||
|
|
||||||
// Make a POL with -2/3 votes.
|
// Make a POL with -2/3 votes.
|
||||||
blockHash := RandBytes(32)
|
blockHash := RandBytes(32)
|
||||||
pol := &POL{
|
pol := &POL{
|
||||||
Height: height, Round: round, BlockHash: blockHash,
|
Height: height, Round: round, BlockHash: blockHash,
|
||||||
|
Votes: make([]POLVoteSignature, valSet.Size()),
|
||||||
}
|
}
|
||||||
voteProto := &Vote{
|
voteProto := &Vote{
|
||||||
Height: height, Round: round, Type: VoteTypePrevote, BlockHash: blockHash,
|
Height: height, Round: round, Type: VoteTypePrevote, BlockHash: blockHash,
|
||||||
}
|
}
|
||||||
for i := 0; i < 6; i++ {
|
for i := 0; i < 6; i++ {
|
||||||
vote := voteProto.Copy()
|
signAddPOLVoteSignature(privValidators[i], valSet, voteProto, pol)
|
||||||
privAccounts[i].Sign(vote)
|
|
||||||
pol.Votes = append(pol.Votes, vote.Signature)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that validation fails.
|
// Check that validation fails.
|
||||||
@ -33,35 +43,31 @@ func TestVerifyVotes(t *testing.T) {
|
|||||||
t.Errorf("Expected POL.Verify() to fail, not enough votes.")
|
t.Errorf("Expected POL.Verify() to fail, not enough votes.")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make a POL with +2/3 votes.
|
// Insert another vote to make +2/3
|
||||||
vote := voteProto.Copy()
|
signAddPOLVoteSignature(privValidators[7], valSet, voteProto, pol)
|
||||||
privAccounts[7].Sign(vote)
|
|
||||||
pol.Votes = append(pol.Votes, vote.Signature)
|
|
||||||
|
|
||||||
// Check that validation succeeds.
|
// Check that validation succeeds.
|
||||||
if err := pol.Verify(valSet); err != nil {
|
if err := pol.Verify(valSet); err != nil {
|
||||||
t.Errorf("Expected POL.Verify() to succeed")
|
t.Errorf("POL.Verify() failed: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestVerifyInvalidVote(t *testing.T) {
|
func TestVerifyInvalidVote(t *testing.T) {
|
||||||
height, round := uint32(1), uint16(0)
|
height, round := uint(1), uint(0)
|
||||||
_, valSet, privAccounts := makeVoteSet(height, round, VoteTypePrevote, 10, 1)
|
_, valSet, privValidators := makeVoteSet(height, round, VoteTypePrevote, 10, 1)
|
||||||
|
|
||||||
// Make a POL with +2/3 votes with the wrong signature.
|
// Make a POL with +2/3 votes with the wrong signature.
|
||||||
blockHash := RandBytes(32)
|
blockHash := RandBytes(32)
|
||||||
pol := &POL{
|
pol := &POL{
|
||||||
Height: height, Round: round, BlockHash: blockHash,
|
Height: height, Round: round, BlockHash: blockHash,
|
||||||
|
Votes: make([]POLVoteSignature, valSet.Size()),
|
||||||
}
|
}
|
||||||
voteProto := &Vote{
|
voteProto := &Vote{
|
||||||
Height: height, Round: round, Type: VoteTypePrevote, BlockHash: blockHash,
|
Height: height, Round: round, Type: VoteTypePrevote, BlockHash: blockHash,
|
||||||
}
|
}
|
||||||
for i := 0; i < 7; i++ {
|
for i := 0; i < 7; i++ {
|
||||||
vote := voteProto.Copy()
|
polVoteSig := signAddPOLVoteSignature(privValidators[i], valSet, voteProto, pol)
|
||||||
privAccounts[i].Sign(vote)
|
polVoteSig.Signature.Bytes[0] += byte(0x01) // mutated!
|
||||||
// Mutate the signature.
|
|
||||||
vote.Signature.Bytes[0] += byte(0x01)
|
|
||||||
pol.Votes = append(pol.Votes, vote.Signature)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that validation fails.
|
// Check that validation fails.
|
||||||
@ -71,47 +77,44 @@ func TestVerifyInvalidVote(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestVerifyCommits(t *testing.T) {
|
func TestVerifyCommits(t *testing.T) {
|
||||||
height, round := uint32(1), uint16(2)
|
height, round := uint(1), uint(2)
|
||||||
_, valSet, privAccounts := makeVoteSet(height, round, VoteTypePrevote, 10, 1)
|
_, valSet, privValidators := makeVoteSet(height, round, VoteTypePrevote, 10, 1)
|
||||||
|
|
||||||
// Make a POL with +2/3 votes.
|
// Make a POL with +2/3 votes.
|
||||||
blockHash := RandBytes(32)
|
blockHash := RandBytes(32)
|
||||||
pol := &POL{
|
pol := &POL{
|
||||||
Height: height, Round: round, BlockHash: blockHash,
|
Height: height, Round: round, BlockHash: blockHash,
|
||||||
|
Votes: make([]POLVoteSignature, valSet.Size()),
|
||||||
}
|
}
|
||||||
voteProto := &Vote{
|
voteProto := &Vote{
|
||||||
Height: height, Round: round - 1, Type: VoteTypeCommit, BlockHash: blockHash,
|
Height: height, Round: round - 1, Type: VoteTypeCommit, BlockHash: blockHash,
|
||||||
}
|
}
|
||||||
for i := 0; i < 7; i++ {
|
for i := 0; i < 7; i++ {
|
||||||
vote := voteProto.Copy()
|
signAddPOLVoteSignature(privValidators[i], valSet, voteProto, pol)
|
||||||
privAccounts[i].Sign(vote)
|
|
||||||
pol.Commits = append(pol.Commits, RoundSignature{round - 1, vote.Signature})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that validation succeeds.
|
// Check that validation succeeds.
|
||||||
if err := pol.Verify(valSet); err != nil {
|
if err := pol.Verify(valSet); err != nil {
|
||||||
t.Errorf("Expected POL.Verify() to succeed")
|
t.Errorf("POL.Verify() failed: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestVerifyInvalidCommits(t *testing.T) {
|
func TestVerifyInvalidCommits(t *testing.T) {
|
||||||
height, round := uint32(1), uint16(2)
|
height, round := uint(1), uint(2)
|
||||||
_, valSet, privAccounts := makeVoteSet(height, round, VoteTypePrevote, 10, 1)
|
_, valSet, privValidators := makeVoteSet(height, round, VoteTypePrevote, 10, 1)
|
||||||
|
|
||||||
// Make a POL with +2/3 votes with the wrong signature.
|
// Make a POL with +2/3 votes with the wrong signature.
|
||||||
blockHash := RandBytes(32)
|
blockHash := RandBytes(32)
|
||||||
pol := &POL{
|
pol := &POL{
|
||||||
Height: height, Round: round, BlockHash: blockHash,
|
Height: height, Round: round, BlockHash: blockHash,
|
||||||
|
Votes: make([]POLVoteSignature, valSet.Size()),
|
||||||
}
|
}
|
||||||
voteProto := &Vote{
|
voteProto := &Vote{
|
||||||
Height: height, Round: round - 1, Type: VoteTypeCommit, BlockHash: blockHash,
|
Height: height, Round: round - 1, Type: VoteTypeCommit, BlockHash: blockHash,
|
||||||
}
|
}
|
||||||
for i := 0; i < 7; i++ {
|
for i := 0; i < 7; i++ {
|
||||||
vote := voteProto.Copy()
|
polVoteSig := signAddPOLVoteSignature(privValidators[i], valSet, voteProto, pol)
|
||||||
privAccounts[i].Sign(vote)
|
polVoteSig.Signature.Bytes[0] += byte(0x01)
|
||||||
// Mutate the signature.
|
|
||||||
vote.Signature.Bytes[0] += byte(0x01)
|
|
||||||
pol.Commits = append(pol.Commits, RoundSignature{round - 1, vote.Signature})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that validation fails.
|
// Check that validation fails.
|
||||||
@ -121,21 +124,20 @@ func TestVerifyInvalidCommits(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestVerifyInvalidCommitRounds(t *testing.T) {
|
func TestVerifyInvalidCommitRounds(t *testing.T) {
|
||||||
height, round := uint32(1), uint16(2)
|
height, round := uint(1), uint(2)
|
||||||
_, valSet, privAccounts := makeVoteSet(height, round, VoteTypePrevote, 10, 1)
|
_, valSet, privValidators := makeVoteSet(height, round, VoteTypePrevote, 10, 1)
|
||||||
|
|
||||||
// Make a POL with +2/3 commits for the current round.
|
// Make a POL with +2/3 commits for the current round.
|
||||||
blockHash := RandBytes(32)
|
blockHash := RandBytes(32)
|
||||||
pol := &POL{
|
pol := &POL{
|
||||||
Height: height, Round: round, BlockHash: blockHash,
|
Height: height, Round: round, BlockHash: blockHash,
|
||||||
|
Votes: make([]POLVoteSignature, valSet.Size()),
|
||||||
}
|
}
|
||||||
voteProto := &Vote{
|
voteProto := &Vote{
|
||||||
Height: height, Round: round, Type: VoteTypeCommit, BlockHash: blockHash,
|
Height: height, Round: round, Type: VoteTypeCommit, BlockHash: blockHash,
|
||||||
}
|
}
|
||||||
for i := 0; i < 7; i++ {
|
for i := 0; i < 7; i++ {
|
||||||
vote := voteProto.Copy()
|
signAddPOLVoteSignature(privValidators[i], valSet, voteProto, pol)
|
||||||
privAccounts[i].Sign(vote)
|
|
||||||
pol.Commits = append(pol.Commits, RoundSignature{round, vote.Signature})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that validation fails.
|
// Check that validation fails.
|
||||||
@ -145,21 +147,21 @@ func TestVerifyInvalidCommitRounds(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestVerifyInvalidCommitRounds2(t *testing.T) {
|
func TestVerifyInvalidCommitRounds2(t *testing.T) {
|
||||||
height, round := uint32(1), uint16(2)
|
height, round := uint(1), uint(2)
|
||||||
_, valSet, privAccounts := makeVoteSet(height, round, VoteTypePrevote, 10, 1)
|
_, valSet, privValidators := makeVoteSet(height, round, VoteTypePrevote, 10, 1)
|
||||||
|
|
||||||
// Make a POL with +2/3 commits for future round.
|
// Make a POL with +2/3 commits for future round.
|
||||||
blockHash := RandBytes(32)
|
blockHash := RandBytes(32)
|
||||||
pol := &POL{
|
pol := &POL{
|
||||||
Height: height, Round: round, BlockHash: blockHash,
|
Height: height, Round: round, BlockHash: blockHash,
|
||||||
|
Votes: make([]POLVoteSignature, valSet.Size()),
|
||||||
}
|
}
|
||||||
voteProto := &Vote{
|
voteProto := &Vote{
|
||||||
Height: height, Round: round + 1, Type: VoteTypeCommit, BlockHash: blockHash,
|
Height: height, Round: round + 1, Type: VoteTypeCommit, BlockHash: blockHash,
|
||||||
}
|
}
|
||||||
for i := 0; i < 7; i++ {
|
for i := 0; i < 7; i++ {
|
||||||
vote := voteProto.Copy()
|
polVoteSig := signAddPOLVoteSignature(privValidators[i], valSet, voteProto, pol)
|
||||||
privAccounts[i].Sign(vote)
|
polVoteSig.Round += 1 // mutate round
|
||||||
pol.Commits = append(pol.Commits, RoundSignature{round + 1, vote.Signature})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that validation fails.
|
// Check that validation fails.
|
||||||
@ -169,39 +171,37 @@ func TestVerifyInvalidCommitRounds2(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestReadWrite(t *testing.T) {
|
func TestReadWrite(t *testing.T) {
|
||||||
height, round := uint32(1), uint16(2)
|
height, round := uint(1), uint(2)
|
||||||
_, valSet, privAccounts := makeVoteSet(height, round, VoteTypePrevote, 10, 1)
|
_, valSet, privValidators := makeVoteSet(height, round, VoteTypePrevote, 10, 1)
|
||||||
|
|
||||||
// Make a POL with +2/3 votes.
|
// Make a POL with +2/3 votes.
|
||||||
blockHash := RandBytes(32)
|
blockHash := RandBytes(32)
|
||||||
pol := &POL{
|
pol := &POL{
|
||||||
Height: height, Round: round, BlockHash: blockHash,
|
Height: height, Round: round, BlockHash: blockHash,
|
||||||
|
Votes: make([]POLVoteSignature, valSet.Size()),
|
||||||
}
|
}
|
||||||
voteProto := &Vote{
|
voteProto := &Vote{
|
||||||
Height: height, Round: round, Type: VoteTypePrevote, BlockHash: blockHash,
|
Height: height, Round: round, Type: VoteTypePrevote, BlockHash: blockHash,
|
||||||
}
|
}
|
||||||
for i := 0; i < 7; i++ {
|
for i := 0; i < 7; i++ {
|
||||||
vote := voteProto.Copy()
|
signAddPOLVoteSignature(privValidators[i], valSet, voteProto, pol)
|
||||||
privAccounts[i].Sign(vote)
|
|
||||||
pol.Votes = append(pol.Votes, vote.Signature)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write it to a buffer.
|
// Write it to a buffer.
|
||||||
buf := new(bytes.Buffer)
|
buf, n, err := new(bytes.Buffer), new(int64), new(error)
|
||||||
_, err := pol.WriteTo(buf)
|
WriteBinary(pol, buf, n, err)
|
||||||
if err != nil {
|
if *err != nil {
|
||||||
t.Fatalf("Failed to write POL")
|
t.Fatalf("Failed to write POL: %v", *err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read from buffer.
|
// Read from buffer.
|
||||||
var n int64
|
pol2 := ReadBinary(&POL{}, buf, n, err).(*POL)
|
||||||
pol2 := ReadPOL(buf, &n, &err)
|
if *err != nil {
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Failed to read POL")
|
t.Fatalf("Failed to read POL")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that validation succeeds.
|
// Check that validation succeeds.
|
||||||
if err := pol2.Verify(valSet); err != nil {
|
if err := pol2.Verify(valSet); err != nil {
|
||||||
t.Errorf("Expected POL.Verify() to succeed")
|
t.Errorf("POL.Verify() failed: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,8 +9,9 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
. "github.com/tendermint/tendermint/binary"
|
. "github.com/tendermint/tendermint/binary"
|
||||||
. "github.com/tendermint/tendermint/blocks"
|
. "github.com/tendermint/tendermint/block"
|
||||||
. "github.com/tendermint/tendermint/common"
|
. "github.com/tendermint/tendermint/common"
|
||||||
|
. "github.com/tendermint/tendermint/consensus/types"
|
||||||
"github.com/tendermint/tendermint/mempool"
|
"github.com/tendermint/tendermint/mempool"
|
||||||
"github.com/tendermint/tendermint/p2p"
|
"github.com/tendermint/tendermint/p2p"
|
||||||
"github.com/tendermint/tendermint/state"
|
"github.com/tendermint/tendermint/state"
|
||||||
@ -198,7 +199,7 @@ func (conR *ConsensusReactor) Receive(chId byte, peer *p2p.Peer, msgBytes []byte
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Sets our private validator account for signing votes.
|
// Sets our private validator account for signing votes.
|
||||||
func (conR *ConsensusReactor) SetPrivValidator(priv *PrivValidator) {
|
func (conR *ConsensusReactor) SetPrivValidator(priv *state.PrivValidator) {
|
||||||
conR.conS.SetPrivValidator(priv)
|
conR.conS.SetPrivValidator(priv)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,9 +62,10 @@ import (
|
|||||||
|
|
||||||
. "github.com/tendermint/tendermint/account"
|
. "github.com/tendermint/tendermint/account"
|
||||||
. "github.com/tendermint/tendermint/binary"
|
. "github.com/tendermint/tendermint/binary"
|
||||||
. "github.com/tendermint/tendermint/blocks"
|
. "github.com/tendermint/tendermint/block"
|
||||||
. "github.com/tendermint/tendermint/common"
|
. "github.com/tendermint/tendermint/common"
|
||||||
. "github.com/tendermint/tendermint/config"
|
. "github.com/tendermint/tendermint/config"
|
||||||
|
. "github.com/tendermint/tendermint/consensus/types"
|
||||||
"github.com/tendermint/tendermint/mempool"
|
"github.com/tendermint/tendermint/mempool"
|
||||||
"github.com/tendermint/tendermint/state"
|
"github.com/tendermint/tendermint/state"
|
||||||
)
|
)
|
||||||
@ -126,7 +127,7 @@ type RoundState struct {
|
|||||||
Precommits *VoteSet
|
Precommits *VoteSet
|
||||||
Commits *VoteSet
|
Commits *VoteSet
|
||||||
LastCommits *VoteSet
|
LastCommits *VoteSet
|
||||||
PrivValidator *PrivValidator
|
PrivValidator *state.PrivValidator
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rs *RoundState) String() string {
|
func (rs *RoundState) String() string {
|
||||||
@ -469,7 +470,7 @@ func (cs *ConsensusState) setupNewRound(round uint) {
|
|||||||
cs.Precommits.AddFromCommits(cs.Commits)
|
cs.Precommits.AddFromCommits(cs.Commits)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cs *ConsensusState) SetPrivValidator(priv *PrivValidator) {
|
func (cs *ConsensusState) SetPrivValidator(priv *state.PrivValidator) {
|
||||||
cs.mtx.Lock()
|
cs.mtx.Lock()
|
||||||
defer cs.mtx.Unlock()
|
defer cs.mtx.Unlock()
|
||||||
cs.PrivValidator = priv
|
cs.PrivValidator = priv
|
||||||
|
@ -1,77 +1,33 @@
|
|||||||
package consensus
|
package consensus
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
|
||||||
|
|
||||||
. "github.com/tendermint/tendermint/blocks"
|
. "github.com/tendermint/tendermint/block"
|
||||||
. "github.com/tendermint/tendermint/common"
|
|
||||||
db_ "github.com/tendermint/tendermint/db"
|
|
||||||
"github.com/tendermint/tendermint/mempool"
|
|
||||||
"github.com/tendermint/tendermint/state"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func randAccountDetail(id uint64, status byte) (*state.AccountDetail, *state.PrivAccount) {
|
|
||||||
privAccount := state.GenPrivAccount()
|
|
||||||
privAccount.Id = id
|
|
||||||
account := privAccount.Account
|
|
||||||
return &state.AccountDetail{
|
|
||||||
Account: account,
|
|
||||||
Sequence: RandUInt(),
|
|
||||||
Balance: 1000,
|
|
||||||
Status: status,
|
|
||||||
}, privAccount
|
|
||||||
}
|
|
||||||
|
|
||||||
// The first numValidators accounts are validators.
|
|
||||||
func randGenesisState(numAccounts int, numValidators int) (*state.State, []*state.PrivAccount) {
|
|
||||||
db := db_.NewMemDB()
|
|
||||||
accountDetails := make([]*state.AccountDetail, numAccounts)
|
|
||||||
privAccounts := make([]*state.PrivAccount, numAccounts)
|
|
||||||
for i := 0; i < numAccounts; i++ {
|
|
||||||
if i < numValidators {
|
|
||||||
accountDetails[i], privAccounts[i] =
|
|
||||||
randAccountDetail(uint64(i), state.AccountStatusBonded)
|
|
||||||
} else {
|
|
||||||
accountDetails[i], privAccounts[i] =
|
|
||||||
randAccountDetail(uint64(i), state.AccountStatusNominal)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
s0 := state.GenesisState(db, time.Now(), accountDetails)
|
|
||||||
s0.Save()
|
|
||||||
return s0, privAccounts
|
|
||||||
}
|
|
||||||
|
|
||||||
func makeConsensusState() (*ConsensusState, []*state.PrivAccount) {
|
|
||||||
state, privAccounts := randGenesisState(20, 10)
|
|
||||||
blockStore := NewBlockStore(db_.NewMemDB())
|
|
||||||
mempool := mempool.NewMempool(state)
|
|
||||||
cs := NewConsensusState(state, blockStore, mempool)
|
|
||||||
return cs, privAccounts
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
func TestSetupRound(t *testing.T) {
|
func TestSetupRound(t *testing.T) {
|
||||||
cs, privAccounts := makeConsensusState()
|
cs, privValidators := makeConsensusState()
|
||||||
|
val0 := privValidators[0]
|
||||||
|
|
||||||
// Add a vote, precommit, and commit by val0.
|
// Add a vote, precommit, and commit by val0.
|
||||||
voteTypes := []byte{VoteTypePrevote, VoteTypePrecommit, VoteTypeCommit}
|
voteTypes := []byte{VoteTypePrevote, VoteTypePrecommit, VoteTypeCommit}
|
||||||
for _, voteType := range voteTypes {
|
for _, voteType := range voteTypes {
|
||||||
vote := &Vote{Height: 1, Round: 0, Type: voteType} // nil vote
|
vote := &Vote{Height: 1, Round: 0, Type: voteType} // nil vote
|
||||||
privAccounts[0].Sign(vote)
|
vote.Signature = val0.SignVote(vote)
|
||||||
cs.AddVote(vote)
|
cs.AddVote(val0.Address, vote)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure that vote appears in RoundState.
|
// Ensure that vote appears in RoundState.
|
||||||
rs0 := cs.GetRoundState()
|
rs0 := cs.GetRoundState()
|
||||||
if vote := rs0.Prevotes.GetById(0); vote == nil || vote.Type != VoteTypePrevote {
|
if vote := rs0.Prevotes.GetByAddress(val0.Address); vote == nil || vote.Type != VoteTypePrevote {
|
||||||
t.Errorf("Expected to find prevote but got %v", vote)
|
t.Errorf("Expected to find prevote but got %v", vote)
|
||||||
}
|
}
|
||||||
if vote := rs0.Precommits.GetById(0); vote == nil || vote.Type != VoteTypePrecommit {
|
if vote := rs0.Precommits.GetByAddress(val0.Address); vote == nil || vote.Type != VoteTypePrecommit {
|
||||||
t.Errorf("Expected to find precommit but got %v", vote)
|
t.Errorf("Expected to find precommit but got %v", vote)
|
||||||
}
|
}
|
||||||
if vote := rs0.Commits.GetById(0); vote == nil || vote.Type != VoteTypeCommit {
|
if vote := rs0.Commits.GetByAddress(val0.Address); vote == nil || vote.Type != VoteTypeCommit {
|
||||||
t.Errorf("Expected to find commit but got %v", vote)
|
t.Errorf("Expected to find commit but got %v", vote)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,13 +37,13 @@ func TestSetupRound(t *testing.T) {
|
|||||||
|
|
||||||
// Now the commit should be copied over to prevotes and precommits.
|
// Now the commit should be copied over to prevotes and precommits.
|
||||||
rs1 := cs.GetRoundState()
|
rs1 := cs.GetRoundState()
|
||||||
if vote := rs1.Prevotes.GetById(0); vote == nil || vote.Type != VoteTypeCommit {
|
if vote := rs1.Prevotes.GetByAddress(val0.Address); vote == nil || vote.Type != VoteTypeCommit {
|
||||||
t.Errorf("Expected to find commit but got %v", vote)
|
t.Errorf("Expected to find commit but got %v", vote)
|
||||||
}
|
}
|
||||||
if vote := rs1.Precommits.GetById(0); vote == nil || vote.Type != VoteTypeCommit {
|
if vote := rs1.Precommits.GetByAddress(val0.Address); vote == nil || vote.Type != VoteTypeCommit {
|
||||||
t.Errorf("Expected to find commit but got %v", vote)
|
t.Errorf("Expected to find commit but got %v", vote)
|
||||||
}
|
}
|
||||||
if vote := rs1.Commits.GetById(0); vote == nil || vote.Type != VoteTypeCommit {
|
if vote := rs1.Commits.GetByAddress(val0.Address); vote == nil || vote.Type != VoteTypeCommit {
|
||||||
t.Errorf("Expected to find commit but got %v", vote)
|
t.Errorf("Expected to find commit but got %v", vote)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,9 +59,9 @@ func TestRunActionProposeNoPrivValidator(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestRunActionPropose(t *testing.T) {
|
func TestRunActionPropose(t *testing.T) {
|
||||||
cs, privAccounts := makeConsensusState()
|
cs, privValidators := makeConsensusState()
|
||||||
priv := NewPrivValidator(db_.NewMemDB(), privAccounts[0])
|
val0 := privValidators[0]
|
||||||
cs.SetPrivValidator(priv)
|
cs.SetPrivValidator(val0)
|
||||||
|
|
||||||
cs.RunActionPropose(1, 0)
|
cs.RunActionPropose(1, 0)
|
||||||
rs := cs.GetRoundState()
|
rs := cs.GetRoundState()
|
||||||
@ -123,7 +79,7 @@ func TestRunActionPropose(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func checkRoundState(t *testing.T, rs *RoundState,
|
func checkRoundState(t *testing.T, rs *RoundState,
|
||||||
height uint32, round uint16, step RoundStep) {
|
height uint, round uint, step RoundStep) {
|
||||||
if rs.Height != height {
|
if rs.Height != height {
|
||||||
t.Errorf("rs.Height should be %v, got %v", height, rs.Height)
|
t.Errorf("rs.Height should be %v, got %v", height, rs.Height)
|
||||||
}
|
}
|
||||||
@ -136,13 +92,13 @@ func checkRoundState(t *testing.T, rs *RoundState,
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestRunActionPrecommitCommitFinalize(t *testing.T) {
|
func TestRunActionPrecommitCommitFinalize(t *testing.T) {
|
||||||
cs, privAccounts := makeConsensusState()
|
cs, privValidators := makeConsensusState()
|
||||||
priv := NewPrivValidator(db_.NewMemDB(), privAccounts[0])
|
val0 := privValidators[0]
|
||||||
cs.SetPrivValidator(priv)
|
cs.SetPrivValidator(val0)
|
||||||
|
|
||||||
cs.RunActionPrecommit(1, 0)
|
cs.RunActionPrecommit(1, 0)
|
||||||
<-cs.NewStepCh() // TODO: test this value too.
|
<-cs.NewStepCh() // TODO: test this value too.
|
||||||
if cs.Precommits.GetById(0) != nil {
|
if cs.Precommits.GetByAddress(val0.Address) != nil {
|
||||||
t.Errorf("RunActionPrecommit should return nil without a proposal")
|
t.Errorf("RunActionPrecommit should return nil without a proposal")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,7 +107,7 @@ func TestRunActionPrecommitCommitFinalize(t *testing.T) {
|
|||||||
|
|
||||||
cs.RunActionPrecommit(1, 0)
|
cs.RunActionPrecommit(1, 0)
|
||||||
<-cs.NewStepCh() // TODO: test this value too.
|
<-cs.NewStepCh() // TODO: test this value too.
|
||||||
if cs.Precommits.GetById(0) != nil {
|
if cs.Precommits.GetByAddress(val0.Address) != nil {
|
||||||
t.Errorf("RunActionPrecommit should return nil, not enough prevotes")
|
t.Errorf("RunActionPrecommit should return nil, not enough prevotes")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -164,20 +120,26 @@ func TestRunActionPrecommitCommitFinalize(t *testing.T) {
|
|||||||
BlockHash: cs.ProposalBlock.Hash(),
|
BlockHash: cs.ProposalBlock.Hash(),
|
||||||
BlockParts: cs.ProposalBlockParts.Header(),
|
BlockParts: cs.ProposalBlockParts.Header(),
|
||||||
}
|
}
|
||||||
privAccounts[i].Sign(vote)
|
vote.Signature = privValidators[i].SignVote(vote)
|
||||||
cs.AddVote(vote)
|
cs.AddVote(privValidators[i].Address, vote)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test RunActionPrecommit success:
|
// Test RunActionPrecommit success:
|
||||||
cs.RunActionPrecommit(1, 0)
|
cs.RunActionPrecommit(1, 0)
|
||||||
<-cs.NewStepCh() // TODO: test this value too.
|
<-cs.NewStepCh() // TODO: test this value too.
|
||||||
if cs.Precommits.GetById(0) == nil {
|
if cs.Precommits.GetByAddress(val0.Address) == nil {
|
||||||
t.Errorf("RunActionPrecommit should have succeeded")
|
t.Errorf("RunActionPrecommit should have succeeded")
|
||||||
}
|
}
|
||||||
checkRoundState(t, cs.GetRoundState(), 1, 0, RoundStepPrecommit)
|
checkRoundState(t, cs.GetRoundState(), 1, 0, RoundStepPrecommit)
|
||||||
|
|
||||||
// Add at least +2/3 precommits.
|
// Add at least +2/3 precommits.
|
||||||
for i := 0; i < 7; i++ {
|
for i := 0; i < 7; i++ {
|
||||||
|
if bytes.Equal(privValidators[i].Address, val0.Address) {
|
||||||
|
if cs.Precommits.GetByAddress(val0.Address) == nil {
|
||||||
|
t.Errorf("Proposer should already have signed a precommit vote")
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
vote := &Vote{
|
vote := &Vote{
|
||||||
Height: 1,
|
Height: 1,
|
||||||
Round: 0,
|
Round: 0,
|
||||||
@ -185,14 +147,17 @@ func TestRunActionPrecommitCommitFinalize(t *testing.T) {
|
|||||||
BlockHash: cs.ProposalBlock.Hash(),
|
BlockHash: cs.ProposalBlock.Hash(),
|
||||||
BlockParts: cs.ProposalBlockParts.Header(),
|
BlockParts: cs.ProposalBlockParts.Header(),
|
||||||
}
|
}
|
||||||
privAccounts[i].Sign(vote)
|
vote.Signature = privValidators[i].SignVote(vote)
|
||||||
cs.AddVote(vote)
|
added, _, err := cs.AddVote(privValidators[i].Address, vote)
|
||||||
|
if !added || err != nil {
|
||||||
|
t.Errorf("Error adding precommit: %v", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test RunActionCommit success:
|
// Test RunActionCommit success:
|
||||||
cs.RunActionCommit(1)
|
cs.RunActionCommit(1)
|
||||||
<-cs.NewStepCh() // TODO: test this value too.
|
<-cs.NewStepCh() // TODO: test this value too.
|
||||||
if cs.Commits.GetById(0) == nil {
|
if cs.Commits.GetByAddress(val0.Address) == nil {
|
||||||
t.Errorf("RunActionCommit should have succeeded")
|
t.Errorf("RunActionCommit should have succeeded")
|
||||||
}
|
}
|
||||||
checkRoundState(t, cs.GetRoundState(), 1, 0, RoundStepCommit)
|
checkRoundState(t, cs.GetRoundState(), 1, 0, RoundStepCommit)
|
||||||
@ -204,15 +169,24 @@ func TestRunActionPrecommitCommitFinalize(t *testing.T) {
|
|||||||
|
|
||||||
// Add at least +2/3 commits.
|
// Add at least +2/3 commits.
|
||||||
for i := 0; i < 7; i++ {
|
for i := 0; i < 7; i++ {
|
||||||
|
if bytes.Equal(privValidators[i].Address, val0.Address) {
|
||||||
|
if cs.Commits.GetByAddress(val0.Address) == nil {
|
||||||
|
t.Errorf("Proposer should already have signed a commit vote")
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
vote := &Vote{
|
vote := &Vote{
|
||||||
Height: 1,
|
Height: 1,
|
||||||
Round: uint16(i), // Doesn't matter what round
|
Round: uint(i), // Doesn't matter what round
|
||||||
Type: VoteTypeCommit,
|
Type: VoteTypeCommit,
|
||||||
BlockHash: cs.ProposalBlock.Hash(),
|
BlockHash: cs.ProposalBlock.Hash(),
|
||||||
BlockParts: cs.ProposalBlockParts.Header(),
|
BlockParts: cs.ProposalBlockParts.Header(),
|
||||||
}
|
}
|
||||||
privAccounts[i].Sign(vote)
|
vote.Signature = privValidators[i].SignVote(vote)
|
||||||
cs.AddVote(vote)
|
added, _, err := cs.AddVote(privValidators[i].Address, vote)
|
||||||
|
if !added || err != nil {
|
||||||
|
t.Errorf("Error adding commit: %v", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test TryFinalizeCommit:
|
// Test TryFinalizeCommit:
|
||||||
|
@ -1,13 +1,18 @@
|
|||||||
package consensus
|
package consensus
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"sort"
|
||||||
|
|
||||||
|
. "github.com/tendermint/tendermint/block"
|
||||||
|
db_ "github.com/tendermint/tendermint/db"
|
||||||
|
mempool_ "github.com/tendermint/tendermint/mempool"
|
||||||
"github.com/tendermint/tendermint/state"
|
"github.com/tendermint/tendermint/state"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Common test methods
|
// Common test methods
|
||||||
|
|
||||||
func makeValidator(votingPower uint64) (*state.Validator, *PrivValidator) {
|
func makeValidator(votingPower uint64) (*state.Validator, *state.PrivValidator) {
|
||||||
privValidator := GenPrivValidator()
|
privValidator := state.GenPrivValidator()
|
||||||
return &state.Validator{
|
return &state.Validator{
|
||||||
Address: privValidator.Address,
|
Address: privValidator.Address,
|
||||||
PubKey: privValidator.PubKey,
|
PubKey: privValidator.PubKey,
|
||||||
@ -19,14 +24,24 @@ func makeValidator(votingPower uint64) (*state.Validator, *PrivValidator) {
|
|||||||
}, privValidator
|
}, privValidator
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeVoteSet(height uint, round uint, type_ byte, numValidators int, votingPower uint64) (*VoteSet, *state.ValidatorSet, []*PrivValidator) {
|
func makeVoteSet(height uint, round uint, type_ byte, numValidators int, votingPower uint64) (*VoteSet, *state.ValidatorSet, []*state.PrivValidator) {
|
||||||
vals := make([]*state.Validator, numValidators)
|
vals := make([]*state.Validator, numValidators)
|
||||||
privValidators := make([]*PrivValidator, numValidators)
|
privValidators := make([]*state.PrivValidator, numValidators)
|
||||||
for i := 0; i < numValidators; i++ {
|
for i := 0; i < numValidators; i++ {
|
||||||
val, privValidator := makeValidator(votingPower)
|
val, privValidator := makeValidator(votingPower)
|
||||||
vals[i] = val
|
vals[i] = val
|
||||||
privValidators[i] = privValidator
|
privValidators[i] = privValidator
|
||||||
}
|
}
|
||||||
valSet := state.NewValidatorSet(vals)
|
valSet := state.NewValidatorSet(vals)
|
||||||
|
sort.Sort(state.PrivValidatorsByAddress(privValidators))
|
||||||
return NewVoteSet(height, round, type_, valSet), valSet, privValidators
|
return NewVoteSet(height, round, type_, valSet), valSet, privValidators
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func makeConsensusState() (*ConsensusState, []*state.PrivValidator) {
|
||||||
|
state, _, privValidators := state.RandGenesisState(20, false, 1000, 10, false, 1000)
|
||||||
|
blockStore := NewBlockStore(db_.NewMemDB())
|
||||||
|
mempool := mempool_.NewMempool(state)
|
||||||
|
mempoolReactor := mempool_.NewMempoolReactor(mempool)
|
||||||
|
cs := NewConsensusState(state, blockStore, mempoolReactor)
|
||||||
|
return cs, privValidators
|
||||||
|
}
|
||||||
|
@ -7,7 +7,7 @@ import (
|
|||||||
|
|
||||||
. "github.com/tendermint/tendermint/account"
|
. "github.com/tendermint/tendermint/account"
|
||||||
. "github.com/tendermint/tendermint/binary"
|
. "github.com/tendermint/tendermint/binary"
|
||||||
. "github.com/tendermint/tendermint/blocks"
|
. "github.com/tendermint/tendermint/block"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
@ -8,7 +8,7 @@ import (
|
|||||||
|
|
||||||
. "github.com/tendermint/tendermint/account"
|
. "github.com/tendermint/tendermint/account"
|
||||||
. "github.com/tendermint/tendermint/binary"
|
. "github.com/tendermint/tendermint/binary"
|
||||||
. "github.com/tendermint/tendermint/blocks"
|
. "github.com/tendermint/tendermint/block"
|
||||||
. "github.com/tendermint/tendermint/common"
|
. "github.com/tendermint/tendermint/common"
|
||||||
"github.com/tendermint/tendermint/state"
|
"github.com/tendermint/tendermint/state"
|
||||||
)
|
)
|
||||||
@ -128,6 +128,9 @@ func (voteSet *VoteSet) addVote(valIndex uint, vote *Vote) (bool, uint, error) {
|
|||||||
// Assumes that commits VoteSet is valid.
|
// Assumes that commits VoteSet is valid.
|
||||||
func (voteSet *VoteSet) AddFromCommits(commits *VoteSet) {
|
func (voteSet *VoteSet) AddFromCommits(commits *VoteSet) {
|
||||||
for valIndex, commit := range commits.votes {
|
for valIndex, commit := range commits.votes {
|
||||||
|
if commit == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
if commit.Round < voteSet.round {
|
if commit.Round < voteSet.round {
|
||||||
voteSet.addVote(uint(valIndex), commit)
|
voteSet.addVote(uint(valIndex), commit)
|
||||||
}
|
}
|
||||||
@ -197,6 +200,9 @@ func (voteSet *VoteSet) MakePOL() *POL {
|
|||||||
Votes: make([]POLVoteSignature, voteSet.valSet.Size()),
|
Votes: make([]POLVoteSignature, voteSet.valSet.Size()),
|
||||||
}
|
}
|
||||||
for valIndex, vote := range voteSet.votes {
|
for valIndex, vote := range voteSet.votes {
|
||||||
|
if vote == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
if !bytes.Equal(vote.BlockHash, voteSet.maj23Hash) {
|
if !bytes.Equal(vote.BlockHash, voteSet.maj23Hash) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -245,14 +251,13 @@ func (voteSet *VoteSet) String() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (voteSet *VoteSet) StringWithIndent(indent string) string {
|
func (voteSet *VoteSet) StringWithIndent(indent string) string {
|
||||||
voteSet.mtx.Lock()
|
|
||||||
defer voteSet.mtx.Unlock()
|
|
||||||
|
|
||||||
voteStrings := make([]string, len(voteSet.votes))
|
voteStrings := make([]string, len(voteSet.votes))
|
||||||
counter := 0
|
for i, vote := range voteSet.votes {
|
||||||
for _, vote := range voteSet.votes {
|
if vote == nil {
|
||||||
voteStrings[counter] = vote.String()
|
voteStrings[i] = "nil"
|
||||||
counter++
|
} else {
|
||||||
|
voteStrings[i] = vote.String()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return fmt.Sprintf(`VoteSet{
|
return fmt.Sprintf(`VoteSet{
|
||||||
%s H:%v R:%v T:%v
|
%s H:%v R:%v T:%v
|
||||||
|
@ -3,7 +3,7 @@ package consensus
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
|
||||||
. "github.com/tendermint/tendermint/blocks"
|
. "github.com/tendermint/tendermint/block"
|
||||||
. "github.com/tendermint/tendermint/common"
|
. "github.com/tendermint/tendermint/common"
|
||||||
. "github.com/tendermint/tendermint/common/test"
|
. "github.com/tendermint/tendermint/common/test"
|
||||||
|
|
||||||
@ -13,13 +13,14 @@ import (
|
|||||||
// NOTE: see consensus/test.go for common test methods.
|
// NOTE: see consensus/test.go for common test methods.
|
||||||
|
|
||||||
func TestAddVote(t *testing.T) {
|
func TestAddVote(t *testing.T) {
|
||||||
height, round := uint32(1), uint16(0)
|
height, round := uint(1), uint(0)
|
||||||
voteSet, _, privAccounts := makeVoteSet(height, round, VoteTypePrevote, 10, 1)
|
voteSet, _, privValidators := makeVoteSet(height, round, VoteTypePrevote, 10, 1)
|
||||||
|
val0 := privValidators[0]
|
||||||
|
|
||||||
// t.Logf(">> %v", voteSet)
|
// t.Logf(">> %v", voteSet)
|
||||||
|
|
||||||
if voteSet.GetById(0) != nil {
|
if voteSet.GetByAddress(val0.Address) != nil {
|
||||||
t.Errorf("Expected GetById(0) to be nil")
|
t.Errorf("Expected GetByAddress(val0.Address) to be nil")
|
||||||
}
|
}
|
||||||
if voteSet.BitArray().GetIndex(0) {
|
if voteSet.BitArray().GetIndex(0) {
|
||||||
t.Errorf("Expected BitArray.GetIndex(0) to be false")
|
t.Errorf("Expected BitArray.GetIndex(0) to be false")
|
||||||
@ -30,11 +31,11 @@ func TestAddVote(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
vote := &Vote{Height: height, Round: round, Type: VoteTypePrevote, BlockHash: nil}
|
vote := &Vote{Height: height, Round: round, Type: VoteTypePrevote, BlockHash: nil}
|
||||||
privAccounts[0].Sign(vote)
|
vote.Signature = val0.SignVoteUnsafe(vote)
|
||||||
voteSet.Add(vote)
|
voteSet.Add(val0.Address, vote)
|
||||||
|
|
||||||
if voteSet.GetById(0) == nil {
|
if voteSet.GetByAddress(val0.Address) == nil {
|
||||||
t.Errorf("Expected GetById(0) to be present")
|
t.Errorf("Expected GetByAddress(val0.Address) to be present")
|
||||||
}
|
}
|
||||||
if !voteSet.BitArray().GetIndex(0) {
|
if !voteSet.BitArray().GetIndex(0) {
|
||||||
t.Errorf("Expected BitArray.GetIndex(0) to be true")
|
t.Errorf("Expected BitArray.GetIndex(0) to be true")
|
||||||
@ -46,15 +47,15 @@ func TestAddVote(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Test2_3Majority(t *testing.T) {
|
func Test2_3Majority(t *testing.T) {
|
||||||
height, round := uint32(1), uint16(0)
|
height, round := uint(1), uint(0)
|
||||||
voteSet, _, privAccounts := makeVoteSet(height, round, VoteTypePrevote, 10, 1)
|
voteSet, _, privValidators := makeVoteSet(height, round, VoteTypePrevote, 10, 1)
|
||||||
|
|
||||||
// 6 out of 10 voted for nil.
|
// 6 out of 10 voted for nil.
|
||||||
voteProto := &Vote{Height: height, Round: round, Type: VoteTypePrevote, BlockHash: nil}
|
voteProto := &Vote{Height: height, Round: round, Type: VoteTypePrevote, BlockHash: nil}
|
||||||
for i := 0; i < 6; i++ {
|
for i := 0; i < 6; i++ {
|
||||||
vote := voteProto.Copy()
|
vote := voteProto.Copy()
|
||||||
privAccounts[i].Sign(vote)
|
vote.Signature = privValidators[i].SignVoteUnsafe(vote)
|
||||||
voteSet.Add(vote)
|
voteSet.Add(privValidators[i].Address, vote)
|
||||||
}
|
}
|
||||||
hash, header, ok := voteSet.TwoThirdsMajority()
|
hash, header, ok := voteSet.TwoThirdsMajority()
|
||||||
if hash != nil || !header.IsZero() || ok {
|
if hash != nil || !header.IsZero() || ok {
|
||||||
@ -65,8 +66,8 @@ func Test2_3Majority(t *testing.T) {
|
|||||||
{
|
{
|
||||||
vote := voteProto.Copy()
|
vote := voteProto.Copy()
|
||||||
vote.BlockHash = CRandBytes(32)
|
vote.BlockHash = CRandBytes(32)
|
||||||
privAccounts[6].Sign(vote)
|
vote.Signature = privValidators[6].SignVoteUnsafe(vote)
|
||||||
voteSet.Add(vote)
|
voteSet.Add(privValidators[6].Address, vote)
|
||||||
hash, header, ok = voteSet.TwoThirdsMajority()
|
hash, header, ok = voteSet.TwoThirdsMajority()
|
||||||
if hash != nil || !header.IsZero() || ok {
|
if hash != nil || !header.IsZero() || ok {
|
||||||
t.Errorf("There should be no 2/3 majority")
|
t.Errorf("There should be no 2/3 majority")
|
||||||
@ -77,8 +78,8 @@ func Test2_3Majority(t *testing.T) {
|
|||||||
{
|
{
|
||||||
vote := voteProto.Copy()
|
vote := voteProto.Copy()
|
||||||
vote.BlockHash = nil
|
vote.BlockHash = nil
|
||||||
privAccounts[7].Sign(vote)
|
vote.Signature = privValidators[7].SignVoteUnsafe(vote)
|
||||||
voteSet.Add(vote)
|
voteSet.Add(privValidators[7].Address, vote)
|
||||||
hash, header, ok = voteSet.TwoThirdsMajority()
|
hash, header, ok = voteSet.TwoThirdsMajority()
|
||||||
if hash != nil || !header.IsZero() || !ok {
|
if hash != nil || !header.IsZero() || !ok {
|
||||||
t.Errorf("There should be 2/3 majority for nil")
|
t.Errorf("There should be 2/3 majority for nil")
|
||||||
@ -87,19 +88,19 @@ func Test2_3Majority(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Test2_3MajorityRedux(t *testing.T) {
|
func Test2_3MajorityRedux(t *testing.T) {
|
||||||
height, round := uint32(1), uint16(0)
|
height, round := uint(1), uint(0)
|
||||||
voteSet, _, privAccounts := makeVoteSet(height, round, VoteTypePrevote, 100, 1)
|
voteSet, _, privValidators := makeVoteSet(height, round, VoteTypePrevote, 100, 1)
|
||||||
|
|
||||||
blockHash := CRandBytes(32)
|
blockHash := CRandBytes(32)
|
||||||
blockPartsTotal := uint16(123)
|
blockPartsTotal := uint(123)
|
||||||
blockParts := PartSetHeader{blockPartsTotal, CRandBytes(32)}
|
blockParts := PartSetHeader{blockPartsTotal, CRandBytes(32)}
|
||||||
|
|
||||||
// 66 out of 100 voted for nil.
|
// 66 out of 100 voted for nil.
|
||||||
voteProto := &Vote{Height: height, Round: round, Type: VoteTypePrevote, BlockHash: blockHash, BlockParts: blockParts}
|
voteProto := &Vote{Height: height, Round: round, Type: VoteTypePrevote, BlockHash: blockHash, BlockParts: blockParts}
|
||||||
for i := 0; i < 66; i++ {
|
for i := 0; i < 66; i++ {
|
||||||
vote := voteProto.Copy()
|
vote := voteProto.Copy()
|
||||||
privAccounts[i].Sign(vote)
|
vote.Signature = privValidators[i].SignVoteUnsafe(vote)
|
||||||
voteSet.Add(vote)
|
voteSet.Add(privValidators[i].Address, vote)
|
||||||
}
|
}
|
||||||
hash, header, ok := voteSet.TwoThirdsMajority()
|
hash, header, ok := voteSet.TwoThirdsMajority()
|
||||||
if hash != nil || !header.IsZero() || ok {
|
if hash != nil || !header.IsZero() || ok {
|
||||||
@ -109,8 +110,8 @@ func Test2_3MajorityRedux(t *testing.T) {
|
|||||||
// 67th validator voted for nil
|
// 67th validator voted for nil
|
||||||
{
|
{
|
||||||
vote := &Vote{Height: height, Round: round, Type: VoteTypePrevote, BlockHash: nil, BlockParts: PartSetHeader{}}
|
vote := &Vote{Height: height, Round: round, Type: VoteTypePrevote, BlockHash: nil, BlockParts: PartSetHeader{}}
|
||||||
privAccounts[66].Sign(vote)
|
vote.Signature = privValidators[66].SignVoteUnsafe(vote)
|
||||||
voteSet.Add(vote)
|
voteSet.Add(privValidators[66].Address, vote)
|
||||||
hash, header, ok = voteSet.TwoThirdsMajority()
|
hash, header, ok = voteSet.TwoThirdsMajority()
|
||||||
if hash != nil || !header.IsZero() || ok {
|
if hash != nil || !header.IsZero() || ok {
|
||||||
t.Errorf("There should be no 2/3 majority: last vote added was nil")
|
t.Errorf("There should be no 2/3 majority: last vote added was nil")
|
||||||
@ -120,8 +121,8 @@ func Test2_3MajorityRedux(t *testing.T) {
|
|||||||
// 68th validator voted for a different BlockParts PartSetHeader
|
// 68th validator voted for a different BlockParts PartSetHeader
|
||||||
{
|
{
|
||||||
vote := &Vote{Height: height, Round: round, Type: VoteTypePrevote, BlockHash: blockHash, BlockParts: PartSetHeader{blockPartsTotal, CRandBytes(32)}}
|
vote := &Vote{Height: height, Round: round, Type: VoteTypePrevote, BlockHash: blockHash, BlockParts: PartSetHeader{blockPartsTotal, CRandBytes(32)}}
|
||||||
privAccounts[67].Sign(vote)
|
vote.Signature = privValidators[67].SignVoteUnsafe(vote)
|
||||||
voteSet.Add(vote)
|
voteSet.Add(privValidators[67].Address, vote)
|
||||||
hash, header, ok = voteSet.TwoThirdsMajority()
|
hash, header, ok = voteSet.TwoThirdsMajority()
|
||||||
if hash != nil || !header.IsZero() || ok {
|
if hash != nil || !header.IsZero() || ok {
|
||||||
t.Errorf("There should be no 2/3 majority: last vote added had different PartSetHeader Hash")
|
t.Errorf("There should be no 2/3 majority: last vote added had different PartSetHeader Hash")
|
||||||
@ -131,8 +132,8 @@ func Test2_3MajorityRedux(t *testing.T) {
|
|||||||
// 69th validator voted for different BlockParts Total
|
// 69th validator voted for different BlockParts Total
|
||||||
{
|
{
|
||||||
vote := &Vote{Height: height, Round: round, Type: VoteTypePrevote, BlockHash: blockHash, BlockParts: PartSetHeader{blockPartsTotal + 1, blockParts.Hash}}
|
vote := &Vote{Height: height, Round: round, Type: VoteTypePrevote, BlockHash: blockHash, BlockParts: PartSetHeader{blockPartsTotal + 1, blockParts.Hash}}
|
||||||
privAccounts[68].Sign(vote)
|
vote.Signature = privValidators[68].SignVoteUnsafe(vote)
|
||||||
voteSet.Add(vote)
|
voteSet.Add(privValidators[68].Address, vote)
|
||||||
hash, header, ok = voteSet.TwoThirdsMajority()
|
hash, header, ok = voteSet.TwoThirdsMajority()
|
||||||
if hash != nil || !header.IsZero() || ok {
|
if hash != nil || !header.IsZero() || ok {
|
||||||
t.Errorf("There should be no 2/3 majority: last vote added had different PartSetHeader Total")
|
t.Errorf("There should be no 2/3 majority: last vote added had different PartSetHeader Total")
|
||||||
@ -142,8 +143,8 @@ func Test2_3MajorityRedux(t *testing.T) {
|
|||||||
// 70th validator voted for different BlockHash
|
// 70th validator voted for different BlockHash
|
||||||
{
|
{
|
||||||
vote := &Vote{Height: height, Round: round, Type: VoteTypePrevote, BlockHash: CRandBytes(32), BlockParts: blockParts}
|
vote := &Vote{Height: height, Round: round, Type: VoteTypePrevote, BlockHash: CRandBytes(32), BlockParts: blockParts}
|
||||||
privAccounts[69].Sign(vote)
|
vote.Signature = privValidators[69].SignVoteUnsafe(vote)
|
||||||
voteSet.Add(vote)
|
voteSet.Add(privValidators[69].Address, vote)
|
||||||
hash, header, ok = voteSet.TwoThirdsMajority()
|
hash, header, ok = voteSet.TwoThirdsMajority()
|
||||||
if hash != nil || !header.IsZero() || ok {
|
if hash != nil || !header.IsZero() || ok {
|
||||||
t.Errorf("There should be no 2/3 majority: last vote added had different BlockHash")
|
t.Errorf("There should be no 2/3 majority: last vote added had different BlockHash")
|
||||||
@ -153,8 +154,8 @@ func Test2_3MajorityRedux(t *testing.T) {
|
|||||||
// 71st validator voted for the right BlockHash & BlockParts
|
// 71st validator voted for the right BlockHash & BlockParts
|
||||||
{
|
{
|
||||||
vote := voteProto.Copy()
|
vote := voteProto.Copy()
|
||||||
privAccounts[70].Sign(vote)
|
vote.Signature = privValidators[70].SignVoteUnsafe(vote)
|
||||||
voteSet.Add(vote)
|
voteSet.Add(privValidators[70].Address, vote)
|
||||||
hash, header, ok = voteSet.TwoThirdsMajority()
|
hash, header, ok = voteSet.TwoThirdsMajority()
|
||||||
if !bytes.Equal(hash, blockHash) || !header.Equals(blockParts) || !ok {
|
if !bytes.Equal(hash, blockHash) || !header.Equals(blockParts) || !ok {
|
||||||
t.Errorf("There should be 2/3 majority")
|
t.Errorf("There should be 2/3 majority")
|
||||||
@ -163,60 +164,60 @@ func Test2_3MajorityRedux(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestBadVotes(t *testing.T) {
|
func TestBadVotes(t *testing.T) {
|
||||||
height, round := uint32(1), uint16(0)
|
height, round := uint(1), uint(0)
|
||||||
voteSet, _, privAccounts := makeVoteSet(height, round, VoteTypePrevote, 10, 1)
|
voteSet, _, privValidators := makeVoteSet(height, round, VoteTypePrevote, 10, 1)
|
||||||
|
|
||||||
// val0 votes for nil.
|
// val0 votes for nil.
|
||||||
vote := &Vote{Height: height, Round: round, Type: VoteTypePrevote, BlockHash: nil}
|
vote := &Vote{Height: height, Round: round, Type: VoteTypePrevote, BlockHash: nil}
|
||||||
privAccounts[0].Sign(vote)
|
vote.Signature = privValidators[0].SignVoteUnsafe(vote)
|
||||||
added, _, err := voteSet.Add(vote)
|
added, _, err := voteSet.Add(privValidators[0].Address, vote)
|
||||||
if !added || err != nil {
|
if !added || err != nil {
|
||||||
t.Errorf("Expected Add(vote) to succeed")
|
t.Errorf("Expected Add() to succeed")
|
||||||
}
|
}
|
||||||
|
|
||||||
// val0 votes again for some block.
|
// val0 votes again for some block.
|
||||||
vote = &Vote{Height: height, Round: round, Type: VoteTypePrevote, BlockHash: CRandBytes(32)}
|
vote = &Vote{Height: height, Round: round, Type: VoteTypePrevote, BlockHash: CRandBytes(32)}
|
||||||
privAccounts[0].Sign(vote)
|
vote.Signature = privValidators[0].SignVoteUnsafe(vote)
|
||||||
added, _, err = voteSet.Add(vote)
|
added, _, err = voteSet.Add(privValidators[0].Address, vote)
|
||||||
if added || err == nil {
|
if added || err == nil {
|
||||||
t.Errorf("Expected Add(vote) to fail, dupeout.")
|
t.Errorf("Expected Add() to fail, dupeout.")
|
||||||
}
|
}
|
||||||
|
|
||||||
// val1 votes on another height
|
// val1 votes on another height
|
||||||
vote = &Vote{Height: height + 1, Round: round, Type: VoteTypePrevote, BlockHash: nil}
|
vote = &Vote{Height: height + 1, Round: round, Type: VoteTypePrevote, BlockHash: nil}
|
||||||
privAccounts[1].Sign(vote)
|
vote.Signature = privValidators[1].SignVoteUnsafe(vote)
|
||||||
added, _, err = voteSet.Add(vote)
|
added, _, err = voteSet.Add(privValidators[1].Address, vote)
|
||||||
if added {
|
if added {
|
||||||
t.Errorf("Expected Add(vote) to fail, wrong height")
|
t.Errorf("Expected Add() to fail, wrong height")
|
||||||
}
|
}
|
||||||
|
|
||||||
// val2 votes on another round
|
// val2 votes on another round
|
||||||
vote = &Vote{Height: height, Round: round + 1, Type: VoteTypePrevote, BlockHash: nil}
|
vote = &Vote{Height: height, Round: round + 1, Type: VoteTypePrevote, BlockHash: nil}
|
||||||
privAccounts[2].Sign(vote)
|
vote.Signature = privValidators[2].SignVoteUnsafe(vote)
|
||||||
added, _, err = voteSet.Add(vote)
|
added, _, err = voteSet.Add(privValidators[2].Address, vote)
|
||||||
if added {
|
if added {
|
||||||
t.Errorf("Expected Add(vote) to fail, wrong round")
|
t.Errorf("Expected Add() to fail, wrong round")
|
||||||
}
|
}
|
||||||
|
|
||||||
// val3 votes of another type.
|
// val3 votes of another type.
|
||||||
vote = &Vote{Height: height, Round: round, Type: VoteTypePrecommit, BlockHash: nil}
|
vote = &Vote{Height: height, Round: round, Type: VoteTypePrecommit, BlockHash: nil}
|
||||||
privAccounts[3].Sign(vote)
|
vote.Signature = privValidators[3].SignVoteUnsafe(vote)
|
||||||
added, _, err = voteSet.Add(vote)
|
added, _, err = voteSet.Add(privValidators[3].Address, vote)
|
||||||
if added {
|
if added {
|
||||||
t.Errorf("Expected Add(vote) to fail, wrong type")
|
t.Errorf("Expected Add() to fail, wrong type")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAddCommitsToPrevoteVotes(t *testing.T) {
|
func TestAddCommitsToPrevoteVotes(t *testing.T) {
|
||||||
height, round := uint32(2), uint16(5)
|
height, round := uint(2), uint(5)
|
||||||
voteSet, _, privAccounts := makeVoteSet(height, round, VoteTypePrevote, 10, 1)
|
voteSet, _, privValidators := makeVoteSet(height, round, VoteTypePrevote, 10, 1)
|
||||||
|
|
||||||
// val0, val1, val2, val3, val4, val5 vote for nil.
|
// val0, val1, val2, val3, val4, val5 vote for nil.
|
||||||
voteProto := &Vote{Height: height, Round: round, Type: VoteTypePrevote, BlockHash: nil}
|
voteProto := &Vote{Height: height, Round: round, Type: VoteTypePrevote, BlockHash: nil}
|
||||||
for i := 0; i < 6; i++ {
|
for i := 0; i < 6; i++ {
|
||||||
vote := voteProto.Copy()
|
vote := voteProto.Copy()
|
||||||
privAccounts[i].Sign(vote)
|
vote.Signature = privValidators[i].SignVoteUnsafe(vote)
|
||||||
voteSet.Add(vote)
|
voteSet.Add(privValidators[i].Address, vote)
|
||||||
}
|
}
|
||||||
hash, header, ok := voteSet.TwoThirdsMajority()
|
hash, header, ok := voteSet.TwoThirdsMajority()
|
||||||
if hash != nil || !header.IsZero() || ok {
|
if hash != nil || !header.IsZero() || ok {
|
||||||
@ -225,42 +226,42 @@ func TestAddCommitsToPrevoteVotes(t *testing.T) {
|
|||||||
|
|
||||||
// Attempt to add a commit from val6 at a previous height
|
// Attempt to add a commit from val6 at a previous height
|
||||||
vote := &Vote{Height: height - 1, Round: round, Type: VoteTypeCommit, BlockHash: nil}
|
vote := &Vote{Height: height - 1, Round: round, Type: VoteTypeCommit, BlockHash: nil}
|
||||||
privAccounts[6].Sign(vote)
|
vote.Signature = privValidators[6].SignVoteUnsafe(vote)
|
||||||
added, _, _ := voteSet.Add(vote)
|
added, _, _ := voteSet.Add(privValidators[6].Address, vote)
|
||||||
if added {
|
if added {
|
||||||
t.Errorf("Expected Add(vote) to fail, wrong height.")
|
t.Errorf("Expected Add() to fail, wrong height.")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attempt to add a commit from val6 at a later round
|
// Attempt to add a commit from val6 at a later round
|
||||||
vote = &Vote{Height: height, Round: round + 1, Type: VoteTypeCommit, BlockHash: nil}
|
vote = &Vote{Height: height, Round: round + 1, Type: VoteTypeCommit, BlockHash: nil}
|
||||||
privAccounts[6].Sign(vote)
|
vote.Signature = privValidators[6].SignVoteUnsafe(vote)
|
||||||
added, _, _ = voteSet.Add(vote)
|
added, _, _ = voteSet.Add(privValidators[6].Address, vote)
|
||||||
if added {
|
if added {
|
||||||
t.Errorf("Expected Add(vote) to fail, cannot add future round vote.")
|
t.Errorf("Expected Add() to fail, cannot add future round vote.")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attempt to add a commit from val6 for currrent height/round.
|
// Attempt to add a commit from val6 for currrent height/round.
|
||||||
vote = &Vote{Height: height, Round: round, Type: VoteTypeCommit, BlockHash: nil}
|
vote = &Vote{Height: height, Round: round, Type: VoteTypeCommit, BlockHash: nil}
|
||||||
privAccounts[6].Sign(vote)
|
vote.Signature = privValidators[6].SignVoteUnsafe(vote)
|
||||||
added, _, err := voteSet.Add(vote)
|
added, _, err := voteSet.Add(privValidators[6].Address, vote)
|
||||||
if added || err == nil {
|
if added || err == nil {
|
||||||
t.Errorf("Expected Add(vote) to fail, only prior round commits can be added.")
|
t.Errorf("Expected Add() to fail, only prior round commits can be added.")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add commit from val6 at a previous round
|
// Add commit from val6 at a previous round
|
||||||
vote = &Vote{Height: height, Round: round - 1, Type: VoteTypeCommit, BlockHash: nil}
|
vote = &Vote{Height: height, Round: round - 1, Type: VoteTypeCommit, BlockHash: nil}
|
||||||
privAccounts[6].Sign(vote)
|
vote.Signature = privValidators[6].SignVoteUnsafe(vote)
|
||||||
added, _, err = voteSet.Add(vote)
|
added, _, err = voteSet.Add(privValidators[6].Address, vote)
|
||||||
if !added || err != nil {
|
if !added || err != nil {
|
||||||
t.Errorf("Expected Add(vote) to succeed, commit for prior rounds are relevant.")
|
t.Errorf("Expected Add() to succeed, commit for prior rounds are relevant.")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Also add commit from val7 for previous round.
|
// Also add commit from val7 for previous round.
|
||||||
vote = &Vote{Height: height, Round: round - 2, Type: VoteTypeCommit, BlockHash: nil}
|
vote = &Vote{Height: height, Round: round - 2, Type: VoteTypeCommit, BlockHash: nil}
|
||||||
privAccounts[7].Sign(vote)
|
vote.Signature = privValidators[7].SignVoteUnsafe(vote)
|
||||||
added, _, err = voteSet.Add(vote)
|
added, _, err = voteSet.Add(privValidators[7].Address, vote)
|
||||||
if !added || err != nil {
|
if !added || err != nil {
|
||||||
t.Errorf("Expected Add(vote) to succeed. err: %v", err)
|
t.Errorf("Expected Add() to succeed. err: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// We should have 2/3 majority
|
// We should have 2/3 majority
|
||||||
@ -272,8 +273,8 @@ func TestAddCommitsToPrevoteVotes(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestMakeValidation(t *testing.T) {
|
func TestMakeValidation(t *testing.T) {
|
||||||
height, round := uint32(1), uint16(0)
|
height, round := uint(1), uint(0)
|
||||||
voteSet, _, privAccounts := makeVoteSet(height, round, VoteTypeCommit, 10, 1)
|
voteSet, _, privValidators := makeVoteSet(height, round, VoteTypeCommit, 10, 1)
|
||||||
blockHash, blockParts := CRandBytes(32), PartSetHeader{123, CRandBytes(32)}
|
blockHash, blockParts := CRandBytes(32), PartSetHeader{123, CRandBytes(32)}
|
||||||
|
|
||||||
// 6 out of 10 voted for some block.
|
// 6 out of 10 voted for some block.
|
||||||
@ -281,8 +282,8 @@ func TestMakeValidation(t *testing.T) {
|
|||||||
BlockHash: blockHash, BlockParts: blockParts}
|
BlockHash: blockHash, BlockParts: blockParts}
|
||||||
for i := 0; i < 6; i++ {
|
for i := 0; i < 6; i++ {
|
||||||
vote := voteProto.Copy()
|
vote := voteProto.Copy()
|
||||||
privAccounts[i].Sign(vote)
|
vote.Signature = privValidators[i].SignVoteUnsafe(vote)
|
||||||
voteSet.Add(vote)
|
voteSet.Add(privValidators[i].Address, vote)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MakeValidation should fail.
|
// MakeValidation should fail.
|
||||||
@ -293,15 +294,15 @@ func TestMakeValidation(t *testing.T) {
|
|||||||
vote := &Vote{Height: height, Round: round, Type: VoteTypeCommit,
|
vote := &Vote{Height: height, Round: round, Type: VoteTypeCommit,
|
||||||
BlockHash: CRandBytes(32),
|
BlockHash: CRandBytes(32),
|
||||||
BlockParts: PartSetHeader{123, CRandBytes(32)}}
|
BlockParts: PartSetHeader{123, CRandBytes(32)}}
|
||||||
privAccounts[6].Sign(vote)
|
vote.Signature = privValidators[6].SignVoteUnsafe(vote)
|
||||||
voteSet.Add(vote)
|
voteSet.Add(privValidators[6].Address, vote)
|
||||||
}
|
}
|
||||||
|
|
||||||
// The 8th voted like everyone else.
|
// The 8th voted like everyone else.
|
||||||
{
|
{
|
||||||
vote := voteProto.Copy()
|
vote := voteProto.Copy()
|
||||||
privAccounts[7].Sign(vote)
|
vote.Signature = privValidators[7].SignVoteUnsafe(vote)
|
||||||
voteSet.Add(vote)
|
voteSet.Add(privValidators[7].Address, vote)
|
||||||
}
|
}
|
||||||
|
|
||||||
validation := voteSet.MakeValidation()
|
validation := voteSet.MakeValidation()
|
||||||
@ -312,24 +313,8 @@ func TestMakeValidation(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Ensure that Validation commits are ordered.
|
// Ensure that Validation commits are ordered.
|
||||||
for i, rsig := range validation.Commits {
|
if err := validation.ValidateBasic(); err != nil {
|
||||||
if i < 6 || i == 7 {
|
t.Errorf("Error in Validation.ValidateBasic(): %v", err)
|
||||||
if rsig.Round != round {
|
|
||||||
t.Errorf("Expected round %v but got %v", round, rsig.Round)
|
|
||||||
}
|
|
||||||
if rsig.SignerId != uint64(i) {
|
|
||||||
t.Errorf("Validation commit signer out of order. Expected %v, got %v", i, rsig.Signature)
|
|
||||||
}
|
|
||||||
vote := &Vote{Height: height, Round: rsig.Round, Type: VoteTypeCommit,
|
|
||||||
BlockHash: blockHash, BlockParts: blockParts,
|
|
||||||
Signature: rsig.Signature}
|
|
||||||
if !privAccounts[i].Verify(vote) {
|
|
||||||
t.Errorf("Validation commit did not verify")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if !rsig.IsZero() {
|
|
||||||
t.Errorf("Expected zero RoundSignature for the rest")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
. "github.com/tendermint/tendermint/binary"
|
. "github.com/tendermint/tendermint/binary"
|
||||||
. "github.com/tendermint/tendermint/blocks"
|
. "github.com/tendermint/tendermint/block"
|
||||||
"github.com/tendermint/tendermint/state"
|
"github.com/tendermint/tendermint/state"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ import (
|
|||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
|
||||||
. "github.com/tendermint/tendermint/binary"
|
. "github.com/tendermint/tendermint/binary"
|
||||||
. "github.com/tendermint/tendermint/blocks"
|
. "github.com/tendermint/tendermint/block"
|
||||||
"github.com/tendermint/tendermint/p2p"
|
"github.com/tendermint/tendermint/p2p"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -120,6 +120,9 @@ func (t *IAVLTree) Save() []byte {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *IAVLTree) Load(hash []byte) {
|
func (t *IAVLTree) Load(hash []byte) {
|
||||||
|
if len(hash) == 0 {
|
||||||
|
panic("IAVLTree.Load() hash was nil")
|
||||||
|
}
|
||||||
t.root = t.ndb.GetNode(t, hash)
|
t.root = t.ndb.GetNode(t, hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -267,7 +267,7 @@ FOR_LOOP:
|
|||||||
break FOR_LOOP
|
break FOR_LOOP
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Info("%v failed @ sendRoutine:\n%v", c, err)
|
log.Warning("%v failed @ sendRoutine:\n%v", c, err)
|
||||||
c.Stop()
|
c.Stop()
|
||||||
break FOR_LOOP
|
break FOR_LOOP
|
||||||
}
|
}
|
||||||
@ -349,7 +349,7 @@ FOR_LOOP:
|
|||||||
c.recvMonitor.Update(int(n))
|
c.recvMonitor.Update(int(n))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if atomic.LoadUint32(&c.stopped) != 1 {
|
if atomic.LoadUint32(&c.stopped) != 1 {
|
||||||
log.Info("%v failed @ recvRoutine with err: %v", c, err)
|
log.Warning("%v failed @ recvRoutine with err: %v", c, err)
|
||||||
c.Stop()
|
c.Stop()
|
||||||
}
|
}
|
||||||
break FOR_LOOP
|
break FOR_LOOP
|
||||||
@ -377,7 +377,7 @@ FOR_LOOP:
|
|||||||
c.recvMonitor.Update(int(*n))
|
c.recvMonitor.Update(int(*n))
|
||||||
if *err != nil {
|
if *err != nil {
|
||||||
if atomic.LoadUint32(&c.stopped) != 1 {
|
if atomic.LoadUint32(&c.stopped) != 1 {
|
||||||
log.Info("%v failed @ recvRoutine", c)
|
log.Warning("%v failed @ recvRoutine", c)
|
||||||
c.Stop()
|
c.Stop()
|
||||||
}
|
}
|
||||||
break FOR_LOOP
|
break FOR_LOOP
|
||||||
@ -506,6 +506,7 @@ func (ch *Channel) nextMsgPacket() msgPacket {
|
|||||||
// Not goroutine-safe
|
// Not goroutine-safe
|
||||||
func (ch *Channel) writeMsgPacketTo(w io.Writer) (n int64, err error) {
|
func (ch *Channel) writeMsgPacketTo(w io.Writer) (n int64, err error) {
|
||||||
packet := ch.nextMsgPacket()
|
packet := ch.nextMsgPacket()
|
||||||
|
WriteByte(packetTypeMsg, w, &n, &err)
|
||||||
WriteBinary(packet, w, &n, &err)
|
WriteBinary(packet, w, &n, &err)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ch.recentlySent += n
|
ch.recentlySent += n
|
||||||
@ -549,8 +550,6 @@ type msgPacket struct {
|
|||||||
Bytes []byte
|
Bytes []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p msgPacket) TypeByte() byte { return packetTypeMsg }
|
|
||||||
|
|
||||||
func (p msgPacket) String() string {
|
func (p msgPacket) String() string {
|
||||||
return fmt.Sprintf("MsgPacket{%X:%X}", p.ChannelId, p.Bytes)
|
return fmt.Sprintf("MsgPacket{%X:%X}", p.ChannelId, p.Bytes)
|
||||||
}
|
}
|
||||||
|
@ -62,9 +62,11 @@ func NewDefaultListener(protocol string, lAddr string) Listener {
|
|||||||
// Determine external address...
|
// Determine external address...
|
||||||
var extAddr *NetAddress
|
var extAddr *NetAddress
|
||||||
// If the lAddrIP is INADDR_ANY, try UPnP
|
// If the lAddrIP is INADDR_ANY, try UPnP
|
||||||
|
if false {
|
||||||
if lAddrIP == "" || lAddrIP == "0.0.0.0" {
|
if lAddrIP == "" || lAddrIP == "0.0.0.0" {
|
||||||
extAddr = getUPNPExternalAddress(lAddrPort, listenerPort)
|
extAddr = getUPNPExternalAddress(lAddrPort, listenerPort)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// Otherwise just use the local address...
|
// Otherwise just use the local address...
|
||||||
if extAddr == nil {
|
if extAddr == nil {
|
||||||
extAddr = getNaiveExternalAddress(listenerPort)
|
extAddr = getNaiveExternalAddress(listenerPort)
|
||||||
|
@ -3,7 +3,7 @@ package rpc
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
//. "github.com/tendermint/tendermint/blocks"
|
//. "github.com/tendermint/tendermint/block"
|
||||||
)
|
)
|
||||||
|
|
||||||
func BlockHandler(w http.ResponseWriter, r *http.Request) {
|
func BlockHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
@ -7,7 +7,7 @@ import (
|
|||||||
|
|
||||||
. "github.com/tendermint/tendermint/account"
|
. "github.com/tendermint/tendermint/account"
|
||||||
. "github.com/tendermint/tendermint/binary"
|
. "github.com/tendermint/tendermint/binary"
|
||||||
. "github.com/tendermint/tendermint/blocks"
|
. "github.com/tendermint/tendermint/block"
|
||||||
. "github.com/tendermint/tendermint/common"
|
. "github.com/tendermint/tendermint/common"
|
||||||
db_ "github.com/tendermint/tendermint/db"
|
db_ "github.com/tendermint/tendermint/db"
|
||||||
"github.com/tendermint/tendermint/merkle"
|
"github.com/tendermint/tendermint/merkle"
|
||||||
@ -16,7 +16,7 @@ import (
|
|||||||
type GenesisDoc struct {
|
type GenesisDoc struct {
|
||||||
GenesisTime time.Time
|
GenesisTime time.Time
|
||||||
Accounts []*Account
|
Accounts []*Account
|
||||||
Validators []*Validator
|
Validators []*ValidatorInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
func GenesisDocFromJSON(jsonBlob []byte) (genState *GenesisDoc) {
|
func GenesisDocFromJSON(jsonBlob []byte) (genState *GenesisDoc) {
|
||||||
@ -51,14 +51,31 @@ func GenesisState(db db_.DB, genDoc *GenesisDoc) *State {
|
|||||||
accounts.Set(acc.Address, acc)
|
accounts.Set(acc.Address, acc)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Make validatorInfos state tree
|
||||||
|
validatorInfos := merkle.NewIAVLTree(BasicCodec, ValidatorInfoCodec, 0, db)
|
||||||
|
for _, valInfo := range genDoc.Validators {
|
||||||
|
validatorInfos.Set(valInfo.Address, valInfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make validators
|
||||||
|
validators := make([]*Validator, len(genDoc.Validators))
|
||||||
|
for i, valInfo := range genDoc.Validators {
|
||||||
|
validators[i] = &Validator{
|
||||||
|
Address: valInfo.Address,
|
||||||
|
PubKey: valInfo.PubKey,
|
||||||
|
VotingPower: valInfo.FirstBondAmount,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return &State{
|
return &State{
|
||||||
DB: db,
|
DB: db,
|
||||||
LastBlockHeight: 0,
|
LastBlockHeight: 0,
|
||||||
LastBlockHash: nil,
|
LastBlockHash: nil,
|
||||||
LastBlockParts: PartSetHeader{},
|
LastBlockParts: PartSetHeader{},
|
||||||
LastBlockTime: genDoc.GenesisTime,
|
LastBlockTime: genDoc.GenesisTime,
|
||||||
BondedValidators: NewValidatorSet(genDoc.Validators),
|
BondedValidators: NewValidatorSet(validators),
|
||||||
UnbondingValidators: NewValidatorSet(nil),
|
UnbondingValidators: NewValidatorSet(nil),
|
||||||
accounts: accounts,
|
accounts: accounts,
|
||||||
|
validatorInfos: validatorInfos,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package consensus
|
package state
|
||||||
|
|
||||||
// TODO: This logic is crude. Should be more transactional.
|
// TODO: This logic is crude. Should be more transactional.
|
||||||
|
|
||||||
@ -12,9 +12,10 @@ import (
|
|||||||
|
|
||||||
. "github.com/tendermint/tendermint/account"
|
. "github.com/tendermint/tendermint/account"
|
||||||
. "github.com/tendermint/tendermint/binary"
|
. "github.com/tendermint/tendermint/binary"
|
||||||
. "github.com/tendermint/tendermint/blocks"
|
. "github.com/tendermint/tendermint/block"
|
||||||
. "github.com/tendermint/tendermint/common"
|
. "github.com/tendermint/tendermint/common"
|
||||||
. "github.com/tendermint/tendermint/config"
|
. "github.com/tendermint/tendermint/config"
|
||||||
|
. "github.com/tendermint/tendermint/consensus/types"
|
||||||
|
|
||||||
"github.com/tendermint/go-ed25519"
|
"github.com/tendermint/go-ed25519"
|
||||||
)
|
)
|
||||||
@ -47,6 +48,10 @@ type PrivValidator struct {
|
|||||||
LastHeight uint
|
LastHeight uint
|
||||||
LastRound uint
|
LastRound uint
|
||||||
LastStep uint8
|
LastStep uint8
|
||||||
|
|
||||||
|
// For persistence.
|
||||||
|
// Overloaded for testing.
|
||||||
|
filename string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generates a new validator with private key.
|
// Generates a new validator with private key.
|
||||||
@ -62,6 +67,7 @@ func GenPrivValidator() *PrivValidator {
|
|||||||
LastHeight: 0,
|
LastHeight: 0,
|
||||||
LastRound: 0,
|
LastRound: 0,
|
||||||
LastStep: stepNone,
|
LastStep: stepNone,
|
||||||
|
filename: PrivValidatorFile(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,16 +130,34 @@ func (privVal *PrivValidator) Save() {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
err = ioutil.WriteFile(PrivValidatorFile(), privValJSONBytes, 0700)
|
err = ioutil.WriteFile(privVal.filename, privValJSONBytes, 0700)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: test
|
||||||
func (privVal *PrivValidator) SignVote(vote *Vote) SignatureEd25519 {
|
func (privVal *PrivValidator) SignVote(vote *Vote) SignatureEd25519 {
|
||||||
if privVal.LastHeight < vote.Height ||
|
|
||||||
privVal.LastHeight == vote.Height && privVal.LastRound < vote.Round ||
|
// If height regression, panic
|
||||||
privVal.LastHeight == vote.Height && privVal.LastRound == vote.Round && privVal.LastStep < voteToStep(vote) {
|
if privVal.LastHeight > vote.Height {
|
||||||
|
panic("Height regression in SignVote")
|
||||||
|
}
|
||||||
|
// More cases for when the height matches
|
||||||
|
if privVal.LastHeight == vote.Height {
|
||||||
|
// If attempting any sign after commit, panic
|
||||||
|
if privVal.LastStep == stepCommit {
|
||||||
|
panic("SignVote on matching height after a commit")
|
||||||
|
}
|
||||||
|
// If round regression, panic
|
||||||
|
if privVal.LastRound > vote.Round {
|
||||||
|
panic("Round regression in SignVote")
|
||||||
|
}
|
||||||
|
// If step regression, panic
|
||||||
|
if privVal.LastRound == vote.Round && privVal.LastStep > voteToStep(vote) {
|
||||||
|
panic("Step regression in SignVote")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Persist height/round/step
|
// Persist height/round/step
|
||||||
privVal.LastHeight = vote.Height
|
privVal.LastHeight = vote.Height
|
||||||
@ -142,10 +166,11 @@ func (privVal *PrivValidator) SignVote(vote *Vote) SignatureEd25519 {
|
|||||||
privVal.Save()
|
privVal.Save()
|
||||||
|
|
||||||
// Sign
|
// Sign
|
||||||
|
return privVal.SignVoteUnsafe(vote)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (privVal *PrivValidator) SignVoteUnsafe(vote *Vote) SignatureEd25519 {
|
||||||
return privVal.PrivKey.Sign(SignBytes(vote)).(SignatureEd25519)
|
return privVal.PrivKey.Sign(SignBytes(vote)).(SignatureEd25519)
|
||||||
} else {
|
|
||||||
panic(fmt.Sprintf("Attempt of duplicate signing of vote: Height %v, Round %v, Type %v", vote.Height, vote.Round, vote.Type))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (privVal *PrivValidator) SignProposal(proposal *Proposal) SignatureEd25519 {
|
func (privVal *PrivValidator) SignProposal(proposal *Proposal) SignatureEd25519 {
|
||||||
@ -181,3 +206,7 @@ func (privVal *PrivValidator) SignRebondTx(rebondTx *RebondTx) SignatureEd25519
|
|||||||
panic(fmt.Sprintf("Attempt of duplicate signing of rebondTx: Height %v", rebondTx.Height))
|
panic(fmt.Sprintf("Attempt of duplicate signing of rebondTx: Height %v", rebondTx.Height))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (privVal *PrivValidator) String() string {
|
||||||
|
return fmt.Sprintf("PrivValidator{%X LH:%v, LR:%v, LS:%v}", privVal.Address, privVal.LastHeight, privVal.LastRound, privVal.LastStep)
|
||||||
|
}
|
@ -8,7 +8,7 @@ import (
|
|||||||
|
|
||||||
. "github.com/tendermint/tendermint/account"
|
. "github.com/tendermint/tendermint/account"
|
||||||
. "github.com/tendermint/tendermint/binary"
|
. "github.com/tendermint/tendermint/binary"
|
||||||
. "github.com/tendermint/tendermint/blocks"
|
. "github.com/tendermint/tendermint/block"
|
||||||
. "github.com/tendermint/tendermint/common"
|
. "github.com/tendermint/tendermint/common"
|
||||||
db_ "github.com/tendermint/tendermint/db"
|
db_ "github.com/tendermint/tendermint/db"
|
||||||
"github.com/tendermint/tendermint/merkle"
|
"github.com/tendermint/tendermint/merkle"
|
||||||
@ -78,6 +78,7 @@ func LoadState(db db_.DB) *State {
|
|||||||
// Save this state into the db.
|
// Save this state into the db.
|
||||||
func (s *State) Save() {
|
func (s *State) Save() {
|
||||||
s.accounts.Save()
|
s.accounts.Save()
|
||||||
|
s.validatorInfos.Save()
|
||||||
buf, n, err := new(bytes.Buffer), new(int64), new(error)
|
buf, n, err := new(bytes.Buffer), new(int64), new(error)
|
||||||
WriteUVarInt(s.LastBlockHeight, buf, n, err)
|
WriteUVarInt(s.LastBlockHeight, buf, n, err)
|
||||||
WriteByteSlice(s.LastBlockHash, buf, n, err)
|
WriteByteSlice(s.LastBlockHash, buf, n, err)
|
||||||
@ -185,6 +186,7 @@ func (s *State) AdjustByInputs(accounts map[string]*Account, ins []*TxInput) {
|
|||||||
panic("AdjustByInputs() expects sufficient funds")
|
panic("AdjustByInputs() expects sufficient funds")
|
||||||
}
|
}
|
||||||
account.Balance -= in.Amount
|
account.Balance -= in.Amount
|
||||||
|
account.Sequence += 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -192,7 +194,7 @@ func (s *State) AdjustByOutputs(accounts map[string]*Account, outs []*TxOutput)
|
|||||||
for _, out := range outs {
|
for _, out := range outs {
|
||||||
account := accounts[string(out.Address)]
|
account := accounts[string(out.Address)]
|
||||||
if account == nil {
|
if account == nil {
|
||||||
panic("AdjustByInputs() expects account in accounts")
|
panic("AdjustByOutputs() expects account in accounts")
|
||||||
}
|
}
|
||||||
account.Balance += out.Amount
|
account.Balance += out.Amount
|
||||||
}
|
}
|
||||||
@ -242,7 +244,7 @@ func (s *State) ExecTx(tx_ Tx) error {
|
|||||||
// add funds, merge UnbondTo outputs, and unbond validator.
|
// add funds, merge UnbondTo outputs, and unbond validator.
|
||||||
return errors.New("Adding coins to existing validators not yet supported")
|
return errors.New("Adding coins to existing validators not yet supported")
|
||||||
}
|
}
|
||||||
accounts, err := s.GetOrMakeAccounts(tx.Inputs, tx.UnbondTo)
|
accounts, err := s.GetOrMakeAccounts(tx.Inputs, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -273,13 +275,14 @@ func (s *State) ExecTx(tx_ Tx) error {
|
|||||||
PubKey: tx.PubKey,
|
PubKey: tx.PubKey,
|
||||||
UnbondTo: tx.UnbondTo,
|
UnbondTo: tx.UnbondTo,
|
||||||
FirstBondHeight: s.LastBlockHeight + 1,
|
FirstBondHeight: s.LastBlockHeight + 1,
|
||||||
|
FirstBondAmount: outTotal,
|
||||||
})
|
})
|
||||||
// Add Validator
|
// Add Validator
|
||||||
added := s.BondedValidators.Add(&Validator{
|
added := s.BondedValidators.Add(&Validator{
|
||||||
Address: tx.PubKey.Address(),
|
Address: tx.PubKey.Address(),
|
||||||
PubKey: tx.PubKey,
|
PubKey: tx.PubKey,
|
||||||
BondHeight: s.LastBlockHeight + 1,
|
BondHeight: s.LastBlockHeight + 1,
|
||||||
VotingPower: inTotal,
|
VotingPower: outTotal,
|
||||||
Accum: 0,
|
Accum: 0,
|
||||||
})
|
})
|
||||||
if !added {
|
if !added {
|
||||||
@ -588,6 +591,12 @@ func (s *State) GetAccount(address []byte) *Account {
|
|||||||
return account.(*Account).Copy()
|
return account.(*Account).Copy()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The account is copied before setting, so mutating it
|
||||||
|
// afterwards has no side effects.
|
||||||
|
func (s *State) SetAccount(account *Account) {
|
||||||
|
s.accounts.Set(account.Address, account.Copy())
|
||||||
|
}
|
||||||
|
|
||||||
// The accounts are copied before setting, so mutating it
|
// The accounts are copied before setting, so mutating it
|
||||||
// afterwards has no side effects.
|
// afterwards has no side effects.
|
||||||
func (s *State) SetAccounts(accounts map[string]*Account) {
|
func (s *State) SetAccounts(accounts map[string]*Account) {
|
||||||
|
@ -3,60 +3,17 @@ package state
|
|||||||
import (
|
import (
|
||||||
. "github.com/tendermint/tendermint/account"
|
. "github.com/tendermint/tendermint/account"
|
||||||
. "github.com/tendermint/tendermint/binary"
|
. "github.com/tendermint/tendermint/binary"
|
||||||
. "github.com/tendermint/tendermint/blocks"
|
. "github.com/tendermint/tendermint/block"
|
||||||
. "github.com/tendermint/tendermint/common"
|
|
||||||
. "github.com/tendermint/tendermint/config"
|
. "github.com/tendermint/tendermint/config"
|
||||||
db_ "github.com/tendermint/tendermint/db"
|
|
||||||
"github.com/tendermint/tendermint/wallet"
|
|
||||||
|
|
||||||
"bytes"
|
"bytes"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func randAccount() (*Account, *PrivAccount) {
|
|
||||||
privAccount := wallet.GenPrivAccount()
|
|
||||||
account := NewAccount(privAccount.PubKey)
|
|
||||||
account.Sequence = RandUInt()
|
|
||||||
account.Balance = RandUInt32() + 1000 // At least 1000.
|
|
||||||
return account, privAccount
|
|
||||||
}
|
|
||||||
|
|
||||||
func genValidator(account *Account) *Validator, *ValidatorInfo {
|
|
||||||
valInfo := &ValidatorInfo{
|
|
||||||
Address: account.Address,
|
|
||||||
PubKey: account.PubKey,
|
|
||||||
UnbondTo: []*TxOutput{&TxOutput{
|
|
||||||
Address:
|
|
||||||
Address []byte
|
|
||||||
PubKey PubKeyEd25519
|
|
||||||
UnbondTo []*TxOutput
|
|
||||||
FirstBondHeight uint
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// The first numValidators accounts are validators.
|
|
||||||
func randGenesisState(numAccounts int, numValidators int) (*State, []*PrivAccount) {
|
|
||||||
db := db_.NewMemDB()
|
|
||||||
accounts := make([]*Account, numAccounts)
|
|
||||||
privAccounts := make([]*PrivAccount, numAccounts)
|
|
||||||
validators := make([]*Validator, numValidators)
|
|
||||||
for i := 0; i < numAccounts; i++ {
|
|
||||||
account, privAccount := randAccount()
|
|
||||||
accounts[i], privAccounts[i] = account, privAccount
|
|
||||||
if i < numValidators {
|
|
||||||
validators[i] = &
|
|
||||||
}
|
|
||||||
}
|
|
||||||
s0 := GenesisState(db, time.Now(), accounts)
|
|
||||||
s0.Save()
|
|
||||||
return s0, privAccounts
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCopyState(t *testing.T) {
|
func TestCopyState(t *testing.T) {
|
||||||
// Generate a state
|
// Generate a state
|
||||||
s0, _ := randGenesisState(10, 5)
|
s0, privAccounts, _ := RandGenesisState(10, true, 1000, 5, true, 1000)
|
||||||
s0Hash := s0.Hash()
|
s0Hash := s0.Hash()
|
||||||
if len(s0Hash) == 0 {
|
if len(s0Hash) == 0 {
|
||||||
t.Error("Expected state hash")
|
t.Error("Expected state hash")
|
||||||
@ -69,15 +26,16 @@ func TestCopyState(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Mutate the original; hash should change.
|
// Mutate the original; hash should change.
|
||||||
accDet := s0.GetAccountDetail(0)
|
acc0Address := privAccounts[0].PubKey.Address()
|
||||||
accDet.Balance += 1
|
acc := s0.GetAccount(acc0Address)
|
||||||
|
acc.Balance += 1
|
||||||
// The account balance shouldn't have changed yet.
|
// The account balance shouldn't have changed yet.
|
||||||
if s0.GetAccountDetail(0).Balance == accDet.Balance {
|
if s0.GetAccount(acc0Address).Balance == acc.Balance {
|
||||||
t.Error("Account balance changed unexpectedly")
|
t.Error("Account balance changed unexpectedly")
|
||||||
}
|
}
|
||||||
// Setting, however, should change the balance.
|
// Setting, however, should change the balance.
|
||||||
s0.SetAccountDetail(accDet)
|
s0.SetAccount(acc)
|
||||||
if s0.GetAccountDetail(0).Balance != accDet.Balance {
|
if s0.GetAccount(acc0Address).Balance != acc.Balance {
|
||||||
t.Error("Account balance wasn't set")
|
t.Error("Account balance wasn't set")
|
||||||
}
|
}
|
||||||
// How that the state changed, the hash should change too.
|
// How that the state changed, the hash should change too.
|
||||||
@ -93,7 +51,7 @@ func TestCopyState(t *testing.T) {
|
|||||||
func TestGenesisSaveLoad(t *testing.T) {
|
func TestGenesisSaveLoad(t *testing.T) {
|
||||||
|
|
||||||
// Generate a state, save & load it.
|
// Generate a state, save & load it.
|
||||||
s0, _ := randGenesisState(10, 5)
|
s0, _, _ := RandGenesisState(10, true, 1000, 5, true, 1000)
|
||||||
// Mutate the state to append one empty block.
|
// Mutate the state to append one empty block.
|
||||||
block := &Block{
|
block := &Block{
|
||||||
Header: &Header{
|
Header: &Header{
|
||||||
@ -168,150 +126,160 @@ func TestGenesisSaveLoad(t *testing.T) {
|
|||||||
if !bytes.Equal(s0.UnbondingValidators.Hash(), s1.UnbondingValidators.Hash()) {
|
if !bytes.Equal(s0.UnbondingValidators.Hash(), s1.UnbondingValidators.Hash()) {
|
||||||
t.Error("UnbondingValidators hash mismatch")
|
t.Error("UnbondingValidators hash mismatch")
|
||||||
}
|
}
|
||||||
if !bytes.Equal(s0.accountDetails.Hash(), s1.accountDetails.Hash()) {
|
if !bytes.Equal(s0.accounts.Hash(), s1.accounts.Hash()) {
|
||||||
t.Error("AccountDetail mismatch")
|
t.Error("Accounts mismatch")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTxSequence(t *testing.T) {
|
func TestTxSequence(t *testing.T) {
|
||||||
|
|
||||||
state, privAccounts := randGenesisState(3, 1)
|
state, privAccounts, _ := RandGenesisState(3, true, 1000, 1, true, 1000)
|
||||||
acc1 := state.GetAccountDetail(1) // Non-validator
|
acc0 := state.GetAccount(privAccounts[0].PubKey.Address())
|
||||||
|
acc1 := state.GetAccount(privAccounts[1].PubKey.Address())
|
||||||
|
|
||||||
// Try executing a SendTx with various sequence numbers.
|
// Try executing a SendTx with various sequence numbers.
|
||||||
stxProto := SendTx{
|
makeSendTx := func(sequence uint) *SendTx {
|
||||||
BaseTx: BaseTx{
|
return &SendTx{
|
||||||
Sequence: acc1.Sequence + 1,
|
Inputs: []*TxInput{
|
||||||
Fee: 0},
|
&TxInput{
|
||||||
To: 2,
|
Address: acc0.Address,
|
||||||
Amount: 1,
|
Amount: 1,
|
||||||
|
Sequence: sequence,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Outputs: []*TxOutput{
|
||||||
|
&TxOutput{
|
||||||
|
Address: acc1.Address,
|
||||||
|
Amount: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test a variety of sequence numbers for the tx.
|
// Test a variety of sequence numbers for the tx.
|
||||||
// The tx should only pass when i == 1.
|
// The tx should only pass when i == 1.
|
||||||
for i := -1; i < 3; i++ {
|
for i := -1; i < 3; i++ {
|
||||||
stxCopy := stxProto
|
sequence := acc0.Sequence + uint(i)
|
||||||
stx := &stxCopy
|
tx := makeSendTx(sequence)
|
||||||
stx.Sequence = uint(int(acc1.Sequence) + i)
|
tx.Inputs[0].Signature = privAccounts[0].Sign(tx)
|
||||||
privAccounts[1].Sign(stx)
|
|
||||||
stateCopy := state.Copy()
|
stateCopy := state.Copy()
|
||||||
err := stateCopy.ExecTx(stx)
|
err := stateCopy.ExecTx(tx)
|
||||||
if i >= 1 {
|
if i == 1 {
|
||||||
// Sequence is good.
|
// Sequence is good.
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Expected good sequence to pass")
|
t.Errorf("Expected good sequence to pass: %v", err)
|
||||||
}
|
}
|
||||||
// Check accDet.Sequence.
|
// Check acc.Sequence.
|
||||||
newAcc1 := stateCopy.GetAccountDetail(1)
|
newAcc0 := stateCopy.GetAccount(acc0.Address)
|
||||||
if newAcc1.Sequence != stx.Sequence {
|
if newAcc0.Sequence != sequence {
|
||||||
t.Errorf("Expected account sequence to change")
|
t.Errorf("Expected account sequence to change to %v, got %v",
|
||||||
|
sequence, newAcc0.Sequence)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Sequence is bad.
|
// Sequence is bad.
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Errorf("Expected bad sequence to fail")
|
t.Errorf("Expected bad sequence to fail")
|
||||||
}
|
}
|
||||||
// Check accDet.Sequence. (shouldn't have changed)
|
// Check acc.Sequence. (shouldn't have changed)
|
||||||
newAcc1 := stateCopy.GetAccountDetail(1)
|
newAcc0 := stateCopy.GetAccount(acc0.Address)
|
||||||
if newAcc1.Sequence != acc1.Sequence {
|
if newAcc0.Sequence != acc0.Sequence {
|
||||||
t.Errorf("Expected account sequence to not change")
|
t.Errorf("Expected account sequence to not change from %v, got %v",
|
||||||
|
acc0.Sequence, newAcc0.Sequence)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: test overflows.
|
||||||
|
// TODO: test for unbonding validators.
|
||||||
func TestTxs(t *testing.T) {
|
func TestTxs(t *testing.T) {
|
||||||
|
|
||||||
state, privAccounts := randGenesisState(3, 1)
|
state, privAccounts, _ := RandGenesisState(3, true, 1000, 1, true, 1000)
|
||||||
|
|
||||||
acc0 := state.GetAccountDetail(0) // Validator
|
//val0 := state.GetValidatorInfo(privValidators[0].Address)
|
||||||
acc1 := state.GetAccountDetail(1) // Non-validator
|
acc0 := state.GetAccount(privAccounts[0].PubKey.Address())
|
||||||
acc2 := state.GetAccountDetail(2) // Non-validator
|
acc1 := state.GetAccount(privAccounts[1].PubKey.Address())
|
||||||
|
|
||||||
// SendTx.
|
// SendTx.
|
||||||
{
|
{
|
||||||
state := state.Copy()
|
state := state.Copy()
|
||||||
stx := &SendTx{
|
tx := &SendTx{
|
||||||
BaseTx: BaseTx{
|
Inputs: []*TxInput{
|
||||||
Sequence: acc1.Sequence + 1,
|
&TxInput{
|
||||||
Fee: 0},
|
Address: acc0.Address,
|
||||||
To: 2,
|
|
||||||
Amount: 1,
|
Amount: 1,
|
||||||
|
Sequence: acc0.Sequence + 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Outputs: []*TxOutput{
|
||||||
|
&TxOutput{
|
||||||
|
Address: acc1.Address,
|
||||||
|
Amount: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
privAccounts[1].Sign(stx)
|
|
||||||
err := state.ExecTx(stx)
|
tx.Inputs[0].Signature = privAccounts[0].Sign(tx)
|
||||||
|
err := state.ExecTx(tx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Got error in executing send transaction, %v", err)
|
t.Errorf("Got error in executing send transaction, %v", err)
|
||||||
}
|
}
|
||||||
newAcc1 := state.GetAccountDetail(1)
|
newAcc0 := state.GetAccount(acc0.Address)
|
||||||
if acc1.Balance-1 != newAcc1.Balance {
|
if acc0.Balance-1 != newAcc0.Balance {
|
||||||
|
t.Errorf("Unexpected newAcc0 balance. Expected %v, got %v",
|
||||||
|
acc0.Balance-1, newAcc0.Balance)
|
||||||
|
}
|
||||||
|
newAcc1 := state.GetAccount(acc1.Address)
|
||||||
|
if acc1.Balance+1 != newAcc1.Balance {
|
||||||
t.Errorf("Unexpected newAcc1 balance. Expected %v, got %v",
|
t.Errorf("Unexpected newAcc1 balance. Expected %v, got %v",
|
||||||
acc1.Balance-1, newAcc1.Balance)
|
acc1.Balance+1, newAcc1.Balance)
|
||||||
}
|
|
||||||
newAcc2 := state.GetAccountDetail(2)
|
|
||||||
if acc2.Balance+1 != newAcc2.Balance {
|
|
||||||
t.Errorf("Unexpected newAcc2 balance. Expected %v, got %v",
|
|
||||||
acc2.Balance+1, newAcc2.Balance)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: test overflows.
|
|
||||||
|
|
||||||
// SendTx should fail for bonded validators.
|
|
||||||
{
|
|
||||||
state := state.Copy()
|
|
||||||
stx := &SendTx{
|
|
||||||
BaseTx: BaseTx{
|
|
||||||
Sequence: acc0.Sequence + 1,
|
|
||||||
Fee: 0},
|
|
||||||
To: 2,
|
|
||||||
Amount: 1,
|
|
||||||
}
|
|
||||||
privAccounts[0].Sign(stx)
|
|
||||||
err := state.ExecTx(stx)
|
|
||||||
if err == nil {
|
|
||||||
t.Errorf("Expected error, SendTx should fail for bonded validators")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: test for unbonding validators.
|
|
||||||
|
|
||||||
// BondTx.
|
// BondTx.
|
||||||
{
|
{
|
||||||
state := state.Copy()
|
state := state.Copy()
|
||||||
btx := &BondTx{
|
tx := &BondTx{
|
||||||
BaseTx: BaseTx{
|
PubKey: acc0.PubKey.(PubKeyEd25519),
|
||||||
Sequence: acc1.Sequence + 1,
|
Inputs: []*TxInput{
|
||||||
Fee: 0},
|
&TxInput{
|
||||||
|
Address: acc0.Address,
|
||||||
|
Amount: 1,
|
||||||
|
Sequence: acc0.Sequence + 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
UnbondTo: []*TxOutput{
|
||||||
|
&TxOutput{
|
||||||
|
Address: acc0.Address,
|
||||||
|
Amount: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
privAccounts[1].Sign(btx)
|
tx.Inputs[0].Signature = privAccounts[0].Sign(tx)
|
||||||
err := state.ExecTx(btx)
|
err := state.ExecTx(tx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Got error in executing bond transaction, %v", err)
|
t.Errorf("Got error in executing bond transaction, %v", err)
|
||||||
}
|
}
|
||||||
newAcc1 := state.GetAccountDetail(1)
|
newAcc0 := state.GetAccount(acc0.Address)
|
||||||
if acc1.Balance != newAcc1.Balance {
|
if newAcc0.Balance != acc0.Balance-1 {
|
||||||
t.Errorf("Unexpected newAcc1 balance. Expected %v, got %v",
|
t.Errorf("Unexpected newAcc0 balance. Expected %v, got %v",
|
||||||
acc1.Balance, newAcc1.Balance)
|
acc0.Balance-1, newAcc0.Balance)
|
||||||
}
|
}
|
||||||
if newAcc1.Status != AccountStatusBonded {
|
_, acc0Val := state.BondedValidators.GetByAddress(acc0.Address)
|
||||||
t.Errorf("Unexpected newAcc1 status.")
|
if acc0Val == nil {
|
||||||
|
t.Errorf("acc0Val not present")
|
||||||
}
|
}
|
||||||
_, acc1Val := state.BondedValidators.GetById(acc1.Id)
|
if acc0Val.BondHeight != state.LastBlockHeight+1 {
|
||||||
if acc1Val == nil {
|
|
||||||
t.Errorf("acc1Val not present")
|
|
||||||
}
|
|
||||||
if acc1Val.BondHeight != state.LastBlockHeight {
|
|
||||||
t.Errorf("Unexpected bond height. Expected %v, got %v",
|
t.Errorf("Unexpected bond height. Expected %v, got %v",
|
||||||
state.LastBlockHeight, acc1Val.BondHeight)
|
state.LastBlockHeight, acc0Val.BondHeight)
|
||||||
}
|
}
|
||||||
if acc1Val.VotingPower != acc1.Balance {
|
if acc0Val.VotingPower != 1 {
|
||||||
t.Errorf("Unexpected voting power. Expected %v, got %v",
|
t.Errorf("Unexpected voting power. Expected %v, got %v",
|
||||||
acc1Val.VotingPower, acc1.Balance)
|
acc0Val.VotingPower, acc0.Balance)
|
||||||
}
|
}
|
||||||
if acc1Val.Accum != 0 {
|
if acc0Val.Accum != 0 {
|
||||||
t.Errorf("Unexpected accum. Expected 0, got %v",
|
t.Errorf("Unexpected accum. Expected 0, got %v",
|
||||||
acc1Val.Accum)
|
acc0Val.Accum)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
98
state/test.go
Normal file
98
state/test.go
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
package state
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"sort"
|
||||||
|
|
||||||
|
. "github.com/tendermint/tendermint/account"
|
||||||
|
. "github.com/tendermint/tendermint/block"
|
||||||
|
. "github.com/tendermint/tendermint/common"
|
||||||
|
db_ "github.com/tendermint/tendermint/db"
|
||||||
|
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Tempfile(prefix string) (*os.File, string) {
|
||||||
|
file, err := ioutil.TempFile("", prefix)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return file, file.Name()
|
||||||
|
}
|
||||||
|
|
||||||
|
func RandAccount(randBalance bool, minBalance uint64) (*Account, *PrivAccount) {
|
||||||
|
privAccount := GenPrivAccount()
|
||||||
|
account := NewAccount(privAccount.PubKey)
|
||||||
|
account.Sequence = RandUInt()
|
||||||
|
account.Balance = minBalance
|
||||||
|
if randBalance {
|
||||||
|
account.Balance += uint64(RandUInt32())
|
||||||
|
}
|
||||||
|
return account, privAccount
|
||||||
|
}
|
||||||
|
|
||||||
|
func RandValidator(randBonded bool, minBonded uint64) (*ValidatorInfo, *PrivValidator) {
|
||||||
|
privVal := GenPrivValidator()
|
||||||
|
_, privVal.filename = Tempfile("priv_validator_")
|
||||||
|
bonded := minBonded
|
||||||
|
if randBonded {
|
||||||
|
bonded += uint64(RandUInt32())
|
||||||
|
}
|
||||||
|
valInfo := &ValidatorInfo{
|
||||||
|
Address: privVal.Address,
|
||||||
|
PubKey: privVal.PubKey,
|
||||||
|
UnbondTo: []*TxOutput{&TxOutput{
|
||||||
|
Amount: bonded,
|
||||||
|
Address: privVal.Address,
|
||||||
|
}},
|
||||||
|
FirstBondHeight: 0,
|
||||||
|
FirstBondAmount: bonded,
|
||||||
|
}
|
||||||
|
return valInfo, privVal
|
||||||
|
}
|
||||||
|
|
||||||
|
// The first numValidators accounts are validators.
|
||||||
|
func RandGenesisState(numAccounts int, randBalance bool, minBalance uint64, numValidators int, randBonded bool, minBonded uint64) (*State, []*PrivAccount, []*PrivValidator) {
|
||||||
|
db := db_.NewMemDB()
|
||||||
|
accounts := make([]*Account, numAccounts)
|
||||||
|
privAccounts := make([]*PrivAccount, numAccounts)
|
||||||
|
for i := 0; i < numAccounts; i++ {
|
||||||
|
account, privAccount := RandAccount(randBalance, minBalance)
|
||||||
|
accounts[i], privAccounts[i] = account, privAccount
|
||||||
|
}
|
||||||
|
validators := make([]*ValidatorInfo, numValidators)
|
||||||
|
privValidators := make([]*PrivValidator, numValidators)
|
||||||
|
for i := 0; i < numValidators; i++ {
|
||||||
|
valInfo, privVal := RandValidator(randBonded, minBonded)
|
||||||
|
validators[i] = valInfo
|
||||||
|
privValidators[i] = privVal
|
||||||
|
}
|
||||||
|
sort.Sort(PrivValidatorsByAddress(privValidators))
|
||||||
|
s0 := GenesisState(db, &GenesisDoc{
|
||||||
|
GenesisTime: time.Now(),
|
||||||
|
Accounts: accounts,
|
||||||
|
Validators: validators,
|
||||||
|
})
|
||||||
|
s0.Save()
|
||||||
|
return s0, privAccounts, privValidators
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------
|
||||||
|
|
||||||
|
type PrivValidatorsByAddress []*PrivValidator
|
||||||
|
|
||||||
|
func (pvs PrivValidatorsByAddress) Len() int {
|
||||||
|
return len(pvs)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pvs PrivValidatorsByAddress) Less(i, j int) bool {
|
||||||
|
return bytes.Compare(pvs[i].Address, pvs[j].Address) == -1
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pvs PrivValidatorsByAddress) Swap(i, j int) {
|
||||||
|
it := pvs[i]
|
||||||
|
pvs[i] = pvs[j]
|
||||||
|
pvs[j] = it
|
||||||
|
}
|
@ -7,7 +7,7 @@ import (
|
|||||||
|
|
||||||
. "github.com/tendermint/tendermint/account"
|
. "github.com/tendermint/tendermint/account"
|
||||||
. "github.com/tendermint/tendermint/binary"
|
. "github.com/tendermint/tendermint/binary"
|
||||||
. "github.com/tendermint/tendermint/blocks"
|
. "github.com/tendermint/tendermint/block"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Persistent static data for each Validator
|
// Persistent static data for each Validator
|
||||||
@ -16,6 +16,7 @@ type ValidatorInfo struct {
|
|||||||
PubKey PubKeyEd25519
|
PubKey PubKeyEd25519
|
||||||
UnbondTo []*TxOutput
|
UnbondTo []*TxOutput
|
||||||
FirstBondHeight uint
|
FirstBondHeight uint
|
||||||
|
FirstBondAmount uint64
|
||||||
|
|
||||||
// If destroyed:
|
// If destroyed:
|
||||||
DestroyedHeight uint
|
DestroyedHeight uint
|
||||||
|
@ -22,9 +22,9 @@ import (
|
|||||||
// TODO: consider validator Accum overflow
|
// TODO: consider validator Accum overflow
|
||||||
// TODO: replace validators []*Validator with github.com/jaekwon/go-ibbs?
|
// TODO: replace validators []*Validator with github.com/jaekwon/go-ibbs?
|
||||||
type ValidatorSet struct {
|
type ValidatorSet struct {
|
||||||
validators []*Validator
|
Validators []*Validator // NOTE: persisted via reflect, must be exported.
|
||||||
|
|
||||||
// cache
|
// cached (unexported)
|
||||||
proposer *Validator
|
proposer *Validator
|
||||||
totalVotingPower uint64
|
totalVotingPower uint64
|
||||||
}
|
}
|
||||||
@ -36,7 +36,7 @@ func NewValidatorSet(vals []*Validator) *ValidatorSet {
|
|||||||
}
|
}
|
||||||
sort.Sort(ValidatorsByAddress(validators))
|
sort.Sort(ValidatorsByAddress(validators))
|
||||||
return &ValidatorSet{
|
return &ValidatorSet{
|
||||||
validators: validators,
|
Validators: validators,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,7 +45,7 @@ func (valSet *ValidatorSet) IncrementAccum(times uint) {
|
|||||||
|
|
||||||
// Add VotingPower * times to each validator and order into heap.
|
// Add VotingPower * times to each validator and order into heap.
|
||||||
validatorsHeap := NewHeap()
|
validatorsHeap := NewHeap()
|
||||||
for _, val := range valSet.validators {
|
for _, val := range valSet.Validators {
|
||||||
val.Accum += int64(val.VotingPower) * int64(times) // TODO: mind overflow
|
val.Accum += int64(val.VotingPower) * int64(times) // TODO: mind overflow
|
||||||
validatorsHeap.Push(val, accumComparable(val.Accum))
|
validatorsHeap.Push(val, accumComparable(val.Accum))
|
||||||
}
|
}
|
||||||
@ -62,48 +62,48 @@ func (valSet *ValidatorSet) IncrementAccum(times uint) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (valSet *ValidatorSet) Copy() *ValidatorSet {
|
func (valSet *ValidatorSet) Copy() *ValidatorSet {
|
||||||
validators := make([]*Validator, len(valSet.validators))
|
validators := make([]*Validator, len(valSet.Validators))
|
||||||
for i, val := range valSet.validators {
|
for i, val := range valSet.Validators {
|
||||||
// NOTE: must copy, since IncrementAccum updates in place.
|
// NOTE: must copy, since IncrementAccum updates in place.
|
||||||
validators[i] = val.Copy()
|
validators[i] = val.Copy()
|
||||||
}
|
}
|
||||||
return &ValidatorSet{
|
return &ValidatorSet{
|
||||||
validators: validators,
|
Validators: validators,
|
||||||
proposer: valSet.proposer,
|
proposer: valSet.proposer,
|
||||||
totalVotingPower: valSet.totalVotingPower,
|
totalVotingPower: valSet.totalVotingPower,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (valSet *ValidatorSet) HasAddress(address []byte) bool {
|
func (valSet *ValidatorSet) HasAddress(address []byte) bool {
|
||||||
idx := sort.Search(len(valSet.validators), func(i int) bool {
|
idx := sort.Search(len(valSet.Validators), func(i int) bool {
|
||||||
return bytes.Compare(address, valSet.validators[i].Address) <= 0
|
return bytes.Compare(address, valSet.Validators[i].Address) <= 0
|
||||||
})
|
})
|
||||||
return idx != len(valSet.validators) && bytes.Compare(valSet.validators[idx].Address, address) == 0
|
return idx != len(valSet.Validators) && bytes.Compare(valSet.Validators[idx].Address, address) == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (valSet *ValidatorSet) GetByAddress(address []byte) (index uint, val *Validator) {
|
func (valSet *ValidatorSet) GetByAddress(address []byte) (index uint, val *Validator) {
|
||||||
idx := sort.Search(len(valSet.validators), func(i int) bool {
|
idx := sort.Search(len(valSet.Validators), func(i int) bool {
|
||||||
return bytes.Compare(address, valSet.validators[i].Address) <= 0
|
return bytes.Compare(address, valSet.Validators[i].Address) <= 0
|
||||||
})
|
})
|
||||||
if idx != len(valSet.validators) && bytes.Compare(valSet.validators[idx].Address, address) == 0 {
|
if idx != len(valSet.Validators) && bytes.Compare(valSet.Validators[idx].Address, address) == 0 {
|
||||||
return uint(idx), valSet.validators[idx].Copy()
|
return uint(idx), valSet.Validators[idx].Copy()
|
||||||
} else {
|
} else {
|
||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (valSet *ValidatorSet) GetByIndex(index uint) (address []byte, val *Validator) {
|
func (valSet *ValidatorSet) GetByIndex(index uint) (address []byte, val *Validator) {
|
||||||
val = valSet.validators[index]
|
val = valSet.Validators[index]
|
||||||
return val.Address, val.Copy()
|
return val.Address, val.Copy()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (valSet *ValidatorSet) Size() uint {
|
func (valSet *ValidatorSet) Size() uint {
|
||||||
return uint(len(valSet.validators))
|
return uint(len(valSet.Validators))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (valSet *ValidatorSet) TotalVotingPower() uint64 {
|
func (valSet *ValidatorSet) TotalVotingPower() uint64 {
|
||||||
if valSet.totalVotingPower == 0 {
|
if valSet.totalVotingPower == 0 {
|
||||||
for _, val := range valSet.validators {
|
for _, val := range valSet.Validators {
|
||||||
valSet.totalVotingPower += val.VotingPower
|
valSet.totalVotingPower += val.VotingPower
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -112,7 +112,7 @@ func (valSet *ValidatorSet) TotalVotingPower() uint64 {
|
|||||||
|
|
||||||
func (valSet *ValidatorSet) Proposer() (proposer *Validator) {
|
func (valSet *ValidatorSet) Proposer() (proposer *Validator) {
|
||||||
if valSet.proposer == nil {
|
if valSet.proposer == nil {
|
||||||
for _, val := range valSet.validators {
|
for _, val := range valSet.Validators {
|
||||||
valSet.proposer = valSet.proposer.CompareAccum(val)
|
valSet.proposer = valSet.proposer.CompareAccum(val)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -120,11 +120,11 @@ func (valSet *ValidatorSet) Proposer() (proposer *Validator) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (valSet *ValidatorSet) Hash() []byte {
|
func (valSet *ValidatorSet) Hash() []byte {
|
||||||
if len(valSet.validators) == 0 {
|
if len(valSet.Validators) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
hashables := make([]merkle.Hashable, len(valSet.validators))
|
hashables := make([]merkle.Hashable, len(valSet.Validators))
|
||||||
for i, val := range valSet.validators {
|
for i, val := range valSet.Validators {
|
||||||
hashables[i] = val
|
hashables[i] = val
|
||||||
}
|
}
|
||||||
return merkle.HashFromHashables(hashables)
|
return merkle.HashFromHashables(hashables)
|
||||||
@ -132,21 +132,21 @@ func (valSet *ValidatorSet) Hash() []byte {
|
|||||||
|
|
||||||
func (valSet *ValidatorSet) Add(val *Validator) (added bool) {
|
func (valSet *ValidatorSet) Add(val *Validator) (added bool) {
|
||||||
val = val.Copy()
|
val = val.Copy()
|
||||||
idx := sort.Search(len(valSet.validators), func(i int) bool {
|
idx := sort.Search(len(valSet.Validators), func(i int) bool {
|
||||||
return bytes.Compare(val.Address, valSet.validators[i].Address) <= 0
|
return bytes.Compare(val.Address, valSet.Validators[i].Address) <= 0
|
||||||
})
|
})
|
||||||
if idx == len(valSet.validators) {
|
if idx == len(valSet.Validators) {
|
||||||
valSet.validators = append(valSet.validators, val)
|
valSet.Validators = append(valSet.Validators, val)
|
||||||
// Invalidate cache
|
// Invalidate cache
|
||||||
valSet.proposer = nil
|
valSet.proposer = nil
|
||||||
valSet.totalVotingPower = 0
|
valSet.totalVotingPower = 0
|
||||||
return true
|
return true
|
||||||
} else if bytes.Compare(valSet.validators[idx].Address, val.Address) == 0 {
|
} else if bytes.Compare(valSet.Validators[idx].Address, val.Address) == 0 {
|
||||||
return false
|
return false
|
||||||
} else {
|
} else {
|
||||||
newValidators := append(valSet.validators[:idx], val)
|
newValidators := append(valSet.Validators[:idx], val)
|
||||||
newValidators = append(newValidators, valSet.validators[idx:]...)
|
newValidators = append(newValidators, valSet.Validators[idx:]...)
|
||||||
valSet.validators = newValidators
|
valSet.Validators = newValidators
|
||||||
// Invalidate cache
|
// Invalidate cache
|
||||||
valSet.proposer = nil
|
valSet.proposer = nil
|
||||||
valSet.totalVotingPower = 0
|
valSet.totalVotingPower = 0
|
||||||
@ -159,7 +159,7 @@ func (valSet *ValidatorSet) Update(val *Validator) (updated bool) {
|
|||||||
if sameVal == nil {
|
if sameVal == nil {
|
||||||
return false
|
return false
|
||||||
} else {
|
} else {
|
||||||
valSet.validators[index] = val.Copy()
|
valSet.Validators[index] = val.Copy()
|
||||||
// Invalidate cache
|
// Invalidate cache
|
||||||
valSet.proposer = nil
|
valSet.proposer = nil
|
||||||
valSet.totalVotingPower = 0
|
valSet.totalVotingPower = 0
|
||||||
@ -168,18 +168,18 @@ func (valSet *ValidatorSet) Update(val *Validator) (updated bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (valSet *ValidatorSet) Remove(address []byte) (val *Validator, removed bool) {
|
func (valSet *ValidatorSet) Remove(address []byte) (val *Validator, removed bool) {
|
||||||
idx := sort.Search(len(valSet.validators), func(i int) bool {
|
idx := sort.Search(len(valSet.Validators), func(i int) bool {
|
||||||
return bytes.Compare(address, valSet.validators[i].Address) <= 0
|
return bytes.Compare(address, valSet.Validators[i].Address) <= 0
|
||||||
})
|
})
|
||||||
if idx == len(valSet.validators) || bytes.Compare(valSet.validators[idx].Address, address) != 0 {
|
if idx == len(valSet.Validators) || bytes.Compare(valSet.Validators[idx].Address, address) != 0 {
|
||||||
return nil, false
|
return nil, false
|
||||||
} else {
|
} else {
|
||||||
removedVal := valSet.validators[idx]
|
removedVal := valSet.Validators[idx]
|
||||||
newValidators := valSet.validators[:idx]
|
newValidators := valSet.Validators[:idx]
|
||||||
if idx+1 < len(valSet.validators) {
|
if idx+1 < len(valSet.Validators) {
|
||||||
newValidators = append(newValidators, valSet.validators[idx+1:]...)
|
newValidators = append(newValidators, valSet.Validators[idx+1:]...)
|
||||||
}
|
}
|
||||||
valSet.validators = newValidators
|
valSet.Validators = newValidators
|
||||||
// Invalidate cache
|
// Invalidate cache
|
||||||
valSet.proposer = nil
|
valSet.proposer = nil
|
||||||
valSet.totalVotingPower = 0
|
valSet.totalVotingPower = 0
|
||||||
@ -188,7 +188,7 @@ func (valSet *ValidatorSet) Remove(address []byte) (val *Validator, removed bool
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (valSet *ValidatorSet) Iterate(fn func(index uint, val *Validator) bool) {
|
func (valSet *ValidatorSet) Iterate(fn func(index uint, val *Validator) bool) {
|
||||||
for i, val := range valSet.validators {
|
for i, val := range valSet.Validators {
|
||||||
stop := fn(uint(i), val.Copy())
|
stop := fn(uint(i), val.Copy())
|
||||||
if stop {
|
if stop {
|
||||||
break
|
break
|
||||||
@ -244,5 +244,5 @@ type accumComparable uint64
|
|||||||
|
|
||||||
// We want to find the validator with the greatest accum.
|
// We want to find the validator with the greatest accum.
|
||||||
func (ac accumComparable) Less(o interface{}) bool {
|
func (ac accumComparable) Less(o interface{}) bool {
|
||||||
return uint64(ac) > o.(uint64)
|
return uint64(ac) > uint64(o.(accumComparable))
|
||||||
}
|
}
|
||||||
|
@ -1,21 +1,18 @@
|
|||||||
package state
|
package state
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
. "github.com/tendermint/tendermint/account"
|
||||||
. "github.com/tendermint/tendermint/common"
|
. "github.com/tendermint/tendermint/common"
|
||||||
|
|
||||||
"bytes"
|
"bytes"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func randValidator() *Validator {
|
func randValidator_() *Validator {
|
||||||
return &Validator{
|
return &Validator{
|
||||||
Account: Account{
|
Address: RandBytes(20),
|
||||||
Id: RandUInt64(),
|
PubKey: PubKeyEd25519{RandBytes(64)},
|
||||||
PubKey: CRandBytes(32),
|
BondHeight: uint(RandUInt32()),
|
||||||
},
|
|
||||||
BondHeight: RandUInt32(),
|
|
||||||
UnbondHeight: RandUInt32(),
|
|
||||||
LastCommitHeight: RandUInt32(),
|
|
||||||
VotingPower: RandUInt64(),
|
VotingPower: RandUInt64(),
|
||||||
Accum: int64(RandUInt64()),
|
Accum: int64(RandUInt64()),
|
||||||
}
|
}
|
||||||
@ -24,7 +21,7 @@ func randValidator() *Validator {
|
|||||||
func randValidatorSet(numValidators int) *ValidatorSet {
|
func randValidatorSet(numValidators int) *ValidatorSet {
|
||||||
validators := make([]*Validator, numValidators)
|
validators := make([]*Validator, numValidators)
|
||||||
for i := 0; i < numValidators; i++ {
|
for i := 0; i < numValidators; i++ {
|
||||||
validators[i] = randValidator()
|
validators[i] = randValidator_()
|
||||||
}
|
}
|
||||||
return NewValidatorSet(validators)
|
return NewValidatorSet(validators)
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user