Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add notary contract #2425

Closed
wants to merge 47 commits into from
Closed
Show file tree
Hide file tree
Changes from 46 commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
6b9cb8c
Merge pull request #16 from neo-project/master
longfeiWan9 Jul 20, 2020
69d2b45
Merge pull request #17 from neo-project/master
longfeiWan9 Jul 31, 2020
61fa3a5
Merge pull request #3 from neo-project/master
longfeiWan9 Nov 3, 2020
9866e97
Merge branch 'master' of https://github.com/neo-ngd/neo
Ashuaidehao Nov 3, 2020
4abe12f
Merge pull request #4 from neo-project/master
Ashuaidehao Dec 21, 2020
c80b546
Merge pull request #5 from neo-project/master
Ashuaidehao Feb 3, 2021
1363486
Merge https://github.com/neo-project/neo
Ashuaidehao Mar 5, 2021
69f33cd
Merge https://github.com/neo-project/neo
Ashuaidehao Mar 8, 2021
7c001f1
Merge https://github.com/neo-project/neo
Ashuaidehao Mar 10, 2021
3f06ee3
Merge https://github.com/neo-project/neo
Ashuaidehao Mar 15, 2021
bbabfde
Merge https://github.com/neo-project/neo
Ashuaidehao Mar 17, 2021
28f874a
Merge https://github.com/neo-project/neo
Ashuaidehao Mar 18, 2021
f0c4525
Merge remote-tracking branch 'upstream/master'
doubiliu Mar 24, 2021
175036f
Add NotaryContract
doubiliu Apr 1, 2021
61aa16f
Merge remote-tracking branch 'upstream/master' into addNotaryContract
doubiliu Apr 1, 2021
d3ffc22
Add NotaryContract
doubiliu Apr 1, 2021
261d45b
Fix Conflicts
doubiliu Apr 2, 2021
8da5ba0
merge update
doubiliu Apr 2, 2021
e1199bb
optimize
ZhangTao1596 Apr 2, 2021
907e4bb
Fix bug
doubiliu Apr 2, 2021
218a19b
merger
doubiliu Apr 2, 2021
4745930
optimize and add NotaryRequst handler
ZhangTao1596 Apr 2, 2021
3b24d28
Fix bug
doubiliu Apr 2, 2021
72443dd
Merge branch 'addNotaryContract' of github.com:neo-ngd/neo into addNo…
doubiliu Apr 2, 2021
12f9412
optimize notary request verify
ZhangTao1596 Apr 6, 2021
7330233
fix notary verify
ZhangTao1596 Apr 6, 2021
2b7ea54
format
ZhangTao1596 Apr 6, 2021
3f51335
Merge branch 'master' into addNotaryContract
ZhangTao1596 Apr 6, 2021
7ab45aa
Add UT
doubiliu Apr 6, 2021
3387d72
Merge branch 'addNotaryContract' of github.com:neo-ngd/neo into addNo…
doubiliu Apr 6, 2021
23df884
rename P2PNotary role to Notary
ZhangTao1596 Apr 6, 2021
151e5dd
remove unused snapshot
ZhangTao1596 Apr 6, 2021
8eb71f1
Merge branch 'addNotaryContract' of github.com:neo-ngd/neo into addNo…
doubiliu Apr 6, 2021
ac7bb1d
conficts check and verify
ZhangTao1596 Apr 7, 2021
9cf903c
Fix ledger
doubiliu Apr 7, 2021
a7d4c52
Merge branch 'addNotaryContract' of github.com:neo-ngd/neo into addNo…
doubiliu Apr 7, 2021
f91d94b
fix build error
ZhangTao1596 Apr 7, 2021
3aab3f5
Merge branch 'addNotaryContract' of github.com:neo-ngd/neo into addNo…
doubiliu Apr 7, 2021
eed170f
format UT
doubiliu Apr 7, 2021
db6da5b
Merge branch 'master' into addNotaryContract
ZhangTao1596 Apr 7, 2021
fb15b67
fix some
ZhangTao1596 Apr 7, 2021
ce5cbfa
fix ut
ZhangTao1596 Apr 7, 2021
fcbc8c4
Merge branch 'master' into addNotaryContract
ZhangTao1596 Apr 14, 2021
9670d22
Merge branch 'master' into addNotaryContract
ZhangTao1596 Apr 20, 2021
023336f
Merge branch 'master' into addNotaryContract
ZhangTao1596 Dec 7, 2021
fcc3182
fix build error
ZhangTao1596 Dec 7, 2021
f9ee8ef
Merge branch 'master' into addNotaryContract
ZhangTao1596 Mar 10, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/neo/Ledger/Blockchain.cs
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,7 @@ private void OnInventory(IInventory inventory, bool relay = true)
Block block => OnNewBlock(block),
Transaction transaction => OnNewTransaction(transaction),
ExtensiblePayload payload => OnNewExtensiblePayload(payload),
NotaryRequest payload => OnNotaryRequest(payload),
_ => throw new NotSupportedException()
};
if (result == VerifyResult.Succeed && relay)
Expand Down Expand Up @@ -329,6 +330,13 @@ private VerifyResult OnNewExtensiblePayload(ExtensiblePayload payload)
return VerifyResult.Succeed;
}

