From 72cee805b66fa79bda94c084c82e2c8f9c94720d Mon Sep 17 00:00:00 2001 From: Charis Date: Tue, 26 Nov 2019 15:00:11 +0800 Subject: [PATCH 01/11] optimize pooltem and transaction --- src/neo/Ledger/PoolItem.cs | 19 +++++++++++++++++- src/neo/Network/P2P/Payloads/Transaction.cs | 22 ++++++++++++++++----- 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/src/neo/Ledger/PoolItem.cs b/src/neo/Ledger/PoolItem.cs index 45316d04db..8fe79b451f 100644 --- a/src/neo/Ledger/PoolItem.cs +++ b/src/neo/Ledger/PoolItem.cs @@ -26,11 +26,23 @@ internal class PoolItem : IComparable /// public DateTime LastBroadcastTimestamp; + /// + /// Cache Tx's Hash to avoid recompute when comparing + /// + public UInt256 TxHashCache; + + /// + /// Cache Tx's Hash to avoid recompute when comparing + /// + public long TxFeePerByteCache; + internal PoolItem(Transaction tx) { Tx = tx; Timestamp = TimeProvider.Current.UtcNow; LastBroadcastTimestamp = Timestamp; + TxHashCache = tx.Hash; + TxFeePerByteCache = tx.FeePerByte; } public int CompareTo(Transaction otherTx) @@ -48,7 +60,12 @@ public int CompareTo(Transaction otherTx) public int CompareTo(PoolItem otherItem) { if (otherItem == null) return 1; - return CompareTo(otherItem.Tx); + if (otherItem.Tx == null) return 1; + int ret = TxFeePerByteCache.CompareTo(otherItem.TxFeePerByte); + if (ret != 0) return ret; + ret = Tx.NetworkFee.CompareTo(otherItem.Tx.NetworkFee); + if (ret != 0) return ret; + return TxHashCache.CompareTo(otherItem.TxHash); } } } diff --git a/src/neo/Network/P2P/Payloads/Transaction.cs b/src/neo/Network/P2P/Payloads/Transaction.cs index de81275877..191206b60c 100644 --- a/src/neo/Network/P2P/Payloads/Transaction.cs +++ b/src/neo/Network/P2P/Payloads/Transaction.cs @@ -74,16 +74,28 @@ public UInt256 Hash sizeof(long) + //NetworkFee sizeof(uint); //ValidUntilBlock - public int Size => HeaderSize + - Attributes.GetVarSize() + //Attributes - Cosigners.GetVarSize() + //Cosigners - Script.GetVarSize() + //Script - Witnesses.GetVarSize(); //Witnesses + /// + /// Assigned when tx is deserialized + /// + private int _size; + public int Size + { + get + { + return _size == 0 ? HeaderSize + + Attributes.GetVarSize() + //Attributes + Cosigners.GetVarSize() + //Cosigners + Script.GetVarSize() + //Script + Witnesses.GetVarSize() //Witnesses + : _size; + } + } void ISerializable.Deserialize(BinaryReader reader) { DeserializeUnsigned(reader); Witnesses = reader.ReadSerializableArray(); + _size = (int)reader.BaseStream.Position; } public void DeserializeUnsigned(BinaryReader reader) From 7ad6eee06ae5bf32a3dcdffce41b431a88b477c0 Mon Sep 17 00:00:00 2001 From: Charis Date: Tue, 26 Nov 2019 15:22:31 +0800 Subject: [PATCH 02/11] format --- src/neo/Network/P2P/Payloads/Transaction.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/neo/Network/P2P/Payloads/Transaction.cs b/src/neo/Network/P2P/Payloads/Transaction.cs index 191206b60c..f7ce8504e1 100644 --- a/src/neo/Network/P2P/Payloads/Transaction.cs +++ b/src/neo/Network/P2P/Payloads/Transaction.cs @@ -87,7 +87,7 @@ public int Size Cosigners.GetVarSize() + //Cosigners Script.GetVarSize() + //Script Witnesses.GetVarSize() //Witnesses - : _size; + : _size; } } From 0a9edb8d9e87e45d7193042b020c4bd51a3a9e18 Mon Sep 17 00:00:00 2001 From: Charis Date: Tue, 26 Nov 2019 15:26:30 +0800 Subject: [PATCH 03/11] fix --- src/neo/Ledger/PoolItem.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/neo/Ledger/PoolItem.cs b/src/neo/Ledger/PoolItem.cs index 8fe79b451f..ad948f7de1 100644 --- a/src/neo/Ledger/PoolItem.cs +++ b/src/neo/Ledger/PoolItem.cs @@ -61,11 +61,11 @@ public int CompareTo(PoolItem otherItem) { if (otherItem == null) return 1; if (otherItem.Tx == null) return 1; - int ret = TxFeePerByteCache.CompareTo(otherItem.TxFeePerByte); + int ret = TxFeePerByteCache.CompareTo(otherItem.TxFeePerByteCache); if (ret != 0) return ret; ret = Tx.NetworkFee.CompareTo(otherItem.Tx.NetworkFee); if (ret != 0) return ret; - return TxHashCache.CompareTo(otherItem.TxHash); + return TxHashCache.CompareTo(otherItem.TxHashCache); } } } From d066d096528dc140e440817a776427cc8e0c2c09 Mon Sep 17 00:00:00 2001 From: Charis Date: Tue, 26 Nov 2019 16:03:37 +0800 Subject: [PATCH 04/11] fix UT --- tests/neo.UnitTests/Ledger/UT_PoolItem.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/neo.UnitTests/Ledger/UT_PoolItem.cs b/tests/neo.UnitTests/Ledger/UT_PoolItem.cs index d94cec8e4c..450c14176b 100644 --- a/tests/neo.UnitTests/Ledger/UT_PoolItem.cs +++ b/tests/neo.UnitTests/Ledger/UT_PoolItem.cs @@ -96,7 +96,7 @@ public Transaction GenerateTxWithFirstByteOfHashGreaterThanOrEqualTo(byte firstH do { tx = GenerateTx(networkFee, size); - } while (tx.Hash >= new UInt256(TestUtils.GetByteArray(32, firstHashByte))); + } while (tx.Hash < new UInt256(TestUtils.GetByteArray(32, firstHashByte))); return tx; } @@ -107,7 +107,7 @@ public Transaction GenerateTxWithFirstByteOfHashLessThanOrEqualTo(byte firstHash do { tx = GenerateTx(networkFee, size); - } while (tx.Hash <= new UInt256(TestUtils.GetByteArray(32, firstHashByte))); + } while (tx.Hash > new UInt256(TestUtils.GetByteArray(32, firstHashByte))); return tx; } From c2dc5a4a8184ce84a6b71ac67f57239d9e91d745 Mon Sep 17 00:00:00 2001 From: Charis Date: Tue, 26 Nov 2019 16:13:16 +0800 Subject: [PATCH 05/11] remove Hash cache --- src/neo/Ledger/PoolItem.cs | 10 ++-------- tests/neo.UnitTests/Ledger/UT_PoolItem.cs | 8 ++++---- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/src/neo/Ledger/PoolItem.cs b/src/neo/Ledger/PoolItem.cs index ad948f7de1..da113341cd 100644 --- a/src/neo/Ledger/PoolItem.cs +++ b/src/neo/Ledger/PoolItem.cs @@ -27,12 +27,7 @@ internal class PoolItem : IComparable public DateTime LastBroadcastTimestamp; /// - /// Cache Tx's Hash to avoid recompute when comparing - /// - public UInt256 TxHashCache; - - /// - /// Cache Tx's Hash to avoid recompute when comparing + /// Cache Tx's FeePerByte to avoid recompute when comparing /// public long TxFeePerByteCache; @@ -41,7 +36,6 @@ internal PoolItem(Transaction tx) Tx = tx; Timestamp = TimeProvider.Current.UtcNow; LastBroadcastTimestamp = Timestamp; - TxHashCache = tx.Hash; TxFeePerByteCache = tx.FeePerByte; } @@ -65,7 +59,7 @@ public int CompareTo(PoolItem otherItem) if (ret != 0) return ret; ret = Tx.NetworkFee.CompareTo(otherItem.Tx.NetworkFee); if (ret != 0) return ret; - return TxHashCache.CompareTo(otherItem.TxHashCache); + return otherItem.Tx.Hash.CompareTo(Tx.Hash); } } } diff --git a/tests/neo.UnitTests/Ledger/UT_PoolItem.cs b/tests/neo.UnitTests/Ledger/UT_PoolItem.cs index 450c14176b..0d37e6edfd 100644 --- a/tests/neo.UnitTests/Ledger/UT_PoolItem.cs +++ b/tests/neo.UnitTests/Ledger/UT_PoolItem.cs @@ -67,11 +67,11 @@ public void PoolItem_CompareTo_Hash() PoolItem pitem1 = new PoolItem(tx1); PoolItem pitem2 = new PoolItem(tx2); - // pitem2 < pitem1 (fee) => -1 - pitem2.CompareTo(pitem1).Should().Be(-1); + // pitem2.tx.Hash < pitem1.tx.Hash => 1 descending order + pitem2.CompareTo(pitem1).Should().Be(1); - // pitem1 > pitem2 (fee) => 1 - pitem1.CompareTo(pitem2).Should().Be(1); + // pitem2.tx.Hash > pitem1.tx.Hash => -1 descending order + pitem1.CompareTo(pitem2).Should().Be(-1); } } From c575f065463ad778a52e7640d3d775c5d814b6c9 Mon Sep 17 00:00:00 2001 From: Charis Date: Wed, 27 Nov 2019 10:04:20 +0800 Subject: [PATCH 06/11] revert FeePerByteCache --- src/neo/Ledger/PoolItem.cs | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/src/neo/Ledger/PoolItem.cs b/src/neo/Ledger/PoolItem.cs index da113341cd..45316d04db 100644 --- a/src/neo/Ledger/PoolItem.cs +++ b/src/neo/Ledger/PoolItem.cs @@ -26,17 +26,11 @@ internal class PoolItem : IComparable /// public DateTime LastBroadcastTimestamp; - /// - /// Cache Tx's FeePerByte to avoid recompute when comparing - /// - public long TxFeePerByteCache; - internal PoolItem(Transaction tx) { Tx = tx; Timestamp = TimeProvider.Current.UtcNow; LastBroadcastTimestamp = Timestamp; - TxFeePerByteCache = tx.FeePerByte; } public int CompareTo(Transaction otherTx) @@ -54,12 +48,7 @@ public int CompareTo(Transaction otherTx) public int CompareTo(PoolItem otherItem) { if (otherItem == null) return 1; - if (otherItem.Tx == null) return 1; - int ret = TxFeePerByteCache.CompareTo(otherItem.TxFeePerByteCache); - if (ret != 0) return ret; - ret = Tx.NetworkFee.CompareTo(otherItem.Tx.NetworkFee); - if (ret != 0) return ret; - return otherItem.Tx.Hash.CompareTo(Tx.Hash); + return CompareTo(otherItem.Tx); } } } From 8d9cd8004ad7bb47ba72e086b64256269fc72dab Mon Sep 17 00:00:00 2001 From: Charis Date: Wed, 27 Nov 2019 16:13:48 +0800 Subject: [PATCH 07/11] update Position --- src/neo/Network/P2P/Payloads/Transaction.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/neo/Network/P2P/Payloads/Transaction.cs b/src/neo/Network/P2P/Payloads/Transaction.cs index f7ce8504e1..7d9cc00a63 100644 --- a/src/neo/Network/P2P/Payloads/Transaction.cs +++ b/src/neo/Network/P2P/Payloads/Transaction.cs @@ -93,9 +93,10 @@ public int Size void ISerializable.Deserialize(BinaryReader reader) { + var startPosition = (int)reader.BaseStream.Position; DeserializeUnsigned(reader); Witnesses = reader.ReadSerializableArray(); - _size = (int)reader.BaseStream.Position; + _size = (int)reader.BaseStream.Position - startPosition; } public void DeserializeUnsigned(BinaryReader reader) From 3da3ddadd2af587d8d92b2e252d235ffe217c138 Mon Sep 17 00:00:00 2001 From: Charis Date: Thu, 28 Nov 2019 10:07:35 +0800 Subject: [PATCH 08/11] change way to cache size --- src/neo/Network/P2P/Payloads/Transaction.cs | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/neo/Network/P2P/Payloads/Transaction.cs b/src/neo/Network/P2P/Payloads/Transaction.cs index 716a216a50..5c241db8a5 100644 --- a/src/neo/Network/P2P/Payloads/Transaction.cs +++ b/src/neo/Network/P2P/Payloads/Transaction.cs @@ -74,29 +74,27 @@ public UInt256 Hash sizeof(long) + //NetworkFee sizeof(uint); //ValidUntilBlock - /// - /// Assigned when tx is deserialized - /// private int _size; public int Size { get { - return _size == 0 ? HeaderSize + + if (_size == 0) + { + _size = HeaderSize + Attributes.GetVarSize() + //Attributes Cosigners.GetVarSize() + //Cosigners Script.GetVarSize() + //Script - Witnesses.GetVarSize() //Witnesses - : _size; + Witnesses.GetVarSize(); //Witnesses + } + return _size; } } void ISerializable.Deserialize(BinaryReader reader) { - var startPosition = (int)reader.BaseStream.Position; DeserializeUnsigned(reader); Witnesses = reader.ReadSerializableArray(); - _size = (int)reader.BaseStream.Position - startPosition; } public void DeserializeUnsigned(BinaryReader reader) From a700695a27ca1484057aa6a53abf0e145779938e Mon Sep 17 00:00:00 2001 From: erikzhang Date: Thu, 28 Nov 2019 12:16:30 +0800 Subject: [PATCH 09/11] Automatically clear the cache when the properties changed. --- src/neo/Network/P2P/Payloads/Transaction.cs | 115 +++++++++++++++----- 1 file changed, 87 insertions(+), 28 deletions(-) diff --git a/src/neo/Network/P2P/Payloads/Transaction.cs b/src/neo/Network/P2P/Payloads/Transaction.cs index 5c241db8a5..977630c65b 100644 --- a/src/neo/Network/P2P/Payloads/Transaction.cs +++ b/src/neo/Network/P2P/Payloads/Transaction.cs @@ -4,7 +4,6 @@ using Neo.Persistence; using Neo.SmartContract; using Neo.SmartContract.Native; -using Neo.VM; using Neo.VM.Types; using Neo.Wallets; using System; @@ -28,22 +27,36 @@ public class Transaction : IEquatable, IInventory, IInteroperable /// private const int MaxCosigners = 16; - public byte Version; - public uint Nonce; - public UInt160 Sender; - /// - /// Distributed to NEO holders. - /// - public long SystemFee; - /// - /// Distributed to consensus nodes. - /// - public long NetworkFee; - public uint ValidUntilBlock; - public TransactionAttribute[] Attributes; - public Cosigner[] Cosigners { get; set; } - public byte[] Script; - public Witness[] Witnesses { get; set; } + private byte version; + private uint nonce; + private UInt160 sender; + private long sysfee; + private long netfee; + private uint validUntilBlock; + private TransactionAttribute[] attributes; + private Cosigner[] cosigners; + private byte[] script; + private Witness[] witnesses; + + public const int HeaderSize = + sizeof(byte) + //Version + sizeof(uint) + //Nonce + 20 + //Sender + sizeof(long) + //SystemFee + sizeof(long) + //NetworkFee + sizeof(uint); //ValidUntilBlock + + public TransactionAttribute[] Attributes + { + get => attributes; + set { attributes = value; _hash = null; _size = 0; } + } + + public Cosigner[] Cosigners + { + get => cosigners; + set { cosigners = value; _hash = null; _size = 0; } + } /// /// The NetworkFee for the transaction divided by its Size. @@ -66,13 +79,32 @@ public UInt256 Hash InventoryType IInventory.InventoryType => InventoryType.TX; - public const int HeaderSize = - sizeof(byte) + //Version - sizeof(uint) + //Nonce - 20 + //Sender - sizeof(long) + //SystemFee - sizeof(long) + //NetworkFee - sizeof(uint); //ValidUntilBlock + /// + /// Distributed to consensus nodes. + /// + public long NetworkFee + { + get => netfee; + set { netfee = value; _hash = null; } + } + + public uint Nonce + { + get => nonce; + set { nonce = value; _hash = null; } + } + + public byte[] Script + { + get => script; + set { script = value; _hash = null; _size = 0; } + } + + public UInt160 Sender + { + get => sender; + set { sender = value; _hash = null; } + } private int _size; public int Size @@ -82,15 +114,42 @@ public int Size if (_size == 0) { _size = HeaderSize + - Attributes.GetVarSize() + //Attributes - Cosigners.GetVarSize() + //Cosigners - Script.GetVarSize() + //Script - Witnesses.GetVarSize(); //Witnesses + Attributes.GetVarSize() + //Attributes + Cosigners.GetVarSize() + //Cosigners + Script.GetVarSize() + //Script + Witnesses.GetVarSize(); //Witnesses } return _size; } } + /// + /// Distributed to NEO holders. + /// + public long SystemFee + { + get => sysfee; + set { sysfee = value; _hash = null; } + } + + public uint ValidUntilBlock + { + get => validUntilBlock; + set { validUntilBlock = value; _hash = null; } + } + + public byte Version + { + get => version; + set { version = value; _hash = null; } + } + + public Witness[] Witnesses + { + get => witnesses; + set { witnesses = value; _size = 0; } + } + void ISerializable.Deserialize(BinaryReader reader) { DeserializeUnsigned(reader); From 75f00890c2e59cb062adb1a11c3d2e27e6c543a0 Mon Sep 17 00:00:00 2001 From: erikzhang Date: Thu, 28 Nov 2019 20:38:16 +0800 Subject: [PATCH 10/11] @Tommo-L's suggestion --- src/neo/Network/P2P/Payloads/Transaction.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/neo/Network/P2P/Payloads/Transaction.cs b/src/neo/Network/P2P/Payloads/Transaction.cs index 977630c65b..df2a182cc8 100644 --- a/src/neo/Network/P2P/Payloads/Transaction.cs +++ b/src/neo/Network/P2P/Payloads/Transaction.cs @@ -152,8 +152,13 @@ public Witness[] Witnesses void ISerializable.Deserialize(BinaryReader reader) { + int startPosition = -1; + if (reader.BaseStream.CanSeek) + startPosition = (int)reader.BaseStream.Position; DeserializeUnsigned(reader); Witnesses = reader.ReadSerializableArray(); + if (startPosition >= 0) + _size = (int)reader.BaseStream.Position - startPosition; } public void DeserializeUnsigned(BinaryReader reader) From e20434ba4e244abf08480ef0890710a5339a2e0a Mon Sep 17 00:00:00 2001 From: Shargon Date: Thu, 28 Nov 2019 16:13:47 +0100 Subject: [PATCH 11/11] Space --- src/neo/Network/P2P/Payloads/Transaction.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/neo/Network/P2P/Payloads/Transaction.cs b/src/neo/Network/P2P/Payloads/Transaction.cs index df2a182cc8..c2adb34017 100644 --- a/src/neo/Network/P2P/Payloads/Transaction.cs +++ b/src/neo/Network/P2P/Payloads/Transaction.cs @@ -117,7 +117,7 @@ public int Size Attributes.GetVarSize() + //Attributes Cosigners.GetVarSize() + //Cosigners Script.GetVarSize() + //Script - Witnesses.GetVarSize(); //Witnesses + Witnesses.GetVarSize(); //Witnesses } return _size; }