/// <summary> /// Inform this Controller that the output pipeline send output data "to the wire". /// </summary> /// <param name="device">ExternalDevice that output the data</param> /// <param name="outputTime">Approximate time the data was sent to the wire</param> /// <param name="duration">Duration of the data block send to the wire</param> /// <param name="configuration">Pipeline node configuration(s) for the output pipeline that processed the outgoing data</param> public virtual void DidOutputData(IExternalDevice device, DateTimeOffset outputTime, TimeSpan duration, IEnumerable <IPipelineNodeConfiguration> configuration) { //virtual for Moq if (CurrentEpoch != null && !CurrentEpoch.IsComplete) { CurrentEpoch.DidOutputData(device, outputTime, duration, configuration); } }
/// <summary> /// Pulls IOutputData from the current Epoch destined for a given external deivce. /// Result will have duration greater than zero, but may not equal the requested duration. /// </summary> /// <param name="device">ExternalDevice for this outputdata</param> /// <param name="duration">Duration of the data requested</param> /// <returns>Output data for the requested device</returns> public virtual IOutputData PullOutputData(IExternalDevice device, TimeSpan duration) { if (CurrentEpoch == null) { return(null); } return(CurrentEpoch.PullOutputData(device, duration)); }
public void AddBlock(Block block, IEnumerable <Transaction> transactions, OracleReaderDelegate oracleReader) { /*if (CurrentEpoch != null && CurrentEpoch.IsSlashed(Timestamp.Now)) * { * return false; * }*/ if (LastBlock != null) { if (LastBlock.Height != block.Height - 1) { throw new BlockGenerationException($"height of block should be {LastBlock.Height + 1}"); } if (block.PreviousHash != LastBlock.Hash) { throw new BlockGenerationException($"previous hash should be {LastBlock.PreviousHash}"); } } var inputHashes = new HashSet <Hash>(transactions.Select(x => x.Hash)); foreach (var hash in block.TransactionHashes) { if (!inputHashes.Contains(hash)) { throw new BlockGenerationException($"missing in inputs transaction with hash {hash}"); } } var outputHashes = new HashSet <Hash>(block.TransactionHashes); foreach (var tx in transactions) { if (!outputHashes.Contains(tx.Hash)) { throw new BlockGenerationException($"missing in outputs transaction with hash {tx.Hash}"); } } foreach (var tx in transactions) { if (!tx.IsValid(this)) { throw new InvalidTransactionException(tx.Hash, $"invalid transaction with hash {tx.Hash}"); } } var changeSet = new StorageChangeSetContext(this.Storage); foreach (var tx in transactions) { byte[] result; if (tx.Execute(this, block, changeSet, block.Notify, oracleReader, out result)) { if (result != null) { block.SetResultForHash(tx.Hash, result); } } else { throw new InvalidTransactionException(tx.Hash, $"transaction execution failed with hash {tx.Hash}"); } } // from here on, the block is accepted _blockHeightMap[block.Height] = block; _blocks[block.Hash] = block; _blockChangeSets[block.Hash] = changeSet; changeSet.Execute(); if (CurrentEpoch == null) { GenerateEpoch(); } CurrentEpoch.AddBlockHash(block.Hash); CurrentEpoch.UpdateHash(); LastBlock = block; foreach (Transaction tx in transactions) { _transactions[tx.Hash] = tx; _transactionBlockMap[tx.Hash] = block.Hash; } Nexus.PluginTriggerBlock(this, block); }
public void AddBlock(Block block, IEnumerable <Transaction> transactions, OracleReaderDelegate oracleReader) { /*if (CurrentEpoch != null && CurrentEpoch.IsSlashed(Timestamp.Now)) * { * return false; * }*/ if (LastBlock != null) { if (LastBlock.Height != block.Height - 1) { throw new BlockGenerationException($"height of block should be {LastBlock.Height + 1}"); } if (block.PreviousHash != LastBlock.Hash) { throw new BlockGenerationException($"previous hash should be {LastBlock.PreviousHash}"); } } var inputHashes = new HashSet <Hash>(transactions.Select(x => x.Hash)); foreach (var hash in block.TransactionHashes) { if (!inputHashes.Contains(hash)) { throw new BlockGenerationException($"missing in inputs transaction with hash {hash}"); } } var outputHashes = new HashSet <Hash>(block.TransactionHashes); foreach (var tx in transactions) { if (!outputHashes.Contains(tx.Hash)) { throw new BlockGenerationException($"missing in outputs transaction with hash {tx.Hash}"); } } foreach (var tx in transactions) { if (!tx.IsValid(this)) { throw new InvalidTransactionException(tx.Hash, $"invalid transaction with hash {tx.Hash}"); } } var changeSet = new StorageChangeSetContext(this.Storage); foreach (var tx in transactions) { byte[] result; try { if (tx.Execute(this, block, changeSet, block.Notify, oracleReader, out result)) { if (result != null) { block.SetResultForHash(tx.Hash, result); } } else { throw new InvalidTransactionException(tx.Hash, $"execution failed"); } } catch (Exception e) { if (e.InnerException != null) { e = e.InnerException; } throw new InvalidTransactionException(tx.Hash, e.Message); } } // from here on, the block is accepted _blockHeightMap[block.Height] = block; _blocks[block.Hash] = block; _blockChangeSets[block.Hash] = changeSet; changeSet.Execute(); if (CurrentEpoch == null) { GenerateEpoch(); } CurrentEpoch.AddBlockHash(block.Hash); CurrentEpoch.UpdateHash(); Dictionary <string, BigInteger> synchMap = null; foreach (Transaction tx in transactions) { _transactions[tx.Hash] = tx; _transactionBlockMap[tx.Hash] = block.Hash; var evts = block.GetEventsForTransaction(tx.Hash); foreach (var evt in evts) { if (evt.Kind == EventKind.TokenMint || evt.Kind == EventKind.TokenBurn || evt.Kind == EventKind.TokenReceive || evt.Kind == EventKind.TokenSend) { if (synchMap == null) { synchMap = new Dictionary <string, BigInteger>(); var eventData = evt.GetContent <TokenEventData>(); var balance = synchMap.ContainsKey(eventData.symbol) ? synchMap[eventData.symbol] : 0; if (evt.Kind == EventKind.TokenBurn || evt.Kind == EventKind.TokenSend) { balance -= eventData.value; } else { balance += eventData.value; } synchMap[eventData.symbol] = balance; } } } } if (synchMap != null) { SynchronizeSupplies(synchMap); } Nexus.PluginTriggerBlock(this, block); }