diff --git a/src/NeoSharp.Application/Controllers/PromptBlockchainController.cs b/src/NeoSharp.Application/Controllers/PromptBlockchainController.cs index f8dc3424..5c047212 100644 --- a/src/NeoSharp.Application/Controllers/PromptBlockchainController.cs +++ b/src/NeoSharp.Application/Controllers/PromptBlockchainController.cs @@ -17,6 +17,9 @@ public class PromptBlockchainController : IPromptController private readonly IBlockPool _blockPool; private readonly ITransactionPool _transactionPool; private readonly IBlockchain _blockchain; + private readonly IBlockModel _blockModel; + private readonly ITransactionModel _transactionModel; + private readonly IAssetModel _assetModel; private readonly IBlockchainContext _blockchainContext; private readonly IConsoleWriter _consoleWriter; private readonly IConsoleReader _consoleReader; @@ -27,6 +30,9 @@ public class PromptBlockchainController : IPromptController /// Constructor /// /// Blockchain + /// The Block Model. + /// + /// /// The block chain context class. /// Block pool /// Transaction Pool @@ -34,6 +40,9 @@ public class PromptBlockchainController : IPromptController /// Console reader public PromptBlockchainController( IBlockchain blockchain, + IBlockModel blockModel, + ITransactionModel transactionModel, + IAssetModel assetModel, IBlockchainContext blockchainContext, IBlockPool blockPool, ITransactionPool transactionPool, @@ -41,6 +50,9 @@ public class PromptBlockchainController : IPromptController IConsoleReader consoleReader) { _blockchain = blockchain; + _blockModel = blockModel; + _transactionModel = transactionModel; + _assetModel = assetModel; _blockchainContext = blockchainContext; _blockPool = blockPool; _transactionPool = transactionPool; @@ -107,7 +119,7 @@ public void StateCommand() [PromptCommand("header", Category = "Blockchain", Help = "Get header by index or by hash")] public async Task HeaderCommand(uint blockIndex, PromptOutputStyle output = PromptOutputStyle.json) { - _consoleWriter.WriteObject(await _blockchain?.GetBlockHeader(blockIndex), output); + _consoleWriter.WriteObject(await this._blockModel.GetBlockHeader(blockIndex), output); } /// @@ -118,7 +130,7 @@ public async Task HeaderCommand(uint blockIndex, PromptOutputStyle output = Prom [PromptCommand("header", Category = "Blockchain", Help = "Get header by index or by hash")] public async Task HeaderCommand(UInt256 blockHash, PromptOutputStyle output = PromptOutputStyle.json) { - _consoleWriter.WriteObject(await _blockchain?.GetBlockHeader(blockHash), output); + _consoleWriter.WriteObject(await this._blockModel.GetBlockHeader(blockHash), output); } /// @@ -129,7 +141,7 @@ public async Task HeaderCommand(UInt256 blockHash, PromptOutputStyle output = Pr [PromptCommand("block", Category = "Blockchain", Help = "Get block by index or by hash")] public async Task BlockCommand(uint blockIndex, PromptOutputStyle output = PromptOutputStyle.json) { - _consoleWriter.WriteObject(await _blockchain?.GetBlock(blockIndex), output); + _consoleWriter.WriteObject(await this._blockModel.GetBlock(blockIndex), output); } /// @@ -140,7 +152,7 @@ public async Task BlockCommand(uint blockIndex, PromptOutputStyle output = Promp [PromptCommand("block", Category = "Blockchain", Help = "Get block by index or by hash")] public async Task BlockCommand(UInt256 blockHash, PromptOutputStyle output = PromptOutputStyle.json) { - _consoleWriter.WriteObject(await _blockchain?.GetBlock(blockHash), output); + _consoleWriter.WriteObject(await this._blockModel.GetBlock(blockHash), output); } /// @@ -151,7 +163,7 @@ public async Task BlockCommand(UInt256 blockHash, PromptOutputStyle output = Pro [PromptCommand("tx", Category = "Blockchain", Help = "Get tx")] public async Task TxCommand(UInt256 hash, PromptOutputStyle output = PromptOutputStyle.json) { - _consoleWriter.WriteObject(await _blockchain?.GetTransaction(hash), output); + _consoleWriter.WriteObject(await this._transactionModel.GetTransaction(hash), output); } /// @@ -163,7 +175,7 @@ public async Task TxCommand(UInt256 hash, PromptOutputStyle output = PromptOutpu [PromptCommand("tx", Category = "Blockchain", Help = "Get tx by block num/tx number")] public async Task TxCommand(uint blockIndex, ushort txNumber, PromptOutputStyle output = PromptOutputStyle.json) { - var block = await _blockchain.GetBlock(blockIndex); + var block = await this._blockModel.GetBlock(blockIndex); _consoleWriter.WriteObject(block.Transactions?[txNumber], output); } @@ -175,7 +187,7 @@ public async Task TxCommand(uint blockIndex, ushort txNumber, PromptOutputStyle [PromptCommand("asset", Category = "Blockchain", Help = "Get asset", Order = 0)] public async Task AssetCommand(UInt256 hash, PromptOutputStyle output = PromptOutputStyle.json) { - _consoleWriter.WriteObject(await _blockchain?.GetAsset(hash), output); + _consoleWriter.WriteObject(await this._assetModel.GetAsset(hash), output); } /// @@ -187,7 +199,7 @@ public async Task AssetCommand(UInt256 hash, PromptOutputStyle output = PromptOu [PromptCommand("asset", Category = "Blockchain", Help = "Get asset", Order = 1)] public async Task AssetCommand(string query, EnumerableExtensions.QueryMode mode = EnumerableExtensions.QueryMode.Contains, PromptOutputStyle output = PromptOutputStyle.json) { - var assets = await _blockchain?.GetAssets(); + var assets = await this._assetModel.GetAssets(); var result = assets.QueryResult(query, mode).ToArray(); _consoleWriter.WriteObject(result, output); diff --git a/src/NeoSharp.Core/Blockchain/AssetModel.cs b/src/NeoSharp.Core/Blockchain/AssetModel.cs new file mode 100644 index 00000000..e93054a7 --- /dev/null +++ b/src/NeoSharp.Core/Blockchain/AssetModel.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using NeoSharp.Core.Models; +using NeoSharp.Core.Persistence; +using NeoSharp.Core.Types; + +namespace NeoSharp.Core.Blockchain +{ + public class AssetModel : IAssetModel + { + #region Private Fields + private readonly IRepository _repository; + #endregion + + #region Constructor + public AssetModel(IRepository repository) + { + this._repository = repository; + } + #endregion + + #region IAssetModel implementation + + /// + public Task GetAsset(UInt256 hash) + { + return this._repository.GetAsset(hash); + } + + /// + public Task> GetAssets() + { + throw new NotImplementedException(); + } + #endregion + } +} \ No newline at end of file diff --git a/src/NeoSharp.Core/Blockchain/BlockModel.cs b/src/NeoSharp.Core/Blockchain/BlockModel.cs new file mode 100644 index 00000000..221a25da --- /dev/null +++ b/src/NeoSharp.Core/Blockchain/BlockModel.cs @@ -0,0 +1,133 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using NeoSharp.Core.Models; +using NeoSharp.Core.Persistence; +using NeoSharp.Core.Types; +using Org.BouncyCastle.Crypto.Digests; + +namespace NeoSharp.Core.Blockchain +{ + public class BlockModel : IBlockModel + { + #region Private Fields + private readonly IRepository _repository; + private readonly ITransactionModel _transactionModel; + #endregion + + #region Constructor + public BlockModel(IRepository repository, ITransactionModel transactionModel) + { + this._repository = repository; + _transactionModel = transactionModel; + } + #endregion + + #region IBlocksModel implementation + /// + public async Task GetBlock(uint height) + { + var hash = await this.GetBlockHash(height); + + return hash == null ? null : await GetBlock(hash); + } + + /// + public async Task GetBlock(UInt256 hash) + { + var header = await this._repository.GetBlockHeader(hash); + + if (header == null || header.Type != HeaderType.Extended) return null; + + var transactions = new Transaction[header.TransactionCount]; + + for (int x = 0, m = header.TransactionCount; x < m; x++) + { + transactions[x] = await this._transactionModel.GetTransaction(header.TransactionHashes[x]); + } + + header.Hash = hash; + + return header.GetBlock(transactions); + } + + /// + public async Task> GetBlocks(IReadOnlyCollection blockHashes) + { + var blocks = new List(); + + foreach (var hash in blockHashes) + { + var block = await this.GetBlock(hash); + + if (block == null) continue; + + blocks.Add(block); + } + + return blocks; + } + + /// + public async Task GetBlockHash(uint height) + { + return await this._repository.GetBlockHashFromHeight(height); + } + + /// + public async Task GetNextBlock(UInt256 hash) + { + var header = await this._repository.GetBlockHeader(hash); + + if (header != null) + { + return await this.GetBlock(header.Index + 1); + } + + return null; + } + + /// + public async Task GetNextBlockHash(UInt256 hash) + { + var header = await this._repository.GetBlockHeader(hash); + + if (header != null) + { + return await this._repository.GetBlockHashFromHeight(header.Index + 1); + } + + return UInt256.Zero; + } + + /// + public async Task GetSysFeeAmount(uint height) + { + return GetSysFeeAmount(await GetBlockHash(height)); + } + + /// + public long GetSysFeeAmount(UInt256 hash) + { + return 0; + } + + /// + public async Task GetBlockHeader(uint height) + { + var hash = await this._repository.GetBlockHashFromHeight(height); + + if (hash != null) return await this.GetBlockHeader(hash); + return null; + } + + /// + public async Task GetBlockHeader(UInt256 hash) + { + var header = await this._repository.GetBlockHeader(hash); + + if (header != null) header.Hash = hash; + return header; + } + #endregion + } +} \ No newline at end of file diff --git a/src/NeoSharp.Core/Blockchain/Blockchain.cs b/src/NeoSharp.Core/Blockchain/Blockchain.cs index 1ae60def..f2ee81ea 100644 --- a/src/NeoSharp.Core/Blockchain/Blockchain.cs +++ b/src/NeoSharp.Core/Blockchain/Blockchain.cs @@ -20,6 +20,7 @@ public class Blockchain : IBlockchain, IDisposable private readonly IBlockProcessor _blockProcessor; private readonly IBlockchainContext _blockchainContext; private readonly IGenesis _genesis; + private readonly IBlockModel _blockModel; private int _initialized; private readonly List _validators = new List(); @@ -33,18 +34,21 @@ public class Blockchain : IBlockchain, IDisposable /// Block Processor /// Block chain context class. /// Genesis block generator. + /// The block model. public Blockchain( IRepository repository, IBlockHeaderPersister blockHeaderPersister, IBlockProcessor blockProcessor, IBlockchainContext blockchainContext, - IGenesis genesis) + IGenesis genesis, + IBlockModel blockModel) { _repository = repository ?? throw new ArgumentNullException(nameof(repository)); _blockHeaderPersister = blockHeaderPersister ?? throw new ArgumentNullException(nameof(blockHeaderPersister)); _blockProcessor = blockProcessor ?? throw new ArgumentNullException(nameof(blockProcessor)); _blockchainContext = blockchainContext ?? throw new ArgumentNullException(nameof(blockchainContext)); _genesis = genesis ?? throw new ArgumentNullException(nameof(genesis)); + _blockModel = blockModel; _blockHeaderPersister.OnBlockHeadersPersisted += (_, blockHeaders) => this._blockchainContext.LastBlockHeader = blockHeaders.Last(); _blockProcessor.OnBlockProcessed += (_, block) => this._blockchainContext.CurrentBlock = block; @@ -60,8 +64,8 @@ public async Task InitializeBlockchain() var blockHeight = await _repository.GetTotalBlockHeight(); var blockHeaderHeight = await _repository.GetTotalBlockHeaderHeight(); - this._blockchainContext.CurrentBlock = await GetBlock(blockHeight); - this._blockchainContext.LastBlockHeader = await GetBlockHeader(blockHeaderHeight); + this._blockchainContext.CurrentBlock = await this._blockModel.GetBlock(blockHeight); + this._blockchainContext.LastBlockHeader = await this._blockModel.GetBlockHeader(blockHeaderHeight); this._blockHeaderPersister.LastBlockHeader = this._blockchainContext.LastBlockHeader; @@ -74,114 +78,115 @@ public async Task InitializeBlockchain() #region Blocks - /// - public async Task GetBlock(uint height) - { - var hash = await GetBlockHash(height); + ///// + //public async Task GetBlock(uint height) + //{ + // var hash = await GetBlockHash(height); - return hash == null ? null : await GetBlock(hash); - } + // return hash == null ? null : await GetBlock(hash); + //} - /// - public async Task GetBlock(UInt256 hash) - { - var header = await _repository.GetBlockHeader(hash); + ///// + //public async Task GetBlock(UInt256 hash) + //{ + // var header = await _repository.GetBlockHeader(hash); - if (header == null || header.Type != HeaderType.Extended) return null; + // if (header == null || header.Type != HeaderType.Extended) return null; - var transactions = new Transaction[header.TransactionCount]; + // var transactions = new Transaction[header.TransactionCount]; - for (int x = 0, m = header.TransactionCount; x < m; x++) - { - transactions[x] = await _repository.GetTransaction(header.TransactionHashes[x]); - } + // for (int x = 0, m = header.TransactionCount; x < m; x++) + // { + // transactions[x] = await _repository.GetTransaction(header.TransactionHashes[x]); + // } - header.Hash = hash; + // header.Hash = hash; - return header.GetBlock(transactions); - } + // return header.GetBlock(transactions); + //} - public async Task> GetBlocks(IReadOnlyCollection blockHashes) - { - var blocks = new List(); + //public async Task> GetBlocks(IReadOnlyCollection blockHashes) + //{ + // var blocks = new List(); - foreach (var hash in blockHashes) - { - var block = await GetBlock(hash); + // foreach (var hash in blockHashes) + // { + // var block = await GetBlock(hash); - if (block == null) continue; + // if (block == null) continue; - blocks.Add(block); - } + // blocks.Add(block); + // } - return blocks; - } + // return blocks; + //} - /// - public async Task GetBlockHash(uint height) - { - return await _repository.GetBlockHashFromHeight(height); - } + ///// + //public async Task GetBlockHash(uint height) + //{ + // return await _repository.GetBlockHashFromHeight(height); + //} - /// - public async Task GetNextBlock(UInt256 hash) - { - var header = await _repository.GetBlockHeader(hash); + ///// + //public async Task GetNextBlock(UInt256 hash) + //{ + // var header = await _repository.GetBlockHeader(hash); - if (header != null) - { - return await GetBlock(header.Index + 1); - } + // if (header != null) + // { + // return await GetBlock(header.Index + 1); + // } - return null; - } + // return null; + //} - /// - public async Task GetNextBlockHash(UInt256 hash) - { - var header = await _repository.GetBlockHeader(hash); + ///// + //public async Task GetNextBlockHash(UInt256 hash) + //{ + // var header = await _repository.GetBlockHeader(hash); - if (header != null) - { - return await _repository.GetBlockHashFromHeight(header.Index + 1); - } + // if (header != null) + // { + // return await _repository.GetBlockHashFromHeight(header.Index + 1); + // } - return UInt256.Zero; - } + // return UInt256.Zero; + //} #endregion #region BlockHeaders - /// - public async Task GetBlockHeader(uint height) - { - var hash = await _repository.GetBlockHashFromHeight(height); + ///// + //public async Task GetBlockHeader(uint height) + //{ + // var hash = await _repository.GetBlockHashFromHeight(height); - if (hash != null) return await GetBlockHeader(hash); + // if (hash != null) return await GetBlockHeader(hash); - return null; - } + // return null; + //} - /// - public async Task GetBlockHeader(UInt256 hash) - { - var header = await _repository.GetBlockHeader(hash); + ///// + //public async Task GetBlockHeader(UInt256 hash) + //{ + // var header = await _repository.GetBlockHeader(hash); - if (header != null) header.Hash = hash; + // if (header != null) header.Hash = hash; - return header; - } + // return header; + //} #endregion #region Transactions /// - public async Task GetTransaction(UInt256 hash) - { - return await _repository.GetTransaction(hash); - } + //[Obsolete] + //public async Task GetTransaction(UInt256 hash) + //{ + // return await _repository.GetTransaction(hash); + //} // TODO #390 [AboimPinto] Async methods cannot have out parameters. Method not used for now. ///// @@ -193,20 +198,21 @@ public async Task GetTransaction(UInt256 hash) // return await _repository.GetTransaction(hash); //} - public async Task> GetTransactions(IReadOnlyCollection transactionHashes) - { - var transactions = new List(); + //[Obsolete] + //public async Task> GetTransactions(IReadOnlyCollection transactionHashes) + //{ + // var transactions = new List(); - foreach (var hash in transactionHashes) - { - var tx = await GetTransaction(hash); + // foreach (var hash in transactionHashes) + // { + // var tx = await GetTransaction(hash); - if (tx == null) continue; - transactions.Add(tx); - } + // if (tx == null) continue; + // transactions.Add(tx); + // } - return transactions; - } + // return transactions; + //} /// public async Task ContainsTransaction(UInt256 hash) @@ -244,16 +250,17 @@ public Task GetContract(UInt160 hash) } /// - public Task GetAsset(UInt256 hash) - { - return _repository.GetAsset(hash); - } + //[Obsolete] + //public Task GetAsset(UInt256 hash) + //{ + // return _repository.GetAsset(hash); + //} - /// - public Task> GetAssets() - { - throw new NotImplementedException(); - } + ///// + //public Task> GetAssets() + //{ + // throw new NotImplementedException(); + //} /// public Task> GetContracts() @@ -288,70 +295,71 @@ public virtual IEnumerable GetValidators(IEnumerable other yield break; } - /// - public virtual async Task GetSysFeeAmount(uint height) - { - return GetSysFeeAmount(await GetBlockHash(height)); - } + ///// + //public virtual async Task GetSysFeeAmount(uint height) + //{ + // return GetSysFeeAmount(await GetBlockHash(height)); + //} - /// - public long GetSysFeeAmount(UInt256 hash) - { - return 0; - } + ///// + //public long GetSysFeeAmount(UInt256 hash) + //{ + // return 0; + //} - /// - public TransactionOutput GetUnspent(UInt256 hash, ushort index) - { - var states = _repository.GetCoinStates(hash).Result; + ///// + //public TransactionOutput GetUnspent(UInt256 hash, ushort index) + //{ + // var states = _repository.GetCoinStates(hash).Result; - if (states == null || index >= states.Length || states[index].HasFlag(CoinState.Spent)) - { - return null; - } + // if (states == null || index >= states.Length || states[index].HasFlag(CoinState.Spent)) + // { + // return null; + // } - return GetTransaction(hash).Result.Outputs[index]; - } + // return GetTransaction(hash).Result.Outputs[index]; + //} - public IEnumerable GetUnspent(UInt256 hash) - { - var outputs = new List(); + //public IEnumerable GetUnspent(UInt256 hash) + //{ + // var outputs = new List(); - var states = _repository.GetCoinStates(hash).Result; - if (states != null) - { - var tx = GetTransaction(hash).Result; - for (var i = 0; i < states.Length; i++) - { - if (!states[i].HasFlag(CoinState.Spent)) - { - outputs.Add(tx.Outputs[i]); - } - } - } - return outputs; - } + // var states = _repository.GetCoinStates(hash).Result; + // if (states != null) + // { + // var tx = GetTransaction(hash).Result; + // for (var i = 0; i < states.Length; i++) + // { + // if (!states[i].HasFlag(CoinState.Spent)) + // { + // outputs.Add(tx.Outputs[i]); + // } + // } + // } + // return outputs; + //} /// - public bool IsDoubleSpend(Transaction tx) - { - if (tx.Inputs.Length == 0) - { - return false; - } - - foreach (var group in tx.Inputs.GroupBy(p => p.PrevHash)) - { - var states = _repository.GetCoinStates(group.Key).Result; - - if (states == null || group.Any(p => p.PrevIndex >= states.Length || states[p.PrevIndex].HasFlag(CoinState.Spent))) - { - return true; - } - } + //[Obsolete] + //public bool IsDoubleSpend(Transaction tx) + //{ + // if (tx.Inputs.Length == 0) + // { + // return false; + // } + + // foreach (var group in tx.Inputs.GroupBy(p => p.PrevHash)) + // { + // var states = _repository.GetCoinStates(group.Key).Result; + + // if (states == null || group.Any(p => p.PrevIndex >= states.Length || states[p.PrevIndex].HasFlag(CoinState.Spent))) + // { + // return true; + // } + // } - return false; - } + // return false; + //} /// public void Dispose() diff --git a/src/NeoSharp.Core/Blockchain/Genesis.cs b/src/NeoSharp.Core/Blockchain/Genesis.cs index f7ad9ab1..242231f9 100644 --- a/src/NeoSharp.Core/Blockchain/Genesis.cs +++ b/src/NeoSharp.Core/Blockchain/Genesis.cs @@ -30,28 +30,26 @@ public Genesis(IGenesisAssets genesisAssets, IBlockOperationsManager blockOperat var nextConsensusAddress = genesisAssets.GetGenesisNextConsensusAddress(); - //var nextConsensusAddress = GenesisAssets.GetGenesisNextConsensusAddress(); - - //GenesisBlock = new Block - //{ - // PreviousBlockHash = UInt256.Zero, - // Timestamp = genesisTimestamp, - // Index = 0, - // ConsensusData = genesisConsensusData, - // NextConsensus = nextConsensusAddress, - // Witness = genesisWitness, - // Transactions = new Transaction[] - // { - // //First transaction is always a miner transaction - // genesisMinerTransaction, - // //Creates NEO - // governingToken, - // //Creates GAS - // utilityToken, - // //Send all NEO to seed contract - // genesisIssueTransaction - // } - //}; + GenesisBlock = new Block + { + PreviousBlockHash = UInt256.Zero, + Timestamp = genesisTimestamp, + Index = 0, + ConsensusData = genesisConsensusData, + NextConsensus = nextConsensusAddress, + Witness = genesisWitness, + Transactions = new Transaction[] + { + //First transaction is always a miner transaction + genesisMinerTransaction, + //Creates NEO + governingToken, + //Creates GAS + utilityToken, + //Send all NEO to seed contract + genesisIssueTransaction + } + }; blockOperationsManager.Sign(GenesisBlock); } diff --git a/src/NeoSharp.Core/Blockchain/IAssetModel.cs b/src/NeoSharp.Core/Blockchain/IAssetModel.cs new file mode 100644 index 00000000..7cbe96b0 --- /dev/null +++ b/src/NeoSharp.Core/Blockchain/IAssetModel.cs @@ -0,0 +1,23 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using NeoSharp.Core.Models; +using NeoSharp.Core.Types; + +namespace NeoSharp.Core.Blockchain +{ + public interface IAssetModel + { + /// + /// Return the corresponding asset information according to the specified hash + /// + /// The asset hash. + /// The corresponding asset. + Task GetAsset(UInt256 hash); + + /// + /// Return all assets + /// + /// List of all assets. + Task> GetAssets(); + } +} diff --git a/src/NeoSharp.Core/Blockchain/IBlockModel.cs b/src/NeoSharp.Core/Blockchain/IBlockModel.cs new file mode 100644 index 00000000..696a59e0 --- /dev/null +++ b/src/NeoSharp.Core/Blockchain/IBlockModel.cs @@ -0,0 +1,80 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using NeoSharp.Core.Models; +using NeoSharp.Core.Types; + +namespace NeoSharp.Core.Blockchain +{ + public interface IBlockModel + { + /// + /// Return the corresponding block information according to the specified height + /// + /// The height of the blockchain. + /// Block + Task GetBlock(uint height); + + /// + /// Return the corresponding block information according to the specified height + /// + /// + /// Block + Task GetBlock(UInt256 hash); + + /// + /// Get blocks + /// + /// Block hashes + /// List of Blocks + Task> GetBlocks(IReadOnlyCollection blockHashes); + + /// + /// Returns the hash of the corresponding block based on the specified height + /// + /// The height of the blockchain. + /// + Task GetBlockHash(uint height); + + /// + /// Returns the information for the next block based on the specified hash value + /// + /// Block hash. + /// Block + Task GetNextBlock(UInt256 hash); + + /// + /// Returns the hash value of the next block based on the specified hash value + /// + /// + /// + Task GetNextBlockHash(UInt256 hash); + + /// + /// Returns the total amount of system costs contained in the corresponding block and all previous blocks based on the specified block height + /// + /// + /// + Task GetSysFeeAmount(uint height); + + /// + /// Returns the total amount of system charges contained in the corresponding block and all previous blocks based on the specified block hash value + /// + /// + /// + long GetSysFeeAmount(UInt256 hash); + + /// + /// Return the corresponding block header information according to the specified height + /// + /// + /// + Task GetBlockHeader(uint height); + + /// + /// Returns the corresponding block header information according to the specified hash value + /// + /// + /// + Task GetBlockHeader(UInt256 hash); + } +} diff --git a/src/NeoSharp.Core/Blockchain/IBlockchain.cs b/src/NeoSharp.Core/Blockchain/IBlockchain.cs index 51270a5f..52507bfb 100644 --- a/src/NeoSharp.Core/Blockchain/IBlockchain.cs +++ b/src/NeoSharp.Core/Blockchain/IBlockchain.cs @@ -27,61 +27,61 @@ public interface IBlockchain ///// //BlockHeader LastBlockHeader { get; } - /// - /// Return the corresponding block information according to the specified height - /// - /// - /// - Task GetBlock(uint height); + ///// + ///// Return the corresponding block information according to the specified height + ///// + ///// + ///// + //Task GetBlock(uint height); - /// - /// Return the corresponding block information according to the specified height - /// - /// - /// - Task GetBlock(UInt256 hash); + ///// + ///// Return the corresponding block information according to the specified height + ///// + ///// + ///// + //Task GetBlock(UInt256 hash); - /// - /// Get blocks - /// - /// Block hashes - /// Block - Task> GetBlocks(IReadOnlyCollection blockHashes); + ///// Task GetNextBlock(UInt256 hash) + ///// Get blocks + ///// + ///// Block hashes + ///// Block + //Task> GetBlocks(IReadOnlyCollection blockHashes); - /// - /// Returns the hash of the corresponding block based on the specified height - /// - /// - /// - Task GetBlockHash(uint height); + ///// + ///// Returns the hash of the corresponding block based on the specified height + ///// + ///// + ///// + //Task GetBlockHash(uint height); - /// - /// Return the corresponding block header information according to the specified height - /// - /// - /// - Task GetBlockHeader(uint height); + ///// + ///// Return the corresponding block header information according to the specified height + ///// + ///// + ///// + //Task GetBlockHeader(uint height); - /// - /// Returns the corresponding block header information according to the specified hash value - /// - /// - /// - Task GetBlockHeader(UInt256 hash); + ///// + ///// Returns the corresponding block header information according to the specified hash value + ///// + ///// + ///// + //Task GetBlockHeader(UInt256 hash); - /// - /// Returns the information for the next block based on the specified hash value - /// - /// - /// - Task GetNextBlock(UInt256 hash); + ///// + ///// Returns the information for the next block based on the specified hash value + ///// + ///// + ///// + //Task GetNextBlock(UInt256 hash); - /// - /// Returns the hash value of the next block based on the specified hash value - /// - /// - /// - Task GetNextBlockHash(UInt256 hash); + ///// + ///// Returns the hash value of the next block based on the specified hash value + ///// + ///// + ///// + //Task GetNextBlockHash(UInt256 hash); #endregion @@ -100,12 +100,12 @@ public interface IBlockchain bool ContainsUnspent(UInt256 hash, ushort index); - /// - /// Return the corresponding asset information according to the specified hash - /// - /// Hash - /// - Task GetAsset(UInt256 hash); + ///// + ///// Return the corresponding asset information according to the specified hash + ///// + ///// Hash + ///// + //Task GetAsset(UInt256 hash); /// /// Return the corresponding contract information according to the specified hash @@ -120,35 +120,35 @@ public interface IBlockchain /// Task> GetContracts(); - /// - /// Return all assets - /// - /// - Task> GetAssets(); + ///// + ///// Return all assets + ///// + ///// + //Task> GetAssets(); ECPoint[] GetValidators(); IEnumerable GetValidators(IEnumerable others); - /// - /// Returns the total amount of system costs contained in the corresponding block and all previous blocks based on the specified block height - /// - /// - /// - Task GetSysFeeAmount(uint height); + ///// + ///// Returns the total amount of system costs contained in the corresponding block and all previous blocks based on the specified block height + ///// + ///// + ///// GetBlocks + //Task GetSysFeeAmount(uint height); - /// - /// Returns the total amount of system charges contained in the corresponding block and all previous blocks based on the specified block hash value - /// - /// - /// - long GetSysFeeAmount(UInt256 hash); + ///// + ///// Returns the total amount of system charges contained in the corresponding block and all previous blocks based on the specified block hash value + ///// + ///// + ///// + //long GetSysFeeAmount(UInt256 hash); - /// - /// Returns the corresponding transaction information according to the specified hash value - /// - /// - /// - Task GetTransaction(UInt256 hash); + ///// + ///// Returns the corresponding transaction information according to the specified hash value + ///// + ///// + ///// + //Task GetTransaction(UInt256 hash); // TODO #385 [AboimPinto] Async methods cannot have out parameters. Method not used for now. ///// @@ -159,23 +159,23 @@ public interface IBlockchain ///// //Task GetTransaction(UInt256 hash, out int height); - Task> GetTransactions(IReadOnlyCollection transactionHashes); + //Task> GetTransactions(IReadOnlyCollection transactionHashes); - /// - /// Get the corresponding unspent assets based on the specified hash value and index - /// - /// - /// - /// - TransactionOutput GetUnspent(UInt256 hash, ushort index); + ///// + ///// Get the corresponding unspent assets based on the specified hash value and index + ///// + ///// + ///// + ///// + //TransactionOutput GetUnspent(UInt256 hash, ushort index); - IEnumerable GetUnspent(UInt256 hash); + //IEnumerable GetUnspent(UInt256 hash); - /// - /// Determine if the transaction is double - /// - /// - /// - bool IsDoubleSpend(Transaction tx); + ///// + ///// Determine if the transaction is double + ///// + ///// + ///// + //bool IsDoubleSpend(Transaction tx); } } \ No newline at end of file diff --git a/src/NeoSharp.Core/Blockchain/ITransactionModel.cs b/src/NeoSharp.Core/Blockchain/ITransactionModel.cs index a6e75a75..32d58dfc 100644 --- a/src/NeoSharp.Core/Blockchain/ITransactionModel.cs +++ b/src/NeoSharp.Core/Blockchain/ITransactionModel.cs @@ -1,9 +1,36 @@ -using NeoSharp.Core.Models; +using System.Collections.Generic; +using System.Threading.Tasks; +using NeoSharp.Core.Models; +using NeoSharp.Core.Types; namespace NeoSharp.Core.Blockchain { public interface ITransactionModel { + /// + /// Returns the corresponding transaction information according to the specified hash value + /// + /// Transaction hash. + /// The transaction. + Task GetTransaction(UInt256 hash); + + Task> GetTransactions(IReadOnlyCollection transactionHashes); + + /// + /// Determine if the transaction is double + /// + /// The transaction. + /// Boolean value indicating if is a double spend or not. bool IsDoubleSpend(Transaction transaction); + + /// + /// Get the corresponding unspent assets based on the specified hash value and index + /// + /// The hash of the asset. + /// The index of the output. + /// The transaction output. + TransactionOutput GetUnspent(UInt256 hash, ushort index); + + IEnumerable GetUnspent(UInt256 hash); } } diff --git a/src/NeoSharp.Core/Blockchain/TransactionModel.cs b/src/NeoSharp.Core/Blockchain/TransactionModel.cs index 798134f7..ecc8bf49 100644 --- a/src/NeoSharp.Core/Blockchain/TransactionModel.cs +++ b/src/NeoSharp.Core/Blockchain/TransactionModel.cs @@ -1,6 +1,9 @@ -using System.Linq; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; using NeoSharp.Core.Models; using NeoSharp.Core.Persistence; +using NeoSharp.Core.Types; namespace NeoSharp.Core.Blockchain { @@ -18,6 +21,29 @@ public TransactionModel(IRepository repository) #endregion #region ITransactionModel Implementation + + /// + public async Task GetTransaction(UInt256 hash) + { + return await _repository.GetTransaction(hash); + } + + public async Task> GetTransactions(IReadOnlyCollection transactionHashes) + { + var transactions = new List(); + + foreach (var hash in transactionHashes) + { + var transaction = await this.GetTransaction(hash); + + if (transaction == null) continue; + transactions.Add(transaction); + } + + return transactions; + } + + /// public bool IsDoubleSpend(Transaction transaction) { if (transaction.Inputs.Length == 0) @@ -37,6 +63,39 @@ public bool IsDoubleSpend(Transaction transaction) return false; } + + /// + public TransactionOutput GetUnspent(UInt256 hash, ushort index) + { + var states = this._repository.GetCoinStates(hash).Result; + + if (states == null || index >= states.Length || states[index].HasFlag(CoinState.Spent)) + { + return null; + } + + return this.GetTransaction(hash).Result.Outputs[index]; + } + + /// + public IEnumerable GetUnspent(UInt256 hash) + { + var outputs = new List(); + + var states = this._repository.GetCoinStates(hash).Result; + if (states != null) + { + var tx = this.GetTransaction(hash).Result; + for (var i = 0; i < states.Length; i++) + { + if (!states[i].HasFlag(CoinState.Spent)) + { + outputs.Add(tx.Outputs[i]); + } + } + } + return outputs; + } #endregion } } \ No newline at end of file diff --git a/src/NeoSharp.Core/DI/Modules/BlockchainModule.cs b/src/NeoSharp.Core/DI/Modules/BlockchainModule.cs index 72e7c52c..02217b7b 100644 --- a/src/NeoSharp.Core/DI/Modules/BlockchainModule.cs +++ b/src/NeoSharp.Core/DI/Modules/BlockchainModule.cs @@ -43,6 +43,9 @@ public void Register(IContainerBuilder containerBuilder) #endregion containerBuilder.RegisterSingleton(); + + containerBuilder.RegisterSingleton(); + containerBuilder.RegisterSingleton(); } } } \ No newline at end of file diff --git a/src/NeoSharp.Core/Messaging/Handlers/GetBlockHeadersMessageHandler.cs b/src/NeoSharp.Core/Messaging/Handlers/GetBlockHeadersMessageHandler.cs index 58b80aa3..318572ba 100644 --- a/src/NeoSharp.Core/Messaging/Handlers/GetBlockHeadersMessageHandler.cs +++ b/src/NeoSharp.Core/Messaging/Handlers/GetBlockHeadersMessageHandler.cs @@ -14,16 +14,16 @@ public class GetBlockHeadersMessageHandler : MessageHandler GetBlockHeader(UInt256 hash) => _blockchain.GetBlockHeader(hash); + private Task GetBlockHeader(UInt256 hash) => this._blockModel.GetBlockHeader(hash); #endregion #region Constructor - public GetBlockHeadersMessageHandler(IBlockchain blockchain) + public GetBlockHeadersMessageHandler(IBlockModel blockModel) { // TODO #434: Remove Blockchain dependency from GetBlockHeadersMessageHandler and GetBlocksMessageHandler - _blockchain = blockchain ?? throw new ArgumentNullException(nameof(blockchain)); + _blockModel = blockModel ?? throw new ArgumentNullException(nameof(blockModel)); } #endregion @@ -52,11 +52,11 @@ public override async Task Handle(GetBlockHeadersMessage message, IPeer sender) do { - blockHash = await _blockchain.GetNextBlockHash(blockHash); + blockHash = await this._blockModel.GetNextBlockHash(blockHash); if (blockHash == null || blockHash == hashStop) break; - blockHeaders.Add(await _blockchain.GetBlockHeader(blockHash)); + blockHeaders.Add(await this._blockModel.GetBlockHeader(blockHash)); } while (blockHeaders.Count < MaxBlockHeadersCountToReturn); if (blockHeaders.Count == 0) return; diff --git a/src/NeoSharp.Core/Messaging/Handlers/GetBlocksMessageHandler.cs b/src/NeoSharp.Core/Messaging/Handlers/GetBlocksMessageHandler.cs index 2c7fa690..b86927b9 100644 --- a/src/NeoSharp.Core/Messaging/Handlers/GetBlocksMessageHandler.cs +++ b/src/NeoSharp.Core/Messaging/Handlers/GetBlocksMessageHandler.cs @@ -14,16 +14,16 @@ public class GetBlocksMessageHandler : MessageHandler { #region Private Fields private const int MaxBlocksCountToReturn = 500; - private readonly IBlockchain _blockchain; + private readonly IBlockModel _blockModel; - private Task GetBlockHeader(UInt256 hash) => _blockchain.GetBlockHeader(hash); + private Task GetBlockHeader(UInt256 hash) => this._blockModel.GetBlockHeader(hash); #endregion #region Constructor - public GetBlocksMessageHandler(IBlockchain blockchain) + public GetBlocksMessageHandler(IBlockModel blockModel) { // TODO #434: Remove Blockchain dependency from GetBlockHeadersMessageHandler and GetBlocksMessageHandler - _blockchain = blockchain ?? throw new ArgumentNullException(nameof(blockchain)); + this._blockModel = blockModel ?? throw new ArgumentNullException(nameof(blockModel)); } #endregion @@ -58,7 +58,7 @@ public override async Task Handle(GetBlocksMessage message, IPeer sender) do { - blockHash = await _blockchain.GetNextBlockHash(blockHash); + blockHash = await this._blockModel.GetNextBlockHash(blockHash); if (blockHash == null || blockHash == hashStop) break; diff --git a/src/NeoSharp.Core/Messaging/Handlers/GetDataMessageHandler.cs b/src/NeoSharp.Core/Messaging/Handlers/GetDataMessageHandler.cs index abb0f286..5206476e 100644 --- a/src/NeoSharp.Core/Messaging/Handlers/GetDataMessageHandler.cs +++ b/src/NeoSharp.Core/Messaging/Handlers/GetDataMessageHandler.cs @@ -16,7 +16,9 @@ namespace NeoSharp.Core.Messaging.Handlers public class GetDataMessageHandler : MessageHandler { #region Private fields - private readonly IBlockchain _blockchain; + + private readonly IBlockModel _blockModel; + private readonly ITransactionModel _transactionModel; private readonly ILogger _logger; #endregion @@ -24,13 +26,18 @@ public class GetDataMessageHandler : MessageHandler /// /// Constructor /// - /// Blockchain + /// The block model. + /// The transaction model. /// Logger - public GetDataMessageHandler(IBlockchain blockchain, ILogger logger) + public GetDataMessageHandler( + IBlockModel blockModel, + ITransactionModel transactionModel, + ILogger logger) { // TODO #434: Title not aligned but the context is the same. - _blockchain = blockchain ?? throw new ArgumentNullException(nameof(blockchain)); + _blockModel = blockModel; + _transactionModel = transactionModel ?? throw new ArgumentNullException(nameof(transactionModel)); _logger = logger ?? throw new ArgumentNullException(nameof(logger)); } #endregion @@ -85,7 +92,7 @@ public override bool CanHandle(Message message) #region Private Methods private async Task SendTransactions(IReadOnlyCollection transactionHashes, IPeer peer) { - var transactions = await _blockchain.GetTransactions(transactionHashes); + var transactions = await _transactionModel.GetTransactions(transactionHashes); // TODO #378: The more efficient operation would be to send many transactions per one message // but it breaks backward compatibility @@ -94,7 +101,7 @@ private async Task SendTransactions(IReadOnlyCollection transactionHash private async Task SendBlocks(IReadOnlyCollection blockHashes, IPeer peer) { - var blocks = (await _blockchain.GetBlocks(blockHashes)).ToList(); + var blocks = (await this._blockModel.GetBlocks(blockHashes)).ToList(); if (!blocks.Any()) return; diff --git a/src/NeoSharp.Core/Models/OperationManger/TransactionOperationManager.cs b/src/NeoSharp.Core/Models/OperationManger/TransactionOperationManager.cs index 426f36ca..0ba19eb6 100644 --- a/src/NeoSharp.Core/Models/OperationManger/TransactionOperationManager.cs +++ b/src/NeoSharp.Core/Models/OperationManger/TransactionOperationManager.cs @@ -1,7 +1,10 @@ -using System.Linq; +using System; +using System.Collections.Generic; +using System.Linq; using NeoSharp.BinarySerialization; using NeoSharp.Core.Blockchain; using NeoSharp.Core.Cryptography; +using NeoSharp.Core.Extensions; using NeoSharp.Core.Types; namespace NeoSharp.Core.Models.OperationManger @@ -13,17 +16,25 @@ public class TransactionOperationManager : ITransactionOperationsManager private readonly IBinarySerializer _binarySerializer; private readonly IWitnessOperationsManager _witnessOperationsManager; private readonly ITransactionModel _transactionModel; + private readonly IAssetModel _assetModel; + private readonly ITransactionContext _transactionContext; #endregion #region Constructor public TransactionOperationManager( Crypto crypto, IBinarySerializer binarySerializer, - IWitnessOperationsManager witnessOperationsManager) + IWitnessOperationsManager witnessOperationsManager, + ITransactionModel transactionModel, + IAssetModel assetModel, + ITransactionContext transactionContext) { this._crypto = crypto; this._binarySerializer = binarySerializer; this._witnessOperationsManager = witnessOperationsManager; + this._transactionModel = transactionModel; + this._assetModel = assetModel; + _transactionContext = transactionContext; } #endregion @@ -67,126 +78,126 @@ public bool Verify(Transaction transaction) return false; } - //foreach (var group in transaction.Outputs.GroupBy(p => p.AssetId)) - //{ - // var asset = _blockchain.GetAsset(group.Key).Result; - - // if (asset == null) - // { - // return false; - // } - - // // TODO: Should we check for `asset.Expiration <= _blockchain.Height + 1` ?? - // if (asset.AssetType != AssetType.GoverningToken - // && asset.AssetType != AssetType.UtilityToken) - // { - // return false; - // } - - // var tenPoweredToEightMinusAssetPrecision = (long)Math.Pow(10, 8 - asset.Precision); - - // if (group.Any(output => output.Value.Value % tenPoweredToEightMinusAssetPrecision != 0)) - // { - // return false; - // } - //} - - //var results = GetTransactionResults(transaction)?.ToArray(); - - //if (results == null) - //{ - // return false; - //} - - //var resultsDestroy = results.Where(p => p.Amount > Fixed8.Zero).ToArray(); - - //if (resultsDestroy.Length > 1) - //{ - // return false; - //} - - //if (resultsDestroy.Length == 1 - // && resultsDestroy[0].AssetId != _transactionContext.UtilityTokenHash) - //{ - // return false; - //} - - //if (_transactionContext.GetSystemFee(transaction) > Fixed8.Zero - // && (resultsDestroy.Length == 0 - // || resultsDestroy[0].Amount < _transactionContext.GetSystemFee(transaction))) - //{ - // return false; - //} - - //var resultsIssue = results.Where(p => p.Amount < Fixed8.Zero).ToArray(); - - //if (resultsIssue.Any(p => p.AssetId != _transactionContext.UtilityTokenHash) - // && (transaction.Type == TransactionType.ClaimTransaction - // || transaction.Type == TransactionType.IssueTransaction)) - //{ - // return false; - //} - - //if (transaction.Type != TransactionType.MinerTransaction - // && resultsIssue.Length > 0) - //{ - // return false; - //} - - //// TODO: Verify Receiving Scripts? - - //if (transaction.Witness.Any(witness => !_witnessOperationsManager.Verify(witness))) - //{ - // return false; - //} + foreach (var group in transaction.Outputs.GroupBy(p => p.AssetId)) + { + var asset = this._assetModel.GetAsset(group.Key).Result; + + if (asset == null) + { + return false; + } + + // TODO: Should we check for `asset.Expiration <= _blockchain.Height + 1` ?? + if (asset.AssetType != AssetType.GoverningToken + && asset.AssetType != AssetType.UtilityToken) + { + return false; + } + + var tenPoweredToEightMinusAssetPrecision = (long)Math.Pow(10, 8 - asset.Precision); + + if (group.Any(output => output.Value.Value % tenPoweredToEightMinusAssetPrecision != 0)) + { + return false; + } + } + + var results = this.GetTransactionResults(transaction)?.ToArray(); + + if (results == null) + { + return false; + } + + var resultsDestroy = results.Where(p => p.Amount > Fixed8.Zero).ToArray(); + + if (resultsDestroy.Length > 1) + { + return false; + } + + if (resultsDestroy.Length == 1 + && resultsDestroy[0].AssetId != this._transactionContext.UtilityTokenHash) + { + return false; + } + + if (this._transactionContext.GetSystemFee(transaction) > Fixed8.Zero + && (resultsDestroy.Length == 0 + || resultsDestroy[0].Amount < this._transactionContext.GetSystemFee(transaction))) + { + return false; + } + + var resultsIssue = results.Where(p => p.Amount < Fixed8.Zero).ToArray(); + + if (resultsIssue.Any(p => p.AssetId != this._transactionContext.UtilityTokenHash) + && (transaction.Type == TransactionType.ClaimTransaction + || transaction.Type == TransactionType.IssueTransaction)) + { + return false; + } + + if (transaction.Type != TransactionType.MinerTransaction + && resultsIssue.Length > 0) + { + return false; + } + + // TODO: Verify Receiving Scripts? + + if (transaction.Witness.Any(witness => !_witnessOperationsManager.Verify(witness))) + { + return false; + } return true; } #endregion #region Private Methods - //private IEnumerable GetTransactionResults(Transaction transaction) - //{ - // return GetReferences(transaction)?.Values.Select(p => new - // { - // p.AssetId, - // p.Value - // }).Concat(transaction.Outputs.Select(p => new - // { - // p.AssetId, - // Value = -p.Value - // })).GroupBy(p => p.AssetId, (k, g) => new TransactionResult - // { - // AssetId = k, - // Amount = g.Sum(p => p.Value) - // }).Where(p => p.Amount != Fixed8.Zero); - //} - - //private Dictionary GetReferences(Transaction transaction) - //{ - // var references = new Dictionary(); - - // foreach (var group in transaction.Inputs.GroupBy(p => p.PrevHash)) - // { - // var tx = _blockchain.GetTransaction(group.Key).Result; - - // if (tx == null) - // { - // references = null; - // break; - // } - - // foreach (var p in group) - // { - // if (tx.Outputs.Length > p.PrevIndex) - // { - // references.Add(p, tx.Outputs[p.PrevIndex]); - // } - // } - // } - - // return references; - //} + private IEnumerable GetTransactionResults(Transaction transaction) + { + return GetReferences(transaction)?.Values.Select(p => new + { + p.AssetId, + p.Value + }).Concat(transaction.Outputs.Select(p => new + { + p.AssetId, + Value = -p.Value + })).GroupBy(p => p.AssetId, (k, g) => new TransactionResult + { + AssetId = k, + Amount = g.Sum(p => p.Value) + }).Where(p => p.Amount != Fixed8.Zero); + } + + private Dictionary GetReferences(Transaction transaction) + { + var references = new Dictionary(); + + foreach (var group in transaction.Inputs.GroupBy(p => p.PrevHash)) + { + var tx = this._transactionModel.GetTransaction(group.Key).Result; + + if (tx == null) + { + references = null; + break; + } + + foreach (var p in group) + { + if (tx.Outputs.Length > p.PrevIndex) + { + references.Add(p, tx.Outputs[p.PrevIndex]); + } + } + } + + return references; + } #endregion } } \ No newline at end of file diff --git a/test/NeoSharp.Core.Test/Blockchain/UtBlockchain.cs b/test/NeoSharp.Core.Test/Blockchain/UtBlockchain.cs index 1b67b1dc..6fa4b7a5 100644 --- a/test/NeoSharp.Core.Test/Blockchain/UtBlockchain.cs +++ b/test/NeoSharp.Core.Test/Blockchain/UtBlockchain.cs @@ -1,6 +1,7 @@ using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; +using NeoSharp.Core.Blockchain; using NeoSharp.Core.Models; using NeoSharp.Core.Persistence; using NeoSharp.Core.Types; @@ -24,7 +25,7 @@ public void Ctor_CreateValidBlockchainObject() [TestMethod] public void IsDoubleSpend_NoInputs() { - var testee = AutoMockContainer.Create(); + var testee = AutoMockContainer.Create(); var tx = new Transaction(); @@ -36,7 +37,7 @@ public void IsDoubleSpend_NoInputs() [TestMethod] public void IsDoubleSpend_InputWithoutFoundHash() { - var testee = AutoMockContainer.Create(); + var testee = AutoMockContainer.Create(); var tx = new Transaction { Inputs = new[] { new CoinReference() } }; tx.Inputs[0].PrevHash = new UInt256(); @@ -49,7 +50,7 @@ public void IsDoubleSpend_InputWithoutFoundHash() [TestMethod] public void IsDoubleSpend_SpentInput() { - var testee = AutoMockContainer.Create(); + var testee = AutoMockContainer.Create(); var tx = new Transaction { Inputs = new[] { new CoinReference() } }; tx.Inputs[0].PrevHash = new UInt256(new byte[]{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 }); @@ -69,7 +70,7 @@ public void IsDoubleSpend_SpentInput() [TestMethod] public void IsDoubleSpend_ConfirmedInput() { - var testee = AutoMockContainer.Create(); + var testee = AutoMockContainer.Create(); var tx = new Transaction { Inputs = new[] { new CoinReference() } }; tx.Inputs[0].PrevHash = new UInt256(new byte[]{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 }); diff --git a/test/NeoSharp.Core.Test/Blockchain/UtGenesis.cs b/test/NeoSharp.Core.Test/Blockchain/UtGenesis.cs index c7eb80e6..4ca767e1 100644 --- a/test/NeoSharp.Core.Test/Blockchain/UtGenesis.cs +++ b/test/NeoSharp.Core.Test/Blockchain/UtGenesis.cs @@ -1,9 +1,11 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; using NeoSharp.BinarySerialization; using NeoSharp.Core.Blockchain; using NeoSharp.Core.Cryptography; using NeoSharp.Core.Models; using NeoSharp.Core.Models.OperationManger; +using NeoSharp.Core.Types; using NeoSharp.TestHelpers; namespace NeoSharp.Core.Test.Blockchain @@ -19,7 +21,7 @@ public void GenesisHashTest() var crypto = Crypto.Default; var binarySerialier = BinarySerializer.Default; var witnessOperationManager = new WitnessOperationsManager(crypto); - var transactionOperationManager = new TransactionOperationManager(crypto, binarySerialier, witnessOperationManager); + var transactionOperationManager = new TransactionOperationManager(crypto, binarySerialier, witnessOperationManager, new Mock().Object, new Mock().Object, new TransactionContext()); var blockOperationManager = new BlockOperationsManager(crypto, binarySerialier, transactionOperationManager, witnessOperationManager); this.AutoMockContainer.Register(crypto); diff --git a/test/NeoSharp.Core.Test/Models/UtTransactionVerifier.cs b/test/NeoSharp.Core.Test/Models/UtTransactionVerifier.cs index ae0b4986..ad97caef 100644 --- a/test/NeoSharp.Core.Test/Models/UtTransactionVerifier.cs +++ b/test/NeoSharp.Core.Test/Models/UtTransactionVerifier.cs @@ -13,7 +13,6 @@ namespace NeoSharp.Core.Test.Models public class UtTransactionOperationManager : TestBase { [TestMethod] - [Ignore] // Code is comment out. Will be added again when the Circle Reference is solved. public void Verify_AttributeUsageECDH02() { var testee = AutoMockContainer.Create(); @@ -35,7 +34,6 @@ public void Verify_AttributeUsageECDH02() } [TestMethod] - [Ignore] // Code is comment out. Will be added again when the Circle Reference is solved. public void Verify_WithInputsWithSamePrevHashAndPrevIndex() { var testee = AutoMockContainer.Create(); @@ -70,7 +68,6 @@ public void Verify_WithInputsWithSamePrevHashAndPrevIndex() } [TestMethod] - [Ignore] // Code is comment out. Will be added again when the Circle Reference is solved. public void Verify_WithDoubleSpending() { var testee = AutoMockContainer.Create(); @@ -99,9 +96,9 @@ public void Verify_WithDoubleSpending() } }; - var blockchainMock = AutoMockContainer.GetMock(); - - blockchainMock.Setup(b => b.IsDoubleSpend(transaction)).Returns(true); + this.AutoMockContainer.GetMock() + .Setup(b => b.IsDoubleSpend(transaction)) + .Returns(true); var result = testee.Verify(transaction); @@ -109,7 +106,6 @@ public void Verify_WithDoubleSpending() } [TestMethod] - [Ignore] // Code is comment out. Will be added again when the Circle Reference is solved. public void Verify_WithStrangeAssetId() { var testee = AutoMockContainer.Create(); @@ -144,11 +140,16 @@ public void Verify_WithStrangeAssetId() } } }; - - var blockchainMock = AutoMockContainer.GetMock(); - blockchainMock.Setup(b => b.IsDoubleSpend(transaction)).Returns(false); - blockchainMock.Setup(b => b.GetAsset(It.IsAny())).ReturnsAsync(() => null); + this.AutoMockContainer + .GetMock() + .Setup(b => b.IsDoubleSpend(transaction)) + .Returns(false); + + this.AutoMockContainer + .GetMock() + .Setup(b => b.GetAsset(It.IsAny())) + .ReturnsAsync(() => null); var result = testee.Verify(transaction); @@ -156,7 +157,6 @@ public void Verify_WithStrangeAssetId() } [TestMethod] - [Ignore] // Code is comment out. Will be added again when the Circle Reference is solved. public void Verify_WithKnownAssetIdButNotGeverningAndNotUtility() { var testee = AutoMockContainer.Create(); @@ -191,14 +191,19 @@ public void Verify_WithKnownAssetIdButNotGeverningAndNotUtility() } } }; - - var blockchainMock = AutoMockContainer.GetMock(); - blockchainMock.Setup(b => b.IsDoubleSpend(transaction)).Returns(false); - blockchainMock.Setup(b => b.GetAsset(It.IsAny())).ReturnsAsync(() => new Asset - { - AssetType = AssetType.DutyFlag - }); + this.AutoMockContainer + .GetMock() + .Setup(b => b.IsDoubleSpend(transaction)) + .Returns(false); + + this.AutoMockContainer + .GetMock() + .Setup(b => b.GetAsset(It.IsAny())) + .ReturnsAsync(() => new Asset + { + AssetType = AssetType.DutyFlag + }); var result = testee.Verify(transaction); @@ -206,7 +211,6 @@ public void Verify_WithKnownAssetIdButNotGeverningAndNotUtility() } [TestMethod] - [Ignore] // Code is comment out. Will be added again when the Circle Reference is solved. public void Verify_WithOutputValueDivisibleByAssetRule() { var testee = AutoMockContainer.Create(); @@ -242,14 +246,19 @@ public void Verify_WithOutputValueDivisibleByAssetRule() } } }; - - var blockchainMock = AutoMockContainer.GetMock(); - blockchainMock.Setup(b => b.IsDoubleSpend(transaction)).Returns(false); - blockchainMock.Setup(b => b.GetAsset(It.IsAny())).ReturnsAsync(() => new Asset - { - AssetType = AssetType.GoverningToken - }); + this.AutoMockContainer + .GetMock() + .Setup(b => b.IsDoubleSpend(transaction)) + .Returns(false); + + this.AutoMockContainer + .GetMock() + .Setup(b => b.GetAsset(It.IsAny())) + .ReturnsAsync(() => new Asset + { + AssetType = AssetType.GoverningToken + }); var result = testee.Verify(transaction); @@ -257,7 +266,6 @@ public void Verify_WithOutputValueDivisibleByAssetRule() } [TestMethod] - [Ignore] // Code is comment out. Will be added again when the Circle Reference is solved. public void Verify_WithoutReferences() { var testee = AutoMockContainer.Create(); @@ -293,15 +301,22 @@ public void Verify_WithoutReferences() } } }; - - var blockchainMock = AutoMockContainer.GetMock(); - blockchainMock.Setup(b => b.IsDoubleSpend(transaction)).Returns(false); - blockchainMock.Setup(b => b.GetAsset(It.IsAny())).ReturnsAsync(() => new Asset - { - AssetType = AssetType.GoverningToken - }); - blockchainMock.Setup(b => b.GetTransaction(It.IsAny())).ReturnsAsync(() => null); + var transactionModelMock = this.AutoMockContainer.GetMock(); + transactionModelMock + .Setup(b => b.IsDoubleSpend(transaction)) + .Returns(false); + transactionModelMock + .Setup(x => x.GetTransaction(It.IsAny())) + .ReturnsAsync(() => null); + + this.AutoMockContainer + .GetMock() + .Setup(b => b.GetAsset(It.IsAny())) + .ReturnsAsync(() => new Asset + { + AssetType = AssetType.GoverningToken + }); var result = testee.Verify(transaction); @@ -309,7 +324,6 @@ public void Verify_WithoutReferences() } [TestMethod] - [Ignore] // Code is comment out. Will be added again when the Circle Reference is solved. public void Verify_WithMoreThanOneReferenceAmountGreaterThanZero() { var testee = AutoMockContainer.Create(); @@ -363,15 +377,22 @@ public void Verify_WithMoreThanOneReferenceAmountGreaterThanZero() } } }; - - var blockchainMock = AutoMockContainer.GetMock(); - blockchainMock.Setup(b => b.IsDoubleSpend(transaction)).Returns(false); - blockchainMock.Setup(b => b.GetAsset(It.IsAny())).ReturnsAsync(() => new Asset - { - AssetType = AssetType.GoverningToken - }); - blockchainMock.Setup(b => b.GetTransaction(It.IsAny())).ReturnsAsync(() => transactionOfPreviousHash); + var transactionModelMock = this.AutoMockContainer.GetMock(); + transactionModelMock + .Setup(b => b.IsDoubleSpend(transaction)) + .Returns(false); + transactionModelMock + .Setup(x => x.GetTransaction(It.IsAny())) + .ReturnsAsync(() => transactionOfPreviousHash); + + this.AutoMockContainer + .GetMock() + .Setup(b => b.GetAsset(It.IsAny())) + .ReturnsAsync(() => new Asset + { + AssetType = AssetType.GoverningToken + }); var result = testee.Verify(transaction); @@ -379,7 +400,6 @@ public void Verify_WithMoreThanOneReferenceAmountGreaterThanZero() } [TestMethod] - [Ignore] // Code is comment out. Will be added again when the Circle Reference is solved. public void Verify_WithOnlyOneReferenceAmountGreaterThanZeroButItsNotUtilityToken() { var testee = AutoMockContainer.Create(); @@ -433,19 +453,26 @@ public void Verify_WithOnlyOneReferenceAmountGreaterThanZeroButItsNotUtilityToke } } }; - - var blockchainMock = AutoMockContainer.GetMock(); - blockchainMock.Setup(b => b.IsDoubleSpend(transaction)).Returns(false); - blockchainMock.Setup(b => b.GetAsset(It.IsAny())).ReturnsAsync(() => new Asset - { - AssetType = AssetType.GoverningToken - }); - blockchainMock.Setup(b => b.GetTransaction(It.IsAny())).ReturnsAsync(() => transactionOfPreviousHash); - - var transactionContextMock = AutoMockContainer.GetMock(); - - transactionContextMock.SetupGet(x => x.UtilityTokenHash) + var transactionModelMock = this.AutoMockContainer.GetMock(); + transactionModelMock + .Setup(b => b.IsDoubleSpend(transaction)) + .Returns(false); + transactionModelMock + .Setup(x => x.GetTransaction(It.IsAny())) + .ReturnsAsync(() => transactionOfPreviousHash); + + this.AutoMockContainer + .GetMock() + .Setup(b => b.GetAsset(It.IsAny())) + .ReturnsAsync(() => new Asset + { + AssetType = AssetType.GoverningToken + }); + + this.AutoMockContainer + .GetMock() + .SetupGet(x => x.UtilityTokenHash) .Returns(UInt256.Parse("602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7")); var result = testee.Verify(transaction); @@ -454,7 +481,6 @@ public void Verify_WithOnlyOneReferenceAmountGreaterThanZeroButItsNotUtilityToke } [TestMethod] - [Ignore] // Code is comment out. Will be added again when the Circle Reference is solved. public void Verify_WithReferenceAmountZeroAndExistingSystemFee() { var testee = AutoMockContainer.Create(); @@ -508,22 +534,29 @@ public void Verify_WithReferenceAmountZeroAndExistingSystemFee() } } }; - - var blockchainMock = AutoMockContainer.GetMock(); - blockchainMock.Setup(b => b.IsDoubleSpend(transaction)).Returns(false); - blockchainMock.Setup(b => b.GetAsset(It.IsAny())).ReturnsAsync(() => new Asset - { - AssetType = AssetType.GoverningToken - }); - blockchainMock.Setup(b => b.GetTransaction(It.IsAny())).ReturnsAsync(() => transactionOfPreviousHash); - - var transactionContextMock = AutoMockContainer.GetMock(); - - transactionContextMock.SetupGet(x => x.UtilityTokenHash) + var transactionModelMock = this.AutoMockContainer.GetMock(); + transactionModelMock + .Setup(b => b.IsDoubleSpend(transaction)) + .Returns(false); + transactionModelMock + .Setup(x => x.GetTransaction(It.IsAny())) + .ReturnsAsync(() => transactionOfPreviousHash); + + this.AutoMockContainer + .GetMock() + .Setup(b => b.GetAsset(It.IsAny())) + .ReturnsAsync(() => new Asset + { + AssetType = AssetType.GoverningToken + }); + + var transactionContextMock = this.AutoMockContainer.GetMock(); + transactionContextMock + .SetupGet(x => x.UtilityTokenHash) .Returns(UInt256.Parse("602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7")); - - transactionContextMock.Setup(x => x.GetSystemFee(It.IsAny())) + transactionContextMock + .Setup(x => x.GetSystemFee(It.IsAny())) .Returns(Fixed8.One); var result = testee.Verify(transaction); @@ -532,7 +565,6 @@ public void Verify_WithReferenceAmountZeroAndExistingSystemFee() } [TestMethod] - [Ignore] // Code is comment out. Will be added again when the Circle Reference is solved. public void Verify_WithReferenceAmountLessThanSystemFee() { var testee = AutoMockContainer.Create(); @@ -586,31 +618,37 @@ public void Verify_WithReferenceAmountLessThanSystemFee() } } }; - - var blockchainMock = AutoMockContainer.GetMock(); - - blockchainMock.Setup(b => b.IsDoubleSpend(transaction)).Returns(false); - blockchainMock.Setup(b => b.GetAsset(It.IsAny())).ReturnsAsync(() => new Asset - { - AssetType = AssetType.GoverningToken - }); - blockchainMock.Setup(b => b.GetTransaction(It.IsAny())).ReturnsAsync(() => transactionOfPreviousHash); - var transactionContextMock = AutoMockContainer.GetMock(); - - transactionContextMock.SetupGet(x => x.UtilityTokenHash) + var transactionModelMock = this.AutoMockContainer.GetMock(); + transactionModelMock + .Setup(b => b.IsDoubleSpend(transaction)) + .Returns(false); + transactionModelMock + .Setup(x => x.GetTransaction(It.IsAny())) + .ReturnsAsync(() => transactionOfPreviousHash); + + this.AutoMockContainer + .GetMock() + .Setup(b => b.GetAsset(It.IsAny())) + .ReturnsAsync(() => new Asset + { + AssetType = AssetType.GoverningToken + }); + + var transactionContextMock = this.AutoMockContainer.GetMock(); + transactionContextMock + .SetupGet(x => x.UtilityTokenHash) .Returns(UInt256.Parse("602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7")); - - transactionContextMock.Setup(x => x.GetSystemFee(It.IsAny())) + transactionContextMock + .Setup(x => x.GetSystemFee(It.IsAny())) .Returns(new Fixed8(300000000)); - + var result = testee.Verify(transaction); result.Should().BeFalse(); } [TestMethod] - [Ignore] // Code is comment out. Will be added again when the Circle Reference is solved. public void Verify_ClaimTransacWithNegativeResultOfUtilityToken() { var testee = AutoMockContainer.Create(); @@ -659,31 +697,37 @@ public void Verify_ClaimTransacWithNegativeResultOfUtilityToken() } } }; - - var blockchainMock = AutoMockContainer.GetMock(); - - blockchainMock.Setup(b => b.IsDoubleSpend(transaction)).Returns(false); - blockchainMock.Setup(b => b.GetAsset(It.IsAny())).ReturnsAsync(() => new Asset - { - AssetType = AssetType.GoverningToken - }); - blockchainMock.Setup(b => b.GetTransaction(It.IsAny())).ReturnsAsync(() => transactionOfPreviousHash); - - var transactionContextMock = AutoMockContainer.GetMock(); - transactionContextMock.SetupGet(x => x.UtilityTokenHash) + var transactionModelMock = this.AutoMockContainer.GetMock(); + transactionModelMock + .Setup(b => b.IsDoubleSpend(transaction)) + .Returns(false); + transactionModelMock + .Setup(x => x.GetTransaction(It.IsAny())) + .ReturnsAsync(() => transactionOfPreviousHash); + + this.AutoMockContainer + .GetMock() + .Setup(b => b.GetAsset(It.IsAny())) + .ReturnsAsync(() => new Asset + { + AssetType = AssetType.GoverningToken + }); + + var transactionContextMock = this.AutoMockContainer.GetMock(); + transactionContextMock + .SetupGet(x => x.UtilityTokenHash) .Returns(UInt256.Parse("602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7")); - - transactionContextMock.Setup(x => x.GetSystemFee(It.IsAny())) + transactionContextMock + .Setup(x => x.GetSystemFee(It.IsAny())) .Returns(Fixed8.Zero); - + var result = testee.Verify(transaction); result.Should().BeFalse(); } [TestMethod] - [Ignore] // Code is comment out. Will be added again when the Circle Reference is solved. public void Verify_NotMinerTransacWithNegativeResults() { var testee = AutoMockContainer.Create(); @@ -737,31 +781,37 @@ public void Verify_NotMinerTransacWithNegativeResults() } } }; - - var blockchainMock = AutoMockContainer.GetMock(); - - blockchainMock.Setup(b => b.IsDoubleSpend(transaction)).Returns(false); - blockchainMock.Setup(b => b.GetAsset(It.IsAny())).ReturnsAsync(() => new Asset - { - AssetType = AssetType.GoverningToken - }); - blockchainMock.Setup(b => b.GetTransaction(It.IsAny())).ReturnsAsync(() => transactionOfPreviousHash); - - var transactionContextMock = AutoMockContainer.GetMock(); - transactionContextMock.SetupGet(x => x.UtilityTokenHash) + var transactionModelMock = this.AutoMockContainer.GetMock(); + transactionModelMock + .Setup(b => b.IsDoubleSpend(transaction)) + .Returns(false); + transactionModelMock + .Setup(x => x.GetTransaction(It.IsAny())) + .ReturnsAsync(() => transactionOfPreviousHash); + + this.AutoMockContainer + .GetMock() + .Setup(b => b.GetAsset(It.IsAny())) + .ReturnsAsync(() => new Asset + { + AssetType = AssetType.GoverningToken + }); + + var transactionContextMock = this.AutoMockContainer.GetMock(); + transactionContextMock + .SetupGet(x => x.UtilityTokenHash) .Returns(UInt256.Parse("602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7")); - - transactionContextMock.Setup(x => x.GetSystemFee(It.IsAny())) + transactionContextMock + .Setup(x => x.GetSystemFee(It.IsAny())) .Returns(new Fixed8(190000000)); - + var result = testee.Verify(transaction); result.Should().BeFalse(); } [TestMethod] - [Ignore] // Code is comment out. Will be added again when the Circle Reference is solved. public void Verify_WitnessVerifiedWrong() { var testee = AutoMockContainer.Create(); @@ -819,27 +869,35 @@ public void Verify_WitnessVerifiedWrong() } } }; - - var blockchainMock = AutoMockContainer.GetMock(); - blockchainMock.Setup(b => b.IsDoubleSpend(transaction)).Returns(false); - blockchainMock.Setup(b => b.GetAsset(It.IsAny())).ReturnsAsync(() => new Asset - { - AssetType = AssetType.GoverningToken - }); - blockchainMock.Setup(b => b.GetTransaction(It.IsAny())).ReturnsAsync(() => transactionOfPreviousHash); - - var transactionContextMock = AutoMockContainer.GetMock(); - - transactionContextMock.SetupGet(x => x.UtilityTokenHash) + var transactionModelMock = this.AutoMockContainer.GetMock(); + transactionModelMock + .Setup(b => b.IsDoubleSpend(transaction)) + .Returns(false); + transactionModelMock + .Setup(x => x.GetTransaction(It.IsAny())) + .ReturnsAsync(() => transactionOfPreviousHash); + + this.AutoMockContainer + .GetMock() + .Setup(b => b.GetAsset(It.IsAny())) + .ReturnsAsync(() => new Asset + { + AssetType = AssetType.GoverningToken + }); + + var transactionContextMock = this.AutoMockContainer.GetMock(); + transactionContextMock + .SetupGet(x => x.UtilityTokenHash) .Returns(UInt256.Parse("602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7")); - - transactionContextMock.Setup(x => x.GetSystemFee(It.IsAny())) + transactionContextMock + .Setup(x => x.GetSystemFee(It.IsAny())) .Returns(new Fixed8(190000000)); - var witnessOperationsManagerMock = AutoMockContainer.GetMock(); - - witnessOperationsManagerMock.Setup(x => x.Verify(It.IsAny())).Returns(false); + this.AutoMockContainer + .GetMock() + .Setup(x => x.Verify(It.IsAny())) + .Returns(false); var result = testee.Verify(transaction); @@ -847,7 +905,6 @@ public void Verify_WitnessVerifiedWrong() } [TestMethod] - [Ignore] // Code is comment out. Will be added again when the Circle Reference is solved. public void Verify_Success() { var testee = AutoMockContainer.Create(); @@ -905,28 +962,36 @@ public void Verify_Success() } } }; - - var blockchainMock = AutoMockContainer.GetMock(); - - blockchainMock.Setup(b => b.IsDoubleSpend(transaction)).Returns(false); - blockchainMock.Setup(b => b.GetAsset(It.IsAny())).ReturnsAsync(() => new Asset - { - AssetType = AssetType.GoverningToken - }); - blockchainMock.Setup(b => b.GetTransaction(It.IsAny())).ReturnsAsync(() => transactionOfPreviousHash); - var transactionContextMock = AutoMockContainer.GetMock(); - - transactionContextMock.SetupGet(x => x.UtilityTokenHash) + var transactionModelMock = this.AutoMockContainer.GetMock(); + transactionModelMock + .Setup(b => b.IsDoubleSpend(transaction)) + .Returns(false); + transactionModelMock + .Setup(x => x.GetTransaction(It.IsAny())) + .ReturnsAsync(() => transactionOfPreviousHash); + + this.AutoMockContainer + .GetMock() + .Setup(b => b.GetAsset(It.IsAny())) + .ReturnsAsync(() => new Asset + { + AssetType = AssetType.GoverningToken + }); + + var transactionContextMock = this.AutoMockContainer.GetMock(); + transactionContextMock + .SetupGet(x => x.UtilityTokenHash) .Returns(UInt256.Parse("602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7")); - - transactionContextMock.Setup(x => x.GetSystemFee(It.IsAny())) + transactionContextMock + .Setup(x => x.GetSystemFee(It.IsAny())) .Returns(new Fixed8(190000000)); - var witnessOperationsManagerMock = AutoMockContainer.GetMock(); + this.AutoMockContainer + .GetMock() + .Setup(x => x.Verify(It.IsAny())) + .Returns(true); - witnessOperationsManagerMock.Setup(x => x.Verify(It.IsAny())).Returns(true); - var result = testee.Verify(transaction); result.Should().BeTrue(); diff --git a/test/NeoSharp.Core.Test/Serializers/UtBinarySerializerRaw.cs b/test/NeoSharp.Core.Test/Serializers/UtBinarySerializerRaw.cs index 5d7987f1..49b1c7f9 100644 --- a/test/NeoSharp.Core.Test/Serializers/UtBinarySerializerRaw.cs +++ b/test/NeoSharp.Core.Test/Serializers/UtBinarySerializerRaw.cs @@ -1,12 +1,15 @@ using System.Collections.Generic; using System.IO; using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; using NeoSharp.BinarySerialization; +using NeoSharp.Core.Blockchain; using NeoSharp.Core.Cryptography; using NeoSharp.Core.Extensions; using NeoSharp.Core.Models; using NeoSharp.Core.Models.OperationManger; using NeoSharp.Core.SmartContract; +using NeoSharp.Core.Types; namespace NeoSharp.Core.Test.Serializers { @@ -77,7 +80,7 @@ public void SerializeDeserialize_Block() // MainNet - Block 1 var witnessOperationsManager = new WitnessOperationsManager(Crypto.Default); - var transactionOperationsManager = new TransactionOperationManager(Crypto.Default, this._serializer, witnessOperationsManager); + var transactionOperationsManager = new TransactionOperationManager(Crypto.Default, this._serializer, witnessOperationsManager, new Mock().Object, new Mock().Object, new TransactionContext()); var blockOperationsManager = new BlockOperationsManager(Crypto.Default, BinarySerializer.Default, transactionOperationsManager, witnessOperationsManager); var blockHeaderOperationsManager = new BlockHeaderOperationsManager(Crypto.Default, BinarySerializer.Default, witnessOperationsManager); @@ -130,7 +133,7 @@ public void SerializeDeserialize_ClaimTransaction() // Mainnet Block=4275 / Tx=1 var witnessOperationsManager = new WitnessOperationsManager(Crypto.Default); - var transactionOperationsManager = new TransactionOperationManager(Crypto.Default, this._serializer, witnessOperationsManager); + var transactionOperationsManager = new TransactionOperationManager(Crypto.Default, this._serializer, witnessOperationsManager, new Mock().Object, new Mock().Object, new TransactionContext()); var data = "020001fda149910702cc19ed967c32f883a322f2e1713790c1398f538a42e489d485ee0000000001e72d286979ee6cb1b7e65dfddfb2e384100b8d148e7758de42e4168b71792c60c074110000000000f41cdd4b7ec41847443fa36bf8dde0009d7ecebc01414019fcb645e67b870a657fe028bcb057f866347d211dc26a25fe0570250f41d0c881113e1820ac55a029e6fc5acab80587f9bebf8b84dbd4503ba816c417b8bf522321039f07df7861c216de3b78c647b77f8b01404b400a437302b651cdf206ec1af626ac".HexToBytes(); var tx = (ClaimTransaction)_deserializer.Deserialize(data); @@ -167,7 +170,7 @@ public void SerializeDeserialize_ContractTransaction() // Mainnet Block=47320 / Tx=1 var witnessOperationsManager = new WitnessOperationsManager(Crypto.Default); - var transactionOperationsManager = new TransactionOperationManager(Crypto.Default, this._serializer, witnessOperationsManager); + var transactionOperationsManager = new TransactionOperationManager(Crypto.Default, this._serializer, witnessOperationsManager, new Mock().Object, new Mock().Object, new TransactionContext()); var data = "80000730cf62fd54fc761f291d07d68088dd81b8b35a7c444f3af8acd78a3ad4ff75d16330aac6d49da8f63cf6442c5f707317bc3e7490029af1a75b83adc0ec3b1b3e1f0f30febc956626564e8318c1f6c11cb4e36d4ded9af1be07e25b40af39d73e4b3dc630ce2e790a02d3794e60109450943358d280389e9cdba1d09f6c105d136f38e731303329124a4a2ea122fa14dbfee41b0fae43a35b29eed33ac81c699202018dfe1530509da7d029445f07d8218fcb73a0cff2acaf76659d1f5eda826b9e896eba991030c214154a649ce8ac5ee97f3c170b6574c122731f757f2a425e5eaeab62d66586012346ed8739bb9d76afb4df8254dc237eff14013041ed694c7dab2e76753d319f0000019b7cffdaa674beae0f930ebe6085af9093e5fe56b34a5c220ccdcf6efc336fc50080e03779c311005fa99d93303775fe50ca119c327759313eccfa1c01fd0401403d2ccc242d953c3b312f37b1b3aaa21a372cbb7adc1efcfc8e07f3704caa0e82aecbff5f28f17935b6432a571754060881d221a6069270c2e532f58f68248aea408cecfdd1639cae103fcf853bdf44600a6617592928fba26fa9301a222a9b4a384751453c793c2c99460a0e6e324f340abb54daf229b807cf4c8a634e5a4a1f574078891ade2cf73114de7e47b454cb88c71cca614162a7728df5f2511fd20e809ed12827139f6efae0d152cfa411d3e072f63f27f2cef4ee698327f600cc4281ff4056d91a17c56287aba509877eedc2e0541370880fb9bd4cb24a9fc754442048c29975018fbe5d16f27eeb47ca7d17d53d70fbefb8fd5c8144a82c3b72e6ca190cf1542102486fd15702c4490a26703112a5cc1d0923fd697a33406bd5a1c00e0013b09a7021024c7b7fb6c310fccf1ba33b082519d82964ea93868d676662d4a59ad548df0e7d2102aaec38470f6aad0042c6e877cfd8087d2676b0f516fddd362801b9bd3936399e2103b209fd4f53a7170ea4444e0cb0a6bb6a53c2bd016926989cf85f9b0fba17a70c2103b8d9d5771d8f513aa0869b9cc8d50986403b78c6da36890638c3d46a5adce04a2102ca0e27697b9c248f6f16e085fd0061e26f44da85b58ee835c110caa5ec3ba5542102df48f60e8f3e01c48ff40b9b7f1310d7a8b2a193188befe1c2e3df740e89509357ae".HexToBytes(); var tx = (ContractTransaction)_deserializer.Deserialize(data); @@ -216,7 +219,7 @@ public void SerializeDeserialize_IssueTransaction() // Mainnet Block=12285 / Tx=3 var witnessOperationsManager = new WitnessOperationsManager(Crypto.Default); - var transactionOperationsManager = new TransactionOperationManager(Crypto.Default, this._serializer, witnessOperationsManager); + var transactionOperationsManager = new TransactionOperationManager(Crypto.Default, this._serializer, witnessOperationsManager, new Mock().Object, new Mock().Object, new TransactionContext()); var data = "010000017ded1c83bd63e8871c8c2ad57607fe1423e8796606f2f5c2fe25be3f27f89a430000037ded1c83bd63e8871c8c2ad57607fe1423e8796606f2f5c2fe25be3f27f89a43001f8ed117000000f41cdd4b7ec41847443fa36bf8dde0009d7ecebc7ded1c83bd63e8871c8c2ad57607fe1423e8796606f2f5c2fe25be3f27f89a4300e1f5050000000055d6bc2c5a139c894df2344e03d1d2e1fbb7b609e72d286979ee6cb1b7e65dfddfb2e384100b8d148e7758de42e4168b71792c6040469af32a020000f41cdd4b7ec41847443fa36bf8dde0009d7ecebc014140420d9cdc020c525f95ae8464f7c51d0b84ee820e0073536a658f35428bd44e1941f4b1697a27cbdf3975da3366db6d3e6ec8e4aef3c50eff376a330bf728b5b42321039f07df7861c216de3b78c647b77f8b01404b400a437302b651cdf206ec1af626ac".HexToBytes(); var tx = (IssueTransaction)_deserializer.Deserialize(data); @@ -259,7 +262,7 @@ public void SerializeDeserialize_MinerTransaction() // Mainnet Block=1 / tx=0 var witnessOperationsManager = new WitnessOperationsManager(Crypto.Default); - var transactionOperationsManager = new TransactionOperationManager(Crypto.Default, this._serializer, witnessOperationsManager); + var transactionOperationsManager = new TransactionOperationManager(Crypto.Default, this._serializer, witnessOperationsManager, new Mock().Object, new Mock().Object, new TransactionContext()); var data = "00004490d0bb00000000".HexToBytes(); var tx = (MinerTransaction)_deserializer.Deserialize(data); @@ -283,7 +286,7 @@ public void SerializeDeserialize_InvocationTransaction() // Mainnet Block=2421128 / Tx=7 var witnessOperationsManager = new WitnessOperationsManager(Crypto.Default); - var transactionOperationsManager = new TransactionOperationManager(Crypto.Default, this._serializer, witnessOperationsManager); + var transactionOperationsManager = new TransactionOperationManager(Crypto.Default, this._serializer, witnessOperationsManager, new Mock().Object, new Mock().Object, new TransactionContext()); var data = "d1015e0800e1f50500000000209b7cffdaa674beae0f930ebe6085af9093e5fe56b34a5c220ccdcf6efc336fc5141e542e30389997d4c076ed65d0a7438719969cd653c1076465706f73697467bd097b2fcf70e1fd30a5c3ef51e662feeafeba0100000000000000000001a50be4db475e02e665229d22e82d8820e5bf8b4022c60a5806d9f1c801672cb10100019b7cffdaa674beae0f930ebe6085af9093e5fe56b34a5c220ccdcf6efc336fc500e1f50500000000bd097b2fcf70e1fd30a5c3ef51e662feeafeba010141409d689aa663e04da2b74d1eba6608e4a3bacdd416a68b0102df7072e25263b63a7bfd1de1d2d3c951efa3c10c456ab41f6e3a6edaa021a309c6e31e12604132922321021958d772f0cb49220752c74c8ff6e873b8b3f69905d32c2d688cfae570fb98e0ac".HexToBytes(); var tx = (InvocationTransaction)_deserializer.Deserialize(data); @@ -322,7 +325,7 @@ public void SerializeDeserialize_RegisterTransaction() // Mainnet Block=4329 / Tx=1 var witnessOperationsManager = new WitnessOperationsManager(Crypto.Default); - var transactionOperationsManager = new TransactionOperationManager(Crypto.Default, this._serializer, witnessOperationsManager); + var transactionOperationsManager = new TransactionOperationManager(Crypto.Default, this._serializer, witnessOperationsManager, new Mock().Object, new Mock().Object, new TransactionContext()); var data = "400060335b7b226c616e67223a227a682d434e222c226e616d65223a2248656c6c6f20416e74536861726573204d61696e6e6574227d5d000084d71700000008039f07df7861c216de3b78c647b77f8b01404b400a437302b651cdf206ec1af626f41cdd4b7ec41847443fa36bf8dde0009d7ecebc0001b3ba761da52f1f5c7ce0e069707a3235613e77263b9da5dcff0737f2d09ea1f5000001e72d286979ee6cb1b7e65dfddfb2e384100b8d148e7758de42e4168b71792c6040bad59736020000f41cdd4b7ec41847443fa36bf8dde0009d7ecebc0141403af6b2ad6f7630f81eaaff485073c0fe4f337102d1ecf0a48ed9bcfbd4a4bbeb5d7ae26f7dd5e0e04527b313187dfe6a6a0cd7f85fd0ce431f609acce1d34aff2321039f07df7861c216de3b78c647b77f8b01404b400a437302b651cdf206ec1af626ac".HexToBytes(); #pragma warning disable CS0612 // Type or member is obsolete @@ -367,7 +370,7 @@ public void SerializeDeserialize_StateTransaction() // Mainnet Block=2394986 / Tx=6 var witnessOperationsManager = new WitnessOperationsManager(Crypto.Default); - var transactionOperationsManager = new TransactionOperationManager(Crypto.Default, this._serializer, witnessOperationsManager); + var transactionOperationsManager = new TransactionOperationManager(Crypto.Default, this._serializer, witnessOperationsManager, new Mock().Object, new Mock().Object, new TransactionContext()); var data = "9000014821025bdf3f181f53e9696227843950deb72dcd374ded17c057159513c3d0abe20b640a52656769737465726564010100015a8e6d99a868ae249878516ac521441b3f5098221ce15bcdd712efb58dda494900000001414098910b485b34a52340ac3baab13a63695b5ca44538c968ca6f2aa540654e8394ee08cc7a312144f794e780f56510f5f581e1df41859813d4bb3746b02fab15bb2321025bdf3f181f53e9696227843950deb72dcd374ded17c057159513c3d0abe20b64ac".HexToBytes(); var tx = (StateTransaction)_deserializer.Deserialize(data); @@ -406,7 +409,7 @@ public void SerializeDeserialize_PublishTransaction() // Mainnet Block=917083 / Tx=1 var witnessOperationsManager = new WitnessOperationsManager(Crypto.Default); - var transactionOperationsManager = new TransactionOperationManager(Crypto.Default, this._serializer, witnessOperationsManager); + var transactionOperationsManager = new TransactionOperationManager(Crypto.Default, this._serializer, witnessOperationsManager, new Mock().Object, new Mock().Object, new TransactionContext()); var data = "d000fd8f09746b4c04000000004c04000000004c04000000004c04000000004c04000000004c04000000004c04000000004c04000000004c04000000004c04000000004c04000000004c04000000004c04000000004c04000000004c04000000004c04000000004c04000000004c04000000004c04000000004c04000000004c04000000004c04000000004c04000000004c04000000004c040000000061744c0403000000936c766b9479744c0406000000936c766b9479617cac744c0406000000948c6c766b947275744c0406000000948c6c766b9479641b004c0401000000744c0407000000948c6c766b94727562b207744c0400000000936c766b9479744c0406000000936c766b9479617cac4c04000000009c744c0408000000948c6c766b947275744c0408000000948c6c766b9479641b004c0400000000744c0407000000948c6c766b947275625607744c0404000000936c766b9479744c0409000000948c6c766b947275744c0409000000948c6c766b947964400061744c0401000000936c766b9479744c0400000000948c6c766b947275744c0402000000936c766b9479744c0401000000948c6c766b94727561623d0061744c0402000000936c766b9479744c0400000000948c6c766b947275744c0401000000936c766b9479744c0401000000948c6c766b947275614c0400000000744c0402000000948c6c766b9472754c0400000000744c0403000000948c6c766b94727561682953797374656d2e457865637574696f6e456e67696e652e476574536372697074436f6e7461696e6572616823416e745368617265732e5472616e73616374696f6e2e4765745265666572656e636573744c0404000000948c6c766b94727561744c0404000000948c6c766b9479744c040a000000948c6c766b9472754c0400000000744c040b000000948c6c766b947275629501744c040a000000948c6c766b9479744c040b000000948c6c766b9479c3744c040c000000948c6c766b94727561744c040c000000948c6c766b947961681e416e745368617265732e4f75747075742e4765745363726970744861736861682953797374656d2e457865637574696f6e456e67696e652e476574456e7472795363726970744861736887744c040d000000948c6c766b947275744c040d000000948c6c766b947964c70061744c040c000000948c6c766b947961681b416e745368617265732e4f75747075742e47657441737365744964744c0400000000948c6c766b9479874c04000000009c744c040e000000948c6c766b947275744c040e000000948c6c766b9479641b004c0400000000744c0407000000948c6c766b94727562cd04744c0402000000948c6c766b9479744c040c000000948c6c766b9479616819416e745368617265732e4f75747075742e47657456616c756593744c0402000000948c6c766b9472756161744c040b000000948c6c766b94794c040100000093744c040b000000948c6c766b947275744c040b000000948c6c766b9479744c040a000000948c6c766b9479c09f6350fe61682953797374656d2e457865637574696f6e456e67696e652e476574536372697074436f6e7461696e6572616820416e745368617265732e5472616e73616374696f6e2e4765744f757470757473744c0405000000948c6c766b94727561744c0405000000948c6c766b9479744c040f000000948c6c766b9472754c0400000000744c0410000000948c6c766b947275621c02744c040f000000948c6c766b9479744c0410000000948c6c766b9479c3744c0411000000948c6c766b94727561744c0411000000948c6c766b947961681e416e745368617265732e4f75747075742e4765745363726970744861736861682953797374656d2e457865637574696f6e456e67696e652e476574456e7472795363726970744861736887744c0412000000948c6c766b947275744c0412000000948c6c766b9479644e0161744c0411000000948c6c766b947961681b416e745368617265732e4f75747075742e47657441737365744964744c0400000000948c6c766b947987744c0413000000948c6c766b947275744c0413000000948c6c766b9479644e00744c0402000000948c6c766b9479744c0411000000948c6c766b9479616819416e745368617265732e4f75747075742e47657456616c756594744c0402000000948c6c766b94727562a600744c0411000000948c6c766b947961681b416e745368617265732e4f75747075742e47657441737365744964744c0401000000948c6c766b947987744c0414000000948c6c766b947275744c0414000000948c6c766b9479644b00744c0403000000948c6c766b9479744c0411000000948c6c766b9479616819416e745368617265732e4f75747075742e47657456616c756593744c0403000000948c6c766b9472756161744c0410000000948c6c766b94794c040100000093744c0410000000948c6c766b947275744c0410000000948c6c766b9479744c040f000000948c6c766b9479c09f63c9fd744c0402000000948c6c766b94794c0400000000a1744c0415000000948c6c766b947275744c0415000000948c6c766b9479641b004c0401000000744c0407000000948c6c766b947275622301744c0404000000936c766b9479744c0416000000948c6c766b947275744c0416000000948c6c766b947964720061744c0403000000948c6c766b94794c0400e1f50595744c0402000000948c6c766b9479744c0405000000936c766b9479959f744c0417000000948c6c766b947275744c0417000000948c6c766b9479641b004c0400000000744c0407000000948c6c766b947275628b0061626f0061744c0402000000948c6c766b94794c0400e1f50595744c0403000000948c6c766b9479744c0405000000936c766b947995a0744c0418000000948c6c766b947275744c0418000000948c6c766b9479641b004c0400000000744c0407000000948c6c766b947275621c00614c0401000000744c0407000000948c6c766b947275620300744c0407000000948c6c766b947961748c6c766b946d748c6c766b946d748c6c766b946d748c6c766b946d748c6c766b946d748c6c766b946d748c6c766b946d748c6c766b946d748c6c766b946d748c6c766b946d748c6c766b946d748c6c766b946d748c6c766b946d748c6c766b946d748c6c766b946d748c6c766b946d748c6c766b946d748c6c766b946d748c6c766b946d748c6c766b946d748c6c766b946d748c6c766b946d748c6c766b946d748c6c766b946d748c6c766b946d746c768c6b946d746c768c6b946d746c768c6b946d746c768c6b946d746c768c6b946d746c768c6b946d746c768c6b946d6c75660703040403010200010e4167656e6379436f6e74726163740e322e302e312d70726576696577310a4572696b205a68616e67126572696b40616e747368617265732e6f7267134167656e637920436f6e747261637420322e3000017d87a0660bbc929d5eccde32787fcfc790c719cff5dd848c48a2a25eff62bf68000001e72d286979ee6cb1b7e65dfddfb2e384100b8d148e7758de42e4168b71792c6000e1f50500000000ae0211ab29b392cfc71f6bc2a44358634bb22a2e01414086270040b5378a1b9afb5387e705d381afd19f08ee9dd3d5a3ec164132c5085e2e7298a172fabfae827044acc81393e8ee3f3eae514bbb523c6dc2db0b03c456232102abab730e3b83ae352a1d5210d8c4dac9cf2cacc6baf479709d7b989c2151b867ac".HexToBytes(); #pragma warning disable CS0612 // Type or member is obsolete @@ -460,7 +463,7 @@ public void SerializeDeserialize_EnrollmentTransaction() // Mainnet Block=47293 / Tx=1 var witnessOperationsManager = new WitnessOperationsManager(Crypto.Default); - var transactionOperationsManager = new TransactionOperationManager(Crypto.Default, this._serializer, witnessOperationsManager); + var transactionOperationsManager = new TransactionOperationManager(Crypto.Default, this._serializer, witnessOperationsManager, new Mock().Object, new Mock().Object, new TransactionContext()); var data = "200003b209fd4f53a7170ea4444e0cb0a6bb6a53c2bd016926989cf85f9b0fba17a70c0001f2f5be8a2d2d3d62e1601646b1c8b4ab58b8ee1595caf3e4a0bbfefe029719e2000001e72d286979ee6cb1b7e65dfddfb2e384100b8d148e7758de42e4168b71792c6000e1f505000000009f2d1729a79436148dc442c25f41335ef9f78bbd014140831597a1f22cba5fb4aa85ade9629a8fd18b46a05ba576a0ab71bcccb6e3fba9593555951f219baeb3368e0c2d722694455403d191d200177afb8f5ac69b5566232103b209fd4f53a7170ea4444e0cb0a6bb6a53c2bd016926989cf85f9b0fba17a70cac".HexToBytes(); #pragma warning disable CS0612 // Type or member is obsolete diff --git a/test/NeoSharp.Core.Test/Serializers/UtBinarySerializerTx.cs b/test/NeoSharp.Core.Test/Serializers/UtBinarySerializerTx.cs index fd0a74fb..4806fb15 100644 --- a/test/NeoSharp.Core.Test/Serializers/UtBinarySerializerTx.cs +++ b/test/NeoSharp.Core.Test/Serializers/UtBinarySerializerTx.cs @@ -2,7 +2,9 @@ using System.Collections.Generic; using System.Linq; using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; using NeoSharp.BinarySerialization; +using NeoSharp.Core.Blockchain; using NeoSharp.Core.Cryptography; using NeoSharp.Core.Models; using NeoSharp.Core.Models.OperationManger; @@ -313,7 +315,7 @@ public void SerializeDeserialize_ClaimTransaction() private void FillRandomTx(Transaction tx) { var witnessOperationsManager = new WitnessOperationsManager(Crypto.Default); - var transactionOperationsManager = new TransactionOperationManager(Crypto.Default, this._serializer, witnessOperationsManager); + var transactionOperationsManager = new TransactionOperationManager(Crypto.Default, this._serializer, witnessOperationsManager, new Mock().Object, new Mock().Object, new TransactionContext()); tx.Attributes = RandomTransactionAtrributes().ToArray(); tx.Inputs = RandomCoinReferences(_random.Next(1, 255)).ToArray(); @@ -326,7 +328,7 @@ private void FillRandomTx(Transaction tx) void EqualTx(Transaction original, params Transaction[] copies) { var witnessOperationsManager = new WitnessOperationsManager(Crypto.Default); - var transactionOperationsManager = new TransactionOperationManager(Crypto.Default, this._serializer, witnessOperationsManager); + var transactionOperationsManager = new TransactionOperationManager(Crypto.Default, this._serializer, witnessOperationsManager, new Mock().Object, new Mock().Object, new TransactionContext()); foreach (var copy in copies) {