Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Utxocache #1

Draft
wants to merge 24 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
fafa61d
Assert that we are building for little-endian
Ultra-Code Oct 27, 2022
ba03ca7
Use Type aliases inplace of primative types
Ultra-Code Oct 27, 2022
de43fd3
Organize Exit codes
Ultra-Code Oct 28, 2022
afaa417
Fix flag changes not getting commited when using named dbs
Ultra-Code Jan 6, 2023
5e1cb9d
Update submodules
Ultra-Code Jan 6, 2023
857d584
Update build.zig to use zig's new api
Ultra-Code Feb 8, 2023
693bbac
feat(s2s): add s2s as a zig package
Ultra-Code May 7, 2023
59261dd
Overhaul of Lmdb, Blockchain module
Ultra-Code May 7, 2023
dd776d9
Use default upstream lmdb
Ultra-Code May 7, 2023
4a61250
Use UTXOcache in Cli and update Iterator to improved Lmdb API
Ultra-Code May 7, 2023
f3c874e
Use zig's updated crypto and memcpy api
Ultra-Code May 7, 2023
0a573b6
Initial LmdbCursor implementation for cursor operations
Ultra-Code May 7, 2023
e8937fc
fix: zig breaking change update
Ultra-Code Jul 5, 2023
f220b9b
follow up to breaking change fixes
Ultra-Code Jul 5, 2023
e970974
fix(dupsort): improve dupsort error detection
Ultra-Code Jul 8, 2023
062a0c4
lmdb: add compress and decompress fns
Ultra-Code Jul 8, 2023
2a0c536
lmdb: fix deadlock caused by starting two .rw transactions
Ultra-Code Jul 15, 2023
3a8d23a
Lmdb: follow up on lmdb api changes
Ultra-Code Jul 15, 2023
3cde8e3
fix build.zig for zig 0.11.0
Ultra-Code Aug 19, 2023
068681e
update s2s
Ultra-Code Aug 22, 2023
e0446be
catch key exist error on put in update fn
Ultra-Code Aug 22, 2023
d3bb980
Update s2s after upstream incooperated my changes
Ultra-Code Aug 27, 2023
a6e1acb
Fix type hash mismatch in update fn
Ultra-Code Aug 27, 2023
237ae34
Improve signature of sendValue fn
Ultra-Code Aug 28, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
[submodule "deps/s2s"]
path = deps/s2s
url = https://github.com/Ultra-Code/s2s
[submodule "deps/lmdb"]
path = deps/lmdb
url = [email protected]:LMDB/lmdb.git
75 changes: 43 additions & 32 deletions build.zig
Original file line number Diff line number Diff line change
@@ -1,50 +1,59 @@
const std = @import("std");
const builtin = @import("builtin");
const Pkg = std.build.Pkg;
const pkgs = struct {
const s2s = Pkg{
.name = "s2s",
.source = .{ .path = "./deps/s2s/s2s.zig" },
.dependencies = &[_]Pkg{},
};
};
const LMDB_PATH = "./deps/lmdb/libraries/liblmdb/";
const Build = std.Build;

