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

Implement native Notary contract #3178

Open
wants to merge 45 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
6da4ae2
Implement NotaryAssisted transaction attribute
AnnaShaleva Mar 6, 2024
acec1b0
Payloads: add doc to CalculateNetworkFee method of NotaryAssisted att…
AnnaShaleva Mar 6, 2024
1508d4f
Native: add NotaryAssisted attributes handler to Gas OnPersist
AnnaShaleva Mar 7, 2024
8b547c9
Payloads: adjust comment to NotaryAssisted attribute
AnnaShaleva Mar 7, 2024
b16a28c
Payloads: temporary use hard-coded Notary contract hash
AnnaShaleva Mar 7, 2024
00b54ff
Merge branch 'master' into notary-assisted
Jim8y Mar 8, 2024
24135ff
Payloads: replace hard-coded Notary hash value with calculated one
AnnaShaleva Mar 12, 2024
77ffe09
Native: implement native Notary contract
AnnaShaleva Mar 19, 2024
cb4bdda
Native: fix typo in the exception message
AnnaShaleva Mar 21, 2024
8f9f5f7
Native: use more syntactic sugar
AnnaShaleva Mar 21, 2024
5ee1855
Merge branch 'master' into notary-contract
Jim8y Mar 26, 2024
02c6a89
Notary: add unit tests for OnNEP17Payment and ExpirationOf methods
AnnaShaleva Apr 4, 2024
21f5fcf
Fix transfer
shargon Apr 8, 2024
af4a87a
Merge branch 'master' into notary-contract
shargon Apr 8, 2024
e8d384e
Update tests/Neo.UnitTests/SmartContract/Native/UT_Notary.cs
shargon Apr 8, 2024
26c9430
Update UT_Notary.cs
shargon Apr 8, 2024
b23859f
fix
shargon Apr 8, 2024
ecfba77
Merge branch 'notary-contract' of https://github.com/neo-project/neo …
shargon Apr 8, 2024
ff03214
Fix notary
shargon Apr 8, 2024
adf0bb0
Fix notary
shargon Apr 8, 2024
08da1f0
Notary: add unit tests for LockDepositUntil and BalanceOf methods
AnnaShaleva Apr 8, 2024
f7924ca
Merge branch 'master' into notary-contract
AnnaShaleva Apr 10, 2024
6705469
Notary: test GAS distribution with FeePerKey update
AnnaShaleva Apr 10, 2024
8864ff5
Notary: add test for Withdraw
AnnaShaleva Apr 10, 2024
498f2ff
Notary: remove unused code
AnnaShaleva Apr 11, 2024
efa9958
Attributtes: fix NotaryAssisted attribute documentation format
AnnaShaleva Apr 11, 2024
dd0b965
Merge branch 'master' into notary-contract
cschuchardt88 Apr 11, 2024
f6cbd36
Merge branch 'master' into notary-contract
cschuchardt88 May 23, 2024
deafea9
Native: update to the fresh master
AnnaShaleva May 23, 2024
2f1d38c
Merge branch 'master' into notary-contract
shargon May 24, 2024
e9bc666
Merge branch 'master' into notary-contract
AnnaShaleva Mar 4, 2025
b49fb96
Notary: sync up with master changes
AnnaShaleva Mar 4, 2025
4cf8718
Notary: make the contract active starting from Echidna.
AnnaShaleva Mar 4, 2025
d67b6d4
Notary: add NEP-27 to the list of supported standards
AnnaShaleva Mar 4, 2025
7b7aede
Notary: adjust deposit expiration rule
AnnaShaleva Mar 4, 2025
08162ec
clean usings
shargon Mar 5, 2025
c9ce04b
Update tests/Neo.UnitTests/Extensions/Nep17NativeContractExtensions.cs
shargon Mar 5, 2025
bb153eb
Notary: improve long line format
AnnaShaleva Mar 5, 2025
516ca30
Notary: prettify exception thrown on unexpected OnNEP17Payment data
AnnaShaleva Mar 6, 2025
af09772
Notary: don't FAULT execution in case of non-tx verification container
AnnaShaleva Mar 6, 2025
30521fa
Merge branch 'master' into notary-contract
AnnaShaleva Mar 6, 2025
8c57a7f
Merge branch 'master' into notary-contract
AnnaShaleva Mar 10, 2025
59520ca
Merge branch 'master' into notary-contract
cschuchardt88 Mar 11, 2025
61e2bbe
Notary: unify deposit lock validity check
AnnaShaleva Mar 11, 2025
eba8f98
Merge branch 'master' into notary-contract
AnnaShaleva Mar 11, 2025
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
5 changes: 5 additions & 0 deletions src/Neo/SmartContract/Native/NativeContract.cs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,11 @@ public CacheEntry GetAllowedMethods(NativeContract native, ApplicationEngine eng
/// </summary>
public static OracleContract Oracle { get; } = new();

/// <summary>
/// Gets the instance of the <see cref="Notary"/> class.
/// </summary>
public static Notary Notary { get; } = new();

#endregion

/// <summary>
Expand Down
332 changes: 332 additions & 0 deletions src/Neo/SmartContract/Native/Notary.cs

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions tests/Neo.UnitTests/Extensions/NativeContractExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,11 @@ public static StackItem Call(this NativeContract contract, DataCache snapshot, s
public static StackItem Call(this NativeContract contract, DataCache snapshot, IVerifiable container, Block persistingBlock, string method, params ContractParameter[] args)
{
using var engine = ApplicationEngine.Create(TriggerType.Application, container, snapshot, persistingBlock, settings: TestBlockchain.TheNeoSystem.Settings);
return Call(contract, engine, method, args);
}

public static StackItem Call(this NativeContract contract, ApplicationEngine engine, string method, params ContractParameter[] args)
{
using var script = new ScriptBuilder();
script.EmitDynamicCall(contract.Hash, method, args);
engine.LoadScript(script.ToArray());
Expand Down
28 changes: 27 additions & 1 deletion tests/Neo.UnitTests/Extensions/Nep17NativeContractExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,38 @@ public void SerializeUnsigned(BinaryWriter writer) { }
}

public static bool Transfer(this NativeContract contract, DataCache snapshot, byte[] from, byte[] to, BigInteger amount, bool signFrom, Block persistingBlock)
{
return Transfer(contract, snapshot, from, to, amount, signFrom, persistingBlock, null);
}

public static bool Transfer(this NativeContract contract, DataCache snapshot, byte[] from, byte[] to, BigInteger amount, bool signFrom, Block persistingBlock, object data)
{
using var engine = ApplicationEngine.Create(TriggerType.Application,
new ManualWitness(signFrom ? new UInt160(from) : null), snapshot, persistingBlock, settings: TestBlockchain.TheNeoSystem.Settings);

using var script = new ScriptBuilder();
script.EmitDynamicCall(contract.Hash, "transfer", from, to, amount, null);
script.EmitDynamicCall(contract.Hash, "transfer", from, to, amount, data);
engine.LoadScript(script.ToArray());

if (engine.Execute() == VMState.FAULT)
{
throw engine.FaultException;
}

var result = engine.ResultStack.Pop();
Assert.IsInstanceOfType(result, typeof(Boolean));

return result.GetBoolean();
}

public static bool TransferWithTransaction(this NativeContract contract, DataCache snapshot, byte[] from, byte[] to, BigInteger amount, bool signFrom, Block persistingBlock, object data)
{
using var engine = ApplicationEngine.Create(TriggerType.Application,
new Transaction() { Signers = [new() { Account = signFrom ? new(from) : null, Scopes = WitnessScope.Global }], Attributes = [] },
snapshot, persistingBlock, settings: TestBlockchain.TheNeoSystem.Settings);

using var script = new ScriptBuilder();
script.EmitDynamicCall(contract.Hash, "transfer", from, to, amount, data);
engine.LoadScript(script.ToArray());

if (engine.Execute() == VMState.FAULT)
Expand Down
58 changes: 1 addition & 57 deletions tests/Neo.UnitTests/SmartContract/Native/UT_GasToken.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@
using Neo.VM;
using Neo.Wallets;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Threading.Tasks;
using VMTypes = Neo.VM.Types;

namespace Neo.UnitTests.SmartContract.Native
{
Expand Down Expand Up @@ -154,61 +154,5 @@ internal static StorageKey CreateStorageKey(byte prefix, byte[] key = null)
Key = buffer
};
}

[TestMethod]
public void Check_OnPersist_NotaryAssisted()
{
// Hardcode test values.
const uint defaultNotaryssestedFeePerKey = 1000_0000;
const byte NKeys1 = 4;
const byte NKeys2 = 6;

// Generate two transactions with NotaryAssisted attributes with hardcoded NKeys values.
var from = Contract.GetBFTAddress(TestProtocolSettings.Default.StandbyValidators);
var tx1 = TestUtils.GetTransaction(from);
tx1.Attributes = new TransactionAttribute[] { new NotaryAssisted() { NKeys = NKeys1 } };
var netFee1 = 1_0000_0000;
tx1.NetworkFee = netFee1;
var tx2 = TestUtils.GetTransaction(from);
tx2.Attributes = new TransactionAttribute[] { new NotaryAssisted() { NKeys = NKeys2 } };
var netFee2 = 2_0000_0000;
tx2.NetworkFee = netFee2;

// Calculate expected Notary nodes reward.
var expectedNotaryReward = (NKeys1 + 1) * defaultNotaryssestedFeePerKey + (NKeys2 + 1) * defaultNotaryssestedFeePerKey;

// Build block to check transaction fee distribution during Gas OnPersist.
var persistingBlock = new Block
{
Header = new Header
{
Index = (uint)TestProtocolSettings.Default.CommitteeMembersCount,
MerkleRoot = UInt256.Zero,
NextConsensus = UInt160.Zero,
PrevHash = UInt256.Zero,
Witness = new Witness() { InvocationScript = Array.Empty<byte>(), VerificationScript = Array.Empty<byte>() }
},
Transactions = new Transaction[] { tx1, tx2 }
};
var snapshot = _snapshotCache.CloneCache();
var script = new ScriptBuilder();
script.EmitSysCall(ApplicationEngine.System_Contract_NativeOnPersist);
var engine = ApplicationEngine.Create(TriggerType.OnPersist, null, snapshot, persistingBlock, settings: TestBlockchain.TheNeoSystem.Settings);

// Check that block's Primary balance is 0.
ECPoint[] validators = NativeContract.NEO.GetNextBlockValidators(engine.SnapshotCache, engine.ProtocolSettings.ValidatorsCount);
var primary = Contract.CreateSignatureRedeemScript(validators[engine.PersistingBlock.PrimaryIndex]).ToScriptHash();
Assert.AreEqual(0, NativeContract.GAS.BalanceOf(engine.SnapshotCache, primary));

// Execute OnPersist script.
engine.LoadScript(script.ToArray());
Assert.IsTrue(engine.Execute() == VMState.HALT);

// Check that proper amount of GAS was minted to block's Primary and the rest
// will be minted to Notary nodes as a reward once Notary contract is implemented.
Assert.AreEqual(2 + 1, engine.Notifications.Count()); // burn tx1 and tx2 network fee + mint primary reward
Assert.AreEqual(netFee1 + netFee2 - expectedNotaryReward, engine.Notifications[2].State[2]);
Assert.AreEqual(netFee1 + netFee2 - expectedNotaryReward, NativeContract.GAS.BalanceOf(engine.SnapshotCache, primary));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ public void TestSetup()
{"PolicyContract", """{"id":-7,"updatecounter":0,"hash":"0xcc5e4edd9f5f8dba8bb65734541df7a1c081c67b","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0A=","checksum":1094259016},"manifest":{"name":"PolicyContract","groups":[],"features":{},"supportedstandards":[],"abi":{"methods":[{"name":"blockAccount","parameters":[{"name":"account","type":"Hash160"}],"returntype":"Boolean","offset":0,"safe":false},{"name":"getAttributeFee","parameters":[{"name":"attributeType","type":"Integer"}],"returntype":"Integer","offset":7,"safe":true},{"name":"getExecFeeFactor","parameters":[],"returntype":"Integer","offset":14,"safe":true},{"name":"getFeePerByte","parameters":[],"returntype":"Integer","offset":21,"safe":true},{"name":"getStoragePrice","parameters":[],"returntype":"Integer","offset":28,"safe":true},{"name":"isBlocked","parameters":[{"name":"account","type":"Hash160"}],"returntype":"Boolean","offset":35,"safe":true},{"name":"setAttributeFee","parameters":[{"name":"attributeType","type":"Integer"},{"name":"value","type":"Integer"}],"returntype":"Void","offset":42,"safe":false},{"name":"setExecFeeFactor","parameters":[{"name":"value","type":"Integer"}],"returntype":"Void","offset":49,"safe":false},{"name":"setFeePerByte","parameters":[{"name":"value","type":"Integer"}],"returntype":"Void","offset":56,"safe":false},{"name":"setStoragePrice","parameters":[{"name":"value","type":"Integer"}],"returntype":"Void","offset":63,"safe":false},{"name":"unblockAccount","parameters":[{"name":"account","type":"Hash160"}],"returntype":"Boolean","offset":70,"safe":false}],"events":[]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null}}"""},
{"RoleManagement", """{"id":-8,"updatecounter":0,"hash":"0x49cf4e5378ffcd4dec034fd98a174c5491e395e2","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0A=","checksum":983638438},"manifest":{"name":"RoleManagement","groups":[],"features":{},"supportedstandards":[],"abi":{"methods":[{"name":"designateAsRole","parameters":[{"name":"role","type":"Integer"},{"name":"nodes","type":"Array"}],"returntype":"Void","offset":0,"safe":false},{"name":"getDesignatedByRole","parameters":[{"name":"role","type":"Integer"},{"name":"index","type":"Integer"}],"returntype":"Array","offset":7,"safe":true}],"events":[{"name":"Designation","parameters":[{"name":"Role","type":"Integer"},{"name":"BlockIndex","type":"Integer"},{"name":"Old","type":"Array"},{"name":"New","type":"Array"}]}]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null}}"""},
{"OracleContract", """{"id":-9,"updatecounter":0,"hash":"0xfe924b7cfe89ddd271abaf7210a80a7e11178758","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0A=","checksum":2663858513},"manifest":{"name":"OracleContract","groups":[],"features":{},"supportedstandards":[],"abi":{"methods":[{"name":"finish","parameters":[],"returntype":"Void","offset":0,"safe":false},{"name":"getPrice","parameters":[],"returntype":"Integer","offset":7,"safe":true},{"name":"request","parameters":[{"name":"url","type":"String"},{"name":"filter","type":"String"},{"name":"callback","type":"String"},{"name":"userData","type":"Any"},{"name":"gasForResponse","type":"Integer"}],"returntype":"Void","offset":14,"safe":false},{"name":"setPrice","parameters":[{"name":"price","type":"Integer"}],"returntype":"Void","offset":21,"safe":false},{"name":"verify","parameters":[],"returntype":"Boolean","offset":28,"safe":true}],"events":[{"name":"OracleRequest","parameters":[{"name":"Id","type":"Integer"},{"name":"RequestContract","type":"Hash160"},{"name":"Url","type":"String"},{"name":"Filter","type":"String"}]},{"name":"OracleResponse","parameters":[{"name":"Id","type":"Integer"},{"name":"OriginalTx","type":"Hash256"}]}]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null}}"""},
{"Notary", """{"id":-10,"updatecounter":0,"hash":"0xc1e14f19c3e60d0b9244d06dd7ba9b113135ec3b","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0A=","checksum":1110259869},"manifest":{"name":"Notary","groups":[],"features":{},"supportedstandards":["NEP-27"],"abi":{"methods":[{"name":"balanceOf","parameters":[{"name":"acc","type":"Hash160"}],"returntype":"Integer","offset":0,"safe":true},{"name":"expirationOf","parameters":[{"name":"acc","type":"Hash160"}],"returntype":"Integer","offset":7,"safe":true},{"name":"getMaxNotValidBeforeDelta","parameters":[],"returntype":"Integer","offset":14,"safe":true},{"name":"lockDepositUntil","parameters":[{"name":"addr","type":"Hash160"},{"name":"till","type":"Integer"}],"returntype":"Boolean","offset":21,"safe":false},{"name":"onNEP17Payment","parameters":[{"name":"from","type":"Hash160"},{"name":"amount","type":"Integer"},{"name":"data","type":"Any"}],"returntype":"Void","offset":28,"safe":false},{"name":"setMaxNotValidBeforeDelta","parameters":[{"name":"value","type":"Integer"}],"returntype":"Void","offset":35,"safe":false},{"name":"verify","parameters":[{"name":"sig","type":"ByteArray"}],"returntype":"Boolean","offset":42,"safe":true},{"name":"withdraw","parameters":[{"name":"from","type":"Hash160"},{"name":"to","type":"Hash160"}],"returntype":"Boolean","offset":49,"safe":false}],"events":[]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null}}"""}
};
}

Expand Down
Loading