Skip to content

Commit

Permalink
new pool functions; miner reset with new block; popTxns method 🔫; com…
Browse files Browse the repository at this point in the history
…ments
  • Loading branch information
chadlagore committed Jul 13, 2017
1 parent f4f8b68 commit eee77fb
Show file tree
Hide file tree
Showing 6 changed files with 109 additions and 40 deletions.
7 changes: 7 additions & 0 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,8 @@ func ConnectAndDiscover(target string) {
// on peers whos RequestHandlers have been overridden.
func RequestHandler(req *msg.Request) msg.Response {
res := msg.Response{ID: req.ID}

// Build some error types.
typeErr := msg.NewProtocolError(msg.InvalidResourceType,
"Invalid resource type")
paramErr := msg.NewProtocolError(msg.InvalidResourceType,
Expand All @@ -134,18 +136,23 @@ func RequestHandler(req *msg.Request) msg.Response {
case msg.ResourcePeerInfo:
res.Resource = peer.PStore.Addrs()
case msg.ResourceBlock:
// Block is requested by number.
blockNumber, ok := req.Params["blockNumber"].(uint32)
if ok {
// If its ok, we make try to a copy of it.
blk, err := chain.CopyBlockByIndex(blockNumber)
if err != nil {
// Bad index parameter.
res.Error = paramErr
} else {
res.Resource = blk
}
} else {
// No index parameter.
res.Error = paramErr
}
default:
// Return err by default.
res.Error = typeErr
}

Expand Down
11 changes: 8 additions & 3 deletions app/worker.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,13 +72,18 @@ func (w *AppWorker) HandleTransaction(work TransactionWork) {
}
}

// HandleBlock handles TransactionWork.
// HandleBlock handles new instance of BlockWork.
func (w *AppWorker) HandleBlock(work BlockWork) {
ok, _ := chain.ValidBlock(work.Block)
ok := tpool.Update(work.Block, chain)

if ok {
// Append to the chain before requesting
// the next block so that the block
// numbers make sense.
chain.AppendBlock(work.Block)
blk := tpool.NextBlock(chain)
if miner.IsMining() {
miner.RestartMiner(chain, work.Block)
miner.RestartMiner(chain, blk)
}
}

Expand Down
9 changes: 9 additions & 0 deletions blockchain/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,15 @@ import (
"io"
)

const (
// BlockSize is the maximum size of a block in bytes when marshaled (about 250K).
BlockSize = 1 << 18
// BlockHeaderLen is the length in bytes of a block header.
BlockHeaderLen = 2*(32/8) + 64/8 + 2*HashLen
// MaxTransactionsPerBlock is the maximum number of transactions in a block.
MaxTransactionsPerBlock = BlockSize / MinTxnLen
)

// BlockHeader contains metadata about a block
type BlockHeader struct {
// BlockNumber is the position of the block within the blockchain
Expand Down
9 changes: 9 additions & 0 deletions blockchain/transaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,15 @@ import (
"io"
)

const (
// TxHashPointerLen is the length in bytes of a hash pointer.
TxHashPointerLen = 32/8 + HashLen
// TxOutputLen is the length in bytes of a transaction output.
TxOutputLen = 64/8 + AddrLen
// MinTxnLen is the minimum length in bytes of a transaction.
MinTxnLen = TxHashPointerLen + TxOutputLen + SigLen + AddrLen
)

// TxHashPointer is a reference to a transaction on the blockchain.
type TxHashPointer struct {
BlockNumber uint32
Expand Down
57 changes: 44 additions & 13 deletions pool/pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,20 +107,51 @@ func (p *Pool) Update(b *blockchain.Block, bc *blockchain.BlockChain) bool {
return true
}

// PopTxns returns the the largest of l or size of pool transactions.
// It selects the highest priority transactions, and removes them from the pool.
func (p *Pool) PopTxns(l int) []*blockchain.Transaction {
if p.Len() == 0 {
return make([]*blockchain.Transaction, 0)
// Pop returns the next transaction and removes it from the pool.
func (p *Pool) Pop() *blockchain.Transaction {
if p.Len() > 0 {
next := p.GetN(0)
p.Delete(next)
return next
}
if p.Len() < l {
l = p.Len()
return nil
}

// Peek returns the next transaction and does not remove it from the pool.
func (p *Pool) Peek() *blockchain.Transaction {
if p.Len() > 0 {
return p.GetN(0)
}
txns := make([]*blockchain.Transaction, l)
for i := 0; i < l; i++ {
t := p.GetN(i)
txns[i] = t
p.Delete(t)
return nil
}

// NextBlock produces a new block from the pool for mining.
func (p *Pool) NextBlock(chain *blockchain.BlockChain) *blockchain.Block {
var txns []*blockchain.Transaction

// Hash the last block in the chain.
ix := len(chain.Blocks) - 1
lastHash := blockchain.HashSum(chain.Blocks[ix])

// Build a new block for mining.
b := &blockchain.Block{
BlockHeader: blockchain.BlockHeader{
BlockNumber: uint32(len(chain.Blocks)),
LastBlock: lastHash,
Time: uint32(time.Now().Second()),
Nonce: 0,
}, Transactions: txns,
}

// Try to grab as many transactions as the block will allow.
// Test each transaction to see if we break size before adding.
for p.Len() > 0 {
if b.Len()+p.Peek().Len() < blockchain.BlockSize {
b.Transactions = append(b.Transactions, p.Pop())
} else {
break
}
}
return txns

return b
}
56 changes: 32 additions & 24 deletions pool/pool_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package pool
import (
"testing"

"github.com/stretchr/testify/assert"
"github.com/ubclaunchpad/cumulus/blockchain"
)

Expand Down Expand Up @@ -66,32 +67,10 @@ func TestUpdatePool(t *testing.T) {
}
}

func TestGetTxns(t *testing.T) {
p := New()
bc, b := blockchain.NewValidTestChainAndBlock()
for _, tr := range b.Transactions[1:] {
if !p.Set(tr, bc) {
t.FailNow()
}
}
nTxns := len(b.Transactions[1:]) + 12 // arbitrary.
txns := p.PopTxns(nTxns)
for _, tr := range txns {
if ok, _ := b.ContainsTransaction(tr); !ok {
t.FailNow()
}
}
if p.Len() != 0 {
t.FailNow()
}
}

func TestGetNewBlockEmpty(t *testing.T) {
p := New()
txns := p.PopTxns(305)
if len(txns) != 0 {
t.FailNow()
}
txn := p.Pop()
assert.Nil(t, txn)
}

func TestGetIndex(t *testing.T) {
Expand All @@ -111,3 +90,32 @@ func TestGetIndex(t *testing.T) {
}
}
}

func TestNextBlock(t *testing.T) {
p := New()
chain, _ := blockchain.NewValidTestChainAndBlock()
nBlks := len(chain.Blocks)
lastBlk := chain.Blocks[nBlks-1]
numTxns := 1000
for i := 0; i < numTxns; i++ {
p.SetUnsafe(blockchain.NewTestTransaction())
}
b := p.NextBlock(chain)
assert.NotNil(t, b)
assert.True(t, b.Len() < blockchain.BlockSize)
assert.True(t, b.Len() > 0)
assert.Equal(t, len(b.Transactions), numTxns-p.Len())
assert.Equal(t, blockchain.HashSum(lastBlk), b.LastBlock)
assert.Equal(t, uint64(0), b.Nonce)
assert.Equal(t, uint32(nBlks), b.BlockNumber)
}

func TestPeek(t *testing.T) {
p := New()
assert.Nil(t, p.Peek())
}

func TestPop(t *testing.T) {
p := New()
assert.Nil(t, p.Pop())
}

0 comments on commit eee77fb

Please sign in to comment.