mirror of
https://github.com/fluencelabs/tendermint
synced 2025-05-29 22:21:21 +00:00
consensus & account txs are all in Block.Data.Txs
This commit is contained in:
parent
d772282c25
commit
03d1af711a
@ -17,7 +17,7 @@ const (
|
|||||||
type Block struct {
|
type Block struct {
|
||||||
Header
|
Header
|
||||||
Validation
|
Validation
|
||||||
Txs
|
Data
|
||||||
|
|
||||||
// Volatile
|
// Volatile
|
||||||
hash []byte
|
hash []byte
|
||||||
@ -27,14 +27,14 @@ func ReadBlock(r io.Reader, n *int64, err *error) *Block {
|
|||||||
return &Block{
|
return &Block{
|
||||||
Header: ReadHeader(r, n, err),
|
Header: ReadHeader(r, n, err),
|
||||||
Validation: ReadValidation(r, n, err),
|
Validation: ReadValidation(r, n, err),
|
||||||
Txs: ReadTxs(r, n, err),
|
Data: ReadData(r, n, err),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Block) WriteTo(w io.Writer) (n int64, err error) {
|
func (b *Block) WriteTo(w io.Writer) (n int64, err error) {
|
||||||
WriteBinary(w, &b.Header, &n, &err)
|
WriteBinary(w, &b.Header, &n, &err)
|
||||||
WriteBinary(w, &b.Validation, &n, &err)
|
WriteBinary(w, &b.Validation, &n, &err)
|
||||||
WriteBinary(w, &b.Txs, &n, &err)
|
WriteBinary(w, &b.Data, &n, &err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,7 +50,7 @@ func (b *Block) Hash() []byte {
|
|||||||
hashes := [][]byte{
|
hashes := [][]byte{
|
||||||
b.Header.Hash(),
|
b.Header.Hash(),
|
||||||
b.Validation.Hash(),
|
b.Validation.Hash(),
|
||||||
b.Txs.Hash(),
|
b.Data.Hash(),
|
||||||
}
|
}
|
||||||
// Merkle hash from sub-hashes.
|
// Merkle hash from sub-hashes.
|
||||||
return merkle.HashFromByteSlices(hashes)
|
return merkle.HashFromByteSlices(hashes)
|
||||||
@ -79,6 +79,21 @@ func (b *Block) ToBlockPartSet() *BlockPartSet {
|
|||||||
return NewBlockPartSet(b.Height, parts)
|
return NewBlockPartSet(b.Height, parts)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Makes an empty next block.
|
||||||
|
func (b *Block) MakeNextBlock() *Block {
|
||||||
|
return &Block{
|
||||||
|
Header: Header{
|
||||||
|
Name: b.Header.Name,
|
||||||
|
Height: b.Header.Height + 1,
|
||||||
|
//Fees: uint64(0),
|
||||||
|
Time: time.Now(),
|
||||||
|
PrevHash: b.Hash(),
|
||||||
|
//ValidationStateHash: nil,
|
||||||
|
//AccountStateHash: nil,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -133,15 +148,14 @@ func (bp *BlockPart) Hash() []byte {
|
|||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
/* Header is part of a Block */
|
|
||||||
type Header struct {
|
type Header struct {
|
||||||
Name string
|
Name string
|
||||||
Height uint32
|
Height uint32
|
||||||
Fees uint64
|
Fees uint64
|
||||||
Time time.Time
|
Time time.Time
|
||||||
PrevHash []byte
|
PrevHash []byte
|
||||||
ValidationHash []byte
|
ValidationStateHash []byte
|
||||||
TxsHash []byte
|
AccountStateHash []byte
|
||||||
|
|
||||||
// Volatile
|
// Volatile
|
||||||
hash []byte
|
hash []byte
|
||||||
@ -152,13 +166,13 @@ func ReadHeader(r io.Reader, n *int64, err *error) (h Header) {
|
|||||||
return Header{}
|
return Header{}
|
||||||
}
|
}
|
||||||
return Header{
|
return Header{
|
||||||
Name: ReadString(r, n, err),
|
Name: ReadString(r, n, err),
|
||||||
Height: ReadUInt32(r, n, err),
|
Height: ReadUInt32(r, n, err),
|
||||||
Fees: ReadUInt64(r, n, err),
|
Fees: ReadUInt64(r, n, err),
|
||||||
Time: ReadTime(r, n, err),
|
Time: ReadTime(r, n, err),
|
||||||
PrevHash: ReadByteSlice(r, n, err),
|
PrevHash: ReadByteSlice(r, n, err),
|
||||||
ValidationHash: ReadByteSlice(r, n, err),
|
ValidationStateHash: ReadByteSlice(r, n, err),
|
||||||
TxsHash: ReadByteSlice(r, n, err),
|
AccountStateHash: ReadByteSlice(r, n, err),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -168,8 +182,8 @@ func (h *Header) WriteTo(w io.Writer) (n int64, err error) {
|
|||||||
WriteUInt64(w, h.Fees, &n, &err)
|
WriteUInt64(w, h.Fees, &n, &err)
|
||||||
WriteTime(w, h.Time, &n, &err)
|
WriteTime(w, h.Time, &n, &err)
|
||||||
WriteByteSlice(w, h.PrevHash, &n, &err)
|
WriteByteSlice(w, h.PrevHash, &n, &err)
|
||||||
WriteByteSlice(w, h.ValidationHash, &n, &err)
|
WriteByteSlice(w, h.ValidationStateHash, &n, &err)
|
||||||
WriteByteSlice(w, h.TxsHash, &n, &err)
|
WriteByteSlice(w, h.AccountStateHash, &n, &err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -187,10 +201,10 @@ func (h *Header) Hash() []byte {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Validation is part of a block */
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
type Validation struct {
|
type Validation struct {
|
||||||
Signatures []Signature
|
Signatures []Signature
|
||||||
Txs []Tx
|
|
||||||
|
|
||||||
// Volatile
|
// Volatile
|
||||||
hash []byte
|
hash []byte
|
||||||
@ -198,30 +212,20 @@ type Validation struct {
|
|||||||
|
|
||||||
func ReadValidation(r io.Reader, n *int64, err *error) Validation {
|
func ReadValidation(r io.Reader, n *int64, err *error) Validation {
|
||||||
numSigs := ReadUInt32(r, n, err)
|
numSigs := ReadUInt32(r, n, err)
|
||||||
numAdjs := ReadUInt32(r, n, err)
|
|
||||||
sigs := make([]Signature, 0, numSigs)
|
sigs := make([]Signature, 0, numSigs)
|
||||||
for i := uint32(0); i < numSigs; i++ {
|
for i := uint32(0); i < numSigs; i++ {
|
||||||
sigs = append(sigs, ReadSignature(r, n, err))
|
sigs = append(sigs, ReadSignature(r, n, err))
|
||||||
}
|
}
|
||||||
tx := make([]Tx, 0, numAdjs)
|
|
||||||
for i := uint32(0); i < numAdjs; i++ {
|
|
||||||
tx = append(tx, ReadTx(r, n, err))
|
|
||||||
}
|
|
||||||
return Validation{
|
return Validation{
|
||||||
Signatures: sigs,
|
Signatures: sigs,
|
||||||
Txs: tx,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *Validation) WriteTo(w io.Writer) (n int64, err error) {
|
func (v *Validation) WriteTo(w io.Writer) (n int64, err error) {
|
||||||
WriteUInt32(w, uint32(len(v.Signatures)), &n, &err)
|
WriteUInt32(w, uint32(len(v.Signatures)), &n, &err)
|
||||||
WriteUInt32(w, uint32(len(v.Txs)), &n, &err)
|
|
||||||
for _, sig := range v.Signatures {
|
for _, sig := range v.Signatures {
|
||||||
WriteBinary(w, sig, &n, &err)
|
WriteBinary(w, sig, &n, &err)
|
||||||
}
|
}
|
||||||
for _, tx := range v.Txs {
|
|
||||||
WriteBinary(w, tx, &n, &err)
|
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -239,40 +243,41 @@ func (v *Validation) Hash() []byte {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Txs is part of a block */
|
//-----------------------------------------------------------------------------
|
||||||
type Txs struct {
|
|
||||||
|
type Data struct {
|
||||||
Txs []Tx
|
Txs []Tx
|
||||||
|
|
||||||
// Volatile
|
// Volatile
|
||||||
hash []byte
|
hash []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func ReadTxs(r io.Reader, n *int64, err *error) Txs {
|
func ReadData(r io.Reader, n *int64, err *error) Data {
|
||||||
numTxs := ReadUInt32(r, n, err)
|
numTxs := ReadUInt32(r, n, err)
|
||||||
txs := make([]Tx, 0, numTxs)
|
txs := make([]Tx, 0, numTxs)
|
||||||
for i := uint32(0); i < numTxs; i++ {
|
for i := uint32(0); i < numTxs; i++ {
|
||||||
txs = append(txs, ReadTx(r, n, err))
|
txs = append(txs, ReadTx(r, n, err))
|
||||||
}
|
}
|
||||||
return Txs{Txs: txs}
|
return Data{Txs: txs}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (txs *Txs) WriteTo(w io.Writer) (n int64, err error) {
|
func (data *Data) WriteTo(w io.Writer) (n int64, err error) {
|
||||||
WriteUInt32(w, uint32(len(txs.Txs)), &n, &err)
|
WriteUInt32(w, uint32(len(data.Txs)), &n, &err)
|
||||||
for _, tx := range txs.Txs {
|
for _, tx := range data.Txs {
|
||||||
WriteBinary(w, tx, &n, &err)
|
WriteBinary(w, tx, &n, &err)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (txs *Txs) Hash() []byte {
|
func (data *Data) Hash() []byte {
|
||||||
if txs.hash != nil {
|
if data.hash != nil {
|
||||||
return txs.hash
|
return data.hash
|
||||||
} else {
|
} else {
|
||||||
bs := make([]Binary, 0, len(txs.Txs))
|
bs := make([]Binary, 0, len(data.Txs))
|
||||||
for i, tx := range txs.Txs {
|
for i, tx := range data.Txs {
|
||||||
bs[i] = Binary(tx)
|
bs[i] = Binary(tx)
|
||||||
}
|
}
|
||||||
txs.hash = merkle.HashFromBinarySlice(bs)
|
data.hash = merkle.HashFromBinarySlice(bs)
|
||||||
return txs.hash
|
return data.hash
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -63,7 +63,7 @@ func TestBlock(t *testing.T) {
|
|||||||
PubKey: randBytes(32),
|
PubKey: randBytes(32),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Consensus Txs
|
// Validation Txs
|
||||||
|
|
||||||
bond := &Bond{
|
bond := &Bond{
|
||||||
Signature: randSig(),
|
Signature: randSig(),
|
||||||
@ -106,15 +106,14 @@ func TestBlock(t *testing.T) {
|
|||||||
Time: randTime(),
|
Time: randTime(),
|
||||||
PrevHash: randBytes(32),
|
PrevHash: randBytes(32),
|
||||||
ValidationHash: randBytes(32),
|
ValidationHash: randBytes(32),
|
||||||
TxsHash: randBytes(32),
|
DataHash: randBytes(32),
|
||||||
},
|
},
|
||||||
Validation: Validation{
|
Validation: Validation{
|
||||||
Signatures: []Signature{randSig(), randSig()},
|
Signatures: []Signature{randSig(), randSig()},
|
||||||
Txs: []Txs{bond, unbond, timeout, dupeout},
|
Txs: []Txs{bond, unbond, timeout, dupeout},
|
||||||
},
|
},
|
||||||
Txs: Txs{
|
Data: Data{
|
||||||
Txs: []Tx{sendTx, nameTx},
|
Txs: []Tx{sendTx, nameTx},
|
||||||
hash: nil,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ func BenchmarkTestCustom(b *testing.B) {
|
|||||||
Time: time.Unix(123, 0),
|
Time: time.Unix(123, 0),
|
||||||
PrevHash: []byte("prevhash"),
|
PrevHash: []byte("prevhash"),
|
||||||
ValidationHash: []byte("validationhash"),
|
ValidationHash: []byte("validationhash"),
|
||||||
TxsHash: []byte("txshash"),
|
DataHash: []byte("datahash"),
|
||||||
}
|
}
|
||||||
|
|
||||||
buf := bytes.NewBuffer(nil)
|
buf := bytes.NewBuffer(nil)
|
||||||
@ -46,7 +46,7 @@ type HHeader struct {
|
|||||||
Time uint64 `json:"T"`
|
Time uint64 `json:"T"`
|
||||||
PrevHash []byte `json:"PH"`
|
PrevHash []byte `json:"PH"`
|
||||||
ValidationHash []byte `json:"VH"`
|
ValidationHash []byte `json:"VH"`
|
||||||
TxsHash []byte `json:"DH"`
|
DataHash []byte `json:"DH"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkTestJSON(b *testing.B) {
|
func BenchmarkTestJSON(b *testing.B) {
|
||||||
@ -59,7 +59,7 @@ func BenchmarkTestJSON(b *testing.B) {
|
|||||||
Time: 123,
|
Time: 123,
|
||||||
PrevHash: []byte("prevhash"),
|
PrevHash: []byte("prevhash"),
|
||||||
ValidationHash: []byte("validationhash"),
|
ValidationHash: []byte("validationhash"),
|
||||||
TxsHash: []byte("txshash"),
|
DataHash: []byte("datahash"),
|
||||||
}
|
}
|
||||||
h2 := &HHeader{}
|
h2 := &HHeader{}
|
||||||
|
|
||||||
@ -88,7 +88,7 @@ func BenchmarkTestGob(b *testing.B) {
|
|||||||
Time: time.Unix(123, 0),
|
Time: time.Unix(123, 0),
|
||||||
PrevHash: []byte("prevhash"),
|
PrevHash: []byte("prevhash"),
|
||||||
ValidationHash: []byte("validationhash"),
|
ValidationHash: []byte("validationhash"),
|
||||||
TxsHash: []byte("txshash"),
|
DataHash: []byte("datahash"),
|
||||||
}
|
}
|
||||||
h2 := &Header{}
|
h2 := &Header{}
|
||||||
|
|
||||||
@ -117,7 +117,7 @@ func BenchmarkTestMsgPack(b *testing.B) {
|
|||||||
Time: time.Unix(123, 0),
|
Time: time.Unix(123, 0),
|
||||||
PrevHash: []byte("prevhash"),
|
PrevHash: []byte("prevhash"),
|
||||||
ValidationHash: []byte("validationhash"),
|
ValidationHash: []byte("validationhash"),
|
||||||
TxsHash: []byte("txshash"),
|
DataHash: []byte("datahash"),
|
||||||
}
|
}
|
||||||
h2 := &Header{}
|
h2 := &Header{}
|
||||||
|
|
||||||
@ -146,7 +146,7 @@ func BenchmarkTestMsgPack2(b *testing.B) {
|
|||||||
Time: time.Unix(123, 0),
|
Time: time.Unix(123, 0),
|
||||||
PrevHash: []byte("prevhash"),
|
PrevHash: []byte("prevhash"),
|
||||||
ValidationHash: []byte("validationhash"),
|
ValidationHash: []byte("validationhash"),
|
||||||
TxsHash: []byte("txshash"),
|
DataHash: []byte("datahash"),
|
||||||
}
|
}
|
||||||
h2 := &Header{}
|
h2 := &Header{}
|
||||||
var mh codec.MsgpackHandle
|
var mh codec.MsgpackHandle
|
||||||
|
@ -22,7 +22,7 @@ Account Txs:
|
|||||||
1. Send Send coins to account
|
1. Send Send coins to account
|
||||||
2. Name Associate account with a name
|
2. Name Associate account with a name
|
||||||
|
|
||||||
Consensus Txs:
|
Validation Txs:
|
||||||
3. Bond New validator posts a bond
|
3. Bond New validator posts a bond
|
||||||
4. Unbond Validator leaves
|
4. Unbond Validator leaves
|
||||||
5. Timeout Validator times out
|
5. Timeout Validator times out
|
||||||
@ -35,7 +35,7 @@ type Tx interface {
|
|||||||
Type() byte
|
Type() byte
|
||||||
GetSequence() uint64
|
GetSequence() uint64
|
||||||
GetSignature() *Signature
|
GetSignature() *Signature
|
||||||
//IsConsensus() bool
|
//IsValidation() bool
|
||||||
Binary
|
Binary
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,7 +44,7 @@ const (
|
|||||||
TX_TYPE_SEND = byte(0x01)
|
TX_TYPE_SEND = byte(0x01)
|
||||||
TX_TYPE_NAME = byte(0x02)
|
TX_TYPE_NAME = byte(0x02)
|
||||||
|
|
||||||
// Consensus transactions
|
// Validation transactions
|
||||||
TX_TYPE_BOND = byte(0x11)
|
TX_TYPE_BOND = byte(0x11)
|
||||||
TX_TYPE_UNBOND = byte(0x12)
|
TX_TYPE_UNBOND = byte(0x12)
|
||||||
TX_TYPE_TIMEOUT = byte(0x13)
|
TX_TYPE_TIMEOUT = byte(0x13)
|
||||||
|
@ -1,12 +1,3 @@
|
|||||||
package mempool
|
|
||||||
|
|
||||||
import (
|
|
||||||
"sync"
|
|
||||||
|
|
||||||
. "github.com/tendermint/tendermint/blocks"
|
|
||||||
. "github.com/tendermint/tendermint/state"
|
|
||||||
)
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Mempool receives new transactions and applies them to the latest committed state.
|
Mempool receives new transactions and applies them to the latest committed state.
|
||||||
If the transaction is acceptable, then it broadcasts a fingerprint to peers.
|
If the transaction is acceptable, then it broadcasts a fingerprint to peers.
|
||||||
@ -20,24 +11,33 @@ When this node happens to be the next proposer, it simply takes the recently
|
|||||||
modified state (and the associated transactions) and use that as the proposal.
|
modified state (and the associated transactions) and use that as the proposal.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
package mempool
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
. "github.com/tendermint/tendermint/blocks"
|
||||||
|
. "github.com/tendermint/tendermint/state"
|
||||||
|
)
|
||||||
|
|
||||||
type Mempool struct {
|
type Mempool struct {
|
||||||
mtx sync.Mutex
|
mtx sync.Mutex
|
||||||
state *State
|
lastBlock *Block
|
||||||
txs []Tx
|
state *State
|
||||||
|
txs []Tx
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewMempool(state *State) *Mempool {
|
func NewMempool(lastBlock *Block, state *State) *Mempool {
|
||||||
return &Mempool{
|
return &Mempool{
|
||||||
state: state,
|
lastBlock: lastBlock,
|
||||||
|
state: state,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Apply tx to the state and remember it.
|
||||||
func (mem *Mempool) AddTx(tx Tx) (err error) {
|
func (mem *Mempool) AddTx(tx Tx) (err error) {
|
||||||
mem.mtx.Lock()
|
mem.mtx.Lock()
|
||||||
defer mem.mtx.Unlock()
|
defer mem.mtx.Unlock()
|
||||||
// Add the tx to the state.
|
|
||||||
err = mem.state.CommitTx(tx)
|
err = mem.state.CommitTx(tx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -46,3 +46,54 @@ func (mem *Mempool) AddTx(tx Tx) (err error) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns a new block from the current state and associated transactions.
|
||||||
|
// The block's Validation is empty, and some parts of the header too.
|
||||||
|
func (mem *Mempool) MakeProposal() (*Block, *State) {
|
||||||
|
mem.mtx.Lock()
|
||||||
|
defer mem.mtx.Unlock()
|
||||||
|
nextBlock := mem.lastBlock.MakeNextBlock()
|
||||||
|
nextBlock.Data.Txs = mem.txs
|
||||||
|
return nextBlock, mem.state
|
||||||
|
}
|
||||||
|
|
||||||
|
// Txs that are present in block are discarded from mempool.
|
||||||
|
// Txs that have become invalid in the new state are also discarded.
|
||||||
|
func (mem *Mempool) ResetForBlockandState(block *Block, state *State) {
|
||||||
|
mem.mtx.Lock()
|
||||||
|
defer mem.mtx.Unlock()
|
||||||
|
mem.lastBlock = block
|
||||||
|
mem.state = state.Copy()
|
||||||
|
|
||||||
|
// First, create a lookup map of txns in new block.
|
||||||
|
blockTxsMap := make(map[string]struct{})
|
||||||
|
for _, tx := range block.Data.Txs {
|
||||||
|
txHash := BinaryHash(tx)
|
||||||
|
blockTxsMap[string(txHash)] = struct{}{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next, filter all txs from mem.txs that are in blockTxsMap
|
||||||
|
txs := []Tx{}
|
||||||
|
for _, tx := range mem.txs {
|
||||||
|
txHash := BinaryHash(tx)
|
||||||
|
if _, ok := blockTxsMap[string(txHash)]; ok {
|
||||||
|
continue
|
||||||
|
} else {
|
||||||
|
txs = append(txs, tx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next, filter all txs that aren't valid given new state.
|
||||||
|
validTxs := []Tx{}
|
||||||
|
for _, tx := range txs {
|
||||||
|
err := mem.state.CommitTx(tx)
|
||||||
|
if err != nil {
|
||||||
|
validTxs = append(validTxs, tx)
|
||||||
|
} else {
|
||||||
|
// tx is no longer valid.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We're done!
|
||||||
|
mem.txs = validTxs
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user