Creating a Blockchain: Part 9 - Broadcast blocks

Creating a Blockchain: Part 9 - Broadcast blocks


Visit commit refactor of mempool, to check modifications consist of,

  • Modifications in Transaction pool data structure, optimised it

Block Encoder and Decoder


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() {


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


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
    go s.broadcastBlock(block)

    return nil

let's break down each function:

  1. 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.

  2. 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.

  3. 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.

  4. 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.


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.

Did you find this article valuable?

Support Siddharth Patel by becoming a sponsor. Any amount is appreciated!