private VerifyResult OnNotaryRequest(NotaryRequest payload)
{
if (!payload.Verify(system.Settings)) return VerifyResult.Invalid;
system.RelayCache.Add(payload);
return VerifyResult.Succeed;
}

private VerifyResult OnNewTransaction(Transaction transaction)
{
if (system.ContainsTransaction(transaction.Hash)) return VerifyResult.AlreadyExists;
Expand Down
32 changes: 32 additions & 0 deletions src/neo/Ledger/MemoryPool.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
using Neo.Network.P2P.Payloads;
using Neo.Persistence;
using Neo.Plugins;
using Neo.Wallets;
using System;
using System.Collections;
using System.Collections.Generic;
Expand Down Expand Up @@ -293,6 +294,7 @@ internal VerifyResult TryAdd(Transaction tx, DataCache snapshot)
{
VerifyResult result = tx.VerifyStateDependent(_system.Settings, snapshot, VerificationContext);
if (result != VerifyResult.Succeed) return result;
if (!CheckConflicts(tx)) return VerifyResult.Invalid;

_unsortedTransactions.Add(tx.Hash, poolItem);
VerificationContext.AddTransaction(tx);
Expand All @@ -317,6 +319,36 @@ internal VerifyResult TryAdd(Transaction tx, DataCache snapshot)
return VerifyResult.Succeed;
}

private bool CheckConflicts(Transaction tx)
{
List<PoolItem> to_removed = new();
foreach (var hash in tx.GetAttributes<ConflictAttribute>().Select(p => p.Hash))
{
if (_unsortedTransactions.TryGetValue(hash, out PoolItem item))
{
if (!tx.Signers.Select(p => p.Account).Contains(item.Tx.Sender)) return false;
if (tx.NetworkFee < item.Tx.NetworkFee) return false;
to_removed.Add(item);
}
}
foreach (var item in _sortedTransactions)
{
var conflicts = item.Tx.GetAttributes<ConflictAttribute>().Select(p => p.Hash);
if (conflicts.Contains(tx.Hash))
{
if (item.Tx.Signers.Select(p => p.Account).Contains(tx.Sender) && tx.NetworkFee < item.Tx.NetworkFee) return false;
to_removed.Add(item);
}
}
foreach (var item in to_removed)
{
_unsortedTransactions.Remove(item.Tx.Hash);
_sortedTransactions.Remove(item);
VerificationContext.RemoveTransaction(item.Tx);
}
return true;
}

private List<Transaction> RemoveOverCapacity()
{
List<Transaction> removedTransactions = new();
Expand Down
6 changes: 6 additions & 0 deletions src/neo/Network/P2P/MessageCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,12 @@ public enum MessageCommand : byte
[ReflectionCache(typeof(Block))]
Block = 0x2c,

/// <summary>
/// Sent to send an <see cref="NotaryRequest"/>.
/// </summary>
[ReflectionCache(typeof(NotaryRequest))]
Notary = 0x2d,

/// <summary>
/// Sent to send an <see cref="ExtensiblePayload"/>.
/// </summary>
Expand Down
45 changes: 45 additions & 0 deletions src/neo/Network/P2P/Payloads/ConflictAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
using Neo.IO;
using Neo.IO.Json;
using Neo.Persistence;
using Neo.SmartContract.Native;
using System.IO;

namespace Neo.Network.P2P.Payloads
{
/// <summary>
/// Indicates that the transaction is conflict with another.
/// </summary>
public class ConflictAttribute : TransactionAttribute
{
/// <summary>
/// Indicates the conflict transaction hash.
/// </summary>
public UInt256 Hash;

public override TransactionAttributeType Type => TransactionAttributeType.Conflict;

public override bool AllowMultiple => true;

protected override void DeserializeWithoutType(BinaryReader reader)
{
Hash = reader.ReadSerializable<UInt256>();
}

protected override void SerializeWithoutType(BinaryWriter writer)
{
writer.Write(Hash);
}

public override JObject ToJson()
{
JObject json = base.ToJson();
json["hash"] = Hash.ToString();
return json;
}

public override bool Verify(DataCache snapshot, Transaction tx)
{
return NativeContract.Ledger.ContainsTransaction(snapshot, Hash);
}
}
}
7 changes: 6 additions & 1 deletion src/neo/Network/P2P/Payloads/InventoryType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ public enum InventoryType : byte
/// <summary>
/// Indicates that the inventory is an <see cref="ExtensiblePayload"/>.
/// </summary>
Extensible = MessageCommand.Extensible
Extensible = MessageCommand.Extensible,

/// <summary>
/// Indicates that the inventory is an <see cref="NotaryRequest"/>.
/// </summary>
Notary = MessageCommand.Notary
}
}
48 changes: 48 additions & 0 deletions src/neo/Network/P2P/Payloads/NotValidBefore.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
using Neo.IO.Json;
using Neo.Persistence;
using Neo.SmartContract.Native;
using System.IO;

