Table of contents
Modifications
Visit commit refactor of mempool, to check modifications consist of,
- Modifications in Transaction pool data structure, optimised it
Block Encoder and Decoder
core/encoding.go
type GobBlockEncoder struct {
w io.Writer
}
func (e *GobBlockEncoder) Encode(b *Block) error {
return gob.NewEncoder(e.w).Encode(b)
}
func NewGobBlockEncoder(w io.Writer) *GobBlockEncoder {
return &GobBlockEncoder{
w : w,
}
}
type GobBlockDecoder struct {
r io.Reader
}
func NewGobBlockDecoder(r io.Reader) *GobBlockDecoder {
return &GobBlockDecoder{
r : r,
}
}
func (d *GobBlockDecoder) Decode(b *Block) error {
return gob.NewDecoder(d.r).Decode(b)
}
func init() {
gob.Register(elliptic.P256())
}
core/block_test.go
func TestEncodeDecodeBlock(t *testing.T){
b := randomBlock(t,0, types.Hash{})
buf := &bytes.Buffer{}
assert.Nil(t, NewGobBlockEncoder(buf).Encode(b))
decodedBlock := new(Block)
assert.Nil(t, NewGobBlockDecoder(buf).Decode(decodedBlock))
assert.Equal(t, b, decodedBlock)
}
Broadcasting blocks
These functions are part of a blockchain server implementation. They handle the processing of received messages, addition of blocks to the blockchain, and broadcasting of blocks to other nodes in the network. Additionally, the createNewBlock
function is responsible for generating and broadcasting new blocks based on pending transactions in the server's transaction pool
network/server.go
func (s *Server) ProcessMessage(msg *DecodedMessage) error {
switch t := msg.Data.(type) {
case *core.Transaction:
return s.processTransaction(t)
case *core.Block:
return s.processBlock(t)
}
return nil
}
func (s *Server)processBlock(b *core.Block) error {
if err := s.chain.AddBlock(b); err != nil {
return err
}
go s.broadcastBlock(b)
return nil
}
func (s *Server) broadcastBlock(b *core.Block) error {
buf := &bytes.Buffer{}
if err := core.NewGobBlockEncoder(buf).Encode(b); err != nil {
return err
}
msg := NewMessage(MessageTypeBlock, buf.Bytes())
return s.broadcast(msg.Bytes())
}
func (s *Server) createNewBlock() error {
// other code
s.mempool.ClearPending()
go s.broadcastBlock(block)
return nil
}
let's break down each function:
ProcessMessage
(onServer
):Processes decoded messages received by the server.
Switches on the type of the decoded message's data.
If it's a transaction, calls
processTransaction
.If it's a block, calls
processBlock
.
processBlock
(onServer
):Processes a received block by adding it to the blockchain (
s.chain.AddBlock(b)
).Concurrently broadcasts the block to other nodes in the network using
broadcastBlock
.
broadcastBlock
(onServer
):Encodes the provided block using a gob encoder and writes it to a buffer.
Creates a new message of type
MessageTypeBlock
with the encoded block data.Broadcasts the message to other nodes in the network using
broadcast
.
createNewBlock
(onServer
):Generates a new block using the server's transaction pool and blockchain.
Clears pending transactions from the server's transaction pool (
s.mempool.ClearPending()
).Concurrently broadcasts the newly created block to other nodes in the network using
broadcastBlock
.
Testing
To check broadcast transaction working fine, test it with
Still this can not handle syncing of blocks yet, we'll do it when it's needed.
make run
working fine!
The following blog post will explore the code related to Implementation of virtual machine
In this blog series, I'll be sharing code snippets related to blockchain architecture. While the code will be available on my GitHub, I want to highlight that the entire architecture isn't solely my own. I'm learning as I go, drawing inspiration and knowledge from various sources, including a helpful YouTube playlist that has contributed to my learning process.