diff --git a/neo.UnitTests/README.md b/neo.UnitTests/README.md
index 1b8a238e9c..48acf51de0 100644
--- a/neo.UnitTests/README.md
+++ b/neo.UnitTests/README.md
@@ -28,7 +28,6 @@ Coverage
* Header.cs
* Helper.cs
* InvocationTransaction.cs
- * IssueTransaction.cs
* MinerTransaction.cs
* SpentCoin.cs
* SpentCoinState.cs
diff --git a/neo.UnitTests/TestBlockchain.cs b/neo.UnitTests/TestBlockchain.cs
deleted file mode 100644
index 3e7e222b46..0000000000
--- a/neo.UnitTests/TestBlockchain.cs
+++ /dev/null
@@ -1,161 +0,0 @@
-using Neo.Core;
-using Neo.Cryptography.ECC;
-using Neo.IO.Caching;
-using System;
-using System.Collections.Generic;
-
-namespace Neo.UnitTests
-{
- public class TestBlockchain : Blockchain
- {
- private UInt256 _assetId;
-
- ///
- /// Return true if haven't got valid handle
- ///
- public override bool IsDisposed => false;
-
- public TestBlockchain(UInt256 assetId)
- {
- _assetId = assetId;
- }
-
- public override UInt256 CurrentBlockHash => throw new NotImplementedException();
-
- public override UInt256 CurrentHeaderHash => throw new NotImplementedException();
-
- public override uint HeaderHeight => throw new NotImplementedException();
-
- public override uint Height => throw new NotImplementedException();
-
- public override bool AddBlock(Block block)
- {
- throw new NotImplementedException();
- }
-
- public override bool ContainsBlock(UInt256 hash)
- {
- return true; // for verify in UT_Block
- }
-
- public override bool ContainsTransaction(UInt256 hash)
- {
- throw new NotImplementedException();
- }
-
- public override bool ContainsUnspent(UInt256 hash, ushort index)
- {
- throw new NotImplementedException();
- }
-
- public override MetaDataCache GetMetaData()
- {
- return new TestMetaDataCache();
- }
-
- public override DataCache GetStates()
- {
- return new TestDataCache();
- }
-
- public override void Dispose()
- {
- // do nothing
- }
-
- public override AccountState GetAccountState(UInt160 script_hash)
- {
- throw new NotImplementedException();
- }
-
- public override AssetState GetAssetState(UInt256 asset_id)
- {
- if (asset_id == UInt256.Zero) return null;
- UInt160 val = new UInt160(TestUtils.GetByteArray(20, asset_id.ToArray()[0]));
- return new AssetState() { Issuer = val };
- }
-
- public override Block GetBlock(UInt256 hash)
- {
- throw new NotImplementedException();
- }
-
- public override UInt256 GetBlockHash(uint height)
- {
- throw new NotImplementedException();
- }
-
- public override ContractState GetContract(UInt160 hash)
- {
- throw new NotImplementedException();
- }
-
- public override IEnumerable GetEnrollments()
- {
- ECPoint ecp = TestUtils.StandbyValidators[0];
- return new ValidatorState[] { new ValidatorState() { PublicKey = ecp } };
- }
-
- public override Header GetHeader(uint height)
- {
- throw new NotImplementedException();
- }
-
- public override Header GetHeader(UInt256 hash)
- {
- throw new NotImplementedException();
- }
-
- public override Block GetNextBlock(UInt256 hash)
- {
- throw new NotImplementedException();
- }
-
- public override UInt256 GetNextBlockHash(UInt256 hash)
- {
- throw new NotImplementedException();
- }
-
- public override StorageItem GetStorageItem(StorageKey key)
- {
- throw new NotImplementedException();
- }
-
- public override long GetSysFeeAmount(UInt256 hash)
- {
- throw new NotImplementedException();
- }
-
- public override Transaction GetTransaction(UInt256 hash, out int height)
- {
- height = 0;
- // take part of the trans hash and use that for the scripthash of the testtransaction
- return new TestTransaction(_assetId, TransactionType.ClaimTransaction, new UInt160(TestUtils.GetByteArray(20, hash.ToArray()[0])));
- }
-
- public override Dictionary GetUnclaimed(UInt256 hash)
- {
- throw new NotImplementedException();
- }
-
- public override TransactionOutput GetUnspent(UInt256 hash, ushort index)
- {
- throw new NotImplementedException();
- }
-
- public override IEnumerable GetUnspent(UInt256 hash)
- {
- throw new NotImplementedException();
- }
-
- public override bool IsDoubleSpend(Transaction tx)
- {
- throw new NotImplementedException();
- }
-
- protected override void AddHeaders(IEnumerable headers)
- {
- throw new NotImplementedException();
- }
- }
-}
diff --git a/neo.UnitTests/TestMetaDataCache.cs b/neo.UnitTests/TestMetaDataCache.cs
index b274b25c0a..55dca734f4 100644
--- a/neo.UnitTests/TestMetaDataCache.cs
+++ b/neo.UnitTests/TestMetaDataCache.cs
@@ -3,16 +3,24 @@
namespace Neo.UnitTests
{
- public class TestMetaDataCache : MetaDataCache where T : class, ISerializable, new()
+ public class TestMetaDataCache : MetaDataCache where T : class, ICloneable, ISerializable, new()
{
public TestMetaDataCache()
: base(null)
{
}
+ protected override void AddInternal(T item)
+ {
+ }
+
protected override T TryGetInternal()
{
return null;
}
+
+ protected override void UpdateInternal(T item)
+ {
+ }
}
}
diff --git a/neo.UnitTests/TestTransaction.cs b/neo.UnitTests/TestTransaction.cs
index 6036a8d558..a507bbeb36 100644
--- a/neo.UnitTests/TestTransaction.cs
+++ b/neo.UnitTests/TestTransaction.cs
@@ -1,7 +1,4 @@
-using Neo.Core;
-using System;
-using System.Collections.Generic;
-using System.Text;
+using Neo.Network.P2P.Payloads;
namespace Neo.UnitTests
{
diff --git a/neo.UnitTests/TestUtils.cs b/neo.UnitTests/TestUtils.cs
index ba3c595870..1e73f84cea 100644
--- a/neo.UnitTests/TestUtils.cs
+++ b/neo.UnitTests/TestUtils.cs
@@ -1,9 +1,7 @@
-using System;
-using Neo.Core;
-using Neo.Cryptography.ECC;
+using Neo.Cryptography.ECC;
+using Neo.Network.P2P.Payloads;
using Neo.VM;
-using Neo.Wallets;
-using Neo.SmartContract;
+using System;
namespace Neo.UnitTests
{
@@ -30,7 +28,7 @@ public static ClaimTransaction GetClaimTransaction()
Attributes = new TransactionAttribute[0],
Inputs = new CoinReference[0],
Outputs = new TransactionOutput[0],
- Scripts = new Witness[0]
+ Witnesses = new Witness[0]
};
}
@@ -42,48 +40,7 @@ public static MinerTransaction GetMinerTransaction()
Attributes = new TransactionAttribute[0],
Inputs = new CoinReference[0],
Outputs = new TransactionOutput[0],
- Scripts = new Witness[0]
- };
- }
-
- public static IssueTransaction GetIssueTransaction(bool inputVal, decimal outputVal, UInt256 assetId)
- {
- TestUtils.SetupTestBlockchain(assetId);
-
- CoinReference[] inputsVal;
- if (inputVal)
- {
- inputsVal = new[]
- {
- TestUtils.GetCoinReference(null)
- };
- }
- else
- {
- inputsVal = new CoinReference[0];
- }
-
- return new IssueTransaction
- {
- Attributes = new TransactionAttribute[0],
- Inputs = inputsVal,
- Outputs = new[]
- {
- new TransactionOutput
- {
- AssetId = assetId,
- Value = Fixed8.FromDecimal(outputVal),
- ScriptHash = Contract.CreateMultiSigRedeemScript(1, TestUtils.StandbyValidators).ToScriptHash()
- }
- },
- Scripts = new[]
- {
- new Witness
- {
- InvocationScript = new byte[0],
- VerificationScript = new[] { (byte)OpCode.PUSHT }
- }
- }
+ Witnesses = new Witness[0]
};
}
@@ -97,12 +54,6 @@ public static CoinReference GetCoinReference(UInt256 prevHash)
};
}
- public static void SetupTestBlockchain(UInt256 assetId)
- {
- Blockchain testBlockchain = new TestBlockchain(assetId);
- Blockchain.RegisterBlockchain(testBlockchain);
- }
-
public static void SetupHeaderWithValues(Header header, UInt256 val256, out UInt256 merkRootVal, out UInt160 val160, out uint timestampVal, out uint indexVal, out ulong consensusDataVal, out Witness scriptVal)
{
setupBlockBaseWithValues(header, val256, out merkRootVal, out val160, out timestampVal, out indexVal, out consensusDataVal, out scriptVal);
@@ -142,7 +93,7 @@ private static void setupBlockBaseWithValues(BlockBase bb, UInt256 val256, out U
InvocationScript = new byte[0],
VerificationScript = new[] { (byte)OpCode.PUSHT }
};
- bb.Script = scriptVal;
+ bb.Witness = scriptVal;
}
}
}
diff --git a/neo.UnitTests/TestVerifiable.cs b/neo.UnitTests/TestVerifiable.cs
index e02ce3b9ac..ee8877aee2 100644
--- a/neo.UnitTests/TestVerifiable.cs
+++ b/neo.UnitTests/TestVerifiable.cs
@@ -1,6 +1,7 @@
+using Neo.Network.P2P.Payloads;
+using Neo.Persistence;
using System;
using System.IO;
-using Neo.Core;
namespace Neo.UnitTests
{
@@ -8,7 +9,7 @@ public class TestVerifiable : IVerifiable
{
private string testStr = "testStr";
- public Witness[] Scripts { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
+ public Witness[] Witnesses { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
public int Size => throw new NotImplementedException();
@@ -27,7 +28,7 @@ public byte[] GetMessage()
throw new NotImplementedException();
}
- public UInt160[] GetScriptHashesForVerifying()
+ public UInt160[] GetScriptHashesForVerifying(Snapshot snapshot)
{
throw new NotImplementedException();
}
diff --git a/neo.UnitTests/UT_AccountState.cs b/neo.UnitTests/UT_AccountState.cs
index 9e18dfef87..290db33040 100644
--- a/neo.UnitTests/UT_AccountState.cs
+++ b/neo.UnitTests/UT_AccountState.cs
@@ -1,8 +1,8 @@
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
-using Neo.Core;
using Neo.Cryptography.ECC;
using Neo.IO;
+using Neo.Ledger;
using System.Collections.Generic;
using System.IO;
using System.Text;
diff --git a/neo.UnitTests/UT_AssetState.cs b/neo.UnitTests/UT_AssetState.cs
index 7dd1bbab95..a609bd86fb 100644
--- a/neo.UnitTests/UT_AssetState.cs
+++ b/neo.UnitTests/UT_AssetState.cs
@@ -1,8 +1,9 @@
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
-using Neo.Core;
using Neo.Cryptography.ECC;
using Neo.IO;
+using Neo.Ledger;
+using Neo.Network.P2P.Payloads;
using System.Globalization;
using System.IO;
using System.Text;
diff --git a/neo.UnitTests/UT_Block.cs b/neo.UnitTests/UT_Block.cs
index fce6367bab..1007eabe9c 100644
--- a/neo.UnitTests/UT_Block.cs
+++ b/neo.UnitTests/UT_Block.cs
@@ -1,7 +1,8 @@
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
-using Neo.Core;
using Neo.IO.Json;
+using Neo.Ledger;
+using Neo.Network.P2P.Payloads;
using Neo.SmartContract;
using Neo.VM;
using System.IO;
@@ -54,7 +55,7 @@ public void Header_Get()
uut.Header.Timestamp.Should().Be(timestampVal);
uut.Header.Index.Should().Be(indexVal);
uut.Header.ConsensusData.Should().Be(consensusDataVal);
- uut.Header.Script.Should().Be(scriptVal);
+ uut.Header.Witness.Should().Be(scriptVal);
}
[TestMethod]
@@ -75,7 +76,6 @@ public void Size_Get()
private IssueTransaction getIssueTransaction(bool inputVal, decimal outputVal, UInt256 assetId)
{
- TestUtils.SetupTestBlockchain(assetId);
CoinReference[] inputsVal;
if (inputVal)
@@ -104,7 +104,7 @@ private IssueTransaction getIssueTransaction(bool inputVal, decimal outputVal, U
ScriptHash = Contract.CreateMultiSigRedeemScript(1, TestUtils.StandbyValidators).ToScriptHash()
}
},
- Scripts = new[]
+ Witnesses = new[]
{
new Witness
{
@@ -117,7 +117,6 @@ private IssueTransaction getIssueTransaction(bool inputVal, decimal outputVal, U
private ContractTransaction getContractTransaction(bool inputVal, decimal outputVal, UInt256 assetId)
{
- TestUtils.SetupTestBlockchain(assetId);
CoinReference[] inputsVal;
if (inputVal)
@@ -145,7 +144,7 @@ private ContractTransaction getContractTransaction(bool inputVal, decimal output
ScriptHash = Contract.CreateMultiSigRedeemScript(1, TestUtils.StandbyValidators).ToScriptHash()
}
},
- Scripts = new[]
+ Witnesses = new[]
{
new Witness
{
@@ -275,63 +274,6 @@ public void CalculateNetFee_Out()
Block.CalculateNetFee(uut.Transactions).Should().Be(Fixed8.FromDecimal(-100));
}
- [TestMethod]
- public void CalculateNetFee_In()
- {
- UInt256 val256 = UInt256.Zero;
- UInt256 merkRootVal;
- UInt160 val160;
- uint timestampVal, indexVal;
- ulong consensusDataVal;
- Witness scriptVal;
- Transaction[] transactionsVal;
- TestUtils.SetupBlockWithValues(uut, val256, out merkRootVal, out val160, out timestampVal, out indexVal, out consensusDataVal, out scriptVal, out transactionsVal, 0);
-
- uut.Transactions = new Transaction[1] {
- getContractTransaction(true, 0, Blockchain.UtilityToken.Hash)
- };
-
- Block.CalculateNetFee(uut.Transactions).Should().Be(Fixed8.FromDecimal(50));
- }
-
- [TestMethod]
- public void CalculateNetFee_In_And_Out()
- {
- UInt256 val256 = UInt256.Zero;
- UInt256 merkRootVal;
- UInt160 val160;
- uint timestampVal, indexVal;
- ulong consensusDataVal;
- Witness scriptVal;
- Transaction[] transactionsVal;
- TestUtils.SetupBlockWithValues(uut, val256, out merkRootVal, out val160, out timestampVal, out indexVal, out consensusDataVal, out scriptVal, out transactionsVal, 0);
-
- uut.Transactions = new Transaction[1] {
- getContractTransaction(true, 100, Blockchain.UtilityToken.Hash)
- };
-
- Block.CalculateNetFee(uut.Transactions).Should().Be(Fixed8.FromDecimal(-50));
- }
-
- [TestMethod]
- public void CalculateNetFee_SystemFee()
- {
- UInt256 val256 = UInt256.Zero;
- UInt256 merkRootVal;
- UInt160 val160;
- uint timestampVal, indexVal;
- ulong consensusDataVal;
- Witness scriptVal;
- Transaction[] transactionsVal;
- TestUtils.SetupBlockWithValues(uut, val256, out merkRootVal, out val160, out timestampVal, out indexVal, out consensusDataVal, out scriptVal, out transactionsVal, 0);
-
- uut.Transactions = new Transaction[1] {
- TestUtils.GetIssueTransaction(true, 0, new UInt256(TestUtils.GetByteArray(32, 0x42)))
- };
-
- Block.CalculateNetFee(uut.Transactions).Should().Be(Fixed8.FromDecimal(-500));
- }
-
[TestMethod]
public void Serialize()
{
@@ -398,9 +340,9 @@ private void assertStandardBlockTestVals(UInt256 val256, UInt256 merkRoot, UInt1
uut.Index.Should().Be(indexVal);
uut.ConsensusData.Should().Be(consensusDataVal);
uut.NextConsensus.Should().Be(val160);
- uut.Script.InvocationScript.Length.Should().Be(0);
- uut.Script.Size.Should().Be(scriptVal.Size);
- uut.Script.VerificationScript[0].Should().Be(scriptVal.VerificationScript[0]);
+ uut.Witness.InvocationScript.Length.Should().Be(0);
+ uut.Witness.Size.Should().Be(scriptVal.Size);
+ uut.Witness.VerificationScript[0].Should().Be(scriptVal.VerificationScript[0]);
if (testTransactions)
{
uut.Transactions.Length.Should().Be(1);
@@ -456,71 +398,6 @@ public void Equals_SameHash()
uut.Equals(newBlock).Should().BeTrue();
}
- [TestMethod]
- public void Trim()
- {
- UInt256 val256 = UInt256.Zero;
- UInt256 merkRoot;
- UInt160 val160;
- uint timestampVal, indexVal;
- ulong consensusDataVal;
- Witness scriptVal;
- Transaction[] transactionsVal;
- TestUtils.SetupBlockWithValues(uut, val256, out merkRoot, out val160, out timestampVal, out indexVal, out consensusDataVal, out scriptVal, out transactionsVal, 1);
-
- byte[] data = uut.Trim();
- byte[] requiredData = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 214, 87, 42, 69, 155, 149, 217, 19, 107, 122, 113, 60, 84, 133, 202, 112, 159, 158, 250, 79, 8, 241, 194, 93, 215, 146, 103, 45, 43, 215, 91, 251, 128, 171, 4, 253, 0, 0, 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 81, 1, 214, 87, 42, 69, 155, 149, 217, 19, 107, 122, 113, 60, 84, 133, 202, 112, 159, 158, 250, 79, 8, 241, 194, 93, 215, 146, 103, 45, 43, 215, 91, 251 };
-
- data.Length.Should().Be(141);
- for (int i = 0; i < 141; i++)
- {
- data[i].Should().Be(requiredData[i]);
- }
- }
-
- [TestMethod]
- public void FromTrimmedData()
- {
- UInt256 val256 = UInt256.Zero;
- UInt256 merkRoot;
- UInt160 val160;
- uint timestampVal, indexVal;
- ulong consensusDataVal;
- Witness scriptVal;
- Transaction[] transactionsVal;
- TestUtils.SetupBlockWithValues(new Block(), val256, out merkRoot, out val160, out timestampVal, out indexVal, out consensusDataVal, out scriptVal, out transactionsVal, 1);
-
- byte[] data = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 214, 87, 42, 69, 155, 149, 217, 19, 107, 122, 113, 60, 84, 133, 202, 112, 159, 158, 250, 79, 8, 241, 194, 93, 215, 146, 103, 45, 43, 215, 91, 251, 128, 171, 4, 253, 0, 0, 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 81, 1, 214, 87, 42, 69, 155, 149, 217, 19, 107, 122, 113, 60, 84, 133, 202, 112, 159, 158, 250, 79, 8, 241, 194, 93, 215, 146, 103, 45, 43, 215, 91, 251 };
-
- uut = Block.FromTrimmedData(data, 0, x => TestUtils.GetMinerTransaction());
-
- assertStandardBlockTestVals(val256, merkRoot, val160, timestampVal, indexVal, consensusDataVal, scriptVal, transactionsVal);
- uut.Transactions[0].Should().Be(TestUtils.GetMinerTransaction());
- }
-
- [TestMethod]
- public void FromTrimmedData_MultipleTx()
- {
- UInt256 val256 = UInt256.Zero;
- UInt256 merkRoot;
- UInt160 val160;
- uint timestampVal, indexVal;
- ulong consensusDataVal;
- Witness scriptVal;
- Transaction[] transactionsVal;
- TestUtils.SetupBlockWithValues(new Block(), val256, out merkRoot, out val160, out timestampVal, out indexVal, out consensusDataVal, out scriptVal, out transactionsVal, 3);
-
- byte[] data = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 214, 87, 42, 69, 155, 149, 217, 19, 107, 122, 113, 60, 84, 133, 202, 112, 159, 158, 250, 79, 8, 241, 194, 93, 215, 146, 103, 45, 43, 215, 91, 251, 128, 171, 4, 253, 0, 0, 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 81, 3, 214, 87, 42, 69, 155, 149, 217, 19, 107, 122, 113, 60, 84, 133, 202, 112, 159, 158, 250, 79, 8, 241, 194, 93, 215, 146, 103, 45, 43, 215, 91, 251, 214, 87, 42, 69, 155, 149, 217, 19, 107, 122, 113, 60, 84, 133, 202, 112, 159, 158, 250, 79, 8, 241, 194, 93, 215, 146, 103, 45, 43, 215, 91, 251, 214, 87, 42, 69, 155, 149, 217, 19, 107, 122, 113, 60, 84, 133, 202, 112, 159, 158, 250, 79, 8, 241, 194, 93, 215, 146, 103, 45, 43, 215, 91, 251 };
-
- uut = Block.FromTrimmedData(data, 0, x => TestUtils.GetMinerTransaction());
-
- assertStandardBlockTestVals(val256, merkRoot, val160, timestampVal, indexVal, consensusDataVal, scriptVal, transactionsVal, testTransactions: false);
- uut.Transactions.Length.Should().Be(3);
- uut.Transactions[0].Should().Be(TestUtils.GetMinerTransaction());
- uut.Transactions[1].Should().Be(TestUtils.GetMinerTransaction());
- uut.Transactions[2].Should().Be(TestUtils.GetMinerTransaction());
- }
-
[TestMethod]
public void RebuildMerkleRoot_Updates()
{
@@ -583,58 +460,5 @@ public void ToJson()
((JArray)txObj[0]["scripts"]).Count.Should().Be(0);
txObj[0]["nonce"].AsNumber().Should().Be(2083236893);
}
-
- [TestMethod]
- public void Verify_CompletelyFalse()
- {
- UInt256 val256 = UInt256.Zero;
- UInt256 merkRoot;
- UInt160 val160;
- uint timestampVal, indexVal;
- ulong consensusDataVal;
- Witness scriptVal;
- Transaction[] transactionsVal;
- TestUtils.SetupBlockWithValues(uut, val256, out merkRoot, out val160, out timestampVal, out indexVal, out consensusDataVal, out scriptVal, out transactionsVal, 1);
-
- TestUtils.SetupTestBlockchain(UInt256.Zero);
-
- uut.Verify(false).Should().BeTrue();
- }
-
- [TestMethod]
- public void Verify_CompletelyFalse_MinerTransaction_After_First()
- {
- UInt256 val256 = UInt256.Zero;
- UInt256 merkRoot;
- UInt160 val160;
- uint timestampVal, indexVal;
- ulong consensusDataVal;
- Witness scriptVal;
- Transaction[] transactionsVal;
- TestUtils.SetupBlockWithValues(uut, val256, out merkRoot, out val160, out timestampVal, out indexVal, out consensusDataVal, out scriptVal, out transactionsVal, 3);
-
- TestUtils.SetupTestBlockchain(UInt256.Zero);
-
- uut.Verify(false).Should().BeFalse();
- }
-
- [TestMethod]
- public void Verify_CompletelyTrue_NextConsensus_Fail()
- {
- UInt256 val256 = UInt256.Zero;
- UInt256 merkRoot;
- UInt160 val160;
- uint timestampVal, indexVal;
- ulong consensusDataVal;
- Witness scriptVal;
- Transaction[] transactionsVal;
- TestUtils.SetupBlockWithValues(uut, val256, out merkRoot, out val160, out timestampVal, out indexVal, out consensusDataVal, out scriptVal, out transactionsVal, 1);
- // passing NextConsensus below
- // uut.NextConsensus = new UInt160(new byte[] { 23, 52, 98, 203, 0, 206, 138, 37, 140, 16, 251, 231, 61, 120, 218, 200, 182, 125, 120, 73 });
-
- TestUtils.SetupTestBlockchain(UInt256.Zero);
-
- uut.Verify(true).Should().BeFalse();
- }
}
}
diff --git a/neo.UnitTests/UT_ClaimTransaction.cs b/neo.UnitTests/UT_ClaimTransaction.cs
index 969b166abb..32353052f2 100644
--- a/neo.UnitTests/UT_ClaimTransaction.cs
+++ b/neo.UnitTests/UT_ClaimTransaction.cs
@@ -1,11 +1,7 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Text;
-using FluentAssertions;
+using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
-using Neo.Core;
using Neo.IO.Json;
+using Neo.Network.P2P.Payloads;
namespace Neo.UnitTests
{
@@ -51,7 +47,7 @@ public void Size__Get_0_Claims()
uut.Attributes = new TransactionAttribute[0];
uut.Inputs = new CoinReference[0];
uut.Outputs = new TransactionOutput[0];
- uut.Scripts = new Witness[0];
+ uut.Witnesses = new Witness[0];
uut.Size.Should().Be(7); // 1, 1, 1, 1, 1, 1 + claims 1
}
@@ -64,7 +60,7 @@ public void Size__Get_1_Claims()
uut.Attributes = new TransactionAttribute[0];
uut.Inputs = new CoinReference[0];
uut.Outputs = new TransactionOutput[0];
- uut.Scripts = new Witness[0];
+ uut.Witnesses = new Witness[0];
uut.Size.Should().Be(41); // 1, 1, 1, 1, 1, 1 + claims 35
}
@@ -77,56 +73,11 @@ public void Size__Get_3_Claims()
uut.Attributes = new TransactionAttribute[0];
uut.Inputs = new CoinReference[0];
uut.Outputs = new TransactionOutput[0];
- uut.Scripts = new Witness[0];
+ uut.Witnesses = new Witness[0];
uut.Size.Should().Be(109); // 1, 1, 1, 1, 1, 1 + claims 103
}
- [TestMethod]
- public void GetScriptHashesForVerifying_0_Claims()
- {
- uut.Claims = new CoinReference[0];
- uut.Attributes = new TransactionAttribute[0];
- uut.Inputs = new CoinReference[0];
- uut.Outputs = new TransactionOutput[0];
- uut.Scripts = new Witness[0];
-
- uut.GetScriptHashesForVerifying().Length.Should().Be(0);
- }
-
- [TestMethod]
- public void GetScriptHashesForVerifying_1_Claim()
- {
- CoinReference[] refs = new[] { TestUtils.GetCoinReference(new UInt256(TestUtils.GetByteArray(32, 0x42))) };
- uut.Claims = refs;
- uut.Attributes = new TransactionAttribute[0];
- uut.Inputs = new CoinReference[0];
- uut.Outputs = new TransactionOutput[0];
- uut.Scripts = new Witness[0];
-
- TestUtils.SetupTestBlockchain(UInt256.Zero);
-
- UInt160[] res = uut.GetScriptHashesForVerifying();
- res.Length.Should().Be(1);
- }
-
-
- [TestMethod]
- public void GetScriptHashesForVerifying_2_Claim()
- {
- CoinReference[] refs = new[] { TestUtils.GetCoinReference(new UInt256(TestUtils.GetByteArray(32, 0x42))), TestUtils.GetCoinReference(new UInt256(TestUtils.GetByteArray(32, 0x48))) };
- uut.Claims = refs;
- uut.Attributes = new TransactionAttribute[0];
- uut.Inputs = new CoinReference[0];
- uut.Outputs = new TransactionOutput[0];
- uut.Scripts = new Witness[0];
-
- TestUtils.SetupTestBlockchain(UInt256.Zero);
-
- UInt160[] res = uut.GetScriptHashesForVerifying();
- res.Length.Should().Be(2);
- }
-
[TestMethod]
public void ToJson()
{
@@ -135,7 +86,7 @@ public void ToJson()
uut.Attributes = new TransactionAttribute[0];
uut.Inputs = new CoinReference[0];
uut.Outputs = new TransactionOutput[0];
- uut.Scripts = new Witness[0];
+ uut.Witnesses = new Witness[0];
JObject jObj = uut.ToJson();
jObj.Should().NotBeNull();
diff --git a/neo.UnitTests/UT_CoinReference.cs b/neo.UnitTests/UT_CoinReference.cs
index e850285542..5777a9ea26 100644
--- a/neo.UnitTests/UT_CoinReference.cs
+++ b/neo.UnitTests/UT_CoinReference.cs
@@ -1,12 +1,10 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-using FluentAssertions;
+using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
-using Neo.Core;
-using System.IO;
using Neo.IO;
using Neo.IO.Json;
+using Neo.Network.P2P.Payloads;
+using System.IO;
+using System.Text;
namespace Neo.UnitTests
{
diff --git a/neo.UnitTests/UT_Culture.cs b/neo.UnitTests/UT_Culture.cs
index f1b2fcb57b..28dc09aef4 100644
--- a/neo.UnitTests/UT_Culture.cs
+++ b/neo.UnitTests/UT_Culture.cs
@@ -1,11 +1,8 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
-using Neo.Core;
using System;
-using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Reflection;
-using System.Text;
namespace Neo.UnitTests
{
diff --git a/neo.UnitTests/UT_Header.cs b/neo.UnitTests/UT_Header.cs
index a0a508f9d5..9819148241 100644
--- a/neo.UnitTests/UT_Header.cs
+++ b/neo.UnitTests/UT_Header.cs
@@ -1,10 +1,8 @@
-using System;
-using System.Collections.Generic;
+using FluentAssertions;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Neo.Network.P2P.Payloads;
using System.IO;
using System.Text;
-using FluentAssertions;
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-using Neo.Core;
namespace Neo.UnitTests
{
@@ -68,9 +66,9 @@ private void assertStandardHeaderTestVals(UInt256 val256, UInt256 merkRoot, UInt
uut.Index.Should().Be(indexVal);
uut.ConsensusData.Should().Be(consensusDataVal);
uut.NextConsensus.Should().Be(val160);
- uut.Script.InvocationScript.Length.Should().Be(0);
- uut.Script.Size.Should().Be(scriptVal.Size);
- uut.Script.VerificationScript[0].Should().Be(scriptVal.VerificationScript[0]);
+ uut.Witness.InvocationScript.Length.Should().Be(0);
+ uut.Witness.Size.Should().Be(scriptVal.Size);
+ uut.Witness.VerificationScript[0].Should().Be(scriptVal.VerificationScript[0]);
}
[TestMethod]
@@ -108,24 +106,6 @@ public void Equals_SameObject()
uut.Equals((object)uut).Should().BeTrue();
}
- [TestMethod]
- public void FromTrimmedData()
- {
- UInt256 val256 = UInt256.Zero;
- UInt256 merkRoot;
- UInt160 val160;
- uint timestampVal, indexVal;
- ulong consensusDataVal;
- Witness scriptVal;
- TestUtils.SetupHeaderWithValues(new Header(), val256, out merkRoot, out val160, out timestampVal, out indexVal, out consensusDataVal, out scriptVal);
-
- byte[] data = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 214, 87, 42, 69, 155, 149, 217, 19, 107, 122, 113, 60, 84, 133, 202, 112, 159, 158, 250, 79, 8, 241, 194, 93, 215, 146, 103, 45, 43, 215, 91, 251, 128, 171, 4, 253, 0, 0, 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 81, 0 };
-
- uut = Header.FromTrimmedData(data, 0);
-
- assertStandardHeaderTestVals(val256, merkRoot, val160, timestampVal, indexVal, consensusDataVal, scriptVal);
- }
-
[TestMethod]
public void Serialize()
{
diff --git a/neo.UnitTests/UT_Helper.cs b/neo.UnitTests/UT_Helper.cs
index fddcf06318..c836219b88 100644
--- a/neo.UnitTests/UT_Helper.cs
+++ b/neo.UnitTests/UT_Helper.cs
@@ -1,8 +1,7 @@
-using System.Collections.Generic;
-using System.Text;
+using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
-using FluentAssertions;
-using Neo.Core;
+using Neo.Network.P2P;
+using Neo.SmartContract;
using Neo.Wallets;
namespace Neo.UnitTests
diff --git a/neo.UnitTests/UT_InvocationTransaction.cs b/neo.UnitTests/UT_InvocationTransaction.cs
index 77b665f92a..d97455790b 100644
--- a/neo.UnitTests/UT_InvocationTransaction.cs
+++ b/neo.UnitTests/UT_InvocationTransaction.cs
@@ -1,10 +1,7 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-using FluentAssertions;
+using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
-using Neo.Core;
using Neo.IO.Json;
+using Neo.Network.P2P.Payloads;
namespace Neo.UnitTests
{
@@ -57,7 +54,7 @@ public void Size_Get()
uut.Attributes = new TransactionAttribute[0];
uut.Inputs = new CoinReference[0];
uut.Outputs = new TransactionOutput[0];
- uut.Scripts = new Witness[0];
+ uut.Witnesses = new Witness[0];
byte[] val = TestUtils.GetByteArray(32, 0x42);
uut.Script = val;
@@ -97,7 +94,7 @@ public void ToJson()
uut.Attributes = new TransactionAttribute[0];
uut.Inputs = new CoinReference[0];
uut.Outputs = new TransactionOutput[0];
- uut.Scripts = new Witness[0];
+ uut.Witnesses = new Witness[0];
JObject jObj = uut.ToJson();
jObj.Should().NotBeNull();
diff --git a/neo.UnitTests/UT_IssueTransaction.cs b/neo.UnitTests/UT_IssueTransaction.cs
deleted file mode 100644
index efb6ae8580..0000000000
--- a/neo.UnitTests/UT_IssueTransaction.cs
+++ /dev/null
@@ -1,117 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-using FluentAssertions;
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-using Neo.Core;
-using Neo.IO.Json;
-using Neo.Wallets;
-using Neo.VM;
-using Neo.SmartContract;
-
-namespace Neo.UnitTests
-{
- [TestClass]
- public class UT_IssueTransaction
- {
- IssueTransaction uut;
-
- [TestInitialize]
- public void TestSetup()
- {
- uut = new IssueTransaction();
- }
-
- [TestMethod]
- public void SystemFee_Get()
- {
- uut.Version = 1;
- uut.SystemFee.Should().Be(Fixed8.Zero);
- }
-
- [TestMethod]
- public void SystemFee_Get_Version_0_Share()
- {
- uut = TestUtils.GetIssueTransaction(false, 10, Blockchain.GoverningToken.Hash);
- uut.Version = 0;
-
- uut.SystemFee.Should().Be(Fixed8.Zero);
- }
-
- [TestMethod]
- public void SystemFee_Get_Version_0_Coin()
- {
- uut = TestUtils.GetIssueTransaction(false, 10, Blockchain.UtilityToken.Hash);
- uut.Version = 0;
-
- uut.SystemFee.Should().Be(Fixed8.Zero);
- }
-
- [TestMethod]
- public void SystemFee_Get_Version_0_OtherAsset()
- {
- uut = TestUtils.GetIssueTransaction(false, 10, new UInt256(TestUtils.GetByteArray(32,0x42)));
- uut.Version = 0;
-
- uut.SystemFee.Should().Be(Fixed8.FromDecimal(500));
- }
-
- [TestMethod]
- public void GetScriptHashesForVerifying()
- {
- TestUtils.SetupTestBlockchain(UInt256.Zero);
- uut = TestUtils.GetIssueTransaction(false, 10, Blockchain.UtilityToken.Hash);
- UInt160[] res = uut.GetScriptHashesForVerifying();
- res.Length.Should().Be(1);
- res[0].Should().Be(new UInt160(TestUtils.GetByteArray(20, 0xe7)));
- }
-
- [TestMethod]
- public void GetScriptHashesForVerifying_ThrowsException_NullAsset()
- {
- TestUtils.SetupTestBlockchain(UInt256.Zero);
- uut = TestUtils.GetIssueTransaction(false, 10, UInt256.Zero);
- Action test = () => uut.GetScriptHashesForVerifying();
- test.ShouldThrow();
- }
-
- [TestMethod]
- public void GetScriptHashesForVerifying_Ordered()
- {
- TestUtils.SetupTestBlockchain(UInt256.Zero);
- uut = new IssueTransaction
- {
- Attributes = new TransactionAttribute[0],
- Inputs = new CoinReference[0],
- Outputs = new[]
- {
- new TransactionOutput
- {
- AssetId = Blockchain.UtilityToken.Hash,
- Value = Fixed8.FromDecimal(10),
- ScriptHash = Contract.CreateMultiSigRedeemScript(1, TestUtils.StandbyValidators).ToScriptHash()
- },
- new TransactionOutput
- {
- AssetId = Blockchain.GoverningToken.Hash,
- Value = Fixed8.FromDecimal(10),
- ScriptHash = Contract.CreateMultiSigRedeemScript(1, TestUtils.StandbyValidators).ToScriptHash()
- },
- },
- Scripts = new[]
- {
- new Witness
- {
- InvocationScript = new byte[0],
- VerificationScript = new[] { (byte)OpCode.PUSHT }
- }
- }
- };
- UInt160[] res = uut.GetScriptHashesForVerifying();
- res.Length.Should().Be(2);
- res[0].Should().Be(new UInt160(TestUtils.GetByteArray(20, 0x9b)));
- res[1].Should().Be(new UInt160(TestUtils.GetByteArray(20, 0xe7)));
- }
-
- }
-}
diff --git a/neo.UnitTests/UT_MinerTransaction.cs b/neo.UnitTests/UT_MinerTransaction.cs
index 9c6110e6ad..5b0d2156c3 100644
--- a/neo.UnitTests/UT_MinerTransaction.cs
+++ b/neo.UnitTests/UT_MinerTransaction.cs
@@ -1,12 +1,7 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-using FluentAssertions;
+using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
-using Neo.Core;
using Neo.IO.Json;
-using Neo.Wallets;
-using Neo.VM;
+using Neo.Network.P2P.Payloads;
namespace Neo.UnitTests
{
@@ -47,7 +42,7 @@ public void Size_Get()
uut.Attributes = new TransactionAttribute[0];
uut.Inputs = new CoinReference[0];
uut.Outputs = new TransactionOutput[0];
- uut.Scripts = new Witness[0];
+ uut.Witnesses = new Witness[0];
uut.Size.Should().Be(10); // 1, 1, 1, 1, 1, 1 + 4
}
@@ -58,7 +53,7 @@ public void ToJson()
uut.Attributes = new TransactionAttribute[0];
uut.Inputs = new CoinReference[0];
uut.Outputs = new TransactionOutput[0];
- uut.Scripts = new Witness[0];
+ uut.Witnesses = new Witness[0];
uut.Nonce = 42;
JObject jObj = uut.ToJson();
diff --git a/neo.UnitTests/UT_SpentCoint.cs b/neo.UnitTests/UT_SpentCoint.cs
index 117ceb6d08..831eb10a1f 100644
--- a/neo.UnitTests/UT_SpentCoint.cs
+++ b/neo.UnitTests/UT_SpentCoint.cs
@@ -1,9 +1,7 @@
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
-using Neo.Core;
-using System.Collections.Generic;
-using System.IO;
-using System.Text;
+using Neo.Ledger;
+using Neo.Network.P2P.Payloads;
namespace Neo.UnitTests
{
diff --git a/neo.UnitTests/UT_SpentCointState.cs b/neo.UnitTests/UT_SpentCointState.cs
index c728c4bcf7..bb28ebecf3 100644
--- a/neo.UnitTests/UT_SpentCointState.cs
+++ b/neo.UnitTests/UT_SpentCointState.cs
@@ -1,6 +1,6 @@
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
-using Neo.Core;
+using Neo.Ledger;
using System.Collections.Generic;
using System.IO;
using System.Text;
diff --git a/neo.UnitTests/UT_StorageItem.cs b/neo.UnitTests/UT_StorageItem.cs
index ec36b90762..262cc33e50 100644
--- a/neo.UnitTests/UT_StorageItem.cs
+++ b/neo.UnitTests/UT_StorageItem.cs
@@ -1,7 +1,7 @@
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
-using Neo.Core;
using Neo.IO;
+using Neo.Ledger;
using System.IO;
using System.Text;
diff --git a/neo.UnitTests/UT_StorageKey.cs b/neo.UnitTests/UT_StorageKey.cs
index 037e0c3309..1ba8d61d26 100644
--- a/neo.UnitTests/UT_StorageKey.cs
+++ b/neo.UnitTests/UT_StorageKey.cs
@@ -1,9 +1,6 @@
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
-using Neo.Core;
-using System.Collections.Generic;
-using System.IO;
-using System.Text;
+using Neo.Ledger;
namespace Neo.UnitTests
{
diff --git a/neo.UnitTests/UT_TransactionAttribute.cs b/neo.UnitTests/UT_TransactionAttribute.cs
index c5ff05c7b4..bf79f6ac01 100644
--- a/neo.UnitTests/UT_TransactionAttribute.cs
+++ b/neo.UnitTests/UT_TransactionAttribute.cs
@@ -1,10 +1,7 @@
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
-using Neo.Core;
using Neo.IO.Json;
-using System.Collections.Generic;
-using System.IO;
-using System.Text;
+using Neo.Network.P2P.Payloads;
namespace Neo.UnitTests
{
diff --git a/neo.UnitTests/UT_TransactionOutput.cs b/neo.UnitTests/UT_TransactionOutput.cs
index 20862110e7..00929a3a99 100644
--- a/neo.UnitTests/UT_TransactionOutput.cs
+++ b/neo.UnitTests/UT_TransactionOutput.cs
@@ -1,10 +1,7 @@
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
-using Neo.Core;
using Neo.IO.Json;
-using System.Collections.Generic;
-using System.IO;
-using System.Text;
+using Neo.Network.P2P.Payloads;
namespace Neo.UnitTests
{
diff --git a/neo.UnitTests/UT_TransactionResult.cs b/neo.UnitTests/UT_TransactionResult.cs
index da6165807e..685b653d09 100644
--- a/neo.UnitTests/UT_TransactionResult.cs
+++ b/neo.UnitTests/UT_TransactionResult.cs
@@ -1,10 +1,6 @@
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
-using Neo.Core;
-using Neo.IO.Json;
-using System.Collections.Generic;
-using System.IO;
-using System.Text;
+using Neo.Network.P2P.Payloads;
namespace Neo.UnitTests
{
diff --git a/neo.UnitTests/UT_UnspentCoinState.cs b/neo.UnitTests/UT_UnspentCoinState.cs
index e8a723808b..08f70093e0 100644
--- a/neo.UnitTests/UT_UnspentCoinState.cs
+++ b/neo.UnitTests/UT_UnspentCoinState.cs
@@ -1,6 +1,6 @@
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
-using Neo.Core;
+using Neo.Ledger;
using System.IO;
using System.Text;
diff --git a/neo.UnitTests/UT_ValidatorState.cs b/neo.UnitTests/UT_ValidatorState.cs
index 1c393bc756..11a78050b3 100644
--- a/neo.UnitTests/UT_ValidatorState.cs
+++ b/neo.UnitTests/UT_ValidatorState.cs
@@ -1,7 +1,7 @@
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
-using Neo.Core;
using Neo.Cryptography.ECC;
+using Neo.Ledger;
using System.IO;
using System.Text;
diff --git a/neo.UnitTests/UT_Witness.cs b/neo.UnitTests/UT_Witness.cs
index 48708da55d..26dc8b84dd 100644
--- a/neo.UnitTests/UT_Witness.cs
+++ b/neo.UnitTests/UT_Witness.cs
@@ -1,7 +1,7 @@
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
-using Neo.Core;
using Neo.IO.Json;
+using Neo.Network.P2P.Payloads;
namespace Neo.UnitTests
{
diff --git a/neo/Consensus/ConsensusContext.cs b/neo/Consensus/ConsensusContext.cs
index ee714dd421..a8ba393bae 100644
--- a/neo/Consensus/ConsensusContext.cs
+++ b/neo/Consensus/ConsensusContext.cs
@@ -1,21 +1,24 @@
-using Neo.Core;
-using Neo.Cryptography;
+using Neo.Cryptography;
using Neo.Cryptography.ECC;
using Neo.IO;
-using Neo.Network.Payloads;
+using Neo.Ledger;
+using Neo.Network.P2P.Payloads;
+using Neo.Persistence;
using Neo.Wallets;
+using System;
using System.Collections.Generic;
using System.Linq;
namespace Neo.Consensus
{
- internal class ConsensusContext
+ internal class ConsensusContext : IDisposable
{
public const uint Version = 0;
public ConsensusState State;
public UInt256 PrevHash;
public uint BlockIndex;
public byte ViewNumber;
+ public Snapshot Snapshot;
public ECPoint[] Validators;
public int MyIndex;
public uint PrimaryIndex;
@@ -46,6 +49,11 @@ public void ChangeView(byte view_number)
_header = null;
}
+ public void Dispose()
+ {
+ Snapshot?.Dispose();
+ }
+
public ConsensusPayload MakeChangeView()
{
return MakePayload(new ChangeView
@@ -111,11 +119,13 @@ public ConsensusPayload MakePrepareResponse(byte[] signature)
public void Reset(Wallet wallet)
{
+ Snapshot?.Dispose();
+ Snapshot = Blockchain.Singleton.GetSnapshot();
State = ConsensusState.Initial;
- PrevHash = Blockchain.Default.CurrentBlockHash;
- BlockIndex = Blockchain.Default.Height + 1;
+ PrevHash = Snapshot.CurrentBlockHash;
+ BlockIndex = Snapshot.Height + 1;
ViewNumber = 0;
- Validators = Blockchain.Default.GetValidators();
+ Validators = Snapshot.GetValidators();
MyIndex = -1;
PrimaryIndex = BlockIndex % (uint)Validators.Length;
TransactionHashes = null;
diff --git a/neo/Consensus/ConsensusService.cs b/neo/Consensus/ConsensusService.cs
index 260cd7a00d..3746355181 100644
--- a/neo/Consensus/ConsensusService.cs
+++ b/neo/Consensus/ConsensusService.cs
@@ -1,52 +1,53 @@
-using Neo.Core;
+using Akka.Actor;
+using Akka.Configuration;
using Neo.Cryptography;
using Neo.IO;
-using Neo.Network;
-using Neo.Network.Payloads;
+using Neo.IO.Actors;
+using Neo.Ledger;
+using Neo.Network.P2P;
+using Neo.Network.P2P.Payloads;
+using Neo.Persistence;
using Neo.Plugins;
using Neo.SmartContract;
using Neo.Wallets;
using System;
using System.Collections.Generic;
using System.Linq;
-using System.Threading;
namespace Neo.Consensus
{
- public class ConsensusService : IDisposable
+ public sealed class ConsensusService : UntypedActor
{
- private ConsensusContext context = new ConsensusContext();
- private LocalNode localNode;
- private Wallet wallet;
- private Timer timer;
- private uint timer_height;
- private byte timer_view;
+ public class Start { }
+ internal class Timer { public uint Height; public byte ViewNumber; }
+
+ private readonly ConsensusContext context = new ConsensusContext();
+ private readonly NeoSystem system;
+ private readonly Wallet wallet;
private DateTime block_received_time;
- private bool started = false;
- public ConsensusService(LocalNode localNode, Wallet wallet)
+ public ConsensusService(NeoSystem system, Wallet wallet)
{
- this.localNode = localNode;
+ this.system = system;
this.wallet = wallet;
- this.timer = new Timer(OnTimeout, null, Timeout.Infinite, Timeout.Infinite);
}
private bool AddTransaction(Transaction tx, bool verify)
{
- if (Blockchain.Default.ContainsTransaction(tx.Hash) ||
- (verify && !tx.Verify(context.Transactions.Values)) ||
+ if (context.Snapshot.ContainsTransaction(tx.Hash) ||
+ (verify && !tx.Verify(context.Snapshot, context.Transactions.Values)) ||
!CheckPolicy(tx))
{
- Log($"reject tx: {tx.Hash}{Environment.NewLine}{tx.ToArray().ToHexString()}");
+ Log($"reject tx: {tx.Hash}{Environment.NewLine}{tx.ToArray().ToHexString()}", LogLevel.Warning);
RequestChangeView();
return false;
}
context.Transactions[tx.Hash] = tx;
if (context.TransactionHashes.Length == context.Transactions.Count)
{
- if (Blockchain.GetConsensusAddress(Blockchain.Default.GetValidators(context.Transactions.Values).ToArray()).Equals(context.NextConsensus))
+ if (Blockchain.GetConsensusAddress(context.Snapshot.GetValidators(context.Transactions.Values).ToArray()).Equals(context.NextConsensus))
{
- Log($"send perpare response");
+ Log($"send prepare response");
context.State |= ConsensusState.SignatureSent;
context.Signatures[context.MyIndex] = context.MakeHeader().Sign(context.KeyPair);
SignAndRelay(context.MakePrepareResponse(context.Signatures[context.MyIndex]));
@@ -61,11 +62,13 @@ private bool AddTransaction(Transaction tx, bool verify)
return true;
}
- private void Blockchain_PersistUnlocked(object sender, Block block)
+ private void ChangeTimer(TimeSpan delay)
{
- Log($"persist block: {block.Hash}");
- block_received_time = DateTime.Now;
- InitializeConsensus(0);
+ Context.System.Scheduler.ScheduleTellOnce(delay, Self, new Timer
+ {
+ Height = context.BlockIndex,
+ ViewNumber = context.ViewNumber
+ }, ActorRefs.NoSender);
}
private void CheckExpectedView(byte view_number)
@@ -79,7 +82,7 @@ private void CheckExpectedView(byte view_number)
private bool CheckPolicy(Transaction tx)
{
- foreach (PolicyPlugin plugin in PolicyPlugin.Instances)
+ foreach (IPolicyPlugin plugin in Plugin.Policies)
if (!plugin.CheckPolicy(tx))
return false;
return true;
@@ -98,31 +101,18 @@ private void CheckSignatures()
sc.AddSignature(contract, context.Validators[i], context.Signatures[i]);
j++;
}
- sc.Verifiable.Scripts = sc.GetScripts();
+ sc.Verifiable.Witnesses = sc.GetWitnesses();
block.Transactions = context.TransactionHashes.Select(p => context.Transactions[p]).ToArray();
Log($"relay block: {block.Hash}");
- if (!localNode.Relay(block))
- Log($"reject block: {block.Hash}");
+ system.LocalNode.Tell(new LocalNode.Relay { Inventory = block });
context.State |= ConsensusState.BlockSent;
}
}
- public void Dispose()
- {
- Log("OnStop");
- if (timer != null) timer.Dispose();
- if (started)
- {
- Blockchain.PersistUnlocked -= Blockchain_PersistUnlocked;
- LocalNode.InventoryReceiving -= LocalNode_InventoryReceiving;
- LocalNode.InventoryReceived -= LocalNode_InventoryReceived;
- }
- }
-
private void FillContext()
{
- IEnumerable mem_pool = LocalNode.GetMemoryPool().Where(p => CheckPolicy(p));
- foreach (PolicyPlugin plugin in PolicyPlugin.Instances)
+ IEnumerable mem_pool = Blockchain.Singleton.GetMemoryPool().Where(p => CheckPolicy(p));
+ foreach (IPolicyPlugin plugin in Plugin.Policies)
mem_pool = plugin.Filter(mem_pool);
List transactions = mem_pool.ToList();
Fixed8 amount_netfee = Block.CalculateNetFee(transactions);
@@ -141,9 +131,9 @@ private void FillContext()
Attributes = new TransactionAttribute[0],
Inputs = new CoinReference[0],
Outputs = outputs,
- Scripts = new Witness[0]
+ Witnesses = new Witness[0]
};
- if (Blockchain.Default.GetTransaction(tx.Hash) == null)
+ if (!context.Snapshot.ContainsTransaction(tx.Hash))
{
context.Nonce = nonce;
transactions.Insert(0, tx);
@@ -152,7 +142,7 @@ private void FillContext()
}
context.TransactionHashes = transactions.Select(p => p.Hash).ToArray();
context.Transactions = transactions.ToDictionary(p => p.Hash);
- context.NextConsensus = Blockchain.GetConsensusAddress(Blockchain.Default.GetValidators(transactions).ToArray());
+ context.NextConsensus = Blockchain.GetConsensusAddress(context.Snapshot.GetValidators(transactions).ToArray());
}
private static ulong GetNonce()
@@ -165,117 +155,31 @@ private static ulong GetNonce()
private void InitializeConsensus(byte view_number)
{
- lock (context)
+ if (view_number == 0)
+ context.Reset(wallet);
+ else
+ context.ChangeView(view_number);
+ if (context.MyIndex < 0) return;
+ Log($"initialize: height={context.BlockIndex} view={view_number} index={context.MyIndex} role={(context.MyIndex == context.PrimaryIndex ? ConsensusState.Primary : ConsensusState.Backup)}");
+ if (context.MyIndex == context.PrimaryIndex)
{
- if (view_number == 0)
- context.Reset(wallet);
+ context.State |= ConsensusState.Primary;
+ TimeSpan span = DateTime.Now - block_received_time;
+ if (span >= Blockchain.TimePerBlock)
+ ChangeTimer(TimeSpan.Zero);
else
- context.ChangeView(view_number);
- if (context.MyIndex < 0) return;
- Log($"initialize: height={context.BlockIndex} view={view_number} index={context.MyIndex} role={(context.MyIndex == context.PrimaryIndex ? ConsensusState.Primary : ConsensusState.Backup)}");
- if (context.MyIndex == context.PrimaryIndex)
- {
- context.State |= ConsensusState.Primary;
- if (!context.State.HasFlag(ConsensusState.SignatureSent))
- {
- FillContext();
- }
- if (context.TransactionHashes.Length > 1)
- {
- InvPayload invPayload = InvPayload.Create(InventoryType.TX, context.TransactionHashes.Skip(1).ToArray());
- foreach (RemoteNode node in localNode.GetRemoteNodes())
- node.EnqueueMessage("inv", invPayload);
- }
- timer_height = context.BlockIndex;
- timer_view = view_number;
- TimeSpan span = DateTime.Now - block_received_time;
- if (span >= Blockchain.TimePerBlock)
- timer.Change(0, Timeout.Infinite);
- else
- timer.Change(Blockchain.TimePerBlock - span, Timeout.InfiniteTimeSpan);
- }
- else
- {
- context.State = ConsensusState.Backup;
- timer_height = context.BlockIndex;
- timer_view = view_number;
- timer.Change(TimeSpan.FromSeconds(Blockchain.SecondsPerBlock << (view_number + 1)), Timeout.InfiniteTimeSpan);
- }
+ ChangeTimer(Blockchain.TimePerBlock - span);
}
- }
-
- private void LocalNode_InventoryReceived(object sender, IInventory inventory)
- {
- ConsensusPayload payload = inventory as ConsensusPayload;
- if (payload != null)
+ else
{
- lock (context)
- {
- if (payload.ValidatorIndex == context.MyIndex) return;
-
- if (payload.Version != ConsensusContext.Version)
- return;
- if (payload.PrevHash != context.PrevHash || payload.BlockIndex != context.BlockIndex)
- {
- // Request blocks
-
- if (Blockchain.Default?.Height + 1 < payload.BlockIndex)
- {
- Log($"chain sync: expected={payload.BlockIndex} current: {Blockchain.Default?.Height} nodes={localNode.RemoteNodeCount}");
-
- localNode.RequestGetBlocks();
- }
-
- return;
- }
-
- if (payload.ValidatorIndex >= context.Validators.Length) return;
- ConsensusMessage message;
- try
- {
- message = ConsensusMessage.DeserializeFrom(payload.Data);
- }
- catch
- {
- return;
- }
- if (message.ViewNumber != context.ViewNumber && message.Type != ConsensusMessageType.ChangeView)
- return;
- switch (message.Type)
- {
- case ConsensusMessageType.ChangeView:
- OnChangeViewReceived(payload, (ChangeView)message);
- break;
- case ConsensusMessageType.PrepareRequest:
- OnPrepareRequestReceived(payload, (PrepareRequest)message);
- break;
- case ConsensusMessageType.PrepareResponse:
- OnPrepareResponseReceived(payload, (PrepareResponse)message);
- break;
- }
- }
- }
- }
-
- private void LocalNode_InventoryReceiving(object sender, InventoryReceivingEventArgs e)
- {
- Transaction tx = e.Inventory as Transaction;
- if (tx != null)
- {
- lock (context)
- {
- if (!context.State.HasFlag(ConsensusState.Backup) || !context.State.HasFlag(ConsensusState.RequestReceived) || context.State.HasFlag(ConsensusState.SignatureSent) || context.State.HasFlag(ConsensusState.ViewChanging))
- return;
- if (context.Transactions.ContainsKey(tx.Hash)) return;
- if (!context.TransactionHashes.Contains(tx.Hash)) return;
- AddTransaction(tx, true);
- e.Cancel = true;
- }
+ context.State = ConsensusState.Backup;
+ ChangeTimer(TimeSpan.FromSeconds(Blockchain.SecondsPerBlock << (view_number + 1)));
}
}
- protected virtual void Log(string message)
+ private void Log(string message, LogLevel level = LogLevel.Info)
{
+ Plugin.Log(nameof(ConsensusService), level, message);
}
private void OnChangeViewReceived(ConsensusPayload payload, ChangeView message)
@@ -287,15 +191,61 @@ private void OnChangeViewReceived(ConsensusPayload payload, ChangeView message)
CheckExpectedView(message.NewViewNumber);
}
+ private void OnConsensusPayload(ConsensusPayload payload)
+ {
+ if (payload.ValidatorIndex == context.MyIndex) return;
+ if (payload.Version != ConsensusContext.Version)
+ return;
+ if (payload.PrevHash != context.PrevHash || payload.BlockIndex != context.BlockIndex)
+ {
+ if (context.Snapshot.Height + 1 < payload.BlockIndex)
+ {
+ Log($"chain sync: expected={payload.BlockIndex} current: {context.Snapshot.Height} nodes={LocalNode.Singleton.ConnectedCount}", LogLevel.Warning);
+ }
+ return;
+ }
+ if (payload.ValidatorIndex >= context.Validators.Length) return;
+ ConsensusMessage message;
+ try
+ {
+ message = ConsensusMessage.DeserializeFrom(payload.Data);
+ }
+ catch
+ {
+ return;
+ }
+ if (message.ViewNumber != context.ViewNumber && message.Type != ConsensusMessageType.ChangeView)
+ return;
+ switch (message.Type)
+ {
+ case ConsensusMessageType.ChangeView:
+ OnChangeViewReceived(payload, (ChangeView)message);
+ break;
+ case ConsensusMessageType.PrepareRequest:
+ OnPrepareRequestReceived(payload, (PrepareRequest)message);
+ break;
+ case ConsensusMessageType.PrepareResponse:
+ OnPrepareResponseReceived(payload, (PrepareResponse)message);
+ break;
+ }
+ }
+
+ private void OnPersistCompleted(Block block)
+ {
+ Log($"persist block: {block.Hash}");
+ block_received_time = DateTime.Now;
+ InitializeConsensus(0);
+ }
+
private void OnPrepareRequestReceived(ConsensusPayload payload, PrepareRequest message)
{
Log($"{nameof(OnPrepareRequestReceived)}: height={payload.BlockIndex} view={message.ViewNumber} index={payload.ValidatorIndex} tx={message.TransactionHashes.Length}");
if (!context.State.HasFlag(ConsensusState.Backup) || context.State.HasFlag(ConsensusState.RequestReceived))
return;
if (payload.ValidatorIndex != context.PrimaryIndex) return;
- if (payload.Timestamp <= Blockchain.Default.GetHeader(context.PrevHash).Timestamp || payload.Timestamp > DateTime.Now.AddMinutes(10).ToTimestamp())
+ if (payload.Timestamp <= context.Snapshot.GetHeader(context.PrevHash).Timestamp || payload.Timestamp > DateTime.Now.AddMinutes(10).ToTimestamp())
{
- Log($"Timestamp incorrect: {payload.Timestamp}");
+ Log($"Timestamp incorrect: {payload.Timestamp}", LogLevel.Warning);
return;
}
context.State |= ConsensusState.RequestReceived;
@@ -307,7 +257,7 @@ private void OnPrepareRequestReceived(ConsensusPayload payload, PrepareRequest m
if (!Crypto.Default.VerifySignature(context.MakeHeader().GetHashData(), message.Signature, context.Validators[payload.ValidatorIndex].EncodePoint(false))) return;
context.Signatures = new byte[context.Validators.Length][];
context.Signatures[payload.ValidatorIndex] = message.Signature;
- Dictionary mempool = LocalNode.GetMemoryPool().ToDictionary(p => p.Hash);
+ Dictionary mempool = Blockchain.Singleton.GetMemoryPool().ToDictionary(p => p.Hash);
foreach (UInt256 hash in context.TransactionHashes.Skip(1))
{
if (mempool.TryGetValue(hash, out Transaction tx))
@@ -318,10 +268,10 @@ private void OnPrepareRequestReceived(ConsensusPayload payload, PrepareRequest m
if (context.Transactions.Count < context.TransactionHashes.Length)
{
UInt256[] hashes = context.TransactionHashes.Where(i => !context.Transactions.ContainsKey(i)).ToArray();
- LocalNode.AllowHashes(hashes);
- InvPayload msg = InvPayload.Create(InventoryType.TX, hashes);
- foreach (RemoteNode node in localNode.GetRemoteNodes())
- node.EnqueueMessage("getdata", msg);
+ system.TaskManager.Tell(new TaskManager.RestartTasks
+ {
+ Payload = InvPayload.Create(InventoryType.TX, hashes)
+ });
}
}
@@ -336,29 +286,82 @@ private void OnPrepareResponseReceived(ConsensusPayload payload, PrepareResponse
CheckSignatures();
}
- private void OnTimeout(object state)
+ protected override void OnReceive(object message)
+ {
+ switch (message)
+ {
+ case Start _:
+ OnStart();
+ break;
+ case Timer timer:
+ OnTimer(timer);
+ break;
+ case ConsensusPayload payload:
+ OnConsensusPayload(payload);
+ break;
+ case Transaction transaction:
+ OnTransaction(transaction);
+ break;
+ case Blockchain.PersistCompleted completed:
+ OnPersistCompleted(completed.Block);
+ break;
+ }
+ }
+
+ private void OnStart()
+ {
+ Log("OnStart");
+ InitializeConsensus(0);
+ }
+
+ private void OnTimer(Timer timer)
{
- lock (context)
+ if (timer.Height != context.BlockIndex || timer.ViewNumber != context.ViewNumber) return;
+ Log($"timeout: height={timer.Height} view={timer.ViewNumber} state={context.State}");
+ if (context.State.HasFlag(ConsensusState.Primary) && !context.State.HasFlag(ConsensusState.RequestSent))
{
- if (timer_height != context.BlockIndex || timer_view != context.ViewNumber) return;
- Log($"timeout: height={timer_height} view={timer_view} state={context.State}");
- if (context.State.HasFlag(ConsensusState.Primary) && !context.State.HasFlag(ConsensusState.RequestSent))
+ Log($"send prepare request: height={timer.Height} view={timer.ViewNumber}");
+ context.State |= ConsensusState.RequestSent;
+ if (!context.State.HasFlag(ConsensusState.SignatureSent))
{
- Log($"send perpare request: height={timer_height} view={timer_view}");
- context.State |= ConsensusState.RequestSent;
- if (!context.State.HasFlag(ConsensusState.SignatureSent))
- {
- context.Timestamp = Math.Max(DateTime.Now.ToTimestamp(), Blockchain.Default.GetHeader(context.PrevHash).Timestamp + 1);
- context.Signatures[context.MyIndex] = context.MakeHeader().Sign(context.KeyPair);
- }
- SignAndRelay(context.MakePrepareRequest());
- timer.Change(TimeSpan.FromSeconds(Blockchain.SecondsPerBlock << (timer_view + 1)), Timeout.InfiniteTimeSpan);
+ FillContext();
+ context.Timestamp = Math.Max(DateTime.Now.ToTimestamp(), context.Snapshot.GetHeader(context.PrevHash).Timestamp + 1);
+ context.Signatures[context.MyIndex] = context.MakeHeader().Sign(context.KeyPair);
}
- else if ((context.State.HasFlag(ConsensusState.Primary) && context.State.HasFlag(ConsensusState.RequestSent)) || context.State.HasFlag(ConsensusState.Backup))
+ SignAndRelay(context.MakePrepareRequest());
+ if (context.TransactionHashes.Length > 1)
{
- RequestChangeView();
+ foreach (InvPayload payload in InvPayload.CreateGroup(InventoryType.TX, context.TransactionHashes.Skip(1).ToArray()))
+ system.LocalNode.Tell(Message.Create("inv", payload));
}
+ ChangeTimer(TimeSpan.FromSeconds(Blockchain.SecondsPerBlock << (timer.ViewNumber + 1)));
}
+ else if ((context.State.HasFlag(ConsensusState.Primary) && context.State.HasFlag(ConsensusState.RequestSent)) || context.State.HasFlag(ConsensusState.Backup))
+ {
+ RequestChangeView();
+ }
+ }
+
+ private void OnTransaction(Transaction transaction)
+ {
+ if (transaction.Type == TransactionType.MinerTransaction) return;
+ if (!context.State.HasFlag(ConsensusState.Backup) || !context.State.HasFlag(ConsensusState.RequestReceived) || context.State.HasFlag(ConsensusState.SignatureSent) || context.State.HasFlag(ConsensusState.ViewChanging))
+ return;
+ if (context.Transactions.ContainsKey(transaction.Hash)) return;
+ if (!context.TransactionHashes.Contains(transaction.Hash)) return;
+ AddTransaction(transaction, true);
+ }
+
+ protected override void PostStop()
+ {
+ Log("OnStop");
+ context.Dispose();
+ base.PostStop();
+ }
+
+ public static Props Props(NeoSystem system, Wallet wallet)
+ {
+ return Akka.Actor.Props.Create(() => new ConsensusService(system, wallet)).WithMailbox("consensus-service-mailbox");
}
private void RequestChangeView()
@@ -366,7 +369,7 @@ private void RequestChangeView()
context.State |= ConsensusState.ViewChanging;
context.ExpectedView[context.MyIndex]++;
Log($"request change view: height={context.BlockIndex} view={context.ViewNumber} nv={context.ExpectedView[context.MyIndex]} state={context.State}");
- timer.Change(TimeSpan.FromSeconds(Blockchain.SecondsPerBlock << (context.ExpectedView[context.MyIndex] + 1)), Timeout.InfiniteTimeSpan);
+ ChangeTimer(TimeSpan.FromSeconds(Blockchain.SecondsPerBlock << (context.ExpectedView[context.MyIndex] + 1)));
SignAndRelay(context.MakeChangeView());
CheckExpectedView(context.ExpectedView[context.MyIndex]);
}
@@ -383,18 +386,29 @@ private void SignAndRelay(ConsensusPayload payload)
{
return;
}
- sc.Verifiable.Scripts = sc.GetScripts();
- localNode.RelayDirectly(payload);
+ sc.Verifiable.Witnesses = sc.GetWitnesses();
+ system.LocalNode.Tell(new LocalNode.SendDirectly { Inventory = payload });
}
+ }
- public void Start()
+ internal class ConsensusServiceMailbox : PriorityMailbox
+ {
+ public ConsensusServiceMailbox(Akka.Actor.Settings settings, Config config)
+ : base(settings, config)
{
- Log("OnStart");
- started = true;
- Blockchain.PersistUnlocked += Blockchain_PersistUnlocked;
- LocalNode.InventoryReceiving += LocalNode_InventoryReceiving;
- LocalNode.InventoryReceived += LocalNode_InventoryReceived;
- InitializeConsensus(0);
+ }
+
+ protected override bool IsHighPriority(object message)
+ {
+ switch (message)
+ {
+ case ConsensusPayload _:
+ case ConsensusService.Timer _:
+ case Blockchain.PersistCompleted _:
+ return true;
+ default:
+ return false;
+ }
}
}
}
diff --git a/neo/Consensus/PrepareRequest.cs b/neo/Consensus/PrepareRequest.cs
index a9e9032a54..c88f7b76a1 100644
--- a/neo/Consensus/PrepareRequest.cs
+++ b/neo/Consensus/PrepareRequest.cs
@@ -1,5 +1,5 @@
-using Neo.Core;
-using Neo.IO;
+using Neo.IO;
+using Neo.Network.P2P.Payloads;
using System;
using System.IO;
using System.Linq;
diff --git a/neo/Core/Block.cs b/neo/Core/Block.cs
deleted file mode 100644
index ead1e9e462..0000000000
--- a/neo/Core/Block.cs
+++ /dev/null
@@ -1,196 +0,0 @@
-using Neo.Cryptography;
-using Neo.IO;
-using Neo.IO.Json;
-using Neo.Network;
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-
-namespace Neo.Core
-{
- ///
- /// 区块或区块头
- ///
- public class Block : BlockBase, IInventory, IEquatable
- {
- ///
- /// 交易列表
- ///
- public Transaction[] Transactions;
-
- private Header _header = null;
- ///
- /// 该区块的区块头
- ///
- public Header Header
- {
- get
- {
- if (_header == null)
- {
- _header = new Header
- {
- PrevHash = PrevHash,
- MerkleRoot = MerkleRoot,
- Timestamp = Timestamp,
- Index = Index,
- ConsensusData = ConsensusData,
- NextConsensus = NextConsensus,
- Script = Script
- };
- }
- return _header;
- }
- }
-
- ///
- /// 资产清单的类型
- ///
- InventoryType IInventory.InventoryType => InventoryType.Block;
-
- public override int Size => base.Size + Transactions.GetVarSize();
-
- public static Fixed8 CalculateNetFee(IEnumerable transactions)
- {
- Transaction[] ts = transactions.Where(p => p.Type != TransactionType.MinerTransaction && p.Type != TransactionType.ClaimTransaction).ToArray();
- Fixed8 amount_in = ts.SelectMany(p => p.References.Values.Where(o => o.AssetId == Blockchain.UtilityToken.Hash)).Sum(p => p.Value);
- Fixed8 amount_out = ts.SelectMany(p => p.Outputs.Where(o => o.AssetId == Blockchain.UtilityToken.Hash)).Sum(p => p.Value);
- Fixed8 amount_sysfee = ts.Sum(p => p.SystemFee);
- return amount_in - amount_out - amount_sysfee;
- }
-
- ///
- /// 反序列化
- ///
- /// 数据来源
- public override void Deserialize(BinaryReader reader)
- {
- base.Deserialize(reader);
- Transactions = new Transaction[reader.ReadVarInt(0x10000)];
- if (Transactions.Length == 0) throw new FormatException();
- for (int i = 0; i < Transactions.Length; i++)
- {
- Transactions[i] = Transaction.DeserializeFrom(reader);
- }
- if (MerkleTree.ComputeRoot(Transactions.Select(p => p.Hash).ToArray()) != MerkleRoot)
- throw new FormatException();
- }
-
- ///
- /// 比较当前区块与指定区块是否相等
- ///
- /// 要比较的区块
- /// 返回对象是否相等
- public bool Equals(Block other)
- {
- if (ReferenceEquals(this, other)) return true;
- if (ReferenceEquals(null, other)) return false;
- return Hash.Equals(other.Hash);
- }
-
- ///
- /// 比较当前区块与指定区块是否相等
- ///
- /// 要比较的区块
- /// 返回对象是否相等
- public override bool Equals(object obj)
- {
- return Equals(obj as Block);
- }
-
- public static Block FromTrimmedData(byte[] data, int index, Func txSelector)
- {
- Block block = new Block();
- using (MemoryStream ms = new MemoryStream(data, index, data.Length - index, false))
- using (BinaryReader reader = new BinaryReader(ms))
- {
- ((IVerifiable)block).DeserializeUnsigned(reader);
- reader.ReadByte(); block.Script = reader.ReadSerializable();
- block.Transactions = new Transaction[reader.ReadVarInt(0x10000000)];
- for (int i = 0; i < block.Transactions.Length; i++)
- {
- block.Transactions[i] = txSelector(reader.ReadSerializable());
- }
- }
- return block;
- }
-
- ///
- /// 获得区块的HashCode
- ///
- /// 返回区块的HashCode
- public override int GetHashCode()
- {
- return Hash.GetHashCode();
- }
-
- ///
- /// 根据区块中所有交易的Hash生成MerkleRoot
- ///
- public void RebuildMerkleRoot()
- {
- MerkleRoot = MerkleTree.ComputeRoot(Transactions.Select(p => p.Hash).ToArray());
- }
-
- ///
- /// 序列化
- ///
- /// 存放序列化后的数据
- public override void Serialize(BinaryWriter writer)
- {
- base.Serialize(writer);
- writer.Write(Transactions);
- }
-
- ///
- /// 变成json对象
- ///
- /// 返回json对象
- public override JObject ToJson()
- {
- JObject json = base.ToJson();
- json["tx"] = Transactions.Select(p => p.ToJson()).ToArray();
- return json;
- }
-
- ///
- /// 把区块对象变为只包含区块头和交易Hash的字节数组,去除交易数据
- ///
- /// 返回只包含区块头和交易Hash的字节数组
- public byte[] Trim()
- {
- using (MemoryStream ms = new MemoryStream())
- using (BinaryWriter writer = new BinaryWriter(ms))
- {
- ((IVerifiable)this).SerializeUnsigned(writer);
- writer.Write((byte)1); writer.Write(Script);
- writer.Write(Transactions.Select(p => p.Hash).ToArray());
- writer.Flush();
- return ms.ToArray();
- }
- }
-
- ///
- /// 验证该区块是否合法
- ///
- /// 是否同时验证区块中的每一笔交易
- /// 返回该区块的合法性,返回true即为合法,否则,非法。
- public bool Verify(bool completely)
- {
- if (!Verify()) return false;
- if (Transactions[0].Type != TransactionType.MinerTransaction || Transactions.Skip(1).Any(p => p.Type == TransactionType.MinerTransaction))
- return false;
- if (completely)
- {
- if (NextConsensus != Blockchain.GetConsensusAddress(Blockchain.Default.GetValidators(Transactions).ToArray()))
- return false;
- foreach (Transaction tx in Transactions)
- if (!tx.Verify(Transactions.Where(p => !p.Hash.Equals(tx.Hash)))) return false;
- Transaction tx_gen = Transactions.FirstOrDefault(p => p.Type == TransactionType.MinerTransaction);
- if (tx_gen?.Outputs.Sum(p => p.Value) != CalculateNetFee(Transactions)) return false;
- }
- return true;
- }
- }
-}
diff --git a/neo/Core/Blockchain.cs b/neo/Core/Blockchain.cs
deleted file mode 100644
index f8c17672ab..0000000000
--- a/neo/Core/Blockchain.cs
+++ /dev/null
@@ -1,595 +0,0 @@
-using Neo.Cryptography;
-using Neo.Cryptography.ECC;
-using Neo.IO;
-using Neo.IO.Caching;
-using Neo.SmartContract;
-using Neo.VM;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading;
-
-namespace Neo.Core
-{
- ///
- /// 实现区块链功能的基类
- ///
- public abstract class Blockchain : IDisposable, IScriptTable
- {
- public static event EventHandler PersistCompleted;
- public static event EventHandler PersistUnlocked;
-
- public CancellationTokenSource VerificationCancellationToken { get; protected set; } = new CancellationTokenSource();
- public object PersistLock { get; } = new object();
-
- ///
- /// 产生每个区块的时间间隔,已秒为单位
- ///
- public static readonly uint SecondsPerBlock = Settings.Default.SecondsPerBlock;
- public const uint DecrementInterval = 2000000;
- public const uint MaxValidators = 1024;
- public static readonly uint[] GenerationAmount = { 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
- ///
- /// 产生每个区块的时间间隔
- ///
- public static readonly TimeSpan TimePerBlock = TimeSpan.FromSeconds(SecondsPerBlock);
- ///
- /// 后备记账人列表
- ///
- public static readonly ECPoint[] StandbyValidators = Settings.Default.StandbyValidators.OfType().Select(p => ECPoint.DecodePoint(p.HexToBytes(), ECCurve.Secp256r1)).ToArray();
-
- ///
- /// Return true if haven't got valid handle
- ///
- public abstract bool IsDisposed { get; }
-
-#pragma warning disable CS0612
- public static readonly RegisterTransaction GoverningToken = new RegisterTransaction
- {
- AssetType = AssetType.GoverningToken,
- Name = "[{\"lang\":\"zh-CN\",\"name\":\"小蚁股\"},{\"lang\":\"en\",\"name\":\"AntShare\"}]",
- Amount = Fixed8.FromDecimal(100000000),
- Precision = 0,
- Owner = ECCurve.Secp256r1.Infinity,
- Admin = (new[] { (byte)OpCode.PUSHT }).ToScriptHash(),
- Attributes = new TransactionAttribute[0],
- Inputs = new CoinReference[0],
- Outputs = new TransactionOutput[0],
- Scripts = new Witness[0]
- };
-
- public static readonly RegisterTransaction UtilityToken = new RegisterTransaction
- {
- AssetType = AssetType.UtilityToken,
- Name = "[{\"lang\":\"zh-CN\",\"name\":\"小蚁币\"},{\"lang\":\"en\",\"name\":\"AntCoin\"}]",
- Amount = Fixed8.FromDecimal(GenerationAmount.Sum(p => p) * DecrementInterval),
- Precision = 8,
- Owner = ECCurve.Secp256r1.Infinity,
- Admin = (new[] { (byte)OpCode.PUSHF }).ToScriptHash(),
- Attributes = new TransactionAttribute[0],
- Inputs = new CoinReference[0],
- Outputs = new TransactionOutput[0],
- Scripts = new Witness[0]
- };
-#pragma warning restore CS0612
-
- ///
- /// 创世区块
- ///
- public static readonly Block GenesisBlock = new Block
- {
- PrevHash = UInt256.Zero,
- Timestamp = (new DateTime(2016, 7, 15, 15, 8, 21, DateTimeKind.Utc)).ToTimestamp(),
- Index = 0,
- ConsensusData = 2083236893, //向比特币致敬
- NextConsensus = GetConsensusAddress(StandbyValidators),
- Script = new Witness
- {
- InvocationScript = new byte[0],
- VerificationScript = new[] { (byte)OpCode.PUSHT }
- },
- Transactions = new Transaction[]
- {
- new MinerTransaction
- {
- Nonce = 2083236893,
- Attributes = new TransactionAttribute[0],
- Inputs = new CoinReference[0],
- Outputs = new TransactionOutput[0],
- Scripts = new Witness[0]
- },
- GoverningToken,
- UtilityToken,
- new IssueTransaction
- {
- Attributes = new TransactionAttribute[0],
- Inputs = new CoinReference[0],
- Outputs = new[]
- {
- new TransactionOutput
- {
- AssetId = GoverningToken.Hash,
- Value = GoverningToken.Amount,
- ScriptHash = Contract.CreateMultiSigRedeemScript(StandbyValidators.Length / 2 + 1, StandbyValidators).ToScriptHash()
- }
- },
- Scripts = new[]
- {
- new Witness
- {
- InvocationScript = new byte[0],
- VerificationScript = new[] { (byte)OpCode.PUSHT }
- }
- }
- }
- }
- };
-
- ///
- /// 当前最新区块散列值
- ///
- public abstract UInt256 CurrentBlockHash { get; }
- ///
- /// 当前最新区块头的散列值
- ///
- public abstract UInt256 CurrentHeaderHash { get; }
- ///
- /// 默认的区块链实例
- ///
- public static Blockchain Default { get; private set; } = null;
- ///
- /// 区块头高度
- ///
- public abstract uint HeaderHeight { get; }
- ///
- /// 区块高度
- ///
- public abstract uint Height { get; }
-
- static Blockchain()
- {
- GenesisBlock.RebuildMerkleRoot();
- }
-
- ///
- /// 将指定的区块添加到区块链中
- ///
- /// 要添加的区块
- /// 返回是否添加成功
- public abstract bool AddBlock(Block block);
-
- ///
- /// 将指定的区块头添加到区块头链中
- ///
- /// 要添加的区块头列表
- protected internal abstract void AddHeaders(IEnumerable headers);
-
- public static Fixed8 CalculateBonus(IEnumerable inputs, bool ignoreClaimed = true)
- {
- List unclaimed = new List();
- foreach (var group in inputs.GroupBy(p => p.PrevHash))
- {
- Dictionary claimable = Default.GetUnclaimed(group.Key);
- if (claimable == null || claimable.Count == 0)
- if (ignoreClaimed)
- continue;
- else
- throw new ArgumentException();
- foreach (CoinReference claim in group)
- {
- if (!claimable.TryGetValue(claim.PrevIndex, out SpentCoin claimed))
- if (ignoreClaimed)
- continue;
- else
- throw new ArgumentException();
- unclaimed.Add(claimed);
- }
- }
- return CalculateBonusInternal(unclaimed);
- }
-
- public static Fixed8 CalculateBonus(IEnumerable inputs, uint height_end)
- {
- List unclaimed = new List();
- foreach (var group in inputs.GroupBy(p => p.PrevHash))
- {
- Transaction tx = Default.GetTransaction(group.Key, out int height_start);
- if (tx == null) throw new ArgumentException();
- if (height_start == height_end) continue;
- foreach (CoinReference claim in group)
- {
- if (claim.PrevIndex >= tx.Outputs.Length || !tx.Outputs[claim.PrevIndex].AssetId.Equals(GoverningToken.Hash))
- throw new ArgumentException();
- unclaimed.Add(new SpentCoin
- {
- Output = tx.Outputs[claim.PrevIndex],
- StartHeight = (uint)height_start,
- EndHeight = height_end
- });
- }
- }
- return CalculateBonusInternal(unclaimed);
- }
-
- private static Fixed8 CalculateBonusInternal(IEnumerable unclaimed)
- {
- Fixed8 amount_claimed = Fixed8.Zero;
- foreach (var group in unclaimed.GroupBy(p => new { p.StartHeight, p.EndHeight }))
- {
- uint amount = 0;
- uint ustart = group.Key.StartHeight / DecrementInterval;
- if (ustart < GenerationAmount.Length)
- {
- uint istart = group.Key.StartHeight % DecrementInterval;
- uint uend = group.Key.EndHeight / DecrementInterval;
- uint iend = group.Key.EndHeight % DecrementInterval;
- if (uend >= GenerationAmount.Length)
- {
- uend = (uint)GenerationAmount.Length;
- iend = 0;
- }
- if (iend == 0)
- {
- uend--;
- iend = DecrementInterval;
- }
- while (ustart < uend)
- {
- amount += (DecrementInterval - istart) * GenerationAmount[ustart];
- ustart++;
- istart = 0;
- }
- amount += (iend - istart) * GenerationAmount[ustart];
- }
- amount += (uint)(Default.GetSysFeeAmount(group.Key.EndHeight - 1) - (group.Key.StartHeight == 0 ? 0 : Default.GetSysFeeAmount(group.Key.StartHeight - 1)));
- amount_claimed += group.Sum(p => p.Value) / 100000000 * amount;
- }
- return amount_claimed;
- }
-
- ///
- /// 判断区块链中是否包含指定的区块
- ///
- /// 区块编号
- /// 如果包含指定区块则返回true
- public abstract bool ContainsBlock(UInt256 hash);
-
- ///
- /// 判断区块链中是否包含指定的交易
- ///
- /// 交易编号
- /// 如果包含指定交易则返回true
- public abstract bool ContainsTransaction(UInt256 hash);
-
- public bool ContainsUnspent(CoinReference input)
- {
- return ContainsUnspent(input.PrevHash, input.PrevIndex);
- }
-
- public abstract bool ContainsUnspent(UInt256 hash, ushort index);
-
- public abstract MetaDataCache GetMetaData() where T : class, ISerializable, new();
-
- public abstract DataCache GetStates()
- where TKey : IEquatable, ISerializable, new()
- where TValue : StateBase, ICloneable, new();
-
- public abstract void Dispose();
-
- public abstract AccountState GetAccountState(UInt160 script_hash);
-
- public abstract AssetState GetAssetState(UInt256 asset_id);
-
- ///
- /// 根据指定的高度,返回对应的区块信息
- ///
- /// 区块高度
- /// 返回对应的区块信息
- public Block GetBlock(uint height)
- {
- UInt256 hash = GetBlockHash(height);
- if (hash == null) return null;
- return GetBlock(hash);
- }
-
- ///
- /// 根据指定的散列值,返回对应的区块信息
- ///
- /// 散列值
- /// 返回对应的区块信息
- public abstract Block GetBlock(UInt256 hash);
-
- ///
- /// 根据指定的高度,返回对应区块的散列值
- ///
- /// 区块高度
- /// 返回对应区块的散列值
- public abstract UInt256 GetBlockHash(uint height);
-
- public abstract ContractState GetContract(UInt160 hash);
-
- public abstract IEnumerable GetEnrollments();
-
- ///
- /// 根据指定的高度,返回对应的区块头信息
- ///
- /// 区块高度
- /// 返回对应的区块头信息
- public abstract Header GetHeader(uint height);
-
- ///
- /// 根据指定的散列值,返回对应的区块头信息
- ///
- /// 散列值
- /// 返回对应的区块头信息
- public abstract Header GetHeader(UInt256 hash);
-
- ///
- /// 获取记账人的合约地址
- ///
- /// 记账人的公钥列表
- /// 返回记账人的合约地址
- public static UInt160 GetConsensusAddress(ECPoint[] validators)
- {
- return Contract.CreateMultiSigRedeemScript(validators.Length - (validators.Length - 1) / 3, validators).ToScriptHash();
- }
-
- private List _validators = new List();
- ///
- /// 获取下一个区块的记账人列表
- ///
- /// 返回一组公钥,表示下一个区块的记账人列表
- public ECPoint[] GetValidators()
- {
- lock (_validators)
- {
- if (_validators.Count == 0)
- {
- _validators.AddRange(GetValidators(Enumerable.Empty()));
- }
- return _validators.ToArray();
- }
- }
-
- public virtual IEnumerable GetValidators(IEnumerable others)
- {
- DataCache accounts = GetStates();
- DataCache validators = GetStates();
- MetaDataCache validators_count = GetMetaData();
- foreach (Transaction tx in others)
- {
- foreach (TransactionOutput output in tx.Outputs)
- {
- AccountState account = accounts.GetAndChange(output.ScriptHash, () => new AccountState(output.ScriptHash));
- if (account.Balances.ContainsKey(output.AssetId))
- account.Balances[output.AssetId] += output.Value;
- else
- account.Balances[output.AssetId] = output.Value;
- if (output.AssetId.Equals(GoverningToken.Hash) && account.Votes.Length > 0)
- {
- foreach (ECPoint pubkey in account.Votes)
- validators.GetAndChange(pubkey, () => new ValidatorState(pubkey)).Votes += output.Value;
- validators_count.GetAndChange().Votes[account.Votes.Length - 1] += output.Value;
- }
- }
- foreach (var group in tx.Inputs.GroupBy(p => p.PrevHash))
- {
- Transaction tx_prev = GetTransaction(group.Key, out int height);
- foreach (CoinReference input in group)
- {
- TransactionOutput out_prev = tx_prev.Outputs[input.PrevIndex];
- AccountState account = accounts.GetAndChange(out_prev.ScriptHash);
- if (out_prev.AssetId.Equals(GoverningToken.Hash))
- {
- if (account.Votes.Length > 0)
- {
- foreach (ECPoint pubkey in account.Votes)
- {
- ValidatorState validator = validators.GetAndChange(pubkey);
- validator.Votes -= out_prev.Value;
- if (!validator.Registered && validator.Votes.Equals(Fixed8.Zero))
- validators.Delete(pubkey);
- }
- validators_count.GetAndChange().Votes[account.Votes.Length - 1] -= out_prev.Value;
- }
- }
- account.Balances[out_prev.AssetId] -= out_prev.Value;
- }
- }
- switch (tx)
- {
-#pragma warning disable CS0612
- case EnrollmentTransaction tx_enrollment:
- validators.GetAndChange(tx_enrollment.PublicKey, () => new ValidatorState(tx_enrollment.PublicKey)).Registered = true;
- break;
-#pragma warning restore CS0612
- case StateTransaction tx_state:
- foreach (StateDescriptor descriptor in tx_state.Descriptors)
- switch (descriptor.Type)
- {
- case StateType.Account:
- ProcessAccountStateDescriptor(descriptor, accounts, validators, validators_count);
- break;
- case StateType.Validator:
- ProcessValidatorStateDescriptor(descriptor, validators);
- break;
- }
- break;
- }
- }
- int count = (int)validators_count.Get().Votes.Select((p, i) => new
- {
- Count = i,
- Votes = p
- }).Where(p => p.Votes > Fixed8.Zero).ToArray().WeightedFilter(0.25, 0.75, p => p.Votes.GetData(), (p, w) => new
- {
- p.Count,
- Weight = w
- }).WeightedAverage(p => p.Count, p => p.Weight);
- count = Math.Max(count, StandbyValidators.Length);
- HashSet sv = new HashSet(StandbyValidators);
- ECPoint[] pubkeys = validators.Find().Select(p => p.Value).Where(p => (p.Registered && p.Votes > Fixed8.Zero) || sv.Contains(p.PublicKey)).OrderByDescending(p => p.Votes).ThenBy(p => p.PublicKey).Select(p => p.PublicKey).Take(count).ToArray();
- IEnumerable result;
- if (pubkeys.Length == count)
- {
- result = pubkeys;
- }
- else
- {
- HashSet hashSet = new HashSet(pubkeys);
- for (int i = 0; i < StandbyValidators.Length && hashSet.Count < count; i++)
- hashSet.Add(StandbyValidators[i]);
- result = hashSet;
- }
- return result.OrderBy(p => p);
- }
-
- ///
- /// 根据指定的散列值,返回下一个区块的信息
- ///
- /// 散列值
- /// 返回下一个区块的信息>
- public abstract Block GetNextBlock(UInt256 hash);
-
- ///
- /// 根据指定的散列值,返回下一个区块的散列值
- ///
- /// 散列值
- /// 返回下一个区块的散列值
- public abstract UInt256 GetNextBlockHash(UInt256 hash);
-
- byte[] IScriptTable.GetScript(byte[] script_hash)
- {
- return GetContract(new UInt160(script_hash)).Script;
- }
-
- public abstract StorageItem GetStorageItem(StorageKey key);
-
- ///
- /// 根据指定的区块高度,返回对应区块及之前所有区块中包含的系统费用的总量
- ///
- /// 区块高度
- /// 返回对应的系统费用的总量
- public virtual long GetSysFeeAmount(uint height)
- {
- return GetSysFeeAmount(GetBlockHash(height));
- }
-
- ///
- /// 根据指定的区块散列值,返回对应区块及之前所有区块中包含的系统费用的总量
- ///
- /// 散列值
- /// 返回系统费用的总量
- public abstract long GetSysFeeAmount(UInt256 hash);
-
- ///
- /// 根据指定的散列值,返回对应的交易信息
- ///
- /// 散列值
- /// 返回对应的交易信息
- public Transaction GetTransaction(UInt256 hash)
- {
- return GetTransaction(hash, out _);
- }
-
- ///
- /// 根据指定的散列值,返回对应的交易信息与该交易所在区块的高度
- ///
- /// 交易散列值
- /// 返回该交易所在区块的高度
- /// 返回对应的交易信息
- public abstract Transaction GetTransaction(UInt256 hash, out int height);
-
- public abstract Dictionary GetUnclaimed(UInt256 hash);
-
- ///
- /// 根据指定的散列值和索引,获取对应的未花费的资产
- ///
- /// 交易散列值
- /// 输出的索引
- /// 返回一个交易输出,表示一个未花费的资产
- public abstract TransactionOutput GetUnspent(UInt256 hash, ushort index);
-
- public abstract IEnumerable GetUnspent(UInt256 hash);
-
- ///
- /// 判断交易是否双花
- ///
- /// 交易
- /// 返回交易是否双花
- public abstract bool IsDoubleSpend(Transaction tx);
-
- ///
- /// 当区块被写入到硬盘后调用
- ///
- /// 区块
- protected void OnPersistCompleted(Block block)
- {
- PersistCompleted?.Invoke(this, block);
- }
-
- protected void OnPersistUnlocked(Block block)
- {
- lock (_validators)
- {
- _validators.Clear();
- }
- PersistUnlocked?.Invoke(this, block);
- }
-
- protected void ProcessAccountStateDescriptor(StateDescriptor descriptor, DataCache accounts, DataCache validators, MetaDataCache validators_count)
- {
- UInt160 hash = new UInt160(descriptor.Key);
- AccountState account = accounts.GetAndChange(hash, () => new AccountState(hash));
- switch (descriptor.Field)
- {
- case "Votes":
- Fixed8 balance = account.GetBalance(GoverningToken.Hash);
- foreach (ECPoint pubkey in account.Votes)
- {
- ValidatorState validator = validators.GetAndChange(pubkey);
- validator.Votes -= balance;
- if (!validator.Registered && validator.Votes.Equals(Fixed8.Zero))
- validators.Delete(pubkey);
- }
- ECPoint[] votes = descriptor.Value.AsSerializableArray().Distinct().ToArray();
- if (votes.Length != account.Votes.Length)
- {
- ValidatorsCountState count_state = validators_count.GetAndChange();
- if (account.Votes.Length > 0)
- count_state.Votes[account.Votes.Length - 1] -= balance;
- if (votes.Length > 0)
- count_state.Votes[votes.Length - 1] += balance;
- }
- account.Votes = votes;
- foreach (ECPoint pubkey in account.Votes)
- validators.GetAndChange(pubkey, () => new ValidatorState(pubkey)).Votes += balance;
- break;
- }
- }
-
- protected void ProcessValidatorStateDescriptor(StateDescriptor descriptor, DataCache validators)
- {
- ECPoint pubkey = ECPoint.DecodePoint(descriptor.Key, ECCurve.Secp256r1);
- ValidatorState validator = validators.GetAndChange(pubkey, () => new ValidatorState(pubkey));
- switch (descriptor.Field)
- {
- case "Registered":
- validator.Registered = BitConverter.ToBoolean(descriptor.Value, 0);
- break;
- }
- }
-
- ///
- /// 注册默认的区块链实例
- ///
- /// 区块链实例
- /// 返回注册后的区块链实例
- public static Blockchain RegisterBlockchain(Blockchain blockchain)
- {
- if (Default != null) Default.Dispose();
- Default = blockchain ?? throw new ArgumentNullException();
- return blockchain;
- }
- }
-}
diff --git a/neo/Core/Helper.cs b/neo/Core/Helper.cs
deleted file mode 100644
index 7683b2b952..0000000000
--- a/neo/Core/Helper.cs
+++ /dev/null
@@ -1,85 +0,0 @@
-using Neo.Cryptography;
-using Neo.SmartContract;
-using Neo.VM;
-using Neo.Wallets;
-using System;
-using System.IO;
-using System.Linq;
-
-namespace Neo.Core
-{
- ///
- /// 包含一系列签名与验证的扩展方法
- ///
- public static class Helper
- {
- public static byte[] GetHashData(this IVerifiable verifiable)
- {
- using (MemoryStream ms = new MemoryStream())
- using (BinaryWriter writer = new BinaryWriter(ms))
- {
- verifiable.SerializeUnsigned(writer);
- writer.Flush();
- return ms.ToArray();
- }
- }
-
- ///
- /// 根据传入的账户信息,对可签名的对象进行签名
- ///
- /// 要签名的数据
- /// 用于签名的账户
- /// 返回签名后的结果
- public static byte[] Sign(this IVerifiable verifiable, KeyPair key)
- {
- using (key.Decrypt())
- {
- return Crypto.Default.Sign(verifiable.GetHashData(), key.PrivateKey, key.PublicKey.EncodePoint(false).Skip(1).ToArray());
- }
- }
-
- public static UInt160 ToScriptHash(this byte[] script)
- {
- return new UInt160(Crypto.Default.Hash160(script));
- }
-
- internal static bool VerifyScripts(this IVerifiable verifiable)
- {
- UInt160[] hashes;
- try
- {
- hashes = verifiable.GetScriptHashesForVerifying();
- }
- catch (InvalidOperationException)
- {
- return false;
- }
- if (hashes.Length != verifiable.Scripts.Length) return false;
- for (int i = 0; i < hashes.Length; i++)
- {
- byte[] verification = verifiable.Scripts[i].VerificationScript;
- if (verification.Length == 0)
- {
- using (ScriptBuilder sb = new ScriptBuilder())
- {
- sb.EmitAppCall(hashes[i].ToArray());
- verification = sb.ToArray();
- }
- }
- else
- {
- if (hashes[i] != verifiable.Scripts[i].ScriptHash) return false;
- }
- using (StateReader service = new StateReader())
- {
- ApplicationEngine engine = new ApplicationEngine(TriggerType.Verification, verifiable, Blockchain.Default, service, Fixed8.Zero);
- engine.LoadScript(verification);
- engine.LoadScript(verifiable.Scripts[i].InvocationScript);
- if (!engine.Execute()) return false;
- if (engine.ResultStack.Count != 1 || !engine.ResultStack.Pop().GetBoolean()) return false;
- }
- }
- return true;
- }
- }
-}
diff --git a/neo/Core/IVerifiable.cs b/neo/Core/IVerifiable.cs
deleted file mode 100644
index dcf9fc72b4..0000000000
--- a/neo/Core/IVerifiable.cs
+++ /dev/null
@@ -1,35 +0,0 @@
-using Neo.IO;
-using Neo.VM;
-using System.IO;
-
-namespace Neo.Core
-{
- ///
- /// 为需要签名的数据提供一个接口
- ///
- public interface IVerifiable : ISerializable, IScriptContainer
- {
- ///
- /// 用于验证该对象的脚本列表
- ///
- Witness[] Scripts { get; set; }
-
- ///
- /// 反序列化未签名的数据
- ///
- /// 数据来源
- void DeserializeUnsigned(BinaryReader reader);
-
- ///
- /// 获得需要校验的脚本Hash值
- ///
- /// 返回需要校验的脚本Hash值
- UInt160[] GetScriptHashesForVerifying();
-
- ///
- /// 序列化未签名的数据
- ///
- /// 存放序列化后的结果
- void SerializeUnsigned(BinaryWriter writer);
- }
-}
diff --git a/neo/Core/TransactionResult.cs b/neo/Core/TransactionResult.cs
deleted file mode 100644
index 92448610fa..0000000000
--- a/neo/Core/TransactionResult.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-namespace Neo.Core
-{
- ///
- /// 交易结果,表示交易中资产的变化量
- ///
- public class TransactionResult
- {
- ///
- /// 资产编号
- ///
- public UInt256 AssetId;
- ///
- /// 该资产的变化量
- ///
- public Fixed8 Amount;
- }
-}
diff --git a/neo/Cryptography/Base58.cs b/neo/Cryptography/Base58.cs
index 1d8107c1ff..bb5dd42df9 100644
--- a/neo/Cryptography/Base58.cs
+++ b/neo/Cryptography/Base58.cs
@@ -7,16 +7,8 @@ namespace Neo.Cryptography
{
public static class Base58
{
- ///
- /// base58编码的字母表
- ///
public const string Alphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
- ///
- /// 解码
- ///
- /// 要解码的字符串
- /// 返回解码后的字节数组
public static byte[] Decode(string input)
{
BigInteger bi = BigInteger.Zero;
@@ -40,11 +32,6 @@ public static byte[] Decode(string input)
return tmp;
}
- ///
- /// 编码
- ///
- /// 要编码的字节数组
- /// 返回编码后的字符串
public static string Encode(byte[] input)
{
BigInteger value = new BigInteger(new byte[1].Concat(input).Reverse().ToArray());
diff --git a/neo/Cryptography/ECC/ECCurve.cs b/neo/Cryptography/ECC/ECCurve.cs
index aa4a956f76..9d43bcd25f 100644
--- a/neo/Cryptography/ECC/ECCurve.cs
+++ b/neo/Cryptography/ECC/ECCurve.cs
@@ -3,22 +3,13 @@
namespace Neo.Cryptography.ECC
{
- ///
- /// ECC椭圆曲线参数
- ///
public class ECCurve
{
internal readonly BigInteger Q;
internal readonly ECFieldElement A;
internal readonly ECFieldElement B;
internal readonly BigInteger N;
- ///
- /// 无穷远点
- ///
public readonly ECPoint Infinity;
- ///
- /// 基点
- ///
public readonly ECPoint G;
private ECCurve(BigInteger Q, BigInteger A, BigInteger B, BigInteger N, byte[] G)
@@ -31,9 +22,6 @@ private ECCurve(BigInteger Q, BigInteger A, BigInteger B, BigInteger N, byte[] G
this.G = ECPoint.DecodePoint(G, this);
}
- ///
- /// 曲线secp256k1
- ///
public static readonly ECCurve Secp256k1 = new ECCurve
(
BigInteger.Parse("00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", NumberStyles.AllowHexSpecifier),
@@ -43,9 +31,6 @@ private ECCurve(BigInteger Q, BigInteger A, BigInteger B, BigInteger N, byte[] G
("04" + "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798" + "483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8").HexToBytes()
);
- ///
- /// 曲线secp256r1
- ///
public static readonly ECCurve Secp256r1 = new ECCurve
(
BigInteger.Parse("00FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF", NumberStyles.AllowHexSpecifier),
diff --git a/neo/Cryptography/ECC/ECDsa.cs b/neo/Cryptography/ECC/ECDsa.cs
index 8e0f028e99..a254b4248e 100644
--- a/neo/Cryptography/ECC/ECDsa.cs
+++ b/neo/Cryptography/ECC/ECDsa.cs
@@ -5,30 +5,18 @@
namespace Neo.Cryptography.ECC
{
- ///
- /// 提供椭圆曲线数字签名算法(ECDSA)的功能
- ///
public class ECDsa
{
private readonly byte[] privateKey;
private readonly ECPoint publicKey;
private readonly ECCurve curve;
- ///
- /// 根据指定的私钥和曲线参数来创建新的ECDsa对象,该对象可用于签名
- ///
- /// 私钥
- /// 椭圆曲线参数
public ECDsa(byte[] privateKey, ECCurve curve)
: this(curve.G * privateKey)
{
this.privateKey = privateKey;
}
- ///
- /// 根据指定的公钥来创建新的ECDsa对象,该对象可用于验证签名
- ///
- /// 公钥
public ECDsa(ECPoint publicKey)
{
this.publicKey = publicKey;
@@ -46,11 +34,6 @@ private BigInteger CalculateE(BigInteger n, byte[] message)
return trunc;
}
- ///
- /// 生成椭圆曲线数字签名
- ///
- /// 要签名的消息
- /// 返回签名的数字编码(r,s)
public BigInteger[] GenerateSignature(byte[] message)
{
if (privateKey == null) throw new InvalidOperationException();
@@ -109,13 +92,6 @@ private static ECPoint SumOfTwoMultiplies(ECPoint P, BigInteger k, ECPoint Q, Bi
return R;
}
- ///
- /// 验证签名的合法性
- ///
- /// 要验证的消息
- /// 签名的数字编码
- /// 签名的数字编码
- /// 返回验证的结果
public bool VerifySignature(byte[] message, BigInteger r, BigInteger s)
{
if (r.Sign < 1 || s.Sign < 1 || r.CompareTo(curve.N) >= 0 || s.CompareTo(curve.N) >= 0)
diff --git a/neo/Cryptography/ECC/ECPoint.cs b/neo/Cryptography/ECC/ECPoint.cs
index ba529f8b02..99d2b099e1 100644
--- a/neo/Cryptography/ECC/ECPoint.cs
+++ b/neo/Cryptography/ECC/ECPoint.cs
@@ -12,9 +12,6 @@ public class ECPoint : IComparable, IEquatable, ISerializable
internal ECFieldElement X, Y;
internal readonly ECCurve Curve;
- ///
- /// 判断是否为无穷远点
- ///
public bool IsInfinity
{
get { return X == null && Y == null; }
@@ -36,11 +33,6 @@ internal ECPoint(ECFieldElement x, ECFieldElement y, ECCurve curve)
this.Curve = curve;
}
- ///
- /// 与另一对象进行比较
- ///
- /// 另一对象
- /// 返回比较的结果
public int CompareTo(ECPoint other)
{
if (ReferenceEquals(this, other)) return 0;
@@ -49,12 +41,6 @@ public int CompareTo(ECPoint other)
return Y.CompareTo(other.Y);
}
- ///
- /// 从字节数组中解码
- ///
- /// 要解码的字节数组
- /// 曲线参数
- ///
public static ECPoint DecodePoint(byte[] encoded, ECCurve curve)
{
ECPoint p = null;
@@ -127,12 +113,6 @@ void ISerializable.Deserialize(BinaryReader reader)
Y = p.Y;
}
- ///
- /// 反序列化
- ///
- /// 数据来源
- /// 椭圆曲线参数
- ///
public static ECPoint DeserializeFrom(BinaryReader reader, ECCurve curve)
{
int expectedLength = (curve.Q.GetBitLength() + 7) / 8;
@@ -156,11 +136,6 @@ public static ECPoint DeserializeFrom(BinaryReader reader, ECCurve curve)
}
}
- ///
- /// 将对象编码到字节数组
- ///
- /// 是否为压缩格式的编码
- /// 返回编码后的字节数组
public byte[] EncodePoint(bool commpressed)
{
if (IsInfinity) return new byte[1];
@@ -181,11 +156,6 @@ public byte[] EncodePoint(bool commpressed)
return data;
}
- ///
- /// 比较与另一个对象是否相等
- ///
- /// 另一个对象
- /// 返回比较的结果
public bool Equals(ECPoint other)
{
if (ReferenceEquals(this, other)) return true;
@@ -195,22 +165,11 @@ public bool Equals(ECPoint other)
return X.Equals(other.X) && Y.Equals(other.Y);
}
- ///
- /// 比较与另一个对象是否相等
- ///
- /// 另一个对象
- /// 返回比较的结果
public override bool Equals(object obj)
{
return Equals(obj as ECPoint);
}
- ///
- /// 从指定的字节数组中解析出公钥,这个字节数组可以是任意形式的公钥编码、或者包含私钥的内容
- ///
- /// 要解析的字节数组
- /// 椭圆曲线参数
- /// 返回解析出的公钥
public static ECPoint FromBytes(byte[] pubkey, ECCurve curve)
{
switch (pubkey.Length)
@@ -229,10 +188,6 @@ public static ECPoint FromBytes(byte[] pubkey, ECCurve curve)
}
}
- ///
- /// 获取HashCode
- ///
- /// 返回HashCode
public override int GetHashCode()
{
return X.GetHashCode() + Y.GetHashCode();
@@ -428,7 +383,6 @@ private static sbyte[] WindowNaf(sbyte width, BigInteger k)
throw new ArgumentException();
if (p.IsInfinity)
return p;
- //BigInteger的内存无法被保护,可能会有安全隐患。此处的k需要重写一个SecureBigInteger类来代替
BigInteger k = new BigInteger(n.Reverse().Concat(new byte[1]).ToArray());
if (k.Sign == 0)
return p.Curve.Infinity;
diff --git a/neo/Cryptography/Helper.cs b/neo/Cryptography/Helper.cs
index 539ecf3419..878195d873 100644
--- a/neo/Cryptography/Helper.cs
+++ b/neo/Cryptography/Helper.cs
@@ -1,4 +1,6 @@
-using System;
+using Neo.IO;
+using Neo.Network.P2P.Payloads;
+using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
@@ -9,9 +11,6 @@
namespace Neo.Cryptography
{
- ///
- /// 包含一系列密码学算法的扩展方法
- ///
public static class Helper
{
private static ThreadLocal _sha256 = new ThreadLocal(() => SHA256.Create());
@@ -92,11 +91,6 @@ public static string Base58CheckEncode(this byte[] data)
return Base58.Encode(buffer);
}
- ///
- /// 求字节数组的ripemd160散列值
- ///
- /// 字节数组
- /// 返回该散列值
public static byte[] RIPEMD160(this IEnumerable value)
{
return _ripemd160.Value.ComputeHash(value.ToArray());
@@ -110,28 +104,30 @@ public static uint Murmur32(this IEnumerable value, uint seed)
}
}
- ///
- /// 求字节数组的sha256散列值
- ///
- /// 字节数组
- /// 返回该散列值
public static byte[] Sha256(this IEnumerable value)
{
return _sha256.Value.ComputeHash(value.ToArray());
}
- ///
- /// 求字节数组的sha256散列值
- ///
- /// 字节数组
- /// 偏移量,散列计算时从该偏移量处开始
- /// 要计算散列值的字节数量
- /// 返回该散列值
public static byte[] Sha256(this byte[] value, int offset, int count)
{
return _sha256.Value.ComputeHash(value, offset, count);
}
+ internal static bool Test(this BloomFilter filter, Transaction tx)
+ {
+ if (filter.Check(tx.Hash.ToArray())) return true;
+ if (tx.Outputs.Any(p => filter.Check(p.ScriptHash.ToArray()))) return true;
+ if (tx.Inputs.Any(p => filter.Check(p.ToArray()))) return true;
+ if (tx.Witnesses.Any(p => filter.Check(p.ScriptHash.ToArray())))
+ return true;
+#pragma warning disable CS0612
+ if (tx is RegisterTransaction asset)
+ if (filter.Check(asset.Admin.ToArray())) return true;
+#pragma warning restore CS0612
+ return false;
+ }
+
internal static byte[] ToAesKey(this string password)
{
using (SHA256 sha256 = SHA256.Create())
diff --git a/neo/Cryptography/MerkleTree.cs b/neo/Cryptography/MerkleTree.cs
index 76b2ac198a..4f433aac88 100644
--- a/neo/Cryptography/MerkleTree.cs
+++ b/neo/Cryptography/MerkleTree.cs
@@ -5,9 +5,6 @@
namespace Neo.Cryptography
{
- ///
- /// 哈希树
- ///
public class MerkleTree
{
private MerkleTreeNode root;
@@ -48,11 +45,6 @@ private static MerkleTreeNode Build(MerkleTreeNode[] leaves)
return Build(parents); //TailCall
}
- ///
- /// 计算根节点的值
- ///
- /// 子节点列表
- /// 返回计算的结果
public static UInt256 ComputeRoot(UInt256[] hashes)
{
if (hashes.Length == 0) throw new ArgumentException();
diff --git a/neo/Cryptography/ProtectedMemoryContext.cs b/neo/Cryptography/ProtectedMemoryContext.cs
deleted file mode 100644
index b9453a1a3b..0000000000
--- a/neo/Cryptography/ProtectedMemoryContext.cs
+++ /dev/null
@@ -1,39 +0,0 @@
-#if NET47
-using System;
-using System.Collections.Generic;
-using System.Security.Cryptography;
-
-namespace Neo.Cryptography
-{
- internal class ProtectedMemoryContext : IDisposable
- {
- private static Dictionary counts = new Dictionary();
- private byte[] memory;
- private MemoryProtectionScope scope;
-
- public ProtectedMemoryContext(byte[] memory, MemoryProtectionScope scope)
- {
- this.memory = memory;
- this.scope = scope;
- if (counts.ContainsKey(memory))
- {
- counts[memory]++;
- }
- else
- {
- counts.Add(memory, 1);
- ProtectedMemory.Unprotect(memory, scope);
- }
- }
-
- void IDisposable.Dispose()
- {
- if (--counts[memory] == 0)
- {
- counts.Remove(memory);
- ProtectedMemory.Protect(memory, scope);
- }
- }
- }
-}
-#endif
\ No newline at end of file
diff --git a/neo/Fixed8.cs b/neo/Fixed8.cs
index 2fcd08d46a..7edf94ea41 100644
--- a/neo/Fixed8.cs
+++ b/neo/Fixed8.cs
@@ -233,7 +233,7 @@ public static explicit operator long(Fixed8 value)
public static Fixed8 operator *(Fixed8 x, long y)
{
- x.value *= y;
+ x.value = checked(x.value * y);
return x;
}
diff --git a/neo/Helper.cs b/neo/Helper.cs
index 6bb5173834..7672d078b3 100644
--- a/neo/Helper.cs
+++ b/neo/Helper.cs
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
+using System.Net;
using System.Numerics;
using System.Reflection;
using System.Runtime.CompilerServices;
@@ -216,6 +217,20 @@ unsafe internal static ulong ToUInt64(this byte[] value, int startIndex)
}
}
+ internal static IPAddress Unmap(this IPAddress address)
+ {
+ if (address.IsIPv4MappedToIPv6)
+ address = address.MapToIPv4();
+ return address;
+ }
+
+ internal static IPEndPoint Unmap(this IPEndPoint endPoint)
+ {
+ if (!endPoint.Address.IsIPv4MappedToIPv6)
+ return endPoint;
+ return new IPEndPoint(endPoint.Address.Unmap(), endPoint.Port);
+ }
+
internal static long WeightedAverage(this IEnumerable source, Func valueSelector, Func weightSelector)
{
long sum_weight = 0;
diff --git a/neo/IO/Actors/PriorityMailbox.cs b/neo/IO/Actors/PriorityMailbox.cs
new file mode 100644
index 0000000000..fa345302ea
--- /dev/null
+++ b/neo/IO/Actors/PriorityMailbox.cs
@@ -0,0 +1,24 @@
+using Akka.Actor;
+using Akka.Configuration;
+using Akka.Dispatch;
+using Akka.Dispatch.MessageQueues;
+using System.Collections;
+
+namespace Neo.IO.Actors
+{
+ internal abstract class PriorityMailbox : MailboxType, IProducesMessageQueue
+ {
+ public PriorityMailbox(Akka.Actor.Settings settings, Config config)
+ : base(settings, config)
+ {
+ }
+
+ public override IMessageQueue Create(IActorRef owner, ActorSystem system)
+ {
+ return new PriorityMessageQueue(ShallDrop, IsHighPriority);
+ }
+
+ protected virtual bool IsHighPriority(object message) => false;
+ protected virtual bool ShallDrop(object message, IEnumerable queue) => false;
+ }
+}
diff --git a/neo/IO/Actors/PriorityMessageQueue.cs b/neo/IO/Actors/PriorityMessageQueue.cs
new file mode 100644
index 0000000000..c166d76f08
--- /dev/null
+++ b/neo/IO/Actors/PriorityMessageQueue.cs
@@ -0,0 +1,46 @@
+using Akka.Actor;
+using Akka.Dispatch;
+using Akka.Dispatch.MessageQueues;
+using System;
+using System.Collections;
+using System.Collections.Concurrent;
+using System.Linq;
+
+namespace Neo.IO.Actors
+{
+ internal class PriorityMessageQueue : IMessageQueue, IUnboundedMessageQueueSemantics
+ {
+ private readonly ConcurrentQueue high = new ConcurrentQueue();
+ private readonly ConcurrentQueue low = new ConcurrentQueue();
+ private readonly Func