namespace Neo.Network.P2P.Payloads
{
/// <summary>
/// Indicates that the transaction is not valid before specified height.
/// </summary>
public class NotValidBefore : TransactionAttribute
{
/// <summary>
/// Indicates that the transaction is not valid before this height.
/// </summary>
public uint Height;

public override TransactionAttributeType Type => TransactionAttributeType.NotValidBefore;

public override bool AllowMultiple => false;

protected override void DeserializeWithoutType(BinaryReader reader)
{
Height = reader.ReadUInt32();
}

protected override void SerializeWithoutType(BinaryWriter writer)
{
writer.Write(Height);
}

public override JObject ToJson()
{
JObject json = base.ToJson();
json["height"] = Height;
return json;
}

public override bool Verify(DataCache snapshot, Transaction tx)
{
var maxNVBDelta = NativeContract.Notary.GetMaxNotValidBeforeDelta(snapshot);
var block_height = NativeContract.Ledger.CurrentIndex(snapshot);
if (block_height < Height) return false;
if ((block_height + maxNVBDelta) < Height) return false;
return tx.ValidUntilBlock <= (Height + maxNVBDelta);
}
}
}
45 changes: 45 additions & 0 deletions src/neo/Network/P2P/Payloads/NotaryAssisted.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
using Neo.IO.Json;
using Neo.Persistence;
using Neo.SmartContract.Native;
using System.IO;
using System.Linq;

namespace Neo.Network.P2P.Payloads
{
/// <summary>
/// Indicates that the transaction is an Notrary tx.
/// </summary>
public class NotaryAssisted : TransactionAttribute
{
/// <summary>
/// Indicates how many signatures the Notary need to collect.
/// </summary>
public byte NKeys;

public override TransactionAttributeType Type => TransactionAttributeType.NotaryAssisted;

public override bool AllowMultiple => false;

protected override void DeserializeWithoutType(BinaryReader reader)
{
NKeys = reader.ReadByte();
}

protected override void SerializeWithoutType(BinaryWriter writer)
{
writer.Write(NKeys);
}

public override JObject ToJson()
{
JObject json = base.ToJson();
json["nkeys"] = NKeys;
return json;
}

public override bool Verify(DataCache snapshot, Transaction tx)
{
return tx.Signers.First(p => p.Account.Equals(NativeContract.Notary.Hash)) is not null;
}
}
}
138 changes: 138 additions & 0 deletions src/neo/Network/P2P/Payloads/NotaryRequest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
using Akka.Actor;
using Neo.Cryptography;
using Neo.IO;
using Neo.Persistence;
using Neo.SmartContract;
using Neo.VM;
using System;
using System.IO;
using System.Linq;

