Browse Source

Fixed tests

pull/9/head
Jae Kwon 10 years ago
parent
commit
61d1635085
40 changed files with 781 additions and 592 deletions
  1. +5
    -2
      account/priv_account.go
  2. +6
    -5
      account/signature_test.go
  3. +1
    -1
      binary/binary.go
  4. +9
    -3
      binary/codec.go
  5. +90
    -10
      binary/reflect.go
  6. +5
    -3
      block/block.go
  7. +1
    -1
      block/part_set.go
  8. +1
    -1
      block/part_set_test.go
  9. +1
    -1
      block/store.go
  10. +1
    -1
      block/tx.go
  11. +1
    -1
      block/vote.go
  12. +0
    -15
      blocks/log.go
  13. +5
    -5
      cmd/daemon.go
  14. +2
    -2
      cmd/gen_account.go
  15. +2
    -2
      cmd/gen_validator.go
  16. +35
    -35
      common/bit_array.go
  17. +31
    -28
      common/bit_array_test.go
  18. +16
    -11
      consensus/pol.go
  19. +54
    -54
      consensus/pol_test.go
  20. +3
    -2
      consensus/reactor.go
  21. +4
    -3
      consensus/state.go
  22. +48
    -74
      consensus/state_test.go
  23. +19
    -4
      consensus/test.go
  24. +1
    -1
      consensus/types/proposal.go
  25. +13
    -8
      consensus/vote_set.go
  26. +80
    -95
      consensus/vote_set_test.go
  27. +1
    -1
      mempool/mempool.go
  28. +1
    -1
      mempool/reactor.go
  29. +3
    -0
      merkle/iavl_tree.go
  30. +4
    -5
      p2p/connection.go
  31. +4
    -2
      p2p/listener.go
  32. +1
    -1
      rpc/blocks.go
  33. +20
    -3
      state/genesis.go
  34. +45
    -16
      state/priv_validator.go
  35. +13
    -4
      state/state.go
  36. +107
    -139
      state/state_test.go
  37. +98
    -0
      state/test.go
  38. +2
    -1
      state/validator.go
  39. +40
    -40
      state/validator_set.go
  40. +8
    -11
      state/validator_set_test.go

wallet/priv_account.go → account/priv_account.go View File


+ 6
- 5
account/signature_test.go View File

@ -8,21 +8,22 @@ import (
func TestSignAndValidate(t *testing.T) {
privAccount := GenPrivAccount()
account := &privAccount.Account
pubKey := privAccount.PubKey
privKey := privAccount.PrivKey
msg := CRandBytes(128)
sig := privAccount.SignBytes(msg)
sig := privKey.Sign(msg)
t.Logf("msg: %X, sig: %X", msg, sig)
// Test the signature
if !account.VerifyBytes(msg, sig) {
if !pubKey.VerifyBytes(msg, sig) {
t.Errorf("Account message signature verification failed")
}
// 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")
}
}

+ 1
- 1
binary/binary.go View File

@ -13,7 +13,7 @@ func ReadBinary(o interface{}, r io.Reader, n *int64, err *error) interface{} {
} else {
ptrRv := reflect.New(rt)
readReflect(ptrRv.Elem(), rt, r, n, err)
return ptrRv.Elem()
return ptrRv.Elem().Interface()
}
}


+ 9
- 3
binary/codec.go View File

@ -2,7 +2,9 @@ package binary
import (
"bytes"
"fmt"
"io"
"reflect"
"time"
)
@ -80,7 +82,7 @@ func BasicCodecEncoder(o interface{}, w io.Writer, n *int64, err *error) {
WriteByte(typeTime, w, n, err)
WriteTime(o.(time.Time), w, n, err)
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:
o = ReadTime(r, n, err)
default:
panic("Unsupported type")
if *err != nil {
panic(err)
} else {
panic(fmt.Sprintf("Unsupported type byte: %X", type_))
}
}
return o
}
@ -151,7 +157,7 @@ func BasicCodecComparator(o1 interface{}, o2 interface{}) int {
case time.Time:
return int(o1.(time.Time).UnixNano() - o2.(time.Time).UnixNano())
default:
panic("Unsupported type")
panic(fmt.Sprintf("Unsupported type: %v", reflect.TypeOf(o1)))
}
}


+ 90
- 10
binary/reflect.go View File

