public void TipShouldNotBecomeNewBlock() { block2 = _GenesisBlock.Child(); block3 = block2.Child(); Assert.That(HandleBlock(block3), Is.EqualTo(BlockVerificationHelper.BkResultEnum.AcceptedOrphan)); Assert.That(_BlockChain.Tip.Value.Equals(block1), Is.True); }
public new void OneTimeSetUp() { base.OneTimeSetUp(); block1 = _GenesisBlock.Child().AddTx(tx).Tag("block1"); block2 = _GenesisBlock.Child().AddTx(tx).Tag("block2"); block3 = block2.Child().Tag("block3"); }
Types.Block Child(Types.Block bk, int addHours) { var nonce = new byte[10]; new Random().NextBytes(nonce); //var nonce = new byte[] { }; var timestamp = DateTime.Now.ToUniversalTime().AddHours(addHours).Ticks; var header = new Types.BlockHeader( 0, Merkle.blockHeaderHasher.Invoke(bk.header), bk.header.blockNumber + 1, new byte[] { }, new byte[] { }, new byte[] { }, ListModule.OfSeq <byte[]>(new List <byte[]>()), timestamp, 0, nonce ); var txs = new List <Types.Transaction>(); txs.Add(Utils.GetTx()); return(new Types.Block(header, ListModule.OfSeq(txs))); }
void DispatchBlock() { try { _Hasher.Pause("dispatching block"); MinerTrace.Information($"dispatching block with {_ValidatedTxs.Count()} txs"); var txs = FSharpList <Types.Transaction> .Cons(_Coinbase, ListModule.OfSeq(_ValidatedTxs.Select(TransactionValidation.unpoint))); var block = new Types.Block(_Header, txs); var result = new HandleBlockAction(block).Publish().Result.BkResultEnum; if (result == BlockVerificationHelper.BkResultEnum.Accepted) { if (OnMined != null) { OnMined(block); } } else { Reset(); } MinerTrace.Information($" block {block.header.blockNumber} is " + result); } catch (Exception e) { MinerTrace.Error("Dispatch block exception", e); } }
/// <summary> /// Transmits a block on the network. /// </summary> public void Transmit(Types.Block bk) { if (_MinerBehavior != null) { _MinerBehavior.BroadcastBlock(bk); } }
public static Types.Block Child(this Types.Block bk) { var nonce = new byte[10]; new Random().NextBytes(nonce); //var nonce = new byte[] { }; var header = new Types.BlockHeader( 0, Merkle.blockHeaderHasher.Invoke(bk.header), bk.header.blockNumber + 1, new byte[] { }, new byte[] { }, new byte[] { }, ListModule.OfSeq <byte[]>(new List <byte[]>()), DateTime.Now.ToUniversalTime().Ticks, 0, nonce ); var txs = new List <Types.Transaction>(); txs.Add(Utils.GetCoinbaseTx(bk.header.blockNumber + 1)); return(new Types.Block(header, ListModule.OfSeq(txs))); }
public static Types.Block AddTx(this Types.Block bk, Types.Transaction tx) { //var nonce = new byte[10]; //new Random().NextBytes(nonce); var nonce = new byte[] { }; var header = new Types.BlockHeader( 0, new byte[] { }, bk.header.blockNumber + 1, new byte[] { }, new byte[] { }, new byte[] { }, ListModule.OfSeq <byte[]>(new List <byte[]>()), DateTime.Now.ToUniversalTime().Ticks, 0, nonce ); var txs = bk.transactions.ToList(); txs.Add(tx); return(new Types.Block(bk.header, ListModule.OfSeq <Types.Transaction>(txs))); }
public void Put( TransactionContext transactionContext, byte[] BkHash, Types.Block block, LocationEnum location, double totalWork) { var txs = block.transactions.Select(t => { return(new KeyValuePair <byte[], Types.Transaction>(Merkle.transactionHasher.Invoke(t), t)); }); Put(transactionContext, BkHash, new Block { BlockHeader = block.header, TxHashes = txs.Select(t => t.Key).ToList() }); //children var children = new HashSet <byte[]>(); children.Add(BkHash); transactionContext.Transaction.InsertHashSet <byte[], byte[]>( CHILDREN, block.header.parent, children, 0, false ); //location transactionContext.Transaction.Insert <byte[], int>(LOCATIONS, BkHash, (int)location); //total work transactionContext.Transaction.Insert <byte[], double>(TOTAL_WORK, BkHash, totalWork); //transactions var isFirstTx = true; foreach (var tx in txs) { if (!TxStore.ContainsKey(transactionContext, tx.Key)) { TxStore.Put(transactionContext, tx.Key, new Transaction { Tx = tx.Value, InMainChain = false }); if (isFirstTx) { transactionContext.Transaction.Insert <byte[], byte[]>(COINBASETX_BLOCK, tx.Key, BkHash); isFirstTx = false; } } } }
internal void OnBlockBroadcasted(Types.Block tx) { var evt = BlockBroadcasted; if (evt != null) { evt(tx); } }
internal void OnBlockRejected(Types.Block tx, RejectPayload reject) { var evt = BlockRejected; if (evt != null) { evt(tx, reject); } }
public void OneTimeSetUp() { Environment.CurrentDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); Dispose(); _GenesisBlock = Utils.GetGenesisBlock(); _BlockChain = new BlockChain.BlockChain(BLOCKCHAIN_DB, Merkle.blockHeaderHasher.Invoke(_GenesisBlock.header)); _WalletManager = new WalletManager(_BlockChain, WALLET_DB); }
public void TestCase() { Types.Block block = Util.GetBlock(null, 0); var data = Merkle.serialize <Types.Block>(block); Types.Block _block = Serialization.context.GetSerializer <Types.Block>().UnpackSingleObject(data); Assert.IsTrue(block.Equals(_block)); }
protected LocationEnum Location(Types.Block block) { #if DEBUG return(new GetBlockLocationAction { Block = Merkle.blockHeaderHasher.Invoke(block.header) }.Publish().Result); #else return(LocationEnum.Main); #endif }
void UndoBlock(Types.Block block, byte[] key) { BlockChainTrace.Information($"undoing block {block.header.blockNumber}", block); _BlockChain.BlockStore.SetLocation(_DbTx, key, LocationEnum.Branch); var blockUndoData = _BlockChain.BlockStore.GetUndoData(_DbTx, key); if (blockUndoData != null) { blockUndoData.AddedUTXO.ForEach(u => { BlockChainTrace.Information($"undo block {block.header.blockNumber}: utxo removed, amount {u.Item2.spend.amount}", block); _BlockChain.UTXOStore.Remove(_DbTx, u.Item1.txHash, u.Item1.index); }); blockUndoData.RemovedUTXO.ForEach(u => { BlockChainTrace.Information($"undo block {block.header.blockNumber}: new utxo, amount {u.Item2.spend.amount}", block); _BlockChain.UTXOStore.Put(_DbTx, u.Item1.txHash, u.Item1.index, u.Item2); }); foreach (var item in blockUndoData.ACSDeltas) { if (item.Value.LastBlock.HasValue) // restore last block - undo extend { var current = new ActiveContractSet().Get(_DbTx, item.Key); if (current != null) { current.Value.LastBlock = item.Value.LastBlock.Value; _BlockChain.ActiveContractSet.Add(_DbTx, current.Value); } else { BlockChainTrace.Error("missing ACS item!", new Exception()); } } else if (item.Value.ACSItem != null) // restore entire item - undo expire { _BlockChain.ActiveContractSet.Add(_DbTx, item.Value.ACSItem); } else // remove item - undo activate { _BlockChain.ActiveContractSet.Remove(_DbTx, item.Key); } } } block.transactions.ToList().ForEach(tx => { var txHash = Merkle.transactionHasher.Invoke(tx); UnconfirmedTxs[txHash] = tx; }); }
public void OneTimeSetUp() { Environment.CurrentDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); Dispose(); _TxMessagesListenerScope = MessageProducer <BlockChainMessage> .Instance.AddMessageListener( new MessageListener <BlockChainMessage>(OnBlockChainMessage)); _GenesisBlock = new GenesisBlock().Block; _GenesisBlockHash = Merkle.blockHeaderHasher.Invoke(_GenesisBlock.header); _BlockChain = new BlockChain(DB, _GenesisBlockHash); }
internal void OnBroadcastBlock(Types.Block block) { var nodes = Nodes .Select(n => n.Key.Behaviors.Find <MinerBehavior>()) .Where(n => n != null) .ToArray(); foreach (var node in nodes) { node.BroadcastBlockCore(block); } }
public static Types.Block GetBlock(Types.Block parent, Double difficulty) { UInt32 pdiff = Convert.ToUInt32(difficulty); byte[] parentKey = parent == null ? new byte[] {} : Merkle.blockHeaderHasher.Invoke(parent.header); Types.BlockHeader newBlockHeader = new Types.BlockHeader(1, parentKey, 0, new byte[] { }, new byte[] { }, new byte[] { }, ListModule.OfSeq(new List <byte[]>()), 0, pdiff, null); var transactions = new List <Types.Transaction>(); FSharpList <Types.Transaction> newBlockTransactions = ListModule.OfSeq(transactions); Types.Block newBlock = new Types.Block(newBlockHeader, newBlockTransactions); return(newBlock); }
//demo private byte[] GetHash(Types.Block block) { try { // if (block.Block != null) return(Merkle.blockHeaderHasher.Invoke(block.header)); // else // return Merkle.blockHasher.Invoke(block.Block); } catch (Exception e) { Console.WriteLine(e.Message); return(null); } }
public new void OneTimeSetUp() { base.OneTimeSetUp(); block1_tx = Utils.GetTx().AddOutput(Key.Create().Address, Consensus.Tests.zhash, 1).Tag("block1_tx"); block2_tx = Utils.GetTx().AddOutput(Key.Create().Address, Consensus.Tests.zhash, 1).Tag("block2_tx"); block3_tx = Utils.GetTx().AddOutput(Key.Create().Address, Consensus.Tests.zhash, 1).Tag("block3_tx"); block4_tx = Utils.GetTx().AddOutput(Key.Create().Address, Consensus.Tests.zhash, 1).Tag("block4_tx"); block5_tx = Utils.GetTx().AddOutput(Key.Create().Address, Consensus.Tests.zhash, 1).Tag("block5_tx"); block1 = _GenesisBlock.Child().AddTx(block1_tx).Tag("block1"); block2 = _GenesisBlock.Child().AddTx(block2_tx).Tag("block2"); block3 = block2.Child().AddTx(block3_tx).Tag("block3"); block4 = block1.Child().AddTx(block4_tx).Tag("block4"); block5 = block4.Child().AddTx(block5_tx).Tag("block5"); }
internal void BroadcastBlockCore(Types.Block block) { if (block == null) { throw new ArgumentNullException("block"); } var tx = new BlockBroadcast(); tx.Block = block; tx.State = BroadcastState.NotSent; var hash = GetHash(block); if (_HashToBlock.TryAdd(hash, tx)) { Announce(tx, hash); } }
public Keyed <Types.Block> GetBlock(TransactionContext transactionContext, byte[] key) { var _block = Get(transactionContext, key); if (_block == null) { BlockChainTrace.Information("Block not found: " + Convert.ToBase64String(key)); return(null); } else { var txs = _block.Value.TxHashes.Select(t => TxStore.Get(transactionContext, t).Value).ToList(); var block = new Types.Block(_block.Value.BlockHeader, ListModule.OfSeq <Types.Transaction>(txs.Select(t => t.Tx))); return(new Keyed <Types.Block>(key, block)); } }
public void Render() { if (Value != null) { return; } var parentKey = new byte[] { }; if (Parent != null) { Parent.Render(); parentKey = Parent.Value.Key; } uint version = 1; string date = "2000-02-02"; var blockHeader = new Types.BlockHeader( version, parentKey, 0, new byte[] { }, new byte[] { }, new byte[] { }, ListModule.OfSeq <byte[]>(new List <byte[]>()), DateTime.Parse(date).ToBinary(), 1, new byte[] { } ); //_TestTransactionPool.Render(); //var block = new Types.Block(blockHeader, ListModule.OfSeq<Types.Transaction>(_TestTransactionPool.Values.Select(t => t.Value.Value))); var block = new Types.Block(blockHeader, ListModule.OfSeq <Types.Transaction>(_Transactions)); // byte[] key = Merkle.blockHasher.Invoke(block); byte[] key = Merkle.blockHeaderHasher.Invoke(block.header); Value = new Keyed <Types.Block>(key, block); TestTrace.Transaction(Tag, key); }
/// <summary> /// Broadcast a block on the hub /// </summary> /// <param name="block">The block to broadcast</param> /// <returns>The cause of the rejection or null</returns> public Task <RejectPayload> BroadcastBlockAsync(Types.Block block) { if (block == null) { throw new ArgumentNullException("block"); } TaskCompletionSource <RejectPayload> completion = new TaskCompletionSource <RejectPayload>(); var hash = GetHash(block); if (BroadcastedBlock.TryAdd(hash, block)) { BlockBroadcastedDelegate broadcasted = null; BlockRejectedDelegate rejected = null; broadcasted = (t) => { if (GetHash(t) == hash) { completion.SetResult(null); BlockRejected -= rejected; BlockBroadcasted -= broadcasted; } }; BlockBroadcasted += broadcasted; rejected = (t, r) => { if (r.Hash == hash) { completion.SetResult(r); BlockRejected -= rejected; BlockBroadcasted -= broadcasted; } }; BlockRejected += rejected; OnBroadcastBlock(block); } return(completion.Task); }
public GenesisBlock() { Keys = new Key[10]; CoinbaseKey = Key.Create(); for (int i = 0; i < 10; i++) { Keys[i] = Key.Create(); } var nonce = new byte[10]; new Random().NextBytes(nonce); var header = new Types.BlockHeader( 0, new byte[] { }, 0, new byte[] { }, new byte[] { }, new byte[] { }, ListModule.OfSeq <byte[]>(new List <byte[]>()), DateTime.Now.ToUniversalTime().Ticks, 0, nonce ); var txs = new List <Types.Transaction>(); txs.Add(Utils.GetCoinbaseTx(0)); for (int i = 0; i < 10; i++) { txs.Add(Utils.GetTx().AddOutput(Keys[i].Address, Consensus.Tests.zhash, (ulong)i * 1111)); } Block = new Types.Block(header, ListModule.OfSeq(txs)); }
private Tuple <bool, IList <string> > TryUploadBlock(int index, string minedBy, string data, string previousHash, int nonce, string hash) { var lastBlock = _repository.TryGetLastBlock(); if (lastBlock == null) { throw new ApplicationException("No blocks in blockchain"); } Types.Block block = new Types.Block( index, minedBy, data, previousHash, nonce); var blockWithHash = new Types.BlockWithHash(block, hash); var isValidBlock = Miner.isValidBlock(blockWithHash, DtoHelpers.DtoToBlock(lastBlock)); if (isValidBlock.IsInvalid) { var invalid = isValidBlock as Types.IsValidBlock.Invalid; var errors = invalid.Item.ToList(); return(Tuple.Create <bool, IList <string> >(false, errors)); } _repository.Save(DtoHelpers.BlockToDto(blockWithHash)); return(Tuple.Create <bool, IList <string> >(true, new List <string>())); }
public BlockVerificationHelper( BlockChain blockChain, TransactionContext dbTx, byte[] bkHash, Types.Block bk, bool handleOrphan = false, bool handleBranch = false, HashDictionary <TransactionValidation.PointedTransaction> confirmedTxs = null, HashDictionary <Types.Transaction> invalidatedTxs = null, List <QueueAction> queuedActions = null ) { ConfirmedTxs = confirmedTxs ?? new HashDictionary <TransactionValidation.PointedTransaction>(); UnconfirmedTxs = invalidatedTxs ?? new HashDictionary <Types.Transaction>(); //todo: refactor to set as new obj by default QueueActions = queuedActions ?? new List <QueueAction>(); _BlockChain = blockChain; _DbTx = dbTx; _BkHash = bkHash; _Bk = bk; if (!IsValid()) { BlockChainTrace.Information($"block {_Bk.header.blockNumber} is invalid", _Bk); Result = new BkResult(BkResultEnum.Rejected); return; } if (IsInStore()) { var reject = false; byte[] missingParent = null; var location = blockChain.BlockStore.GetLocation(dbTx, bkHash); switch (location) { case LocationEnum.Branch: reject = !handleBranch; break; case LocationEnum.Orphans: missingParent = GetMissingParent(); reject = !handleOrphan && !handleBranch; break; default: reject = true; break; } if (reject) { BlockChainTrace.Information($"Block {_Bk.header.blockNumber} already in store ({location})", bk); Result = new BkResult(BkResultEnum.Rejected, missingParent); return; } } if (bk.transactions.Count() == 0) { BlockChainTrace.Information("empty tx list", bk); Result = new BkResult(BkResultEnum.Rejected); return; } if (!IsValidTime()) { BlockChainTrace.Information("invalid time", bk); Result = new BkResult(BkResultEnum.Rejected); return; } //TODO: /* * 3. Transaction list must be non - empty * 4. Block hash must satisfy claimed nBits proof of work * 5. Block timestamp must not be more than two hours in the future * 6. First transaction must be coinbase, the rest must not be * 7. For each transaction, apply "tx" checks 2 - 4 * 8. (omitted) * 9. (omitted) * 10. Verify Merkle hash */ if (IsGenesis()) { if (!IsGenesisValid()) { BlockChainTrace.Information("invalid genesis block", bk); Result = new BkResult(BkResultEnum.Rejected); return; } else { blockChain.Timestamps.Init(bk.header.timestamp); ExtendMain(QueueActions, 0, true); Result = new BkResult(BkResultEnum.Accepted); BlockChainTrace.Information("accepted genesis block", bk); return; } } if (IsOrphan()) { var missingParent = GetMissingParent(); blockChain.BlockStore.Put(dbTx, bkHash, bk, LocationEnum.Orphans, 0); BlockChainTrace.Information($"block {_Bk.header.blockNumber} added as orphan", bk); Result = new BkResult(BkResultEnum.AcceptedOrphan, missingParent); return; } //12. Check that nBits value matches the difficulty rules if (!IsValidDifficulty() || !IsValidBlockNumber() || !IsValidTimeStamp()) { BlockChainTrace.Information($"block {_Bk.header.blockNumber} rejected", bk); Result = new BkResult(BkResultEnum.Rejected); return; } //14. For certain old blocks(i.e.on initial block download) check that hash matches known values var totalWork = TotalWork(); UtxoLookup = _BlockChain.UtxoLookupFactory(_DbTx, true); if (handleBranch) // make a branch block main { if (!ExtendMain(QueueActions, totalWork)) { Result = new BkResult(BkResultEnum.Rejected); return; } } else if (!IsNewGreatestWork(totalWork)) { blockChain.BlockStore.Put(dbTx, bkHash, bk, LocationEnum.Branch, totalWork); } else if (blockChain.BlockStore.IsLocation(dbTx, bk.header.parent, LocationEnum.Main)) { if (!ExtendMain(QueueActions, totalWork)) { BlockChainTrace.Information($"block {_Bk.header.blockNumber} rejected", bk); Result = new BkResult(BkResultEnum.Rejected); return; } } else { BlockChainTrace.Information($"block {bk.header.blockNumber} extends a branch with new difficulty", bk); Reorg(); } BlockChainTrace.Information($"block {bk.header.blockNumber} accepted", bk); Result = new BkResult(BkResultEnum.Accepted); }
public HandleBlockAction(Types.Block bk) { BkHash = Merkle.blockHeaderHasher.Invoke(bk.header); Bk = bk; IsOrphan = false; }
public HandleBlockAction(byte[] bkHash, Types.Block bk, bool isOrphan) { BkHash = bkHash; Bk = bk; IsOrphan = isOrphan; }
public void TipShouldBeOfNewBlock() { block1 = _GenesisBlock.Child(); Assert.That(HandleBlock(block1), Is.EqualTo(BlockVerificationHelper.BkResultEnum.Accepted)); Assert.That(_BlockChain.Tip.Value, Is.EqualTo(block1)); }
public static Types.Block Tag(this Types.Block block, string value) { BlockChainTrace.SetTag(block, value); return(block); }