diff --git a/blocks/account.go b/blocks/account.go new file mode 100644 index 000000000..2bc7bc9b2 --- /dev/null +++ b/blocks/account.go @@ -0,0 +1,53 @@ +package blocks + +import ( + . "github.com/tendermint/tendermint/binary" + "io" +) + +type AccountId interface { + Binary + Type() Byte +} + +const ( + ACCOUNT_TYPE_NUMBER = Byte(0x00) + ACCOUNT_TYPE_PUBKEY = Byte(0x01) +) + +func ReadAccountId(r io.Reader) AccountId { + return nil +} + +/* AccountNumber < AccountId */ + +type AccountNumber uint64 + +func (self AccountNumber) Type() Byte { + return ACCOUNT_TYPE_NUMBER +} + +func (self AccountNumber) WriteTo(w io.Writer) (n int64, err error) { + var n_ int64 + n_, err = self.Type().WriteTo(w) + n += n_; if err != nil { return n, err } + n_, err = UInt64(self).WriteTo(w) + n += n_; return +} + + +/* AccountPubKey < AccountId */ + +type AccountPubKey []byte + +func (self AccountPubKey) Type() Byte { + return ACCOUNT_TYPE_PUBKEY +} + +func (self AccountPubKey) WriteTo(w io.Writer) (n int64, err error) { + var n_ int64 + n_, err = self.Type().WriteTo(w) + n += n_; if err != nil { return n, err } + n_, err = ByteSlice(self).WriteTo(w) + n += n_; return +} diff --git a/blocks/adjustment.go b/blocks/adjustment.go new file mode 100644 index 000000000..0d337316d --- /dev/null +++ b/blocks/adjustment.go @@ -0,0 +1,129 @@ +package blocks + +import ( + . "github.com/tendermint/tendermint/binary" + "io" +) + +/* Adjustment + +1. Bond New validator posts a bond +2. Unbond Validator leaves +3. Timeout Validator times out +4. Dupeout Validator dupes out (signs twice) + +TODO: signing a bad checkpoint (block) +*/ + +type Adjustment interface { + Type() Byte + Binary +} + +const ( + ADJ_TYPE_BOND = Byte(0x01) + ADJ_TYPE_UNBOND = Byte(0x02) + ADJ_TYPE_TIMEOUT = Byte(0x03) + ADJ_TYPE_GUILTOUT = Byte(0x04) +) + +func ReadAdjustment(r io.Reader) Adjustment { + return nil +} + + +/* Bond < Adjustment */ + +type Bond struct { + Signature + Fee UInt64 + UnbondTo AccountId + Amount UInt64 +} + +func (self *Bond) Type() Byte { + return ADJ_TYPE_BOND +} + +func (self *Bond) WriteTo(w io.Writer) (n int64, err error) { + var n_ int64 + n_, err = self.Type().WriteTo(w) + n += n_; if err != nil { return n, err } + n_, err = self.Signature.WriteTo(w) + n += n_; if err != nil { return n, err } + n_, err = self.Fee.WriteTo(w) + n += n_; if err != nil { return n, err } + n_, err = self.UnbondTo.WriteTo(w) + n += n_; if err != nil { return n, err } + n_, err = self.Amount.WriteTo(w) + n += n_; return +} + + +/* Unbond < Adjustment */ + +type Unbond struct { + Signature + Fee UInt64 + Amount UInt64 +} + +func (self *Unbond) Type() Byte { + return ADJ_TYPE_UNBOND +} + +func (self *Unbond) WriteTo(w io.Writer) (n int64, err error) { + var n_ int64 + n_, err = self.Type().WriteTo(w) + n += n_; if err != nil { return n, err } + n_, err = self.Signature.WriteTo(w) + n += n_; if err != nil { return n, err } + n_, err = self.Fee.WriteTo(w) + n += n_; if err != nil { return n, err } + n_, err = self.Amount.WriteTo(w) + n += n_; return +} + + +/* Timeout < Adjustment */ + +type Timeout struct { + Account AccountId + Penalty UInt64 +} + +func (self *Timeout) Type() Byte { + return ADJ_TYPE_TIMEOUT +} + +func (self *Timeout) WriteTo(w io.Writer) (n int64, err error) { + var n_ int64 + n_, err = self.Type().WriteTo(w) + n += n_; if err != nil { return n, err } + n_, err = self.Account.WriteTo(w) + n += n_; if err != nil { return n, err } + n_, err = self.Penalty.WriteTo(w) + n += n_; return +} + + +/* Dupeout < Adjustment */ + +type Dupeout struct { + VoteA Vote + VoteB Vote +} + +func (self *Dupeout) Type() Byte { + return ADJ_TYPE_DUPEOUT +} + +func (self *Dupeout) WriteTo(w io.Writer) (n int64, err error) { + var n_ int64 + n_, err = self.Type().WriteTo(w) + n += n_; if err != nil { return n, err } + n_, err = self.Account.WriteTo(w) + n += n_; if err != nil { return n, err } + n_, err = self.Penalty.WriteTo(w) + n += n_; return +} diff --git a/blocks/block.go b/blocks/block.go index 27e0a908e..f7138435a 100644 --- a/blocks/block.go +++ b/blocks/block.go @@ -1,35 +1,100 @@ package blocks import ( + . "github.com/tendermint/tendermint/binary" "io" ) -// BlockHeader -type BlockHeader struct { - Name string - Height uint64 - Version uint8 - Fees uint64 - Time uint64 - PrevBlockHash []byte - ValidationHash []byte - DataHash []byte -} +/* Block */ -func (self *BlockHeader) WriteTo(w io.Writer) (n int64, err error) { - return 0, nil +type Block struct { + Header + Validation + Data + // Checkpoint } -// Block - -type Block struct { - Header *BlockHeader - Validation *BlockValidation - Data *BlockData - //Checkpoint *BlockCheckpoint +func ReadBlock(r io.Reader) *Block { + return nil } func (self *Block) Validate() bool { return false } + + +/* Block > Header */ + +type Header struct { + Name String + Height UInt64 + Fees UInt64 + Time UInt64 + PrevHash ByteSlice + ValidationHash ByteSlice + DataHash ByteSlice +} + +func ReadHeader(r io.Reader) *Header { + return nil +} + +func (self *Header) WriteTo(w io.Writer) (n int64, err error) { + var n_ int64 + n_, err = self.Name.WriteTo(w) + n += n_; if err != nil { return n, err } + n_, err = self.Height.WriteTo(w) + n += n_; if err != nil { return n, err } + n_, err = self.Fees.WriteTo(w) + n += n_; if err != nil { return n, err } + n_, err = self.Time.WriteTo(w) + n += n_; if err != nil { return n, err } + n_, err = self.PrevHash.WriteTo(w) + n += n_; if err != nil { return n, err } + n_, err = self.ValidationHash.WriteTo(w) + n += n_; if err != nil { return n, err } + n_, err = self.DataHash.WriteTo(w) + n += n_; return +} + + +/* Block > Validation */ + +type Validation struct { + Signatures []*Signature + Adjustments []Adjustment +} + +func ReadValidation(r io.Reader) *Validation { + return nil +} + + +/* Block > Data */ + +type Data struct { + Txs []Tx +} + +func ReadData(r io.Reader) *Data { + return nil +} + +func (self *Data) WriteTo(w io.Writer) (n int64, err error) { + var n_ int64 + for _, tx := range self.Txs { + n_, err = tx.WriteTo(w) + n += n_ + if err != nil { return } + } + return +} + +func (self *Data) MerkleHash() ByteSlice { + bs := make([]Binary, 0, len(self.Txs)) + for i, tx := range self.Txs { + bs[i] = Binary(tx) + } + return merkle.HashFromBinarySlice(bs) +} diff --git a/blocks/block_test.go b/blocks/block_test.go new file mode 100644 index 000000000..6d4778173 --- /dev/null +++ b/blocks/block_test.go @@ -0,0 +1,67 @@ +package blocks + +import ( + . "github.com/tendermint/tendermint/binary" + "testing" + "bytes" + "fmt" + "math/rand" +) + +// Distributed pseudo-exponentially to test for various cases +func randVar() UInt64 { + bits := rand.Uint32() % 64 + if bits == 0 { return 0 } + n := uint64(1 << (bits-1)) + n += uint64(rand.Int63()) & ((1 << (bits-1)) - 1) + return UInt64(n) +} + +func randBytes(n int) ByteSlice { + bs := make([]byte, n) + for i:=0; i