mirror of
https://github.com/fluencelabs/tendermint
synced 2025-06-24 18:21:38 +00:00
updated readme, implementing mempool.
This commit is contained in:
@ -2,11 +2,16 @@ TenderMint - proof of concept
|
|||||||
|
|
||||||
* **[p2p](https://github.com/tendermint/tendermint/blob/master/p2p):** P2P networking stack. Designed to be extensible.
|
* **[p2p](https://github.com/tendermint/tendermint/blob/master/p2p):** P2P networking stack. Designed to be extensible.
|
||||||
* **[merkle](https://github.com/tendermint/tendermint/blob/master/merkle):** Immutable Persistent Merkle-ized AVL+ Tree, used primarily for keeping track of mutable state like account balances.
|
* **[merkle](https://github.com/tendermint/tendermint/blob/master/merkle):** Immutable Persistent Merkle-ized AVL+ Tree, used primarily for keeping track of mutable state like account balances.
|
||||||
|
* **[blocks](https://github.com/tendermint/tendermint/blob/master/blocks):** The blockchain, storage of blocks, and all the associated structures.
|
||||||
|
* **[state](https://github.com/tendermint/tendermint/blob/master/state):** The application state, which is mutated by blocks in the blockchain.
|
||||||
|
* **[consensus](https://github.com/tendermint/tendermint/blob/master/consensus):** The core consensus algorithm logic.
|
||||||
|
* **[mempool](https://github.com/tendermint/tendermint/blob/master/mempool):** Handles the broadcasting of uncommitted transactions.
|
||||||
* **[crypto](https://github.com/tendermint/tendermint/blob/master/crypto):** Includes cgo bindings of ed25519.
|
* **[crypto](https://github.com/tendermint/tendermint/blob/master/crypto):** Includes cgo bindings of ed25519.
|
||||||
|
|
||||||
### Status
|
### Status
|
||||||
|
|
||||||
* Consensus *now*
|
* Mempool *now*
|
||||||
|
* Consensus *complete*
|
||||||
* Block propagation *sidelined*
|
* Block propagation *sidelined*
|
||||||
* Node & testnet *complete*
|
* Node & testnet *complete*
|
||||||
* PEX peer exchange *complete*
|
* PEX peer exchange *complete*
|
||||||
|
@ -1,166 +0,0 @@
|
|||||||
package blocks
|
|
||||||
|
|
||||||
import (
|
|
||||||
. "github.com/tendermint/tendermint/binary"
|
|
||||||
. "github.com/tendermint/tendermint/common"
|
|
||||||
"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_DUPEOUT = byte(0x04)
|
|
||||||
)
|
|
||||||
|
|
||||||
func ReadAdjustment(r io.Reader, n *int64, err *error) Adjustment {
|
|
||||||
switch t := ReadByte(r, n, err); t {
|
|
||||||
case ADJ_TYPE_BOND:
|
|
||||||
return &Bond{
|
|
||||||
Fee: ReadUInt64(r, n, err),
|
|
||||||
UnbondTo: ReadUInt64(r, n, err),
|
|
||||||
Amount: ReadUInt64(r, n, err),
|
|
||||||
Signature: ReadSignature(r, n, err),
|
|
||||||
}
|
|
||||||
case ADJ_TYPE_UNBOND:
|
|
||||||
return &Unbond{
|
|
||||||
Fee: ReadUInt64(r, n, err),
|
|
||||||
Amount: ReadUInt64(r, n, err),
|
|
||||||
Signature: ReadSignature(r, n, err),
|
|
||||||
}
|
|
||||||
case ADJ_TYPE_TIMEOUT:
|
|
||||||
return &Timeout{
|
|
||||||
AccountId: ReadUInt64(r, n, err),
|
|
||||||
Penalty: ReadUInt64(r, n, err),
|
|
||||||
}
|
|
||||||
case ADJ_TYPE_DUPEOUT:
|
|
||||||
return &Dupeout{
|
|
||||||
VoteA: ReadBlockVote(r, n, err),
|
|
||||||
VoteB: ReadBlockVote(r, n, err),
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
Panicf("Unknown Adjustment type %x", t)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
/* Bond < Adjustment */
|
|
||||||
type Bond struct {
|
|
||||||
Fee uint64
|
|
||||||
UnbondTo uint64
|
|
||||||
Amount uint64
|
|
||||||
Signature
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *Bond) Type() byte {
|
|
||||||
return ADJ_TYPE_BOND
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *Bond) WriteTo(w io.Writer) (n int64, err error) {
|
|
||||||
WriteByte(w, self.Type(), &n, &err)
|
|
||||||
WriteUInt64(w, self.Fee, &n, &err)
|
|
||||||
WriteUInt64(w, self.UnbondTo, &n, &err)
|
|
||||||
WriteUInt64(w, self.Amount, &n, &err)
|
|
||||||
WriteBinary(w, self.Signature, &n, &err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
/* Unbond < Adjustment */
|
|
||||||
type Unbond struct {
|
|
||||||
Fee uint64
|
|
||||||
Amount uint64
|
|
||||||
Signature
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *Unbond) Type() byte {
|
|
||||||
return ADJ_TYPE_UNBOND
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *Unbond) WriteTo(w io.Writer) (n int64, err error) {
|
|
||||||
WriteByte(w, self.Type(), &n, &err)
|
|
||||||
WriteUInt64(w, self.Fee, &n, &err)
|
|
||||||
WriteUInt64(w, self.Amount, &n, &err)
|
|
||||||
WriteBinary(w, self.Signature, &n, &err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
/* Timeout < Adjustment */
|
|
||||||
type Timeout struct {
|
|
||||||
AccountId uint64
|
|
||||||
Penalty uint64
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *Timeout) Type() byte {
|
|
||||||
return ADJ_TYPE_TIMEOUT
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *Timeout) WriteTo(w io.Writer) (n int64, err error) {
|
|
||||||
WriteByte(w, self.Type(), &n, &err)
|
|
||||||
WriteUInt64(w, self.AccountId, &n, &err)
|
|
||||||
WriteUInt64(w, self.Penalty, &n, &err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
/*
|
|
||||||
The full vote structure is only needed when presented as evidence.
|
|
||||||
Typically only the signature is passed around, as the hash & height are implied.
|
|
||||||
*/
|
|
||||||
type BlockVote struct {
|
|
||||||
Height uint64
|
|
||||||
BlockHash []byte
|
|
||||||
Signature
|
|
||||||
}
|
|
||||||
|
|
||||||
func ReadBlockVote(r io.Reader, n *int64, err *error) BlockVote {
|
|
||||||
return BlockVote{
|
|
||||||
Height: ReadUInt64(r, n, err),
|
|
||||||
BlockHash: ReadByteSlice(r, n, err),
|
|
||||||
Signature: ReadSignature(r, n, err),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self BlockVote) WriteTo(w io.Writer) (n int64, err error) {
|
|
||||||
WriteUInt64(w, self.Height, &n, &err)
|
|
||||||
WriteByteSlice(w, self.BlockHash, &n, &err)
|
|
||||||
WriteBinary(w, self.Signature, &n, &err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Dupeout < Adjustment */
|
|
||||||
type Dupeout struct {
|
|
||||||
VoteA BlockVote
|
|
||||||
VoteB BlockVote
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *Dupeout) Type() byte {
|
|
||||||
return ADJ_TYPE_DUPEOUT
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *Dupeout) WriteTo(w io.Writer) (n int64, err error) {
|
|
||||||
WriteByte(w, self.Type(), &n, &err)
|
|
||||||
WriteBinary(w, self.VoteA, &n, &err)
|
|
||||||
WriteBinary(w, self.VoteB, &n, &err)
|
|
||||||
return
|
|
||||||
}
|
|
@ -189,8 +189,8 @@ func (h *Header) Hash() []byte {
|
|||||||
|
|
||||||
/* Validation is part of a block */
|
/* Validation is part of a block */
|
||||||
type Validation struct {
|
type Validation struct {
|
||||||
Signatures []Signature
|
Signatures []Signature
|
||||||
Adjustments []Adjustment
|
Txs []Tx
|
||||||
|
|
||||||
// Volatile
|
// Volatile
|
||||||
hash []byte
|
hash []byte
|
||||||
@ -203,24 +203,24 @@ func ReadValidation(r io.Reader, n *int64, err *error) Validation {
|
|||||||
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))
|
||||||
}
|
}
|
||||||
adjs := make([]Adjustment, 0, numAdjs)
|
tx := make([]Tx, 0, numAdjs)
|
||||||
for i := uint32(0); i < numAdjs; i++ {
|
for i := uint32(0); i < numAdjs; i++ {
|
||||||
adjs = append(adjs, ReadAdjustment(r, n, err))
|
tx = append(tx, ReadTx(r, n, err))
|
||||||
}
|
}
|
||||||
return Validation{
|
return Validation{
|
||||||
Signatures: sigs,
|
Signatures: sigs,
|
||||||
Adjustments: adjs,
|
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.Adjustments)), &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 _, adj := range v.Adjustments {
|
for _, tx := range v.Txs {
|
||||||
WriteBinary(w, adj, &n, &err)
|
WriteBinary(w, tx, &n, &err)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,7 @@ func randSig() Signature {
|
|||||||
|
|
||||||
func TestBlock(t *testing.T) {
|
func TestBlock(t *testing.T) {
|
||||||
|
|
||||||
// Txs
|
// Account Txs
|
||||||
|
|
||||||
sendTx := &SendTx{
|
sendTx := &SendTx{
|
||||||
Signature: randSig(),
|
Signature: randSig(),
|
||||||
@ -63,7 +63,7 @@ func TestBlock(t *testing.T) {
|
|||||||
PubKey: randBytes(32),
|
PubKey: randBytes(32),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adjs
|
// Consensus Txs
|
||||||
|
|
||||||
bond := &Bond{
|
bond := &Bond{
|
||||||
Signature: randSig(),
|
Signature: randSig(),
|
||||||
@ -109,8 +109,8 @@ func TestBlock(t *testing.T) {
|
|||||||
TxsHash: randBytes(32),
|
TxsHash: randBytes(32),
|
||||||
},
|
},
|
||||||
Validation: Validation{
|
Validation: Validation{
|
||||||
Signatures: []Signature{randSig(), randSig()},
|
Signatures: []Signature{randSig(), randSig()},
|
||||||
Adjustments: []Adjustment{bond, unbond, timeout, dupeout},
|
Txs: []Txs{bond, unbond, timeout, dupeout},
|
||||||
},
|
},
|
||||||
Txs: Txs{
|
Txs: Txs{
|
||||||
Txs: []Tx{sendTx, nameTx},
|
Txs: []Tx{sendTx, nameTx},
|
||||||
|
151
blocks/tx.go
151
blocks/tx.go
@ -18,16 +18,35 @@ Tx wire format:
|
|||||||
A account number, varint encoded (1+ bytes)
|
A account number, varint encoded (1+ bytes)
|
||||||
S signature of all prior bytes (32 bytes)
|
S signature of all prior bytes (32 bytes)
|
||||||
|
|
||||||
|
Account Txs:
|
||||||
|
1. Send Send coins to account
|
||||||
|
2. Name Associate account with a name
|
||||||
|
|
||||||
|
Consensus Txs:
|
||||||
|
3. Bond New validator posts a bond
|
||||||
|
4. Unbond Validator leaves
|
||||||
|
5. Timeout Validator times out
|
||||||
|
6. Dupeout Validator dupes out (signs twice)
|
||||||
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
type Tx interface {
|
type Tx interface {
|
||||||
Type() byte
|
Type() byte
|
||||||
|
IsConsensus() bool
|
||||||
Binary
|
Binary
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
// Account transactions
|
||||||
TX_TYPE_SEND = byte(0x01)
|
TX_TYPE_SEND = byte(0x01)
|
||||||
TX_TYPE_NAME = byte(0x02)
|
TX_TYPE_NAME = byte(0x02)
|
||||||
|
|
||||||
|
// Consensus transactions
|
||||||
|
TX_TYPE_BOND = byte(0x11)
|
||||||
|
TX_TYPE_UNBOND = byte(0x12)
|
||||||
|
TX_TYPE_TIMEOUT = byte(0x13)
|
||||||
|
TX_TYPE_DUPEOUT = byte(0x14)
|
||||||
)
|
)
|
||||||
|
|
||||||
func ReadTx(r io.Reader, n *int64, err *error) Tx {
|
func ReadTx(r io.Reader, n *int64, err *error) Tx {
|
||||||
@ -46,13 +65,36 @@ func ReadTx(r io.Reader, n *int64, err *error) Tx {
|
|||||||
PubKey: ReadByteSlice(r, n, err),
|
PubKey: ReadByteSlice(r, n, err),
|
||||||
Signature: ReadSignature(r, n, err),
|
Signature: ReadSignature(r, n, err),
|
||||||
}
|
}
|
||||||
|
case TX_TYPE_BOND:
|
||||||
|
return &BondTx{
|
||||||
|
Fee: ReadUInt64(r, n, err),
|
||||||
|
UnbondTo: ReadUInt64(r, n, err),
|
||||||
|
Amount: ReadUInt64(r, n, err),
|
||||||
|
Signature: ReadSignature(r, n, err),
|
||||||
|
}
|
||||||
|
case TX_TYPE_UNBOND:
|
||||||
|
return &UnbondTx{
|
||||||
|
Fee: ReadUInt64(r, n, err),
|
||||||
|
Amount: ReadUInt64(r, n, err),
|
||||||
|
Signature: ReadSignature(r, n, err),
|
||||||
|
}
|
||||||
|
case TX_TYPE_TIMEOUT:
|
||||||
|
return &TimeoutTx{
|
||||||
|
AccountId: ReadUInt64(r, n, err),
|
||||||
|
Penalty: ReadUInt64(r, n, err),
|
||||||
|
}
|
||||||
|
case TX_TYPE_DUPEOUT:
|
||||||
|
return &DupeoutTx{
|
||||||
|
VoteA: ReadBlockVote(r, n, err),
|
||||||
|
VoteB: ReadBlockVote(r, n, err),
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
Panicf("Unknown Tx type %x", t)
|
Panicf("Unknown Tx type %x", t)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* SendTx < Tx */
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
type SendTx struct {
|
type SendTx struct {
|
||||||
Fee uint64
|
Fee uint64
|
||||||
@ -74,7 +116,7 @@ func (self *SendTx) WriteTo(w io.Writer) (n int64, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
/* NameTx < Tx */
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
type NameTx struct {
|
type NameTx struct {
|
||||||
Fee uint64
|
Fee uint64
|
||||||
@ -95,3 +137,108 @@ func (self *NameTx) WriteTo(w io.Writer) (n int64, err error) {
|
|||||||
WriteBinary(w, self.Signature, &n, &err)
|
WriteBinary(w, self.Signature, &n, &err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
type BondTx struct {
|
||||||
|
Fee uint64
|
||||||
|
UnbondTo uint64
|
||||||
|
Amount uint64
|
||||||
|
Signature
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *BondTx) Type() byte {
|
||||||
|
return TX_TYPE_BOND
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *BondTx) WriteTo(w io.Writer) (n int64, err error) {
|
||||||
|
WriteByte(w, self.Type(), &n, &err)
|
||||||
|
WriteUInt64(w, self.Fee, &n, &err)
|
||||||
|
WriteUInt64(w, self.UnbondTo, &n, &err)
|
||||||
|
WriteUInt64(w, self.Amount, &n, &err)
|
||||||
|
WriteBinary(w, self.Signature, &n, &err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
type UnbondTx struct {
|
||||||
|
Fee uint64
|
||||||
|
Amount uint64
|
||||||
|
Signature
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *UnbondTx) Type() byte {
|
||||||
|
return TX_TYPE_UNBOND
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *UnbondTx) WriteTo(w io.Writer) (n int64, err error) {
|
||||||
|
WriteByte(w, self.Type(), &n, &err)
|
||||||
|
WriteUInt64(w, self.Fee, &n, &err)
|
||||||
|
WriteUInt64(w, self.Amount, &n, &err)
|
||||||
|
WriteBinary(w, self.Signature, &n, &err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
type TimeoutTx struct {
|
||||||
|
AccountId uint64
|
||||||
|
Penalty uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *TimeoutTx) Type() byte {
|
||||||
|
return TX_TYPE_TIMEOUT
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *TimeoutTx) WriteTo(w io.Writer) (n int64, err error) {
|
||||||
|
WriteByte(w, self.Type(), &n, &err)
|
||||||
|
WriteUInt64(w, self.AccountId, &n, &err)
|
||||||
|
WriteUInt64(w, self.Penalty, &n, &err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/*
|
||||||
|
The full vote structure is only needed when presented as evidence.
|
||||||
|
Typically only the signature is passed around, as the hash & height are implied.
|
||||||
|
*/
|
||||||
|
type BlockVote struct {
|
||||||
|
Height uint64
|
||||||
|
BlockHash []byte
|
||||||
|
Signature
|
||||||
|
}
|
||||||
|
|
||||||
|
func ReadBlockVote(r io.Reader, n *int64, err *error) BlockVote {
|
||||||
|
return BlockVote{
|
||||||
|
Height: ReadUInt64(r, n, err),
|
||||||
|
BlockHash: ReadByteSlice(r, n, err),
|
||||||
|
Signature: ReadSignature(r, n, err),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self BlockVote) WriteTo(w io.Writer) (n int64, err error) {
|
||||||
|
WriteUInt64(w, self.Height, &n, &err)
|
||||||
|
WriteByteSlice(w, self.BlockHash, &n, &err)
|
||||||
|
WriteBinary(w, self.Signature, &n, &err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
type DupeoutTx struct {
|
||||||
|
VoteA BlockVote
|
||||||
|
VoteB BlockVote
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *DupeoutTx) Type() byte {
|
||||||
|
return TX_TYPE_DUPEOUT
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *DupeoutTx) WriteTo(w io.Writer) (n int64, err error) {
|
||||||
|
WriteByte(w, self.Type(), &n, &err)
|
||||||
|
WriteBinary(w, self.VoteA, &n, &err)
|
||||||
|
WriteBinary(w, self.VoteB, &n, &err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
59
mempool/mempool.go
Normal file
59
mempool/mempool.go
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
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.
|
||||||
|
If the transaction is acceptable, then it broadcasts a fingerprint to peers.
|
||||||
|
|
||||||
|
The transaction fingerprint is a short sequence of bytes (shorter than a full hash).
|
||||||
|
Each peer connection uses a different algorithm for turning the tx hash into a
|
||||||
|
fingerprint in order to prevent transaction blocking attacks. Upon inspecting a
|
||||||
|
tx fingerprint, the receiver may query the source for the full tx bytes.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
There are two types of transactions -- consensus txs (e.g. bonding / unbonding /
|
||||||
|
timeout / dupeout txs) and everything else. They are stored separately to allow
|
||||||
|
nodes to only request the kind they need.
|
||||||
|
TODO: make use of this potential feature when the time comes.
|
||||||
|
|
||||||
|
For simplicity we evaluate the consensus transactions after everything else.
|
||||||
|
*/
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
type Mempool struct {
|
||||||
|
mtx sync.Mutex
|
||||||
|
state *State
|
||||||
|
txs []Tx // Regular transactions
|
||||||
|
ctxs []Tx // Validator related transactions
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewMempool(state *State) *Mempool {
|
||||||
|
return &Mempool{
|
||||||
|
state: state,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mem *Mempool) AddTx(tx Tx) bool {
|
||||||
|
mem.mtx.Lock()
|
||||||
|
defer mem.mtx.Unlock()
|
||||||
|
if tx.IsConsensus() {
|
||||||
|
// Remember consensus tx for later staging.
|
||||||
|
// We only keep 1 tx for each validator. TODO what? what about bonding?
|
||||||
|
// TODO talk about prioritization.
|
||||||
|
mem.ctxs = append(mem.ctxs, tx)
|
||||||
|
} else {
|
||||||
|
mem.txs = append(mem.txs, tx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mem *Mempool) CollectForState() {
|
||||||
|
}
|
@ -1,11 +1,8 @@
|
|||||||
## Channels
|
## Channels
|
||||||
|
|
||||||
Each peer connection is multiplexed into channels.
|
Each peer connection is multiplexed into channels.
|
||||||
<hr />
|
The p2p module comes with a channel implementation used for peer
|
||||||
|
discovery (called PEX, short for "peer exchange").
|
||||||
### PEX channel
|
|
||||||
|
|
||||||
The PEX channel is used to exchange peer addresses.
|
|
||||||
|
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
@ -24,90 +21,6 @@ The PEX channel is used to exchange peer addresses.
|
|||||||
</table>
|
</table>
|
||||||
<hr />
|
<hr />
|
||||||
|
|
||||||
### Block channel
|
|
||||||
|
|
||||||
The block channel is used to propagate block or header information to new peers or peers catching up with the blockchain.
|
|
||||||
|
|
||||||
<table>
|
|
||||||
<tr>
|
|
||||||
<td><b>Channel</b></td>
|
|
||||||
<td>"block"</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><b>Messages</b></td>
|
|
||||||
<td>
|
|
||||||
<ul>
|
|
||||||
<li>RequestMsg</li>
|
|
||||||
<li>BlockMsg</li>
|
|
||||||
<li>HeaderMsg</li>
|
|
||||||
</ul>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><b>Notes</b></td>
|
|
||||||
<td>
|
|
||||||
Nodes should only advertise having a header or block at height 'h' if it also has all the headers or blocks less than 'h'. Thus for each peer we need only keep track of two integers -- one for the most recent header height 'h_h' and one for the most recent block height 'h_b', where 'h_b' <= 'h_h'.
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<hr />
|
|
||||||
|
|
||||||
### Mempool channel
|
|
||||||
|
|
||||||
The mempool channel is used for broadcasting new transactions that haven't yet entered the blockchain. It uses a lossy bloom filter on either end, but with sufficient fanout and filter nonce updates every new block, all transactions will eventually reach every node.
|
|
||||||
|
|
||||||
<table>
|
|
||||||
<tr>
|
|
||||||
<td><b>Channel</b></td>
|
|
||||||
<td>"mempool"</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><b>Messages</b></td>
|
|
||||||
<td>
|
|
||||||
<ul>
|
|
||||||
<li>MempoolTxMsg</li>
|
|
||||||
</ul>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><b>Notes</b></td>
|
|
||||||
<td>
|
|
||||||
Instead of keeping a perfect inventory of what peers have, we use a lossy filter.<br/>
|
|
||||||
Bloom filter (n:10k, p:0.02 -> k:6, m:10KB)<br/>
|
|
||||||
Each peer's filter has a random nonce that scrambles the message hashes.<br/>
|
|
||||||
The filter & nonce refreshes every new block.<br/>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<hr />
|
|
||||||
|
|
||||||
### Consensus channel
|
|
||||||
|
|
||||||
The consensus channel broadcasts all information used in the rounds of the Tendermint consensus mechanism.
|
|
||||||
|
|
||||||
<table>
|
|
||||||
<tr>
|
|
||||||
<td><b>Channel</b></td>
|
|
||||||
<td>"consensus"</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><b>Messages</b></td>
|
|
||||||
<td>
|
|
||||||
<ul>
|
|
||||||
<li>ProposalMsg</li>
|
|
||||||
<li>VoteMsg</li>
|
|
||||||
<li>NewBlockMsg</li>
|
|
||||||
</ul>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><b>Notes</b></td>
|
|
||||||
<td>
|
|
||||||
How do optimize/balance propagation speed & bandwidth utilization?
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
## Resources
|
## Resources
|
||||||
|
|
||||||
* http://www.upnp-hacks.org/upnp.html
|
* http://www.upnp-hacks.org/upnp.html
|
||||||
|
Reference in New Issue
Block a user