private void OnGetHeadersMessageReceived(GetBlocksPayload payload) { UInt256 hash = payload.HashStart; int count = payload.Count <0 || payload.Count> HeadersPayload.MaxHeadersCount ? HeadersPayload.MaxHeadersCount : payload.Count; DataCache <UInt256, TrimmedBlock> cache = Blockchain.Singleton.Store.GetBlocks(); TrimmedBlock state = cache.TryGet(hash); if (state == null) { return; } List <Header> headers = new List <Header>(); for (uint i = 1; i <= count; i++) { uint index = state.Index + i; hash = Blockchain.Singleton.GetBlockHash(index); if (hash == null) { break; } Header header = cache.TryGet(hash)?.Header; if (header == null) { break; } headers.Add(header); } if (headers.Count == 0) { return; } Context.Parent.Tell(Message.Create(MessageCommand.Headers, HeadersPayload.Create(headers))); }
public void TestGetIsBlock() { TrimmedBlock block = GetTrimmedBlockWithNoTransaction(); block.Hashes = new UInt256[] { TestUtils.GetTransaction().Hash }; block.IsBlock.Should().BeTrue(); }
public void TestGetSize() { TrimmedBlock tblock = GetTrimmedBlockWithNoTransaction(); tblock.Hashes = new UInt256[] { TestUtils.GetTransaction().Hash }; tblock.Size.Should().Be(146); }
protected virtual JObject GetRawTransaction(JArray _params) { UInt256 hash = UInt256.Parse(_params[0].AsString()); bool verbose = _params.Count >= 2 && _params[1].AsBoolean(); if (system.MemPool.TryGetValue(hash, out Transaction tx) && !verbose) { return(Convert.ToBase64String(tx.ToArray())); } var snapshot = system.StoreView; TransactionState state = NativeContract.Ledger.GetTransactionState(snapshot, hash); tx ??= state?.Transaction; if (tx is null) { throw new RpcException(-100, "Unknown transaction"); } if (!verbose) { return(Convert.ToBase64String(tx.ToArray())); } JObject json = Utility.TransactionToJson(tx, system.Settings); if (state is not null) { TrimmedBlock block = NativeContract.Ledger.GetTrimmedBlock(snapshot, NativeContract.Ledger.GetBlockHash(snapshot, state.BlockIndex)); json["blockhash"] = block.Hash.ToString(); json["confirmations"] = NativeContract.Ledger.CurrentIndex(snapshot) - block.Index + 1; json["blocktime"] = block.Header.Timestamp; } return(json); }
internal bool Verify(ProtocolSettings settings, DataCache snapshot) { if (PrimaryIndex >= settings.ValidatorsCount) { return(false); } TrimmedBlock prev = NativeContract.Ledger.GetTrimmedBlock(snapshot, PrevHash); if (prev is null) { return(false); } if (prev.Index + 1 != Index) { return(false); } if (prev.Header.Timestamp >= Timestamp) { return(false); } if (!this.VerifyWitnesses(settings, snapshot, 1_00000000)) { return(false); } return(true); }
private bool CheckValidators(ApplicationEngine engine) { UInt256 prev_hash = engine.Snapshot.PersistingBlock.PrevHash; TrimmedBlock prev_block = engine.Snapshot.Blocks[prev_hash]; return(InteropService.CheckWitness(engine, prev_block.NextConsensus)); }
private void OnGetBlocksMessageReceived(GetBlocksPayload payload) { UInt256 hash = payload.HashStart; int count = payload.Count <0 || payload.Count> InvPayload.MaxHashesCount ? InvPayload.MaxHashesCount : payload.Count; TrimmedBlock state = Blockchain.Singleton.Store.GetBlocks().TryGet(hash); if (state == null) { return; } List <UInt256> hashes = new List <UInt256>(); for (uint i = 1; i <= count; i++) { uint index = state.Index + i; if (index > Blockchain.Singleton.Height) { break; } hash = Blockchain.Singleton.GetBlockHash(index); if (hash == null) { break; } hashes.Add(hash); } if (hashes.Count == 0) { return; } Context.Parent.Tell(Message.Create(MessageCommand.Inv, InvPayload.Create(InventoryType.Block, hashes.ToArray()))); }
public void TestVerifyWitnesses() { var mockSnapshot1 = new Mock <Snapshot>(); UInt256 index1 = UInt256.Parse("0xa400ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff01"); TestDataCache <UInt256, TrimmedBlock> testDataCache1 = new TestDataCache <UInt256, TrimmedBlock>(); testDataCache1.Add(index1, new TrimmedBlock()); testDataCache1.Delete(index1); mockSnapshot1.SetupGet(p => p.Blocks).Returns(testDataCache1); Assert.AreEqual(false, Neo.SmartContract.Helper.VerifyWitnesses(new Header() { PrevHash = index1 }, mockSnapshot1.Object, 100)); var mockSnapshot2 = new Mock <Snapshot>(); UInt256 index2 = UInt256.Parse("0xa400ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff01"); TrimmedBlock block2 = new TrimmedBlock(); block2.NextConsensus = UInt160.Zero; TestDataCache <UInt256, TrimmedBlock> testDataCache21 = new TestDataCache <UInt256, TrimmedBlock>(); testDataCache21.Add(index2, block2); Header header2 = new Header() { PrevHash = index2, Witness = new Witness { VerificationScript = new byte[0] } }; mockSnapshot2.SetupGet(p => p.Blocks).Returns(testDataCache21); TestDataCache <UInt160, ContractState> testDataCache22 = new TestDataCache <UInt160, ContractState>(); testDataCache22.Add(UInt160.Zero, new ContractState()); testDataCache22.Delete(UInt160.Zero); mockSnapshot2.SetupGet(p => p.Contracts).Returns(testDataCache22); Assert.AreEqual(false, Neo.SmartContract.Helper.VerifyWitnesses(header2, mockSnapshot2.Object, 100)); var mockSnapshot3 = new Mock <Snapshot>(); UInt256 index3 = UInt256.Parse("0xa400ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff01"); TrimmedBlock block3 = new TrimmedBlock(); block3.NextConsensus = UInt160.Zero; TestDataCache <UInt256, TrimmedBlock> testDataCache31 = new TestDataCache <UInt256, TrimmedBlock>(); testDataCache31.Add(index3, block3); Header header3 = new Header() { PrevHash = index3, Witness = new Witness { VerificationScript = new byte[0] } }; mockSnapshot3.SetupGet(p => p.Blocks).Returns(testDataCache31); TestDataCache <UInt160, ContractState> testDataCache32 = new TestDataCache <UInt160, ContractState>(); testDataCache32.Add(UInt160.Zero, new ContractState()); mockSnapshot3.SetupGet(p => p.Contracts).Returns(testDataCache32); Assert.AreEqual(false, Neo.SmartContract.Helper.VerifyWitnesses(header3, mockSnapshot3.Object, 100)); }
public void TestGetHeader() { TrimmedBlock tblock = GetTrimmedBlockWithNoTransaction(); Header header = tblock.Header; header.PrevHash.Should().Be(UInt256.Parse("0xa400ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff01")); header.MerkleRoot.Should().Be(UInt256.Parse("0xa400ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff02")); }
public bool ContainsBlock(UInt256 hash) { TrimmedBlock state = Blocks.TryGet(hash); if (state == null) { return(false); } return(state.IsBlock); }
public void TestClone() { TrimmedBlock tblock = GetTrimmedBlockWithNoTransaction(); tblock.Hashes = new UInt256[] { TestUtils.GetTransaction().Hash }; ICloneable <TrimmedBlock> cloneable = tblock; var clonedBlock = cloneable.Clone(); clonedBlock.ToJson().ToString().Should().Be(tblock.ToJson().ToString()); }
public static UInt256 GetNextBlockHash(this IPersistence persistence, UInt256 hash) { TrimmedBlock state = persistence.Blocks.TryGet(hash); if (state == null) { return(null); } return(Blockchain.Singleton.GetBlockHash(state.Index + 1)); }
public static bool ContainsBlock(this IPersistence persistence, UInt256 hash) { TrimmedBlock state = persistence.Blocks.TryGet(hash); if (state == null) { return(false); } return(state.IsBlock); }
public void TestFromReplica() { TrimmedBlock tblock = GetTrimmedBlockWithNoTransaction(); tblock.Hashes = new UInt256[] { TestUtils.GetTransaction().Hash }; ICloneable <TrimmedBlock> cloneable = new TrimmedBlock(); cloneable.FromReplica(tblock); ((TrimmedBlock)cloneable).ToJson().ToString().Should().Be(tblock.ToJson().ToString()); }
public static Block GetBlock(this IPersistence persistence, UInt256 hash) { TrimmedBlock state = persistence.Blocks.TryGet(hash); if (state == null) { return(null); } if (!state.IsBlock) { return(null); } return(state.GetBlock(persistence.Transactions)); }
public Block GetBlock(UInt256 hash) { TrimmedBlock state = Blocks.TryGet(hash); if (state == null) { return(null); } if (!state.IsBlock) { return(null); } return(state.GetBlock(Transactions)); }
UInt160[] IVerifiable.GetScriptHashesForVerifying(DataCache snapshot) { if (PrevHash == UInt256.Zero) { return new[] { Witness.ScriptHash } } ; TrimmedBlock prev = NativeContract.Ledger.GetTrimmedBlock(snapshot, PrevHash); if (prev is null) { throw new InvalidOperationException(); } return(new[] { prev.Header.NextConsensus }); }
public void TestVerifyWitnesses() { var snapshot1 = Blockchain.Singleton.GetSnapshot(); UInt256 index1 = UInt256.Parse("0xa400ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff01"); snapshot1.Blocks.Add(index1, new TrimmedBlock()); snapshot1.Blocks.Delete(index1); Assert.AreEqual(false, Neo.SmartContract.Helper.VerifyWitnesses(new Header() { PrevHash = index1 }, snapshot1, 100)); var snapshot2 = Blockchain.Singleton.GetSnapshot(); UInt256 index2 = UInt256.Parse("0xa400ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff01"); TrimmedBlock block2 = new TrimmedBlock(); block2.NextConsensus = UInt160.Zero; snapshot2.Blocks.Add(index2, block2); Header header2 = new Header() { PrevHash = index2, Witness = new Witness { VerificationScript = new byte[0] } }; snapshot2.Contracts.Add(UInt160.Zero, new ContractState()); snapshot2.Contracts.Delete(UInt160.Zero); Assert.AreEqual(false, Neo.SmartContract.Helper.VerifyWitnesses(header2, snapshot2, 100)); var snapshot3 = Blockchain.Singleton.GetSnapshot(); UInt256 index3 = UInt256.Parse("0xa400ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff01"); TrimmedBlock block3 = new TrimmedBlock(); block3.NextConsensus = UInt160.Zero; snapshot3.Blocks.Add(index3, block3); Header header3 = new Header() { PrevHash = index3, Witness = new Witness { VerificationScript = new byte[0] } }; snapshot3.Contracts.Add(UInt160.Zero, new ContractState() { Manifest = TestUtils.CreateDefaultManifest(UInt160.Zero, "verify"), }); Assert.AreEqual(false, Neo.SmartContract.Helper.VerifyWitnesses(header3, snapshot3, 100)); }
public void TestDeserialize() { TrimmedBlock tblock = GetTrimmedBlockWithNoTransaction(); tblock.Hashes = new UInt256[] { TestUtils.GetTransaction(UInt160.Zero).Hash }; var newBlock = new TrimmedBlock(); using (MemoryStream ms = new(1024)) using (BinaryWriter writer = new(ms)) { tblock.Serialize(writer); MemoryReader reader = new(ms.ToArray()); newBlock.Deserialize(ref reader); } tblock.Hashes.Length.Should().Be(newBlock.Hashes.Length); tblock.Header.ToJson(ProtocolSettings.Default).ToString().Should().Be(newBlock.Header.ToJson(ProtocolSettings.Default).ToString()); }
public void TestCreateDummyBlock() { var mockSnapshot = new Mock <Snapshot>(); UInt256 currentBlockHash = UInt256.Parse("0x0000000000000000000000000000000000000000000000000000000000000000"); TrimmedBlock block = new TrimmedBlock(); var cache = new TestDataCache <UInt256, TrimmedBlock>(); cache.Add(currentBlockHash, block); mockSnapshot.SetupGet(p => p.Blocks).Returns(cache); TestMetaDataCache <HashIndexState> testCache = new TestMetaDataCache <HashIndexState>(); mockSnapshot.SetupGet(p => p.BlockHashIndex).Returns(testCache); byte[] SyscallSystemRuntimeCheckWitnessHash = new byte[] { 0x68, 0xf8, 0x27, 0xec, 0x8c }; ApplicationEngine.Run(SyscallSystemRuntimeCheckWitnessHash, mockSnapshot.Object); mockSnapshot.Object.PersistingBlock.Version.Should().Be(0); mockSnapshot.Object.PersistingBlock.PrevHash.Should().Be(currentBlockHash); mockSnapshot.Object.PersistingBlock.MerkleRoot.Should().Be(new UInt256()); }
public void TestDeserialize() { TrimmedBlock tblock = GetTrimmedBlockWithNoTransaction(); tblock.Hashes = new UInt256[] { TestUtils.GetTransaction(UInt160.Zero).Hash }; var newBlock = new TrimmedBlock(); using (MemoryStream ms = new MemoryStream(1024)) using (BinaryWriter writer = new BinaryWriter(ms)) using (BinaryReader reader = new BinaryReader(ms)) { tblock.Serialize(writer); ms.Seek(0, SeekOrigin.Begin); newBlock.Deserialize(reader); } tblock.Hashes.Length.Should().Be(newBlock.Hashes.Length); tblock.Header.ToJson().ToString().Should().Be(newBlock.Header.ToJson().ToString()); }
public void TestGetBlock() { var snapshot = TestBlockchain.GetTestSnapshot(); var tx1 = TestUtils.GetTransaction(UInt160.Zero); tx1.Script = new byte[] { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }; var state1 = new TransactionState { Transaction = tx1, BlockIndex = 1 }; var tx2 = TestUtils.GetTransaction(UInt160.Zero); tx2.Script = new byte[] { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02 }; var state2 = new TransactionState { Transaction = tx2, BlockIndex = 1 }; UT_SmartContractHelper.TransactionAdd(snapshot, state1, state2); TrimmedBlock tblock = GetTrimmedBlockWithNoTransaction(); tblock.Hashes = new UInt256[] { tx1.Hash, tx2.Hash }; UT_SmartContractHelper.BlocksAdd(snapshot, tblock.Hash, tblock); Block block = NativeContract.Ledger.GetBlock(snapshot, tblock.Hash); block.Index.Should().Be(1); block.MerkleRoot.Should().Be(UInt256.Parse("0xa400ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff02")); block.Transactions.Length.Should().Be(2); block.Transactions[0].Hash.Should().Be(tx1.Hash); block.Witness.InvocationScript.ToHexString().Should().Be(tblock.Header.Witness.InvocationScript.ToHexString()); block.Witness.VerificationScript.ToHexString().Should().Be(tblock.Header.Witness.VerificationScript.ToHexString()); }
protected internal Transaction GetTransactionFromBlock(byte[] blockIndexOrHash, int txIndex) { UInt256 hash; if (blockIndexOrHash.Length < UInt256.Length) { BigInteger bi = new BigInteger(blockIndexOrHash); if (bi < uint.MinValue || bi > uint.MaxValue) { throw new ArgumentOutOfRangeException(nameof(blockIndexOrHash)); } hash = Blockchain.Singleton.GetBlockHash((uint)bi); } else if (blockIndexOrHash.Length == UInt256.Length) { hash = new UInt256(blockIndexOrHash); } else { throw new ArgumentException(); } if (hash is null) { return(null); } TrimmedBlock block = Snapshot.Blocks.TryGet(hash); if (block is null) { return(null); } if (!IsTraceableBlock(Snapshot, block.Index)) { return(null); } if (txIndex < 0 || txIndex >= block.Hashes.Length - 1) { throw new ArgumentOutOfRangeException(nameof(txIndex)); } return(Snapshot.GetTransaction(block.Hashes[txIndex + 1])); }
internal bool Verify(DataCache snapshot) { TrimmedBlock prev = NativeContract.Ledger.GetTrimmedBlock(snapshot, PrevHash); if (prev is null) { return(false); } if (prev.Index + 1 != Index) { return(false); } if (prev.Header.Timestamp >= Timestamp) { return(false); } if (!this.VerifyWitnesses(snapshot, 1_00000000)) { return(false); } return(true); }
public void TestGetBlock() { var snapshot = Blockchain.Singleton.GetSnapshot(); var tx1 = TestUtils.GetTransaction(); tx1.Script = new byte[] { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }; var state1 = new TransactionState { Transaction = tx1, BlockIndex = 1 }; var tx2 = TestUtils.GetTransaction(); tx2.Script = new byte[] { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02 }; var state2 = new TransactionState { Transaction = tx2, BlockIndex = 1 }; snapshot.Transactions.Add(tx1.Hash, state1); snapshot.Transactions.Add(tx2.Hash, state2); TrimmedBlock tblock = GetTrimmedBlockWithNoTransaction(); tblock.Hashes = new UInt256[] { tx1.Hash, tx2.Hash }; Block block = tblock.GetBlock(snapshot.Transactions); block.Index.Should().Be(1); block.MerkleRoot.Should().Be(UInt256.Parse("0xa400ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff02")); block.Transactions.Length.Should().Be(1); block.Transactions[0].Hash.Should().Be(tx2.Hash); }
public void TestGetBlock() { var cache = new TestDataCache <UInt256, TransactionState>(); var tx1 = TestUtils.GetTransaction(); tx1.Script = new byte[] { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }; var state1 = new TransactionState { Transaction = tx1, BlockIndex = 1 }; var tx2 = TestUtils.GetTransaction(); tx2.Script = new byte[] { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02 }; var state2 = new TransactionState { Transaction = tx2, BlockIndex = 1 }; cache.Add(tx1.Hash, state1); cache.Add(tx2.Hash, state2); TrimmedBlock tblock = GetTrimmedBlockWithNoTransaction(); tblock.Hashes = new UInt256[] { tx1.Hash, tx2.Hash }; Block block = tblock.GetBlock(cache); block.Index.Should().Be(1); block.MerkleRoot.Should().Be(UInt256.Parse("0xa400ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff02")); block.Transactions.Length.Should().Be(1); block.Transactions[0].Hash.Should().Be(tx2.Hash); }
private void RecordTransferHistory(DataCache snapshot, UInt160 scriptHash, UInt160 from, UInt160 to, BigInteger amount, UInt256 txHash, ref ushort transferIndex) { if (!_shouldTrackHistory) { return; } UInt256 hash = NativeContract.Ledger.CurrentHash(snapshot); uint height = NativeContract.Ledger.CurrentIndex(snapshot); TrimmedBlock block = NativeContract.Ledger.GetTrimmedBlock(snapshot, hash); if (_recordNullAddressHistory || from != UInt160.Zero) { Put(Nep17TransferSentPrefix, new Nep17TransferKey(from, block.Header.Timestamp, scriptHash, transferIndex), new Nep17Transfer { Amount = amount, UserScriptHash = to, BlockIndex = height, TxHash = txHash }); } if (_recordNullAddressHistory || to != UInt160.Zero) { Put(Nep17TransferReceivedPrefix, new Nep17TransferKey(to, block.Header.Timestamp, scriptHash, transferIndex), new Nep17Transfer { Amount = amount, UserScriptHash = from, BlockIndex = height, TxHash = txHash }); } transferIndex++; }
public void TestVerifyWitnesses() { var snapshot1 = Blockchain.Singleton.GetSnapshot(); UInt256 index1 = UInt256.Parse("0xa400ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff01"); snapshot1.Blocks.Add(index1, new TrimmedBlock()); snapshot1.Blocks.Delete(index1); Assert.AreEqual(false, Neo.SmartContract.Helper.VerifyWitnesses(new Header() { PrevHash = index1 }, snapshot1, 100)); var snapshot2 = Blockchain.Singleton.GetSnapshot(); UInt256 index2 = UInt256.Parse("0xa400ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff01"); TrimmedBlock block2 = new TrimmedBlock(); block2.NextConsensus = UInt160.Zero; snapshot2.Blocks.Add(index2, block2); Header header2 = new Header() { PrevHash = index2, Witness = new Witness { VerificationScript = new byte[0] } }; snapshot2.Contracts.Add(UInt160.Zero, new ContractState()); snapshot2.Contracts.Delete(UInt160.Zero); Assert.AreEqual(false, Neo.SmartContract.Helper.VerifyWitnesses(header2, snapshot2, 100)); var snapshot3 = Blockchain.Singleton.GetSnapshot(); UInt256 index3 = UInt256.Parse("0xa400ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff01"); TrimmedBlock block3 = new TrimmedBlock(); block3.NextConsensus = UInt160.Zero; snapshot3.Blocks.Add(index3, block3); Header header3 = new Header() { PrevHash = index3, Witness = new Witness { VerificationScript = new byte[0] } }; snapshot3.Contracts.Add(UInt160.Zero, new ContractState() { Manifest = TestUtils.CreateManifest(UInt160.Zero, "verify", ContractParameterType.Boolean, ContractParameterType.Signature), }); Assert.AreEqual(false, Neo.SmartContract.Helper.VerifyWitnesses(header3, snapshot3, 100)); // Smart contract verification var contract = new ContractState() { Script = "11".HexToBytes(), // 17 PUSH1 Manifest = TestUtils.CreateManifest(UInt160.Zero, "verify", ContractParameterType.Boolean, ContractParameterType.Signature), // Offset = 0 }; snapshot3.Contracts.Add(contract.ScriptHash, contract); var tx = new Extensions.Nep5NativeContractExtensions.ManualWitness(contract.ScriptHash) { Witnesses = new Witness[] { new Witness() { InvocationScript = new byte[0], VerificationScript = new byte[0] } } }; Assert.AreEqual(true, Neo.SmartContract.Helper.VerifyWitnesses(tx, snapshot3, 1000)); }
public static void BlocksAdd(DataCache snapshot, UInt256 hash, TrimmedBlock block) { snapshot.Add(NativeContract.Ledger.CreateStorageKey(Prefix_BlockHash, block.Index), new StorageItem(hash.ToArray(), true)); snapshot.Add(NativeContract.Ledger.CreateStorageKey(Prefix_Block, hash), new StorageItem(block.ToArray(), true)); }
public void System_Blockchain_GetBlock() { var tx = new Transaction() { Script = new byte[] { 0x01 }, Attributes = Array.Empty <TransactionAttribute>(), Signers = Array.Empty <Signer>(), NetworkFee = 0x02, SystemFee = 0x03, Nonce = 0x04, ValidUntilBlock = 0x05, Version = 0x06, Witnesses = new Witness[] { new Witness() { VerificationScript = new byte[] { 0x07 } } }, }; var block = new TrimmedBlock() { Header = new Header { Index = 0, Timestamp = 2, Witness = new Witness() { InvocationScript = Array.Empty <byte>(), VerificationScript = Array.Empty <byte>() }, PrevHash = UInt256.Zero, MerkleRoot = UInt256.Zero, PrimaryIndex = 1, NextConsensus = UInt160.Zero, }, Hashes = new[] { tx.Hash } }; var snapshot = TestBlockchain.GetTestSnapshot(); using ScriptBuilder script = new(); script.EmitDynamicCall(NativeContract.Ledger.Hash, "getBlock", block.Hash.ToArray()); // Without block var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot, settings: TestBlockchain.TheVauthSystem.Settings); engine.LoadScript(script.ToArray()); Assert.AreEqual(engine.Execute(), VMState.HALT); Assert.AreEqual(1, engine.ResultStack.Count); Assert.IsTrue(engine.ResultStack.Peek().IsNull); // Not traceable block const byte Prefix_Transaction = 11; const byte Prefix_CurrentBlock = 12; var height = snapshot[NativeContract.Ledger.CreateStorageKey(Prefix_CurrentBlock)].GetInteroperable <HashIndexState>(); height.Index = block.Index + ProtocolSettings.Default.MaxTraceableBlocks; UT_SmartContractHelper.BlocksAdd(snapshot, block.Hash, block); snapshot.Add(NativeContract.Ledger.CreateStorageKey(Prefix_Transaction, tx.Hash), new StorageItem(new TransactionState { BlockIndex = block.Index, Transaction = tx })); engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot, settings: TestBlockchain.TheVauthSystem.Settings); engine.LoadScript(script.ToArray()); Assert.AreEqual(engine.Execute(), VMState.HALT); Assert.AreEqual(1, engine.ResultStack.Count); Assert.IsTrue(engine.ResultStack.Peek().IsNull); // With block height.Index = block.Index; engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot, settings: TestBlockchain.TheVauthSystem.Settings); engine.LoadScript(script.ToArray()); Assert.AreEqual(engine.Execute(), VMState.HALT); Assert.AreEqual(1, engine.ResultStack.Count); var array = engine.ResultStack.Pop <VM.Types.Array>(); Assert.AreEqual(block.Hash, new UInt256(array[0].GetSpan())); }