draft of consensus+state code, compiles.

This commit is contained in:
Jae Kwon
2014-09-04 03:32:38 -07:00
parent e53b148acf
commit f030c69495
13 changed files with 222 additions and 217 deletions
-63
View File
@@ -1,63 +0,0 @@
package blocks
import (
. "github.com/tendermint/tendermint/binary"
"io"
)
// NOTE: consensus/Validator embeds this, so..
type Account struct {
Id uint64 // Numeric id of account, incrementing.
PubKey []byte
}
func (self *Account) Verify(msg []byte, sig []byte) bool {
return false
}
//-----------------------------------------------------------------------------
type PrivAccount struct {
Account
PrivKey []byte
}
func (self *PrivAccount) Sign(msg []byte) Signature {
return Signature{}
}
//-----------------------------------------------------------------------------
/*
Signature message wire format:
|A...|SSS...|
A account number, varint encoded (1+ bytes)
S signature of all prior bytes (32 bytes)
It usually follows the message to be signed.
*/
type Signature struct {
SignerId uint64
Bytes []byte
}
func ReadSignature(r io.Reader, n *int64, err *error) Signature {
return Signature{
SignerId: ReadUInt64(r, n, err),
Bytes: ReadByteSlice(r, n, err),
}
}
func (sig Signature) IsZero() bool {
return len(sig.Bytes) == 0
}
func (sig Signature) WriteTo(w io.Writer) (n int64, err error) {
WriteUInt64(w, sig.SignerId, &n, &err)
WriteByteSlice(w, sig.Bytes, &n, &err)
return
}
-15
View File
@@ -155,21 +155,6 @@ func (bp *BlockPart) BlockPartHash() []byte {
}
}
// Signs the URI, which includes all data and metadata.
// XXX implement or change
func (bp *BlockPart) Sign(acc *PrivAccount) {
// TODO: populate Signature
}
// XXX maybe change.
func (bp *BlockPart) ValidateWithSigner(signer *Account) error {
// TODO: Sanity check height, index, total, bytes, etc.
if !signer.Verify([]byte(bp.URI()), bp.Signature.Bytes) {
return ErrInvalidBlockPartSignature
}
return nil
}
//-----------------------------------------------------------------------------
/* Header is part of a Block */
-136
View File
@@ -1,136 +0,0 @@
package blocks
import (
"bytes"
"errors"
"sync"
)
// Helper for keeping track of block parts.
type BlockPartSet struct {
mtx sync.Mutex
signer *Account
height uint32
round uint16 // Not used
total uint16
numParts uint16
parts []*BlockPart
_block *Block // cache
}
var (
ErrInvalidBlockPartSignature = errors.New("Invalid block part signature") // Peer gave us a fake part
ErrInvalidBlockPartConflict = errors.New("Invalid block part conflict") // Signer signed conflicting parts
)
// Signer may be nil if signer is unknown beforehand.
func NewBlockPartSet(height uint32, round uint16, signer *Account) *BlockPartSet {
return &BlockPartSet{
signer: signer,
height: height,
round: round,
}
}
// In the case where the signer wasn't known prior to NewBlockPartSet(),
// user should call SetSigner() prior to AddBlockPart().
func (bps *BlockPartSet) SetSigner(signer *Account) {
bps.mtx.Lock()
defer bps.mtx.Unlock()
if bps.signer != nil {
panic("BlockPartSet signer already set.")
}
bps.signer = signer
}
func (bps *BlockPartSet) BlockParts() []*BlockPart {
bps.mtx.Lock()
defer bps.mtx.Unlock()
return bps.parts
}
func (bps *BlockPartSet) BitArray() []byte {
bps.mtx.Lock()
defer bps.mtx.Unlock()
if bps.parts == nil {
return nil
}
bitArray := make([]byte, (len(bps.parts)+7)/8)
for i, part := range bps.parts {
if part != nil {
bitArray[i/8] |= 1 << uint(i%8)
}
}
return bitArray
}
// If the part isn't valid, returns an error.
// err can be ErrInvalidBlockPart[Conflict|Signature]
func (bps *BlockPartSet) AddBlockPart(part *BlockPart) (added bool, err error) {
bps.mtx.Lock()
defer bps.mtx.Unlock()
// If part is invalid, return an error.
err = part.ValidateWithSigner(bps.signer)
if err != nil {
return false, err
}
if bps.parts == nil {
// First received part for this round.
bps.parts = make([]*BlockPart, part.Total)
bps.total = uint16(part.Total)
bps.parts[int(part.Index)] = part
bps.numParts++
return true, nil
} else {
// Check part.Index and part.Total
if uint16(part.Index) >= bps.total {
return false, ErrInvalidBlockPartConflict
}
if uint16(part.Total) != bps.total {
return false, ErrInvalidBlockPartConflict
}
// Check for existing parts.
existing := bps.parts[part.Index]
if existing != nil {
if bytes.Equal(existing.Bytes, part.Bytes) {
// Ignore duplicate
return false, nil
} else {
return false, ErrInvalidBlockPartConflict
}
} else {
bps.parts[int(part.Index)] = part
bps.numParts++
return true, nil
}
}
}
func (bps *BlockPartSet) IsComplete() bool {
bps.mtx.Lock()
defer bps.mtx.Unlock()
return bps.total > 0 && bps.total == bps.numParts
}
func (bps *BlockPartSet) Block() *Block {
if !bps.IsComplete() {
return nil
}
bps.mtx.Lock()
defer bps.mtx.Unlock()
if bps._block == nil {
blockBytes := []byte{}
for _, part := range bps.parts {
blockBytes = append(blockBytes, part.Bytes...)
}
var n int64
var err error
block := ReadBlock(bytes.NewReader(blockBytes), &n, &err)
bps._block = block
}
return bps._block
}
-7
View File
@@ -33,13 +33,6 @@ func randTime() time.Time {
return time.Unix(int64(randUInt64()), 0)
}
func randAccount() Account {
return Account{
Id: randUInt64(),
PubKey: randBytes(32),
}
}
func randBytes(n int) []byte {
bs := make([]byte, n)
for i := 0; i < n; i++ {
+40
View File
@@ -0,0 +1,40 @@
package blocks
import (
. "github.com/tendermint/tendermint/binary"
"io"
)
/*
Signature message wire format:
|a...|sss...|
a Account number, varint encoded (1+ bytes)
s Signature of all prior bytes (32 bytes)
It usually follows the message to be signed.
*/
type Signature struct {
SignerId uint64
Bytes []byte
}
func ReadSignature(r io.Reader, n *int64, err *error) Signature {
return Signature{
SignerId: ReadUInt64(r, n, err),
Bytes: ReadByteSlice(r, n, err),
}
}
func (sig Signature) IsZero() bool {
return len(sig.Bytes) == 0
}
func (sig Signature) WriteTo(w io.Writer) (n int64, err error) {
WriteUInt64(w, sig.SignerId, &n, &err)
WriteByteSlice(w, sig.Bytes, &n, &err)
return
}