go-blockchain, v1.4
Posted on

The library that implements models and algorithms of blockchain.
Add merging the blockchain model with another one.
Change Log
- models:
- blockchain:
- operations:
- merging with another blockchain:
- selecting a fork based on a maximal total difficulty;
- with automatic deleting orphan blocks;
- merging with another blockchain:
- operations:
- blockchain:
- storages:
- operations:
- creation from a block group;
- operations:
- additionally:
- return nil instead empty array from
loaders.MemoryLoader.LoadBlocks()method; - copy the loaded blocks in the
storages.MemoryStorage.LoadBlocks()method; - fix the unit tests:
- add the missed tests without blocks;
- add the tests with checking pointers for the
storages.MemoryStorage.LoadBlocks()method;
- examples:
- add the example with merging the blockchain model with another one.
- return nil instead empty array from
Features
- models:
- block data:
- operations:
- conversion to a string;
- comparison for equality with another block data;
- wrappers:
- wrapper that adds support for the following operations to those block data that cannot do them:
- conversion to a string:
- implementation of the
fmt.Stringerinterface; - implementation of the
encoding.TextMarshalerinterface;
- implementation of the
- comparison for equality with another block data;
- conversion to a string:
- wrapper that adds support for the following operations to those block data that cannot do them:
- operations:
- block:
- storing:
- timestamp;
- block data;
- hash;
- previous hash;
- operations:
- creation (using a proofer);
- getting merged data;
- comparison for equality with another block;
- self-validation (using a proofer);
- storing:
- genesis block:
- based on a usual block without a previous hash;
- block group:
- storing:
- group of blocks;
- operations:
- self-validation (using a proofer):
- modes:
- as a full blockchain;
- as a blockchain chunk;
- takes into account a prepended chunk;
- allows empty block groups;
- modes:
- validation of the last block (using a proofer):
- modes:
- as a full blockchain;
- as a blockchain chunk;
- modes:
- search of differences between two block groups:
- returns lengths of different prefixes of the compared block groups;
- based on a hash table index;
- calculating a total difficulty of blocks;
- self-validation (using a proofer):
- storing:
- block group loaders:
- loading block groups via the external interface;
- automatically saving the loaded block groups to a storage;
- search of differences between two block group loaders:
- loads and compares only one block chunk from every block group loader;
- wrappers:
- chunk validating loader:
- automatically validates the loaded block group as a blockchain chunk;
- last block validating loader:
- automatically validates the last block from the loaded block group;
- automatically preloads the next block group to perform the above validation;
- memoizing loader:
- remembers loaded block groups;
- restricts the quantity of the remembered block groups:
- stores the loaded block groups in the LRU cache;
- chunk validating loader:
- kinds:
- memory loader:
- loading blocks from the block group;
- memory loader:
- blockchain:
- storing:
- storage;
- last block;
- operations:
- creation:
- loading the last block from the storage;
- when the storage is empty (optional):
- creation a genesis block using a proofer;
- storing the genesis block to the storage;
- loading block groups from the storage;
- adding a block:
- creation a block using a proofer;
- storing the block to the storage;
- merging with another blockchain:
- selecting a fork based on a maximal total difficulty;
- with automatic deleting orphan blocks;
- creation:
- storing:
- block data:
- proofers:
- operations:
- block hashing;
- block difficulty calculating;
- block validation;
- kinds:
- proof of work:
- based on the Hashcash algorithm;
- additional storing in a block (in a hash actually):
- nonce;
- target bit;
- difficulty is defined as an inverse target bit;
- proof of work:
- operations:
- storages:
- operations:
- creation from a block group;
- loading block groups;
- loading the last block;
- storing a block;
- storing a block group (optional);
- deleting a block;
- deleting a block group (optional);
- wrappers:
- wrapper that adds support for the following operations to those storages that cannot do them:
- storing a block group;
- deleting a block group;
- wrapper that adds support for the following operations to those storages that cannot do them:
- kinds:
- memory storage:
- storing blocks in memory.
- memory storage:
- operations:
Examples
blockchain.Blockchain.Merge():
package main
import (
"encoding/json"
"fmt"
"log"
"time"
blockchain "github.com/thewizardplusplus/go-blockchain"
"github.com/thewizardplusplus/go-blockchain/proofers"
"github.com/thewizardplusplus/go-blockchain/storing"
"github.com/thewizardplusplus/go-blockchain/storing/storages"
)
func main() {
timestamp := time.Date(2006, time.January, 2, 15, 4, 5, 0, time.UTC)
blockGroupOne := blockchain.BlockGroup{
{
Timestamp: timestamp.Add(2*time.Hour + 40*time.Minute),
Data: blockchain.NewData("block #1.2"),
Hash: "250:0:hash #3.2",
PrevHash: "23:0:hash #3.1",
},
{
Timestamp: timestamp.Add(2*time.Hour + 20*time.Minute),
Data: blockchain.NewData("block #1.1"),
Hash: "250:0:hash #3.1",
PrevHash: "23:0:hash #2",
},
{
Timestamp: timestamp.Add(time.Hour),
Data: blockchain.NewData("block #0"),
Hash: "23:0:hash #2",
PrevHash: "23:0:hash #1",
},
{
Timestamp: timestamp,
Data: blockchain.NewData("genesis block"),
Hash: "23:0:hash #1",
PrevHash: "",
},
}
blockchainInstanceOne, err :=
blockchain.NewBlockchain(nil, blockchain.Dependencies{
BlockDependencies: blockchain.BlockDependencies{
Proofer: proofers.ProofOfWork{TargetBit: 248},
},
Storage: storing.NewGroupStorage(storages.NewMemoryStorage(blockGroupOne)),
})
if err != nil {
log.Fatalf("unable to create the blockchain #1: %v", err)
}
blockGroupTwo := blockchain.BlockGroup{
{
Timestamp: timestamp.Add(2 * time.Hour),
Data: blockchain.NewData("block #1"),
Hash: "23:0:hash #3",
PrevHash: "23:0:hash #2",
},
{
Timestamp: timestamp.Add(time.Hour),
Data: blockchain.NewData("block #0"),
Hash: "23:0:hash #2",
PrevHash: "23:0:hash #1",
},
{
Timestamp: timestamp,
Data: blockchain.NewData("genesis block"),
Hash: "23:0:hash #1",
PrevHash: "",
},
}
blockchainInstanceTwo, err :=
blockchain.NewBlockchain(nil, blockchain.Dependencies{
BlockDependencies: blockchain.BlockDependencies{
Proofer: proofers.ProofOfWork{TargetBit: 248},
},
Storage: storing.NewGroupStorage(storages.NewMemoryStorage(blockGroupTwo)),
})
if err != nil {
log.Fatalf("unable to create the blockchain #2: %v", err)
}
if err := blockchainInstanceOne.Merge(blockchainInstanceTwo, 3); err != nil {
log.Fatalf("unable to merge the blockchains: %v", err)
}
mergedBlocks, _, _ := blockchainInstanceOne.LoadBlocks(nil, 10)
blocksBytes, _ := json.MarshalIndent(mergedBlocks, "", " ")
fmt.Println(string(blocksBytes))
// Output:
// [
// {
// "Timestamp": "2006-01-02T17:04:05Z",
// "Data": "block #1",
// "Hash": "23:0:hash #3",
// "PrevHash": "23:0:hash #2"
// },
// {
// "Timestamp": "2006-01-02T16:04:05Z",
// "Data": "block #0",
// "Hash": "23:0:hash #2",
// "PrevHash": "23:0:hash #1"
// },
// {
// "Timestamp": "2006-01-02T15:04:05Z",
// "Data": "genesis block",
// "Hash": "23:0:hash #1",
// "PrevHash": ""
// }
// ]
}
Repository
Link: https://github.com/thewizardplusplus/go-blockchain/tree/v1.4.0.
Content: code.
License: MIT.