namespace Neo.Network.P2P.Payloads
{
public class NotaryRequest : IInventory
{
/// <summary>
/// Represents the fixed value of the <see cref="Transaction.Script"/> field of the fallback transaction.
/// </summary>
public static readonly byte[] FallbackFixedScript = new byte[] { (byte)OpCode.RET };

/// <summary>
/// The transaction need Notary to collect signatures.
/// </summary>
private Transaction mainTransaction;

/// <summary>
/// This transaction is valid when MainTransaction failed.
/// </summary>
private Transaction fallbackTransaction;

/// <summary>
/// The witness of the payload. It must be one of multi-sig address of <see cref="MainTransaction"/>.
/// </summary>
private Witness witness;
private UInt256 hash = null;

public InventoryType InventoryType => InventoryType.Notary;

public UInt256 Hash
{
get
{
if (hash == null)
{
hash = this.CalculateHash();
}
return hash;
}
}

public Witness[] Witnesses
{
get
{
return new Witness[] { witness };
}
set
{
witness = value[0];
}
}

public Transaction MainTransaction
{
get => mainTransaction;
set
{
mainTransaction = value;
hash = null;
}
}

public Transaction FallbackTransaction
{
get => fallbackTransaction;
set
{
fallbackTransaction = value;
hash = null;
}
}

public int Size => mainTransaction.Size + fallbackTransaction.Size + witness.Size;


public void DeserializeUnsigned(BinaryReader reader)
{
mainTransaction = reader.ReadSerializable<Transaction>();
fallbackTransaction = reader.ReadSerializable<Transaction>();
}

public void Deserialize(BinaryReader reader)
{
DeserializeUnsigned(reader);
witness = reader.ReadSerializable<Witness>();
}

public void Serialize(BinaryWriter writer)
{
SerializeUnsigned(writer);
writer.Write(witness);
}

public void SerializeUnsigned(BinaryWriter writer)
{
writer.Write(mainTransaction);
writer.Write(fallbackTransaction);
}

public UInt160[] GetScriptHashesForVerifying(DataCache snapshot)
{
return new UInt160[] { fallbackTransaction.Signers[1].Account };
}

public bool Verify(ProtocolSettings settings)
{
var nKeysMain = MainTransaction.GetAttributes<NotaryAssisted>();
if (!nKeysMain.Any()) return false;
if (nKeysMain.ToArray()[0].NKeys == 0) return false;
if (!fallbackTransaction.Script.SequenceEqual(FallbackFixedScript)) return false;
if (FallbackTransaction.Signers.Length != 2) return false;
if (fallbackTransaction.Signers[1].Scopes != WitnessScope.None) return false;
if (FallbackTransaction.Witnesses[0].InvocationScript.Length != 66
|| FallbackTransaction.Witnesses[0].VerificationScript.Length != 0
|| (FallbackTransaction.Witnesses[0].InvocationScript[0] != (byte)OpCode.PUSHDATA1 && FallbackTransaction.Witnesses[0].InvocationScript[1] != 64))
return false;
if (FallbackTransaction.GetAttribute<NotValidBefore>() is null) return false;
var conflicts = FallbackTransaction.GetAttributes<ConflictAttribute>();
if (conflicts.Count() != 1) return false;
if (conflicts.ToArray()[0].Hash != MainTransaction.Hash) return false;
var nKeysFallback = FallbackTransaction.GetAttributes<NotaryAssisted>();
if (!nKeysFallback.Any()) return false;
if (nKeysFallback.ToArray()[0].NKeys != 0) return false;
if (MainTransaction.ValidUntilBlock != FallbackTransaction.ValidUntilBlock) return false;
if (!fallbackTransaction.VerifyWitness(settings, null, fallbackTransaction.Signers[1].Account, fallbackTransaction.Witnesses[1], 0_02000000, out _)) return false;
return this.VerifyWitnesses(settings, null, 0_02000000);
}
}
}
Loading