public static Block Create(BlockHeader header, ImmutableArray<DecodedTx> transactions) { var blockTxes = ImmutableArray.CreateRange(transactions.Select((tx, txIndex) => new BlockTx(txIndex, tx))); return new Block(header, blockTxes); }
public ChainedHeader(BlockHeader blockHeader, int height, BigInteger totalWork, DateTimeOffset dateSeen) { BlockHeader = blockHeader; Height = height; TotalWork = totalWork; DateSeen = dateSeen; }
public Block With(BlockHeader Header = null, ImmutableArray<BlockTx>? BlockTxes = null) { return new Block ( Header ?? this.Header, BlockTxes ?? this.BlockTxes ); }
public Block With(BlockHeader Header = null, ImmutableArray<Transaction>? Transactions = null) { return new Block ( Header ?? this.Header, Transactions ?? this.Transactions ); }
public static ChainedHeader CreateForGenesisBlock(BlockHeader genesisBlockHeader) { return new ChainedHeader ( blockHeader: genesisBlockHeader, height: 0, totalWork: genesisBlockHeader.CalculateWork() ); }
public static void EncodeBlockHeader(BinaryWriter writer, BlockHeader blockHeader) { writer.WriteUInt32(blockHeader.Version); writer.WriteUInt256(blockHeader.PreviousBlock); writer.WriteUInt256(blockHeader.MerkleRoot); writer.WriteUInt32((uint)blockHeader.Time.ToUnixTimeSeconds()); writer.WriteUInt32(blockHeader.Bits); writer.WriteUInt32(blockHeader.Nonce); }
public static byte[] EncodeBlockHeader(BlockHeader blockHeader) { using (var stream = new MemoryStream()) using (var writer = new BinaryWriter(stream)) { EncodeBlockHeader(writer, blockHeader); return stream.ToArray(); } }
public static ChainedHeader CreateFromPrev(ChainedHeader prevChainedHeader, BlockHeader blockHeader, DateTimeOffset dateSeen) { var headerWork = blockHeader.CalculateWork(); return new ChainedHeader(blockHeader, prevChainedHeader.Height + 1, prevChainedHeader.TotalWork + headerWork.ToBigInteger(), dateSeen); }
public Block(BlockHeader header, ImmutableArray<BlockTx> blockTxes) { Header = header; BlockTxes = blockTxes; lazyTransactions = new Lazy<ImmutableArray<Transaction>>(() => ImmutableArray.CreateRange(blockTxes.Select(x => x.Decode().Transaction))); }
public static ChainedHeader CreateFromPrev(ChainedHeader prevChainedHeader, BlockHeader blockHeader) { var headerWork = blockHeader.CalculateWork(); if (headerWork < 0) return null; return new ChainedHeader(blockHeader, prevChainedHeader.Height + 1, prevChainedHeader.TotalWork + headerWork); }
public static ChainedHeader CreateForGenesisBlock(BlockHeader genesisBlockHeader) { return new ChainedHeader ( blockHeader: genesisBlockHeader, height: 0, totalWork: genesisBlockHeader.CalculateWork().ToBigInteger(), dateSeen: DateTimeOffset.MinValue ); }
public static UInt256 CalculateWork(BlockHeader blockHeader) { bool negative, overflow; var target = FromCompact(blockHeader.Bits, out negative, out overflow); if (negative || overflow || target == UInt256.Zero) return UInt256.Zero; return new UInt256(_2Pow256 / (target.ToBigInteger() + 1)); }
public BlockHeader MineBlockHeader(BlockHeader blockHeader, UInt256 hashTarget) { var blockHeaderBytes = DataEncoder.EncodeBlockHeader(blockHeader); var hashTargetBytes = hashTarget.ToByteArray(); var start = 0; var finish = UInt32.MaxValue; var total = 0L; var nonceIndex = 76; var minedNonce = (UInt32?)null; logger.Debug($"Starting mining: {DateTime.Now:hh':'mm':'ss}"); var stopwatch = Stopwatch.StartNew(); Parallel.For( start, finish, () => new LocalMinerState(blockHeaderBytes), (nonceLong, loopState, localState) => { localState.total++; var nonce = (UInt32)nonceLong; var nonceBytes = Bits.GetBytes(nonce); Buffer.BlockCopy(nonceBytes, 0, localState.headerBytes, nonceIndex, 4); var headerBytes = localState.headerBytes; var hashBytes = SHA256Static.ComputeDoubleHash(headerBytes); if (BytesCompareLE(hashBytes, hashTargetBytes) < 0) { minedNonce = nonce; loopState.Stop(); } return localState; }, localState => { Interlocked.Add(ref total, localState.total); }); stopwatch.Stop(); var hashRate = ((float)total / 1000 / 1000) / ((float)stopwatch.ElapsedMilliseconds / 1000); if (minedNonce != null) { logger.Debug($"Found block in {stopwatch.Elapsed:hh':'mm':'ss} hh:mm:ss at Nonce {minedNonce}, Hash Rate: {hashRate} mHash/s, Total Hash Attempts: {total:N0}, Found Hash: {blockHeader.With(Nonce: minedNonce).Hash}"); return blockHeader.With(Nonce: minedNonce); } else { logger.Debug($"No block found in {stopwatch.Elapsed:hh':'mm':'ss} hh:mm:ss, Hash Rate: {hashRate} mHash/s, Total Hash Attempts: {total:N0}, Found Hash: {blockHeader.With(Nonce: minedNonce).Hash}"); return null; } }
public static BigInteger CalculateWork(BlockHeader blockHeader) { try { return Max256BitTarget / (BigInteger)BitsToTarget(blockHeader.Bits); } catch (Exception) { Debug.WriteLine($"Corrupt block header bits: {blockHeader:X}, block {blockHeader.Hash}"); return -1; } }
public ChainedHeader GenesisChained() { if (this.blockHeaders.Count > 0) throw new InvalidOperationException(); var blockHeader = new BlockHeader(0, UInt256.Zero, UInt256.Zero, 0, this.bits, this.nonce); this.totalWork = blockHeader.CalculateWork(); var chainedHeader = new ChainedHeader(blockHeader, 0, this.totalWork); this.blockHeaders.Add(chainedHeader); return chainedHeader; }
public BlockHeader MineBlockHeader(BlockHeader blockHeader, UInt256 hashTarget) { var blockHeaderBytes = DataEncoder.EncodeBlockHeader(blockHeader); var hashTargetBytes = hashTarget.ToByteArray(); var start = 0; var finish = UInt32.MaxValue; var total = 0L; var nonceIndex = 76; var minedNonce = (UInt32?)null; var stopwatch = Stopwatch.StartNew(); Parallel.For( start, finish, () => new LocalMinerState(blockHeaderBytes), (nonceLong, loopState, localState) => { localState.total++; var nonce = (UInt32)nonceLong; var nonceBytes = Bits.GetBytes(nonce); Buffer.BlockCopy(nonceBytes, 0, localState.headerBytes, nonceIndex, 4); var headerBytes = localState.headerBytes; var hashBytes = SHA256Static.ComputeDoubleHash(headerBytes); if (BytesCompareLE(hashBytes, hashTargetBytes) < 0) { minedNonce = nonce; loopState.Stop(); } return localState; }, localState => { Interlocked.Add(ref total, localState.total); }); stopwatch.Stop(); var hashRate = total / stopwatch.Elapsed.TotalSeconds; if (minedNonce == null) throw new InvalidOperationException(); var minedHeader = blockHeader.With(Nonce: minedNonce); logger.Debug($"Found block in {stopwatch.Elapsed.TotalMilliseconds:N3}ms at Nonce {minedNonce}, Hash Rate: {hashRate / 1.MILLION()} mHash/s, Total Hash Attempts: {total:N0}, Found Hash: {minedHeader.Hash}"); return minedHeader; }
public Block CreateWith(BlockHeader Header = null, ImmutableArray<Transaction>? Transactions = null) { if (Transactions == null) { return new Block ( Header ?? this.Header, this.BlockTxes ); } else { return Create(Header ?? this.Header, Transactions.Value); } }
public void TestCalculateBlockHash() { var expectedHash = UInt256.ParseHex("000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f"); var blockHeader = new BlockHeader ( version: 1, previousBlock: UInt256.Zero, merkleRoot: UInt256.ParseHex("4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"), time: 1231006505, bits: 0x1D00FFFF, nonce: 2083236893 ); Assert.AreEqual(expectedHash, DataCalculator.CalculateBlockHash(blockHeader)); Assert.AreEqual(expectedHash, DataCalculator.CalculateBlockHash(blockHeader.Version, blockHeader.PreviousBlock, blockHeader.MerkleRoot, blockHeader.Time, blockHeader.Bits, blockHeader.Nonce)); }
private bool TryChainHeader(BlockHeader blockHeader, out ChainedHeader chainedHeader, bool suppressEvent) { if (TryGetChainedHeader(blockHeader.Hash, out chainedHeader)) { return false; } else { ChainedHeader previousChainedHeader; if (TryGetChainedHeader(blockHeader.PreviousBlock, out previousChainedHeader)) { chainedHeader = ChainedHeader.CreateFromPrev(previousChainedHeader, blockHeader, DateTimeOffset.Now); if (chainedHeader == null) return false; lock (cachedHeaders) if (this.blockStorage.Value.TryAddChainedHeader(chainedHeader)) { this.cachedHeaders.Value[chainedHeader.Hash] = chainedHeader; if (!suppressEvent) ChainedHeaderAdded?.Invoke(chainedHeader); return true; } else { logger.Warn("Unexpected condition: validly chained header could not be added"); } } } chainedHeader = default(ChainedHeader); return false; }
public ChainedHeader NextChained(UInt32? bits = null) { if (this.blockHeaders.Count == 0) throw new InvalidOperationException(); var prevBlockHeader = this.blockHeaders.Last(); var blockHeader = new BlockHeader(0, prevBlockHeader.Hash, UInt256.Zero, 0, bits ?? this.bits, this.nonce); this.totalWork += blockHeader.CalculateWork(); var chainedHeader = new ChainedHeader(blockHeader, this.blockHeaders.Count, this.totalWork); this.blockHeaders.Add(chainedHeader); return chainedHeader; }
public Block(BlockHeader header, ImmutableArray<Transaction> transactions) { Header = header; Transactions = transactions; }
public ChainedHeader(BlockHeader blockHeader, int height, BigInteger totalWork) { BlockHeader = blockHeader; Height = height; TotalWork = totalWork; }
public bool TryChainHeader(BlockHeader blockHeader, out ChainedHeader chainedHeader) { return TryChainHeader(blockHeader, out chainedHeader, suppressEvent: false); }
public static UInt256 CalculateBlockHash(BlockHeader blockHeader) { return new UInt256(SHA256Static.ComputeDoubleHash(DataEncoder.EncodeBlockHeader(blockHeader))); }