@ -1,6 +1,7 @@
package binary
import (
"errors"
"fmt"
"io"
"reflect"
@ -10,6 +11,9 @@ type TypeInfo struct {
Type reflect.Type // The type
Encoder Encoder // Optional custom encoder function
Decoder Decoder // Optional custom decoder function
HasTypeByte bool
TypeByte byte
}
// If a type implements TypeByte, the byte is included
@ -25,18 +29,33 @@ type HasTypeByte interface {
var typeInfos = map[reflect.Type]*TypeInfo{}
func RegisterType(info *TypeInfo) bool {
func RegisterType(info *TypeInfo) *TypeInfo {
// Register the type info
typeInfos[info.Type] = info
// 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 {
rt := info.Type.Elem()
typeInfos[rt] = info
} else {
ptrRt := reflect.PtrTo(info.Type)
typeInfos[ptrRt] = info
}
// 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 true
return info
}
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()
}
// Custom decoder
// Get typeInfo
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)
decodedRv := reflect.Indirect(reflect.ValueOf(decoded))
rv.Set(decodedRv)
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() {
case reflect.Slice:
elemRt := rt.Elem()
@ -86,7 +119,7 @@ func readReflect(rv reflect.Value, rt reflect.Type, r io.Reader, n *int64, err *
numFields := rt.NumField()
for i := 0; i < numFields; i++ {
field := rt.Field(i)
if field.Anonymous {
if field.PkgPath != "" {
continue
}
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)
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:
num := ReadUInt64(r, n, err)
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) {
// Custom encoder
// Get typeInfo
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)
return
}
@ -135,14 +193,21 @@ func writeReflect(rv reflect.Value, rt reflect.Type, w io.Writer, n *int64, err
if rt.Kind() == reflect.Ptr {
rt = rt.Elem()
rv = rv.Elem()
// RegisterType registers the ptr type,
// so typeInfo is already for the ptr.
} else if rt.Kind() == reflect.Interface {
rv = rv.Elem()
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
if rt.Implements(reflect.TypeOf((*HasTypeByte)(nil)).Elem()) {
WriteByte(rv.Interface().(HasTypeByte).TypeByte(), w, n, err)
if typeInfo.HasTypeByte {
WriteByte(typeInfo.TypeByte, w, n, err)
}
switch rt.Kind() {
@ -167,7 +232,7 @@ func writeReflect(rv reflect.Value, rt reflect.Type, w io.Writer, n *int64, err
numFields := rt.NumField()
for i := 0; i < numFields; i++ {
field := rt.Field(i)
if field.Anonymous {
if field.PkgPath != "" {
continue
}
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:
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:
WriteUInt64(rv.Uint(), w, n, err)


blocks/block.go → block/block.go View File


blocks/part_set.go → block/part_set.go View File


blocks/part_set_test.go → block/part_set_test.go View File


blocks/store.go → block/store.go View File


blocks/tx.go → block/tx.go View File


blocks/vote.go → block/vote.go View File


+ 0
- 15
blocks/log.go View File

@ -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
}

+ 5
- 5
cmd/daemon.go View File

@ -4,7 +4,7 @@ import (
"os"
"os/signal"
"github.com/tendermint/tendermint/blocks"
"github.com/tendermint/tendermint/block"
"github.com/tendermint/tendermint/config"
"github.com/tendermint/tendermint/consensus"
db_ "github.com/tendermint/tendermint/db"
@ -21,13 +21,13 @@ type Node struct {
pexReactor *p2p.PEXReactor
mempoolReactor *mempool_.MempoolReactor
consensusReactor *consensus.ConsensusReactor
privValidator *consensus.PrivValidator
privValidator *state_.PrivValidator
}
func NewNode() *Node {
// Get BlockStore
blockStoreDB := db_.NewMemDB() // TODO configurable db.
blockStore := blocks.NewBlockStore(blockStoreDB)
blockStore := block.NewBlockStore(blockStoreDB)
// Get State
stateDB := db_.NewMemDB() // TODO configurable db.
@ -38,9 +38,9 @@ func NewNode() *Node {
}
// Get PrivValidator
var privValidator *consensus.PrivValidator
var privValidator *state_.PrivValidator
if _, err := os.Stat(config.PrivValidatorFile()); err == nil {
privValidator = consensus.LoadPrivValidator()
privValidator = state_.LoadPrivValidator()
}
// Get PEXReactor


+ 2
- 2
cmd/gen_account.go View File

@ -4,15 +4,15 @@ import (
"encoding/base64"
"fmt"
. "github.com/tendermint/tendermint/account"
. "github.com/tendermint/tendermint/binary"
"github.com/tendermint/tendermint/wallet"
)
func gen_account() {
// TODO: uh, write better logic.
// Generate private account
privAccount := wallet.GenPrivAccount()
privAccount := GenPrivAccount()
fmt.Printf(`Generated account:
Account Public Key: %X


+ 2
- 2
cmd/gen_validator.go View File

@ -5,7 +5,7 @@ import (
"os"
"github.com/tendermint/tendermint/config"
"github.com/tendermint/tendermint/consensus"
"github.com/tendermint/tendermint/state"
)
func gen_validator() {
@ -17,7 +17,7 @@ func gen_validator() {
}
// Generate private validator
privValidator := consensus.GenPrivValidator()
privValidator := state.GenPrivValidator()
privValidator.Save()
fmt.Printf("Generated a new validator at %v\n", filename)
}

+ 35
- 35
common/bit_array.go View File

@ -8,8 +8,8 @@ import (
// Not goroutine safe
type BitArray struct {
bits uint
elems []uint64
Bits uint // NOTE: persisted via reflect, must be exported
Elems []uint64 // NOTE: persisted via reflect, must be exported
}
func NewBitArray(bits uint) BitArray {
@ -17,81 +17,81 @@ func NewBitArray(bits uint) BitArray {
}
func (bA BitArray) Size() uint {
return bA.bits
return bA.Bits
}
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 {
if i >= bA.bits {
if i >= bA.Bits {
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 {
if i >= bA.bits {
if i >= bA.Bits {
return false
}
if v {
bA.elems[i/64] |= uint64(1 << (i % 64))
bA.Elems[i/64] |= uint64(1 << (i % 64))
} else {
bA.elems[i/64] &= ^uint64(1 << (i % 64))
bA.Elems[i/64] &= ^uint64(1 << (i % 64))
}
return true
}
func (bA BitArray) Copy() BitArray {
c := make([]uint64, len(bA.elems))
copy(c, bA.elems)
return BitArray{bA.bits, c}
c := make([]uint64, len(bA.Elems))
copy(c, bA.Elems)
return BitArray{bA.Bits, c}
}
func (bA BitArray) copyBits(bits uint) BitArray {
c := make([]uint64, (bits+63)/64)
copy(c, bA.elems)
copy(c, bA.Elems)
return BitArray{bits, c}
}
// Returns a BitArray of larger bits size.
func (bA BitArray) Or(o BitArray) BitArray {
c := bA.copyBits(MaxUint(bA.bits, o.bits))
for i := 0; i < len(c.elems); i++ {
c.elems[i] |= o.elems[i]
c := bA.copyBits(MaxUint(bA.Bits, o.Bits))
for i := 0; i < len(c.Elems); i++ {
c.Elems[i] |= o.Elems[i]
}
return c
}
// Returns a BitArray of smaller bit size.
func (bA BitArray) And(o BitArray) BitArray {
c := bA.copyBits(MinUint(bA.bits, o.bits))
for i := 0; i < len(c.elems); i++ {
c.elems[i] &= o.elems[i]
c := bA.copyBits(MinUint(bA.Bits, o.Bits))
for i := 0; i < len(c.Elems); i++ {
c.Elems[i] &= o.Elems[i]
}
return c
}
func (bA BitArray) Not() BitArray {
c := bA.Copy()
for i := 0; i < len(c.elems); i++ {
c.elems[i] = ^c.elems[i]
for i := 0; i < len(c.Elems); i++ {
c.Elems[i] = ^c.Elems[i]
}
return c
}
func (bA BitArray) Sub(o BitArray) BitArray {
if bA.bits > o.bits {
if bA.Bits > o.Bits {
c := bA.Copy()
for i := 0; i < len(o.elems)-1; i++ {
c.elems[i] &= ^c.elems[i]
for i := 0; i < len(o.Elems)-1; i++ {
c.Elems[i] &= ^c.Elems[i]
}
i := uint(len(o.elems) - 1)
i := uint(len(o.Elems) - 1)
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))
}
}
@ -102,7 +102,7 @@ func (bA BitArray) Sub(o BitArray) BitArray {
}
func (bA BitArray) PickRandom() (uint, bool) {
length := len(bA.elems)
length := len(bA.Elems)
if length == 0 {
return 0, false
}
@ -110,11 +110,11 @@ func (bA BitArray) PickRandom() (uint, bool) {
for i := 0; i < length; i++ {
elemIdx := ((i + randElemStart) % length)
if elemIdx < length-1 {
if bA.elems[elemIdx] > 0 {
if bA.Elems[elemIdx] > 0 {
randBitStart := rand.Intn(64)
for j := 0; j < 64; j++ {
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
}
}
@ -122,14 +122,14 @@ func (bA BitArray) PickRandom() (uint, bool) {
}
} else {
// Special case for last elem, to ignore straggler bits
elemBits := int(bA.bits) % 64
elemBits := int(bA.Bits) % 64
if elemBits == 0 {
elemBits = 64
}
randBitStart := rand.Intn(elemBits)
for j := 0; j < elemBits; j++ {
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
}
}
@ -145,7 +145,7 @@ func (bA BitArray) String() string {
func (bA BitArray) StringWithIndent(indent string) string {
lines := []string{}
bits := ""
for i := uint(0); i < bA.bits; i++ {
for i := uint(0); i < bA.Bits; i++ {
if bA.GetIndex(i) {
bits += "X"
} else {
@ -165,5 +165,5 @@ func (bA BitArray) StringWithIndent(indent string) string {
if len(bits) > 0 {
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))
}

+ 31
- 28
common/bit_array_test.go View File

@ -2,7 +2,10 @@ package common
import (
"bytes"
"fmt"
"testing"
. "github.com/tendermint/tendermint/binary"
)
func randBitArray(bits uint) (BitArray, []byte) {
@ -22,19 +25,18 @@ func randBitArray(bits uint) (BitArray, []byte) {
func TestReadWriteEmptyBitarray(t *testing.T) {
bA1 := BitArray{}
buf := new(bytes.Buffer)
_, err := bA1.WriteTo(buf)
if err != nil {
buf, n, err := new(bytes.Buffer), new(int64), new(error)
WriteBinary(bA1, buf, n, err)
if *err != nil {
t.Error("Failed to write empty bitarray")
}
var n int64
bA2 := ReadBitArray(buf, &n, &err)
if err != nil {
bA2 := ReadBinary(BitArray{}, buf, n, err).(BitArray)
if *err != nil {
t.Error("Failed to read empty bitarray")
}
if bA2.bits != 0 {
t.Error("Expected to get bA2.bits 0")
if 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
// Write it
buf := new(bytes.Buffer)
_, err := bA1.WriteTo(buf)
if err != nil {
buf, n, err := new(bytes.Buffer), new(int64), new(error)
WriteBinary(bA1, buf, n, err)
if *err != nil {
t.Error("Failed to write bitarray")
}
fmt.Printf("Bytes: %X", buf.Bytes())
// Read it
var n int64
bA2 := ReadBitArray(buf, &n, &err)
if err != nil {
bA2 := ReadBinary(BitArray{}, buf, n, err).(BitArray)
if *err != nil {
t.Error("Failed to read bitarray")
}
testData2 := make([]byte, len(testData))
@ -77,13 +80,13 @@ func TestAnd(t *testing.T) {
bA2, _ := randBitArray(31)
bA3 := bA1.And(bA2)
if bA3.bits != 31 {
t.Error("Expected min bits", bA3.bits)
if bA3.Bits != 31 {
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")
}
for i := uint(0); i < bA3.bits; i++ {
for i := uint(0); i < bA3.Bits; i++ {
expected := bA1.GetIndex(i) && bA2.GetIndex(i)
if bA3.GetIndex(i) != expected {
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)
bA3 := bA1.Or(bA2)
if bA3.bits != 51 {
if bA3.Bits != 51 {
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")
}
for i := uint(0); i < bA3.bits; i++ {
for i := uint(0); i < bA3.Bits; i++ {
expected := bA1.GetIndex(i) || bA2.GetIndex(i)
if bA3.GetIndex(i) != expected {
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)
bA3 := bA1.Sub(bA2)
if bA3.bits != bA1.bits {
if bA3.Bits != 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")
}
for i := uint(0); i < bA3.bits; i++ {
for i := uint(0); i < bA3.Bits; i++ {
expected := bA1.GetIndex(i)
if bA2.GetIndex(i) {
expected = false
@ -140,15 +143,15 @@ func TestSub2(t *testing.T) {
bA2, _ := randBitArray(31)
bA3 := bA1.Sub(bA2)
if bA3.bits != bA1.bits {
if bA3.Bits != 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")
}
for i := uint(0); i < bA3.bits; i++ {
for i := uint(0); i < bA3.Bits; i++ {
expected := bA1.GetIndex(i)
if i < bA2.bits && bA2.GetIndex(i) {
if i < bA2.Bits && bA2.GetIndex(i) {
expected = false
}
if bA3.GetIndex(i) != expected {


+ 16
- 11
consensus/pol.go View File

@ -4,7 +4,7 @@ import (
"fmt"
. "github.com/tendermint/tendermint/account"
. "github.com/tendermint/tendermint/blocks"
. "github.com/tendermint/tendermint/block"
. "github.com/tendermint/tendermint/common"
"github.com/tendermint/tendermint/state"
)
@ -28,7 +28,7 @@ type POL struct {
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 {
if uint(len(pol.Votes)) != valSet.Size() {
@ -44,27 +44,32 @@ func (pol *POL) Verify(valSet *state.ValidatorSet) error {
})
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
_, val := valSet.GetByIndex(uint(idx))
// Commit signature?
if sig.Round < pol.Round {
// Commit vote?
if vote.Round < pol.Round {
voteDoc = SignBytes(&Vote{
Height: pol.Height, Round: sig.Round, Type: VoteTypeCommit,
Height: pol.Height, Round: vote.Round, Type: VoteTypeCommit,
BlockHash: pol.BlockHash,
BlockParts: pol.BlockParts,
})
} else if sig.Round > pol.Round {
return Errorf("Invalid commit round %v for POL %v", sig.Round, pol)
} else if vote.Round > pol.Round {
return Errorf("Invalid commit round %v for POL %v", vote.Round, pol)
}
// Validate
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


+ 54
- 54
consensus/pol_test.go View File

@ -1,8 +1,10 @@
package consensus
import (
. "github.com/tendermint/tendermint/blocks"
. "github.com/tendermint/tendermint/binary"
. "github.com/tendermint/tendermint/block"
. "github.com/tendermint/tendermint/common"
state "github.com/tendermint/tendermint/state"
"bytes"
"testing"
@ -10,22 +12,30 @@ import (
// 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) {
height, round := uint32(1), uint16(0)
_, valSet, privAccounts := makeVoteSet(height, round, VoteTypePrevote, 10, 1)
height, round := uint(1), uint(0)
_, valSet, privValidators := makeVoteSet(height, round, VoteTypePrevote, 10, 1)
// Make a POL with -2/3 votes.
blockHash := RandBytes(32)
pol := &POL{
Height: height, Round: round, BlockHash: blockHash,
Votes: make([]POLVoteSignature, valSet.Size()),
}
voteProto := &Vote{
Height: height, Round: round, Type: VoteTypePrevote, BlockHash: blockHash,
}
for i := 0; i < 6; i++ {
vote := voteProto.Copy()
privAccounts[i].Sign(vote)
pol.Votes = append(pol.Votes, vote.Signature)
signAddPOLVoteSignature(privValidators[i], valSet, voteProto, pol)
}
// Check that validation fails.
@ -33,35 +43,31 @@ func TestVerifyVotes(t *testing.T) {
t.Errorf("Expected POL.Verify() to fail, not enough votes.")
}
// Make a POL with +2/3 votes.
vote := voteProto.Copy()
privAccounts[7].Sign(vote)
pol.Votes = append(pol.Votes, vote.Signature)
// Insert another vote to make +2/3
signAddPOLVoteSignature(privValidators[7], valSet, voteProto, pol)
// Check that validation succeeds.
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) {
height, round := uint32(1), uint16(0)
_, valSet, privAccounts := makeVoteSet(height, round, VoteTypePrevote, 10, 1)
height, round := uint(1), uint(0)
_, valSet, privValidators := makeVoteSet(height, round, VoteTypePrevote, 10, 1)
// Make a POL with +2/3 votes with the wrong signature.
blockHash := RandBytes(32)
pol := &POL{
Height: height, Round: round, BlockHash: blockHash,
Votes: make([]POLVoteSignature, valSet.Size()),
}
voteProto := &Vote{
Height: height, Round: round, Type: VoteTypePrevote, BlockHash: blockHash,
}
for i := 0; i < 7; i++ {
vote := voteProto.Copy()
privAccounts[i].Sign(vote)
// Mutate the signature.
vote.Signature.Bytes[0] += byte(0x01)
pol.Votes = append(pol.Votes, vote.Signature)
polVoteSig := signAddPOLVoteSignature(privValidators[i], valSet, voteProto, pol)
polVoteSig.Signature.Bytes[0] += byte(0x01) // mutated!
}
// Check that validation fails.
@ -71,47 +77,44 @@ func TestVerifyInvalidVote(t *testing.T) {
}
func TestVerifyCommits(t *testing.T) {
height, round := uint32(1), uint16(2)
_, valSet, privAccounts := makeVoteSet(height, round, VoteTypePrevote, 10, 1)
height, round := uint(1), uint(2)
_, valSet, privValidators := makeVoteSet(height, round, VoteTypePrevote, 10, 1)
// Make a POL with +2/3 votes.
blockHash := RandBytes(32)
pol := &POL{
Height: height, Round: round, BlockHash: blockHash,
Votes: make([]POLVoteSignature, valSet.Size()),
}
voteProto := &Vote{
Height: height, Round: round - 1, Type: VoteTypeCommit, BlockHash: blockHash,
}
for i := 0; i < 7; i++ {
vote := voteProto.Copy()
privAccounts[i].Sign(vote)
pol.Commits = append(pol.Commits, RoundSignature{round - 1, vote.Signature})
signAddPOLVoteSignature(privValidators[i], valSet, voteProto, pol)
}
// Check that validation succeeds.
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) {
height, round := uint32(1), uint16(2)
_, valSet, privAccounts := makeVoteSet(height, round, VoteTypePrevote, 10, 1)
height, round := uint(1), uint(2)
_, valSet, privValidators := makeVoteSet(height, round, VoteTypePrevote, 10, 1)
// Make a POL with +2/3 votes with the wrong signature.
blockHash := RandBytes(32)
pol := &POL{
Height: height, Round: round, BlockHash: blockHash,
Votes: make([]POLVoteSignature, valSet.Size()),
}
voteProto := &Vote{
Height: height, Round: round - 1, Type: VoteTypeCommit, BlockHash: blockHash,
}
for i := 0; i < 7; i++ {
vote := voteProto.Copy()
privAccounts[i].Sign(vote)
// Mutate the signature.
vote.Signature.Bytes[0] += byte(0x01)
pol.Commits = append(pol.Commits, RoundSignature{round - 1, vote.Signature})
polVoteSig := signAddPOLVoteSignature(privValidators[i], valSet, voteProto, pol)
polVoteSig.Signature.Bytes[0] += byte(0x01)
}
// Check that validation fails.
@ -121,21 +124,20 @@ func TestVerifyInvalidCommits(t *testing.T) {
}
func TestVerifyInvalidCommitRounds(t *testing.T) {
height, round := uint32(1), uint16(2)
_, valSet, privAccounts := makeVoteSet(height, round, VoteTypePrevote, 10, 1)
height, round := uint(1), uint(2)
_, valSet, privValidators := makeVoteSet(height, round, VoteTypePrevote, 10, 1)
// Make a POL with +2/3 commits for the current round.
blockHash := RandBytes(32)
pol := &POL{
Height: height, Round: round, BlockHash: blockHash,
Votes: make([]POLVoteSignature, valSet.Size()),
}
voteProto := &Vote{
Height: height, Round: round, Type: VoteTypeCommit, BlockHash: blockHash,
}
for i := 0; i < 7; i++ {
vote := voteProto.Copy()
privAccounts[i].Sign(vote)
pol.Commits = append(pol.Commits, RoundSignature{round, vote.Signature})
signAddPOLVoteSignature(privValidators[i], valSet, voteProto, pol)
}
// Check that validation fails.
@ -145,21 +147,21 @@ func TestVerifyInvalidCommitRounds(t *testing.T) {
}
func TestVerifyInvalidCommitRounds2(t *testing.T) {
height, round := uint32(1), uint16(2)
_, valSet, privAccounts := makeVoteSet(height, round, VoteTypePrevote, 10, 1)
height, round := uint(1), uint(2)
_, valSet, privValidators := makeVoteSet(height, round, VoteTypePrevote, 10, 1)
// Make a POL with +2/3 commits for future round.
blockHash := RandBytes(32)
pol := &POL{
Height: height, Round: round, BlockHash: blockHash,
Votes: make([]POLVoteSignature, valSet.Size()),
}
voteProto := &Vote{
Height: height, Round: round + 1, Type: VoteTypeCommit, BlockHash: blockHash,
}
for i := 0; i < 7; i++ {
vote := voteProto.Copy()
privAccounts[i].Sign(vote)
pol.Commits = append(pol.Commits, RoundSignature{round + 1, vote.Signature})
polVoteSig := signAddPOLVoteSignature(privValidators[i], valSet, voteProto, pol)
polVoteSig.Round += 1 // mutate round
}
// Check that validation fails.
@ -169,39 +171,37 @@ func TestVerifyInvalidCommitRounds2(t *testing.T) {
}
func TestReadWrite(t *testing.T) {
height, round := uint32(1), uint16(2)
_, valSet, privAccounts := makeVoteSet(height, round, VoteTypePrevote, 10, 1)
height, round := uint(1), uint(2)
_, valSet, privValidators := makeVoteSet(height, round, VoteTypePrevote, 10, 1)
// Make a POL with +2/3 votes.
blockHash := RandBytes(32)
pol := &POL{
Height: height, Round: round, BlockHash: blockHash,
Votes: make([]POLVoteSignature, valSet.Size()),
}
voteProto := &Vote{
Height: height, Round: round, Type: VoteTypePrevote, BlockHash: blockHash,
}
for i := 0; i < 7; i++ {
vote := voteProto.Copy()
privAccounts[i].Sign(vote)
pol.Votes = append(pol.Votes, vote.Signature)
signAddPOLVoteSignature(privValidators[i], valSet, voteProto, pol)
}
// Write it to a buffer.
buf := new(bytes.Buffer)
_, err := pol.WriteTo(buf)
if err != nil {
t.Fatalf("Failed to write POL")
buf, n, err := new(bytes.Buffer), new(int64), new(error)
WriteBinary(pol, buf, n, err)
if *err != nil {
t.Fatalf("Failed to write POL: %v", *err)
}
// Read from buffer.
var n int64
pol2 := ReadPOL(buf, &n, &err)
if err != nil {
pol2 := ReadBinary(&POL{}, buf, n, err).(*POL)
if *err != nil {
t.Fatalf("Failed to read POL")
}
// Check that validation succeeds.
if err := pol2.Verify(valSet); err != nil {
t.Errorf("Expected POL.Verify() to succeed")
t.Errorf("POL.Verify() failed: %v", err)
}
}

+ 3
- 2
consensus/reactor.go View File

@ -9,8 +9,9 @@ import (
"time"
. "github.com/tendermint/tendermint/binary"
. "github.com/tendermint/tendermint/blocks"
. "github.com/tendermint/tendermint/block"
. "github.com/tendermint/tendermint/common"
. "github.com/tendermint/tendermint/consensus/types"
"github.com/tendermint/tendermint/mempool"
"github.com/tendermint/tendermint/p2p"
"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.
func (conR *ConsensusReactor) SetPrivValidator(priv *PrivValidator) {
func (conR *ConsensusReactor) SetPrivValidator(priv *state.PrivValidator) {
conR.conS.SetPrivValidator(priv)
}


+ 4
- 3
consensus/state.go View File

@ -62,9 +62,10 @@ import (
. "github.com/tendermint/tendermint/account"
. "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/consensus/types"
"github.com/tendermint/tendermint/mempool"
"github.com/tendermint/tendermint/state"
)
@ -126,7 +127,7 @@ type RoundState struct {
Precommits *VoteSet
Commits *VoteSet
LastCommits *VoteSet
PrivValidator *PrivValidator
PrivValidator *state.PrivValidator
}
func (rs *RoundState) String() string {
@ -469,7 +470,7 @@ func (cs *ConsensusState) setupNewRound(round uint) {
cs.Precommits.AddFromCommits(cs.Commits)
}
func (cs *ConsensusState) SetPrivValidator(priv *PrivValidator) {
func (cs *ConsensusState) SetPrivValidator(priv *state.PrivValidator) {
cs.mtx.Lock()
defer cs.mtx.Unlock()
cs.PrivValidator = priv


+ 48
- 74
consensus/state_test.go View File

@ -1,77 +1,33 @@
package consensus
import (
"bytes"
"testing"
"time"
. "github.com/tendermint/tendermint/blocks"
. "github.com/tendermint/tendermint/common"
db_ "github.com/tendermint/tendermint/db"
"github.com/tendermint/tendermint/mempool"
"github.com/tendermint/tendermint/state"
. "github.com/tendermint/tendermint/block"
)
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) {
cs, privAccounts := makeConsensusState()
cs, privValidators := makeConsensusState()
val0 := privValidators[0]
// Add a vote, precommit, and commit by val0.
voteTypes := []byte{VoteTypePrevote, VoteTypePrecommit, VoteTypeCommit}
for _, voteType := range voteTypes {
vote := &Vote{Height: 1, Round: 0, Type: voteType} // nil vote
privAccounts[0].Sign(vote)
cs.AddVote(vote)
vote.Signature = val0.SignVote(vote)
cs.AddVote(val0.Address, vote)
}
// Ensure that vote appears in RoundState.
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)
}
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)
}
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)
}
@ -81,13 +37,13 @@ func TestSetupRound(t *testing.T) {
// Now the commit should be copied over to prevotes and precommits.
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)
}
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)
}
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)
}
@ -103,9 +59,9 @@ func TestRunActionProposeNoPrivValidator(t *testing.T) {
}
func TestRunActionPropose(t *testing.T) {
cs, privAccounts := makeConsensusState()
priv := NewPrivValidator(db_.NewMemDB(), privAccounts[0])
cs.SetPrivValidator(priv)
cs, privValidators := makeConsensusState()
val0 := privValidators[0]
cs.SetPrivValidator(val0)
cs.RunActionPropose(1, 0)
rs := cs.GetRoundState()
@ -123,7 +79,7 @@ func TestRunActionPropose(t *testing.T) {
}
func checkRoundState(t *testing.T, rs *RoundState,
height uint32, round uint16, step RoundStep) {
height uint, round uint, step RoundStep) {
if rs.Height != 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) {
cs, privAccounts := makeConsensusState()
priv := NewPrivValidator(db_.NewMemDB(), privAccounts[0])
cs.SetPrivValidator(priv)
cs, privValidators := makeConsensusState()
val0 := privValidators[0]
cs.SetPrivValidator(val0)
cs.RunActionPrecommit(1, 0)
<-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")
}
@ -151,7 +107,7 @@ func TestRunActionPrecommitCommitFinalize(t *testing.T) {
cs.RunActionPrecommit(1, 0)
<-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")
}
@ -164,20 +120,26 @@ func TestRunActionPrecommitCommitFinalize(t *testing.T) {
BlockHash: cs.ProposalBlock.Hash(),
BlockParts: cs.ProposalBlockParts.Header(),
}
privAccounts[i].Sign(vote)
cs.AddVote(vote)
vote.Signature = privValidators[i].SignVote(vote)
cs.AddVote(privValidators[i].Address, vote)
}
// Test RunActionPrecommit success:
cs.RunActionPrecommit(1, 0)
<-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")
}
checkRoundState(t, cs.GetRoundState(), 1, 0, RoundStepPrecommit)
// Add at least +2/3 precommits.
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{
Height: 1,
Round: 0,
@ -185,14 +147,17 @@ func TestRunActionPrecommitCommitFinalize(t *testing.T) {
BlockHash: cs.ProposalBlock.Hash(),
BlockParts: cs.ProposalBlockParts.Header(),
}
privAccounts[i].Sign(vote)
cs.AddVote(vote)
vote.Signature = privValidators[i].SignVote(vote)
added, _, err := cs.AddVote(privValidators[i].Address, vote)
if !added || err != nil {
t.Errorf("Error adding precommit: %v", err)
}
}
// Test RunActionCommit success:
cs.RunActionCommit(1)
<-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")
}
checkRoundState(t, cs.GetRoundState(), 1, 0, RoundStepCommit)
@ -204,15 +169,24 @@ func TestRunActionPrecommitCommitFinalize(t *testing.T) {
// Add at least +2/3 commits.
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{
Height: 1,
Round: uint16(i), // Doesn't matter what round
Round: uint(i), // Doesn't matter what round
Type: VoteTypeCommit,
BlockHash: cs.ProposalBlock.Hash(),
BlockParts: cs.ProposalBlockParts.Header(),
}
privAccounts[i].Sign(vote)
cs.AddVote(vote)
vote.Signature = privValidators[i].SignVote(vote)
added, _, err := cs.AddVote(privValidators[i].Address, vote)
if !added || err != nil {
t.Errorf("Error adding commit: %v", err)
}
}
// Test TryFinalizeCommit:


+ 19
- 4
consensus/test.go View File

@ -1,13 +1,18 @@
package consensus
import (
"sort"
. "github.com/tendermint/tendermint/block"
db_ "github.com/tendermint/tendermint/db"
mempool_ "github.com/tendermint/tendermint/mempool"
"github.com/tendermint/tendermint/state"
)
// Common test methods
func makeValidator(votingPower uint64) (*state.Validator, *PrivValidator) {
privValidator := GenPrivValidator()
func makeValidator(votingPower uint64) (*state.Validator, *state.PrivValidator) {
privValidator := state.GenPrivValidator()
return &state.Validator{
Address: privValidator.Address,
PubKey: privValidator.PubKey,
@ -19,14 +24,24 @@ func makeValidator(votingPower uint64) (*state.Validator, *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)
privValidators := make([]*PrivValidator, numValidators)
privValidators := make([]*state.PrivValidator, numValidators)
for i := 0; i < numValidators; i++ {
val, privValidator := makeValidator(votingPower)
vals[i] = val
privValidators[i] = privValidator
}
valSet := state.NewValidatorSet(vals)
sort.Sort(state.PrivValidatorsByAddress(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
}

consensus/proposal.go → consensus/types/proposal.go View File


+ 13
- 8
consensus/vote_set.go View File

@ -8,7 +8,7 @@ import (
. "github.com/tendermint/tendermint/account"
. "github.com/tendermint/tendermint/binary"
. "github.com/tendermint/tendermint/blocks"
. "github.com/tendermint/tendermint/block"
. "github.com/tendermint/tendermint/common"
"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.
func (voteSet *VoteSet) AddFromCommits(commits *VoteSet) {
for valIndex, commit := range commits.votes {
if commit == nil {
continue
}
if commit.Round < voteSet.round {
voteSet.addVote(uint(valIndex), commit)
}
@ -197,6 +200,9 @@ func (voteSet *VoteSet) MakePOL() *POL {
Votes: make([]POLVoteSignature, voteSet.valSet.Size()),
}
for valIndex, vote := range voteSet.votes {
if vote == nil {
continue
}
if !bytes.Equal(vote.BlockHash, voteSet.maj23Hash) {
continue
}
@ -245,14 +251,13 @@ func (voteSet *VoteSet) String() string {
}
func (voteSet *VoteSet) StringWithIndent(indent string) string {
voteSet.mtx.Lock()
defer voteSet.mtx.Unlock()
voteStrings := make([]string, len(voteSet.votes))
counter := 0
for _, vote := range voteSet.votes {
voteStrings[counter] = vote.String()
counter++
for i, vote := range voteSet.votes {
if vote == nil {
voteStrings[i] = "nil"
} else {
voteStrings[i] = vote.String()
}
}
return fmt.Sprintf(`VoteSet{
%s H:%v R:%v T:%v


+ 80
- 95
consensus/vote_set_test.go View File

@ -3,7 +3,7 @@ package consensus
import (
"bytes"
. "github.com/tendermint/tendermint/blocks"
. "github.com/tendermint/tendermint/block"
. "github.com/tendermint/tendermint/common"
. "github.com/tendermint/tendermint/common/test"
@ -13,13 +13,14 @@ import (
// NOTE: see consensus/test.go for common test methods.
func TestAddVote(t *testing.T) {
height, round := uint32(1), uint16(0)
voteSet, _, privAccounts := makeVoteSet(height, round, VoteTypePrevote, 10, 1)
height, round := uint(1), uint(0)
voteSet, _, privValidators := makeVoteSet(height, round, VoteTypePrevote, 10, 1)
val0 := privValidators[0]
// t.Logf(">> %v", voteSet)
if voteSet.GetById(0) != nil {
t.Errorf("Expected GetById(0) to be nil")
if voteSet.GetByAddress(val0.Address) != nil {
t.Errorf("Expected GetByAddress(val0.Address) to be nil")
}
if voteSet.BitArray().GetIndex(0) {
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}
privAccounts[0].Sign(vote)
voteSet.Add(vote)
vote.Signature = val0.SignVoteUnsafe(vote)
voteSet.Add(val0.Address, vote)
if voteSet.GetById(0) == nil {
t.Errorf("Expected GetById(0) to be present")
if voteSet.GetByAddress(val0.Address) == nil {
t.Errorf("Expected GetByAddress(val0.Address) to be present")
}
if !voteSet.BitArray().GetIndex(0) {
t.Errorf("Expected BitArray.GetIndex(0) to be true")
@ -46,15 +47,15 @@ func TestAddVote(t *testing.T) {
}
func Test2_3Majority(t *testing.T) {
height, round := uint32(1), uint16(0)
voteSet, _, privAccounts := makeVoteSet(height, round, VoteTypePrevote, 10, 1)
height, round := uint(1), uint(0)
voteSet, _, privValidators := makeVoteSet(height, round, VoteTypePrevote, 10, 1)
// 6 out of 10 voted for nil.
voteProto := &Vote{Height: height, Round: round, Type: VoteTypePrevote, BlockHash: nil}
for i := 0; i < 6; i++ {
vote := voteProto.Copy()
privAccounts[i].Sign(vote)
voteSet.Add(vote)
vote.Signature = privValidators[i].SignVoteUnsafe(vote)
voteSet.Add(privValidators[i].Address, vote)
}
hash, header, ok := voteSet.TwoThirdsMajority()
if hash != nil || !header.IsZero() || ok {
@ -65,8 +66,8 @@ func Test2_3Majority(t *testing.T) {
{
vote := voteProto.Copy()
vote.BlockHash = CRandBytes(32)
privAccounts[6].Sign(vote)
voteSet.Add(vote)
vote.Signature = privValidators[6].SignVoteUnsafe(vote)
voteSet.Add(privValidators[6].Address, vote)
hash, header, ok = voteSet.TwoThirdsMajority()
if hash != nil || !header.IsZero() || ok {
t.Errorf("There should be no 2/3 majority")
@ -77,8 +78,8 @@ func Test2_3Majority(t *testing.T) {
{
vote := voteProto.Copy()
vote.BlockHash = nil
privAccounts[7].Sign(vote)
voteSet.Add(vote)
vote.Signature = privValidators[7].SignVoteUnsafe(vote)
voteSet.Add(privValidators[7].Address, vote)
hash, header, ok = voteSet.TwoThirdsMajority()
if hash != nil || !header.IsZero() || !ok {
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) {
height, round := uint32(1), uint16(0)
voteSet, _, privAccounts := makeVoteSet(height, round, VoteTypePrevote, 100, 1)
height, round := uint(1), uint(0)
voteSet, _, privValidators := makeVoteSet(height, round, VoteTypePrevote, 100, 1)
blockHash := CRandBytes(32)
blockPartsTotal := uint16(123)
blockPartsTotal := uint(123)
blockParts := PartSetHeader{blockPartsTotal, CRandBytes(32)}
// 66 out of 100 voted for nil.
voteProto := &Vote{Height: height, Round: round, Type: VoteTypePrevote, BlockHash: blockHash, BlockParts: blockParts}
for i := 0; i < 66; i++ {
vote := voteProto.Copy()
privAccounts[i].Sign(vote)
voteSet.Add(vote)
vote.Signature = privValidators[i].SignVoteUnsafe(vote)
voteSet.Add(privValidators[i].Address, vote)
}
hash, header, ok := voteSet.TwoThirdsMajority()
if hash != nil || !header.IsZero() || ok {
@ -109,8 +110,8 @@ func Test2_3MajorityRedux(t *testing.T) {
// 67th validator voted for nil
{
vote := &Vote{Height: height, Round: round, Type: VoteTypePrevote, BlockHash: nil, BlockParts: PartSetHeader{}}
privAccounts[66].Sign(vote)
voteSet.Add(vote)
vote.Signature = privValidators[66].SignVoteUnsafe(vote)
voteSet.Add(privValidators[66].Address, vote)
hash, header, ok = voteSet.TwoThirdsMajority()
if hash != nil || !header.IsZero() || ok {
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
{
vote := &Vote{Height: height, Round: round, Type: VoteTypePrevote, BlockHash: blockHash, BlockParts: PartSetHeader{blockPartsTotal, CRandBytes(32)}}
privAccounts[67].Sign(vote)
voteSet.Add(vote)
vote.Signature = privValidators[67].SignVoteUnsafe(vote)
voteSet.Add(privValidators[67].Address, vote)
hash, header, ok = voteSet.TwoThirdsMajority()
if hash != nil || !header.IsZero() || ok {
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
{
vote := &Vote{Height: height, Round: round, Type: VoteTypePrevote, BlockHash: blockHash, BlockParts: PartSetHeader{blockPartsTotal + 1, blockParts.Hash}}
privAccounts[68].Sign(vote)
voteSet.Add(vote)
vote.Signature = privValidators[68].SignVoteUnsafe(vote)
voteSet.Add(privValidators[68].Address, vote)
hash, header, ok = voteSet.TwoThirdsMajority()
if hash != nil || !header.IsZero() || ok {
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
{
vote := &Vote{Height: height, Round: round, Type: VoteTypePrevote, BlockHash: CRandBytes(32), BlockParts: blockParts}
privAccounts[69].Sign(vote)
voteSet.Add(vote)
vote.Signature = privValidators[69].SignVoteUnsafe(vote)
voteSet.Add(privValidators[69].Address, vote)
hash, header, ok = voteSet.TwoThirdsMajority()
if hash != nil || !header.IsZero() || ok {
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
{
vote := voteProto.Copy()
privAccounts[70].Sign(vote)
voteSet.Add(vote)
vote.Signature = privValidators[70].SignVoteUnsafe(vote)
voteSet.Add(privValidators[70].Address, vote)
hash, header, ok = voteSet.TwoThirdsMajority()
if !bytes.Equal(hash, blockHash) || !header.Equals(blockParts) || !ok {
t.Errorf("There should be 2/3 majority")
@ -163,60 +164,60 @@ func Test2_3MajorityRedux(t *testing.T) {
}
func TestBadVotes(t *testing.T) {
height, round := uint32(1), uint16(0)
voteSet, _, privAccounts := makeVoteSet(height, round, VoteTypePrevote, 10, 1)
height, round := uint(1), uint(0)
voteSet, _, privValidators := makeVoteSet(height, round, VoteTypePrevote, 10, 1)
// val0 votes for nil.
vote := &Vote{Height: height, Round: round, Type: VoteTypePrevote, BlockHash: nil}
privAccounts[0].Sign(vote)
added, _, err := voteSet.Add(vote)
vote.Signature = privValidators[0].SignVoteUnsafe(vote)
added, _, err := voteSet.Add(privValidators[0].Address, vote)
if !added || err != nil {
t.Errorf("Expected Add(vote) to succeed")
t.Errorf("Expected Add() to succeed")
}
// val0 votes again for some block.
vote = &Vote{Height: height, Round: round, Type: VoteTypePrevote, BlockHash: CRandBytes(32)}
privAccounts[0].Sign(vote)
added, _, err = voteSet.Add(vote)
vote.Signature = privValidators[0].SignVoteUnsafe(vote)
added, _, err = voteSet.Add(privValidators[0].Address, vote)
if added || err == nil {
t.Errorf("Expected Add(vote) to fail, dupeout.")
t.Errorf("Expected Add() to fail, dupeout.")
}
// val1 votes on another height
vote = &Vote{Height: height + 1, Round: round, Type: VoteTypePrevote, BlockHash: nil}
privAccounts[1].Sign(vote)
added, _, err = voteSet.Add(vote)
vote.Signature = privValidators[1].SignVoteUnsafe(vote)
added, _, err = voteSet.Add(privValidators[1].Address, vote)
if added {
t.Errorf("Expected Add(vote) to fail, wrong height")
t.Errorf("Expected Add() to fail, wrong height")
}
// val2 votes on another round
vote = &Vote{Height: height, Round: round + 1, Type: VoteTypePrevote, BlockHash: nil}
privAccounts[2].Sign(vote)
added, _, err = voteSet.Add(vote)
vote.Signature = privValidators[2].SignVoteUnsafe(vote)
added, _, err = voteSet.Add(privValidators[2].Address, vote)
if added {
t.Errorf("Expected Add(vote) to fail, wrong round")
t.Errorf("Expected Add() to fail, wrong round")
}
// val3 votes of another type.
vote = &Vote{Height: height, Round: round, Type: VoteTypePrecommit, BlockHash: nil}
privAccounts[3].Sign(vote)
added, _, err = voteSet.Add(vote)
vote.Signature = privValidators[3].SignVoteUnsafe(vote)
added, _, err = voteSet.Add(privValidators[3].Address, vote)
if added {
t.Errorf("Expected Add(vote) to fail, wrong type")
t.Errorf("Expected Add() to fail, wrong type")
}
}
func TestAddCommitsToPrevoteVotes(t *testing.T) {
height, round := uint32(2), uint16(5)
voteSet, _, privAccounts := makeVoteSet(height, round, VoteTypePrevote, 10, 1)
height, round := uint(2), uint(5)
voteSet, _, privValidators := makeVoteSet(height, round, VoteTypePrevote, 10, 1)
// val0, val1, val2, val3, val4, val5 vote for nil.
voteProto := &Vote{Height: height, Round: round, Type: VoteTypePrevote, BlockHash: nil}
for i := 0; i < 6; i++ {
vote := voteProto.Copy()
privAccounts[i].Sign(vote)
voteSet.Add(vote)
vote.Signature = privValidators[i].SignVoteUnsafe(vote)
voteSet.Add(privValidators[i].Address, vote)
}
hash, header, ok := voteSet.TwoThirdsMajority()
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
vote := &Vote{Height: height - 1, Round: round, Type: VoteTypeCommit, BlockHash: nil}
privAccounts[6].Sign(vote)
added, _, _ := voteSet.Add(vote)
vote.Signature = privValidators[6].SignVoteUnsafe(vote)
added, _, _ := voteSet.Add(privValidators[6].Address, vote)
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
vote = &Vote{Height: height, Round: round + 1, Type: VoteTypeCommit, BlockHash: nil}
privAccounts[6].Sign(vote)
added, _, _ = voteSet.Add(vote)
vote.Signature = privValidators[6].SignVoteUnsafe(vote)
added, _, _ = voteSet.Add(privValidators[6].Address, vote)
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.
vote = &Vote{Height: height, Round: round, Type: VoteTypeCommit, BlockHash: nil}
privAccounts[6].Sign(vote)
added, _, err := voteSet.Add(vote)
vote.Signature = privValidators[6].SignVoteUnsafe(vote)
added, _, err := voteSet.Add(privValidators[6].Address, vote)
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
vote = &Vote{Height: height, Round: round - 1, Type: VoteTypeCommit, BlockHash: nil}
privAccounts[6].Sign(vote)
added, _, err = voteSet.Add(vote)
vote.Signature = privValidators[6].SignVoteUnsafe(vote)
added, _, err = voteSet.Add(privValidators[6].Address, vote)
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.
vote = &Vote{Height: height, Round: round - 2, Type: VoteTypeCommit, BlockHash: nil}
privAccounts[7].Sign(vote)
added, _, err = voteSet.Add(vote)
vote.Signature = privValidators[7].SignVoteUnsafe(vote)
added, _, err = voteSet.Add(privValidators[7].Address, vote)
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
@ -272,8 +273,8 @@ func TestAddCommitsToPrevoteVotes(t *testing.T) {
}
func TestMakeValidation(t *testing.T) {
height, round := uint32(1), uint16(0)
voteSet, _, privAccounts := makeVoteSet(height, round, VoteTypeCommit, 10, 1)
height, round := uint(1), uint(0)
voteSet, _, privValidators := makeVoteSet(height, round, VoteTypeCommit, 10, 1)
blockHash, blockParts := CRandBytes(32), PartSetHeader{123, CRandBytes(32)}
// 6 out of 10 voted for some block.
@ -281,8 +282,8 @@ func TestMakeValidation(t *testing.T) {
BlockHash: blockHash, BlockParts: blockParts}
for i := 0; i < 6; i++ {
vote := voteProto.Copy()
privAccounts[i].Sign(vote)
voteSet.Add(vote)
vote.Signature = privValidators[i].SignVoteUnsafe(vote)
voteSet.Add(privValidators[i].Address, vote)
}
// MakeValidation should fail.
@ -293,15 +294,15 @@ func TestMakeValidation(t *testing.T) {
vote := &Vote{Height: height, Round: round, Type: VoteTypeCommit,
BlockHash: CRandBytes(32),
BlockParts: PartSetHeader{123, CRandBytes(32)}}
privAccounts[6].Sign(vote)
voteSet.Add(vote)
vote.Signature = privValidators[6].SignVoteUnsafe(vote)
voteSet.Add(privValidators[6].Address, vote)
}
// The 8th voted like everyone else.
{
vote := voteProto.Copy()
privAccounts[7].Sign(vote)
voteSet.Add(vote)
vote.Signature = privValidators[7].SignVoteUnsafe(vote)
voteSet.Add(privValidators[7].Address, vote)
}
validation := voteSet.MakeValidation()
@ -312,24 +313,8 @@ func TestMakeValidation(t *testing.T) {
}
// Ensure that Validation commits are ordered.
for i, rsig := range validation.Commits {
if i < 6 || i == 7 {
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")
}
}
if err := validation.ValidateBasic(); err != nil {
t.Errorf("Error in Validation.ValidateBasic(): %v", err)
}
}

+ 1
- 1
mempool/mempool.go View File

@ -12,7 +12,7 @@ import (
"sync"
. "github.com/tendermint/tendermint/binary"
. "github.com/tendermint/tendermint/blocks"
. "github.com/tendermint/tendermint/block"
"github.com/tendermint/tendermint/state"
)


+ 1
- 1
mempool/reactor.go View File

@ -6,7 +6,7 @@ import (
"sync/atomic"
. "github.com/tendermint/tendermint/binary"
. "github.com/tendermint/tendermint/blocks"
. "github.com/tendermint/tendermint/block"
"github.com/tendermint/tendermint/p2p"
)


+ 3
- 0
merkle/iavl_tree.go View File

@ -120,6 +120,9 @@ func (t *IAVLTree) Save() []byte {
}
func (t *IAVLTree) Load(hash []byte) {
if len(hash) == 0 {
panic("IAVLTree.Load() hash was nil")
}
t.root = t.ndb.GetNode(t, hash)
}


+ 4
- 5
p2p/connection.go View File

@ -267,7 +267,7 @@ FOR_LOOP:
break FOR_LOOP
}
if err != nil {
log.Info("%v failed @ sendRoutine:\n%v", c, err)
log.Warning("%v failed @ sendRoutine:\n%v", c, err)
c.Stop()
break FOR_LOOP
}
@ -349,7 +349,7 @@ FOR_LOOP:
c.recvMonitor.Update(int(n))
if err != nil {
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()
}
break FOR_LOOP
@ -377,7 +377,7 @@ FOR_LOOP:
c.recvMonitor.Update(int(*n))
if *err != nil {
if atomic.LoadUint32(&c.stopped) != 1 {
log.Info("%v failed @ recvRoutine", c)
log.Warning("%v failed @ recvRoutine", c)
c.Stop()
}
break FOR_LOOP
@ -506,6 +506,7 @@ func (ch *Channel) nextMsgPacket() msgPacket {
// Not goroutine-safe
func (ch *Channel) writeMsgPacketTo(w io.Writer) (n int64, err error) {
packet := ch.nextMsgPacket()
WriteByte(packetTypeMsg, w, &n, &err)
WriteBinary(packet, w, &n, &err)
if err != nil {
ch.recentlySent += n
@ -549,8 +550,6 @@ type msgPacket struct {
Bytes []byte
}
func (p msgPacket) TypeByte() byte { return packetTypeMsg }
func (p msgPacket) String() string {
return fmt.Sprintf("MsgPacket{%X:%X}", p.ChannelId, p.Bytes)
}


+ 4
- 2
p2p/listener.go View File

@ -62,8 +62,10 @@ func NewDefaultListener(protocol string, lAddr string) Listener {
// Determine external address...
var extAddr *NetAddress
// If the lAddrIP is INADDR_ANY, try UPnP
if lAddrIP == "" || lAddrIP == "0.0.0.0" {
extAddr = getUPNPExternalAddress(lAddrPort, listenerPort)
if false {
if lAddrIP == "" || lAddrIP == "0.0.0.0" {
extAddr = getUPNPExternalAddress(lAddrPort, listenerPort)
}
}
// Otherwise just use the local address...
if extAddr == nil {


+ 1
- 1
rpc/blocks.go View File

@ -3,7 +3,7 @@ package rpc
import (
"net/http"
//. "github.com/tendermint/tendermint/blocks"
//. "github.com/tendermint/tendermint/block"
)
func BlockHandler(w http.ResponseWriter, r *http.Request) {


+ 20
- 3
state/genesis.go View File

@ -7,7 +7,7 @@ import (
. "github.com/tendermint/tendermint/account"
. "github.com/tendermint/tendermint/binary"
. "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/merkle"
@ -16,7 +16,7 @@ import (
type GenesisDoc struct {
GenesisTime time.Time
Accounts []*Account
Validators []*Validator
Validators []*ValidatorInfo
}
func GenesisDocFromJSON(jsonBlob []byte) (genState *GenesisDoc) {
@ -51,14 +51,31 @@ func GenesisState(db db_.DB, genDoc *GenesisDoc) *State {
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{
DB: db,
LastBlockHeight: 0,
LastBlockHash: nil,
LastBlockParts: PartSetHeader{},
LastBlockTime: genDoc.GenesisTime,
BondedValidators: NewValidatorSet(genDoc.Validators),
BondedValidators: NewValidatorSet(validators),
UnbondingValidators: NewValidatorSet(nil),
accounts: accounts,
validatorInfos: validatorInfos,
}
}

consensus/priv_validator.go → state/priv_validator.go View File


+ 13
- 4
state/state.go View File

@ -8,7 +8,7 @@ import (
. "github.com/tendermint/tendermint/account"
. "github.com/tendermint/tendermint/binary"
. "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/merkle"
@ -78,6 +78,7 @@ func LoadState(db db_.DB) *State {
// Save this state into the db.
func (s *State) Save() {
s.accounts.Save()
s.validatorInfos.Save()
buf, n, err := new(bytes.Buffer), new(int64), new(error)
WriteUVarInt(s.LastBlockHeight, 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")
}
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 {
account := accounts[string(out.Address)]
if account == nil {
panic("AdjustByInputs() expects account in accounts")
panic("AdjustByOutputs() expects account in accounts")
}
account.Balance += out.Amount
}
@ -242,7 +244,7 @@ func (s *State) ExecTx(tx_ Tx) error {
// add funds, merge UnbondTo outputs, and unbond validator.
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 {
return err
}
@ -273,13 +275,14 @@ func (s *State) ExecTx(tx_ Tx) error {
PubKey: tx.PubKey,
UnbondTo: tx.UnbondTo,
FirstBondHeight: s.LastBlockHeight + 1,
FirstBondAmount: outTotal,
})
// Add Validator
added := s.BondedValidators.Add(&Validator{
Address: tx.PubKey.Address(),
PubKey: tx.PubKey,
BondHeight: s.LastBlockHeight + 1,
VotingPower: inTotal,
VotingPower: outTotal,
Accum: 0,
})
if !added {
@ -588,6 +591,12 @@ func (s *State) GetAccount(address []byte) *Account {
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
// afterwards has no side effects.
func (s *State) SetAccounts(accounts map[string]*Account) {


+ 107
- 139
state/state_test.go View File

@ -3,60 +3,17 @@ package state
import (
. "github.com/tendermint/tendermint/account"
. "github.com/tendermint/tendermint/binary"
. "github.com/tendermint/tendermint/blocks"
. "github.com/tendermint/tendermint/common"
. "github.com/tendermint/tendermint/block"
. "github.com/tendermint/tendermint/config"
db_ "github.com/tendermint/tendermint/db"
"github.com/tendermint/tendermint/wallet"
"bytes"
"testing"
"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) {
// Generate a state
s0, _ := randGenesisState(10, 5)
s0, privAccounts, _ := RandGenesisState(10, true, 1000, 5, true, 1000)
s0Hash := s0.Hash()
if len(s0Hash) == 0 {
t.Error("Expected state hash")
@ -69,15 +26,16 @@ func TestCopyState(t *testing.T) {
}
// Mutate the original; hash should change.
accDet := s0.GetAccountDetail(0)
accDet.Balance += 1
acc0Address := privAccounts[0].PubKey.Address()
acc := s0.GetAccount(acc0Address)
acc.Balance += 1
// 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")
}
// Setting, however, should change the balance.
s0.SetAccountDetail(accDet)
if s0.GetAccountDetail(0).Balance != accDet.Balance {
s0.SetAccount(acc)
if s0.GetAccount(acc0Address).Balance != acc.Balance {
t.Error("Account balance wasn't set")
}
// How that the state changed, the hash should change too.
@ -93,7 +51,7 @@ func TestCopyState(t *testing.T) {
func TestGenesisSaveLoad(t *testing.T) {
// 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.
block := &Block{
Header: &Header{
@ -168,150 +126,160 @@ func TestGenesisSaveLoad(t *testing.T) {
if !bytes.Equal(s0.UnbondingValidators.Hash(), s1.UnbondingValidators.Hash()) {
t.Error("UnbondingValidators hash mismatch")
}
if !bytes.Equal(s0.accountDetails.Hash(), s1.accountDetails.Hash()) {
t.Error("AccountDetail mismatch")
if !bytes.Equal(s0.accounts.Hash(), s1.accounts.Hash()) {
t.Error("Accounts mismatch")
}
}
func TestTxSequence(t *testing.T) {
state, privAccounts := randGenesisState(3, 1)
acc1 := state.GetAccountDetail(1) // Non-validator
state, privAccounts, _ := RandGenesisState(3, true, 1000, 1, true, 1000)
acc0 := state.GetAccount(privAccounts[0].PubKey.Address())
acc1 := state.GetAccount(privAccounts[1].PubKey.Address())
// Try executing a SendTx with various sequence numbers.
stxProto := SendTx{
BaseTx: BaseTx{
Sequence: acc1.Sequence + 1,
Fee: 0},
To: 2,
Amount: 1,
makeSendTx := func(sequence uint) *SendTx {
return &SendTx{
Inputs: []*TxInput{
&TxInput{
Address: acc0.Address,
Amount: 1,
Sequence: sequence,
},
},
Outputs: []*TxOutput{
&TxOutput{
Address: acc1.Address,
Amount: 1,
},
},
}
}
// Test a variety of sequence numbers for the tx.
// The tx should only pass when i == 1.
for i := -1; i < 3; i++ {
stxCopy := stxProto
stx := &stxCopy
stx.Sequence = uint(int(acc1.Sequence) + i)
privAccounts[1].Sign(stx)
sequence := acc0.Sequence + uint(i)
tx := makeSendTx(sequence)
tx.Inputs[0].Signature = privAccounts[0].Sign(tx)
stateCopy := state.Copy()
err := stateCopy.ExecTx(stx)
if i >= 1 {
err := stateCopy.ExecTx(tx)
if i == 1 {
// Sequence is good.
if err != nil {
t.Errorf("Expected good sequence to pass")
t.Errorf("Expected good sequence to pass: %v", err)
}
// Check accDet.Sequence.
newAcc1 := stateCopy.GetAccountDetail(1)
if newAcc1.Sequence != stx.Sequence {
t.Errorf("Expected account sequence to change")
// Check acc.Sequence.
newAcc0 := stateCopy.GetAccount(acc0.Address)
if newAcc0.Sequence != sequence {
t.Errorf("Expected account sequence to change to %v, got %v",
sequence, newAcc0.Sequence)
}
} else {
// Sequence is bad.
if err == nil {
t.Errorf("Expected bad sequence to fail")
}
// Check accDet.Sequence. (shouldn't have changed)
newAcc1 := stateCopy.GetAccountDetail(1)
if newAcc1.Sequence != acc1.Sequence {
t.Errorf("Expected account sequence to not change")
// Check acc.Sequence. (shouldn't have changed)
newAcc0 := stateCopy.GetAccount(acc0.Address)
if newAcc0.Sequence != acc0.Sequence {
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) {
state, privAccounts := randGenesisState(3, 1)
state, privAccounts, _ := RandGenesisState(3, true, 1000, 1, true, 1000)
acc0 := state.GetAccountDetail(0) // Validator
acc1 := state.GetAccountDetail(1) // Non-validator
acc2 := state.GetAccountDetail(2) // Non-validator
//val0 := state.GetValidatorInfo(privValidators[0].Address)
acc0 := state.GetAccount(privAccounts[0].PubKey.Address())
acc1 := state.GetAccount(privAccounts[1].PubKey.Address())
// SendTx.
{
state := state.Copy()
stx := &SendTx{
BaseTx: BaseTx{
Sequence: acc1.Sequence + 1,
Fee: 0},
To: 2,
Amount: 1,
tx := &SendTx{
Inputs: []*TxInput{
&TxInput{
Address: acc0.Address,
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 {
t.Errorf("Got error in executing send transaction, %v", err)
}
newAcc1 := state.GetAccountDetail(1)
if acc1.Balance-1 != newAcc1.Balance {
t.Errorf("Unexpected newAcc1 balance. Expected %v, got %v",
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,
newAcc0 := state.GetAccount(acc0.Address)
if acc0.Balance-1 != newAcc0.Balance {
t.Errorf("Unexpected newAcc0 balance. Expected %v, got %v",
acc0.Balance-1, newAcc0.Balance)
}
privAccounts[0].Sign(stx)
err := state.ExecTx(stx)
if err == nil {
t.Errorf("Expected error, SendTx should fail for bonded validators")
newAcc1 := state.GetAccount(acc1.Address)
if acc1.Balance+1 != newAcc1.Balance {
t.Errorf("Unexpected newAcc1 balance. Expected %v, got %v",
acc1.Balance+1, newAcc1.Balance)
}
}
// TODO: test for unbonding validators.
// BondTx.
{
state := state.Copy()
btx := &BondTx{
BaseTx: BaseTx{
Sequence: acc1.Sequence + 1,
Fee: 0},
tx := &BondTx{
PubKey: acc0.PubKey.(PubKeyEd25519),
Inputs: []*TxInput{
&TxInput{
Address: acc0.Address,
Amount: 1,
Sequence: acc0.Sequence + 1,
},
},
UnbondTo: []*TxOutput{
&TxOutput{
Address: acc0.Address,
Amount: 1,
},
},
}
privAccounts[1].Sign(btx)
err := state.ExecTx(btx)
tx.Inputs[0].Signature = privAccounts[0].Sign(tx)
err := state.ExecTx(tx)
if err != nil {
t.Errorf("Got error in executing bond transaction, %v", err)
}
newAcc1 := state.GetAccountDetail(1)
if acc1.Balance != newAcc1.Balance {
t.Errorf("Unexpected newAcc1 balance. Expected %v, got %v",
acc1.Balance, newAcc1.Balance)
}
if newAcc1.Status != AccountStatusBonded {
t.Errorf("Unexpected newAcc1 status.")
newAcc0 := state.GetAccount(acc0.Address)
if newAcc0.Balance != acc0.Balance-1 {
t.Errorf("Unexpected newAcc0 balance. Expected %v, got %v",
acc0.Balance-1, newAcc0.Balance)
}
_, acc1Val := state.BondedValidators.GetById(acc1.Id)
if acc1Val == nil {
t.Errorf("acc1Val not present")
_, acc0Val := state.BondedValidators.GetByAddress(acc0.Address)
if acc0Val == nil {
t.Errorf("acc0Val not present")
}
if acc1Val.BondHeight != state.LastBlockHeight {
if acc0Val.BondHeight != state.LastBlockHeight+1 {
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",
acc1Val.VotingPower, acc1.Balance)
acc0Val.VotingPower, acc0.Balance)
}
if acc1Val.Accum != 0 {
if acc0Val.Accum != 0 {
t.Errorf("Unexpected accum. Expected 0, got %v",
acc1Val.Accum)
acc0Val.Accum)
}
}


+ 98
- 0
state/test.go View 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
}

+ 2
- 1
state/validator.go View File

@ -7,7 +7,7 @@ import (
. "github.com/tendermint/tendermint/account"
. "github.com/tendermint/tendermint/binary"
. "github.com/tendermint/tendermint/blocks"
. "github.com/tendermint/tendermint/block"
)
// Persistent static data for each Validator
@ -16,6 +16,7 @@ type ValidatorInfo struct {
PubKey PubKeyEd25519
UnbondTo []*TxOutput
FirstBondHeight uint
FirstBondAmount uint64
// If destroyed:
DestroyedHeight uint


+ 40
- 40
state/validator_set.go View File

@ -22,9 +22,9 @@ import (
// TODO: consider validator Accum overflow
// TODO: replace validators []*Validator with github.com/jaekwon/go-ibbs?
type ValidatorSet struct {
validators []*Validator
Validators []*Validator // NOTE: persisted via reflect, must be exported.
// cache
// cached (unexported)
proposer *Validator
totalVotingPower uint64
}
@ -36,7 +36,7 @@ func NewValidatorSet(vals []*Validator) *ValidatorSet {
}
sort.Sort(ValidatorsByAddress(validators))
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.
validatorsHeap := NewHeap()
for _, val := range valSet.validators {
for _, val := range valSet.Validators {
val.Accum += int64(val.VotingPower) * int64(times) // TODO: mind overflow
validatorsHeap.Push(val, accumComparable(val.Accum))
}
@ -62,48 +62,48 @@ func (valSet *ValidatorSet) IncrementAccum(times uint) {
}
func (valSet *ValidatorSet) Copy() *ValidatorSet {
validators := make([]*Validator, len(valSet.validators))
for i, val := range valSet.validators {
validators := make([]*Validator, len(valSet.Validators))
for i, val := range valSet.Validators {
// NOTE: must copy, since IncrementAccum updates in place.
validators[i] = val.Copy()
}
return &ValidatorSet{
validators: validators,
Validators: validators,
proposer: valSet.proposer,
totalVotingPower: valSet.totalVotingPower,
}
}
func (valSet *ValidatorSet) HasAddress(address []byte) bool {
idx := sort.Search(len(valSet.validators), func(i int) bool {
return bytes.Compare(address, valSet.validators[i].Address) <= 0
idx := sort.Search(len(valSet.Validators), func(i int) bool {
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) {
idx := sort.Search(len(valSet.validators), func(i int) bool {
return bytes.Compare(address, valSet.validators[i].Address) <= 0
idx := sort.Search(len(valSet.Validators), func(i int) bool {
return bytes.Compare(address, valSet.Validators[i].Address) <= 0
})
if idx != len(valSet.validators) && bytes.Compare(valSet.validators[idx].Address, address) == 0 {
return uint(idx), valSet.validators[idx].Copy()
if idx != len(valSet.Validators) && bytes.Compare(valSet.Validators[idx].Address, address) == 0 {
return uint(idx), valSet.Validators[idx].Copy()
} else {
return 0, nil
}
}
func (valSet *ValidatorSet) GetByIndex(index uint) (address []byte, val *Validator) {
val = valSet.validators[index]
val = valSet.Validators[index]
return val.Address, val.Copy()
}
func (valSet *ValidatorSet) Size() uint {
return uint(len(valSet.validators))
return uint(len(valSet.Validators))
}
func (valSet *ValidatorSet) TotalVotingPower() uint64 {
if valSet.totalVotingPower == 0 {
for _, val := range valSet.validators {
for _, val := range valSet.Validators {
valSet.totalVotingPower += val.VotingPower
}
}
@ -112,7 +112,7 @@ func (valSet *ValidatorSet) TotalVotingPower() uint64 {
func (valSet *ValidatorSet) Proposer() (proposer *Validator) {
if valSet.proposer == nil {
for _, val := range valSet.validators {
for _, val := range valSet.Validators {
valSet.proposer = valSet.proposer.CompareAccum(val)
}
}
@ -120,11 +120,11 @@ func (valSet *ValidatorSet) Proposer() (proposer *Validator) {
}
func (valSet *ValidatorSet) Hash() []byte {
if len(valSet.validators) == 0 {
if len(valSet.Validators) == 0 {
return nil
}
hashables := make([]merkle.Hashable, len(valSet.validators))
for i, val := range valSet.validators {
hashables := make([]merkle.Hashable, len(valSet.Validators))
for i, val := range valSet.Validators {
hashables[i] = val
}
return merkle.HashFromHashables(hashables)
@ -132,21 +132,21 @@ func (valSet *ValidatorSet) Hash() []byte {
func (valSet *ValidatorSet) Add(val *Validator) (added bool) {
val = val.Copy()
idx := sort.Search(len(valSet.validators), func(i int) bool {
return bytes.Compare(val.Address, valSet.validators[i].Address) <= 0
idx := sort.Search(len(valSet.Validators), func(i int) bool {
return bytes.Compare(val.Address, valSet.Validators[i].Address) <= 0
})
if idx == len(valSet.validators) {
valSet.validators = append(valSet.validators, val)
if idx == len(valSet.Validators) {
valSet.Validators = append(valSet.Validators, val)
// Invalidate cache
valSet.proposer = nil
valSet.totalVotingPower = 0
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
} else {
newValidators := append(valSet.validators[:idx], val)
newValidators = append(newValidators, valSet.validators[idx:]...)
valSet.validators = newValidators
newValidators := append(valSet.Validators[:idx], val)
newValidators = append(newValidators, valSet.Validators[idx:]...)
valSet.Validators = newValidators
// Invalidate cache
valSet.proposer = nil
valSet.totalVotingPower = 0
@ -159,7 +159,7 @@ func (valSet *ValidatorSet) Update(val *Validator) (updated bool) {
if sameVal == nil {
return false
} else {
valSet.validators[index] = val.Copy()
valSet.Validators[index] = val.Copy()
// Invalidate cache
valSet.proposer = nil
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) {
idx := sort.Search(len(valSet.validators), func(i int) bool {
return bytes.Compare(address, valSet.validators[i].Address) <= 0
idx := sort.Search(len(valSet.Validators), func(i int) bool {
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
} else {
removedVal := valSet.validators[idx]
newValidators := valSet.validators[:idx]
if idx+1 < len(valSet.validators) {
newValidators = append(newValidators, valSet.validators[idx+1:]...)
removedVal := valSet.Validators[idx]
newValidators := valSet.Validators[:idx]
if idx+1 < len(valSet.Validators) {
newValidators = append(newValidators, valSet.Validators[idx+1:]...)
}
valSet.validators = newValidators
valSet.Validators = newValidators
// Invalidate cache
valSet.proposer = nil
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) {
for i, val := range valSet.validators {
for i, val := range valSet.Validators {
stop := fn(uint(i), val.Copy())
if stop {
break
@ -244,5 +244,5 @@ type accumComparable uint64
// We want to find the validator with the greatest accum.
func (ac accumComparable) Less(o interface{}) bool {
return uint64(ac) > o.(uint64)
return uint64(ac) > uint64(o.(accumComparable))
}

+ 8
- 11
state/validator_set_test.go View File

@ -1,30 +1,27 @@
package state
import (
. "github.com/tendermint/tendermint/account"
. "github.com/tendermint/tendermint/common"
"bytes"
"testing"
)
func randValidator() *Validator {
func randValidator_() *Validator {
return &Validator{
Account: Account{
Id: RandUInt64(),
PubKey: CRandBytes(32),
},
BondHeight: RandUInt32(),
UnbondHeight: RandUInt32(),
LastCommitHeight: RandUInt32(),
VotingPower: RandUInt64(),
Accum: int64(RandUInt64()),
Address: RandBytes(20),
PubKey: PubKeyEd25519{RandBytes(64)},
BondHeight: uint(RandUInt32()),
VotingPower: RandUInt64(),
Accum: int64(RandUInt64()),
}
}
func randValidatorSet(numValidators int) *ValidatorSet {
validators := make([]*Validator, numValidators)
for i := 0; i < numValidators; i++ {
validators[i] = randValidator()
validators[i] = randValidator_()
}
return NewValidatorSet(validators)
}


Loading…
Cancel
Save