pub fn build(b: *std.build.Builder) void {
// Standard target options allows the person running `zig build` to choose
comptime {
//Big endian systems not currently supported
std.debug.assert(builtin.target.cpu.arch.endian() == .Little);
}

pub fn build(b: *Build) void {
const s2s_module = b.dependency("s2s", .{}).module("s2s");

const LMDB_PATH = "./deps/lmdb/libraries/liblmdb/";
// what target to build for. Here we do not override the defaults, which
// means any target is allowed, and the default is native. Other options
// for restricting supported target set are available.
const target = b.standardTargetOptions(.{});

// Standard release options allow the person running `zig build` to select
// between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall.
const mode = b.standardReleaseOptions();
const optimize = b.standardOptimizeOption(.{});

//Add lmdb library for embeded key/value store
const cflags = [_][]const u8{ "-pthread", "-std=c2x" };
const lmdb_sources = [_][]const u8{ LMDB_PATH ++ "mdb.c", LMDB_PATH ++ "midl.c" };
const lmdb = b.addStaticLibrary("lmdb", null);
lmdb.setTarget(target);
lmdb.setBuildMode(mode);
const lmdb = b.addStaticLibrary(.{
.name = "lmdb",
.target = target,
.optimize = optimize,
});
lmdb.addCSourceFiles(&lmdb_sources, &cflags);
lmdb.linkLibC();
lmdb.install();
b.installArtifact(lmdb);

const target_name = target.allocDescription(b.allocator) catch unreachable;
const exe_name = std.fmt.allocPrint(b.allocator, "{[program]s}-{[target]s}", .{ .program = "recblock", .target = target_name }) catch unreachable;
const exe_name = std.fmt.allocPrint(b.allocator, "{[program]s}-{[target]s}", .{
.program = "recblock",
.target = target_name,
}) catch unreachable;

const exe = b.addExecutable(exe_name, "src/main.zig");
exe.setTarget(target);
exe.setBuildMode(mode);
exe.addPackage(pkgs.s2s);
const exe = b.addExecutable(.{
.name = exe_name,
.root_source_file = .{
.path = "src/main.zig",
},
.target = target,
.optimize = optimize,
});
exe.addModule("s2s", s2s_module);
exe.linkLibrary(lmdb);
exe.addIncludePath(LMDB_PATH);
exe.install();
exe.addIncludePath(.{ .path = LMDB_PATH });
b.installArtifact(exe);
exe.stack_size = 1024 * 1024 * 64;

switch (mode) {
.Debug => {},
else => {
switch (optimize) {
.ReleaseFast => {
lmdb.link_function_sections = true;
lmdb.red_zone = true;
lmdb.want_lto = true;
Expand All @@ -59,8 +68,9 @@ pub fn build(b: *std.build.Builder) void {
exe.strip = true;
}
},
else => {},
}
const run_cmd = exe.run();
const run_cmd = b.addRunArtifact(exe);
run_cmd.step.dependOn(b.getInstallStep());
if (b.args) |args| {
run_cmd.addArgs(args);
Expand All @@ -70,12 +80,13 @@ pub fn build(b: *std.build.Builder) void {
run_step.dependOn(&lmdb.step);
run_step.dependOn(&run_cmd.step);

const exe_tests = b.addTest("src/main.zig");
exe_tests.setTarget(target);
exe_tests.setBuildMode(mode);
exe_tests.addPackage(pkgs.s2s);
const exe_tests = b.addTest(.{
.root_source_file = .{ .path = "src/main.zig" },
.target = target,
});
exe_tests.addModule("s2s", s2s_module);
exe_tests.linkLibrary(lmdb);
exe_tests.addIncludePath(LMDB_PATH);
exe_tests.addIncludePath(.{ .path = LMDB_PATH });

const test_step = b.step("test", "Run unit tests");
test_step.dependOn(&lmdb.step);
Expand Down
10 changes: 10 additions & 0 deletions build.zig.zon
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
.{
.name = "recblock",
.version = "0.1.0",
.dependencies = .{
.s2s = .{
.url = "https://github.com/ziglibs/s2s/archive/f1d0508cc47b2af353658d4e52616a45aafa91ce.tar.gz",
.hash = "1220206c698a1890d742a8b98acb16db99275d16f2e7fe2046c3d8f2249ed267ca71",
},
},
}
2 changes: 1 addition & 1 deletion deps/lmdb
Submodule lmdb updated 1 files
+97 −69 libraries/liblmdb/mdb.c
1 change: 0 additions & 1 deletion deps/s2s
Submodule s2s deleted from b58025
33 changes: 17 additions & 16 deletions src/Block.zig
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@ const std = @import("std");
const fmt = std.fmt;
const mem = std.mem;
const Blake3 = std.crypto.hash.Blake3;
const Hash = [Blake3.digest_length]u8;
const testing = std.testing;

const Block = @This();
const Transaction = @import("Transaction.zig");

//TARGET_ZERO_BITS must be a multiple of 4 and it determines the number of zeros in the target hash which determines difficult
//The higer TARGET_ZERO_BITS the harder or time consuming it is to find a hash
//The higher the TARGET_ZERO_BITS the harder or time consuming it is to find a hash
//NOTE: when we define a target adjusting algorithm this won't be a global constant anymore
//it specifies the target hash which is used to check hashes which are valid
//a block is only accepted by the network if its hash meets the network's difficulty target
Expand All @@ -20,16 +21,16 @@ timestamp: i64,
//Thus miners must discover by brute force the "nonce" that, when included in the block, results in an acceptable hash.
nonce: usize = 0,
//stores the hash of the previous block
previous_hash: [32]u8,
previous_hash: Hash,
//hash of the current block
hash: [32]u8 = undefined,
hash: Hash = undefined,
//the actual valuable information contained in the block .eg Transactions
transactions: std.ArrayListUnmanaged(Transaction),
//difficulty bits is the block header storing the difficulty at which the block was mined
difficulty_bits: u7 = TARGET_ZERO_BITS, //u7 limit value from 0 to 127 since we can't have a difficult equal in bitsize to the hashsize which is 256
difficulty_bits: u7 = TARGET_ZERO_BITS, //u7 limit value from 0 to 127 since we can't have a difficult equal in bitsize to the hashsize which is 255

///mine a new block
pub fn newBlock(arena: std.mem.Allocator, previous_hash: [32]u8, transactions: []const Transaction) Block {
pub fn newBlock(arena: std.mem.Allocator, previous_hash: Hash, transactions: []const Transaction) Block {
var new_block = Block{
.timestamp = std.time.timestamp(),
.transactions = std.ArrayListUnmanaged(Transaction){},
Expand All @@ -43,7 +44,7 @@ pub fn newBlock(arena: std.mem.Allocator, previous_hash: [32]u8, transactions: [
}

pub fn genesisBlock(arena: std.mem.Allocator, coinbase: Transaction) Block {
return newBlock(arena, .{'\x00'} ** 32, &.{coinbase});
return newBlock(arena, std.mem.zeroes(Hash), &.{coinbase});
}

///Validate POW
Expand All @@ -58,17 +59,17 @@ pub fn validate(block: Block) bool {

fn hashBlock(self: Block, nonce: usize) u256 {
//TODO : optimize the sizes of these buffers base on the base and use exactly the amount that is needed
var time_buf: [16]u8 = undefined;
var time_buf: [8]u8 = undefined;
var bits_buf: [3]u8 = undefined;
var nonce_buf: [16]u8 = undefined;
var nonce_buf: [8]u8 = undefined;

const timestamp = fmt.bufPrintIntToSlice(&time_buf, self.timestamp, 16, .lower, .{});
const difficulty_bits = fmt.bufPrintIntToSlice(&bits_buf, self.difficulty_bits, 16, .lower, .{});
const nonce_val = fmt.bufPrintIntToSlice(&nonce_buf, nonce, 16, .lower, .{});

var buf: [4096]u8 = undefined;

//timestamp ,previous_hash and hash form the BlockHeader
//timestamp ,previous_hash and hash from the BlockHeader
const block_headers = fmt.bufPrint(&buf, "{[previous_hash]s}{[transactions]s}{[timestamp]s}{[difficulty_bits]s}{[nonce]s}", .{
.previous_hash = self.previous_hash,
.transactions = self.hashTxs(),
Expand All @@ -77,7 +78,7 @@ fn hashBlock(self: Block, nonce: usize) u256 {
.nonce = nonce_val,
}) catch unreachable;

var hash: [Blake3.digest_length]u8 = undefined;
var hash: Hash = undefined;
Blake3.hash(block_headers, &hash, .{});

const hash_int = mem.bytesToValue(u256, hash[0..]);
Expand All @@ -89,14 +90,14 @@ fn getTargetHash(target_dificulty: u7) u256 {
//hast to be compaired with for valid hashes to prove work done
const @"256bit": u9 = 256; //256 bit is 32 byte which is the size of a Blake3 hash
const @"1": u256 = 1; //a 32 byte integer with the value of 1
const difficult = @intCast(u8, @"256bit" - target_dificulty);
const target_hash_difficult = @shlExact(@"1", difficult);
const difficult: u8 = @intCast(@"256bit" - target_dificulty);
const target_hash_difficult: u256 = @shlExact(@"1", difficult);
return target_hash_difficult;
}

///Proof of Work mining algorithm
///The usize returned is the nonce with which a valid block was mined
pub fn POW(block: Block) struct { hash: [32]u8, nonce: usize } {
pub fn POW(block: Block) struct { hash: Hash, nonce: usize } {
const target_hash = getTargetHash(block.difficulty_bits);

var nonce: usize = 0;
Expand All @@ -105,15 +106,15 @@ pub fn POW(block: Block) struct { hash: [32]u8, nonce: usize } {
const hash_int = block.hashBlock(nonce);

if (hash_int < target_hash) {
return .{ .hash = @bitCast([32]u8, hash_int), .nonce = nonce };
return .{ .hash = @bitCast(hash_int), .nonce = nonce };
} else {
nonce += 1;
}
}
unreachable;
}

fn hashTxs(self: Block) [32]u8 {
fn hashTxs(self: Block) Hash {
var txhashes: []u8 = &.{};

var buf: [2048]u8 = undefined;
Expand All @@ -124,7 +125,7 @@ fn hashTxs(self: Block) [32]u8 {
txhashes = std.mem.concat(allocator, u8, &[_][]const u8{ txhashes, txn.id[0..] }) catch unreachable;
}

var hash: [Blake3.digest_length]u8 = undefined;
var hash: Hash = undefined;
Blake3.hash(txhashes, &hash, .{});
return hash;
}
Expand Down
Loading