-
Notifications
You must be signed in to change notification settings - Fork 1k
[N4] Whitelist of Free Contracts #4348
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
Changes from 10 commits
e4ecedc
6d447a9
2101cdb
5f52eef
1348f46
edecbae
234d954
921ce33
07526a3
42e3542
d4d67b4
0b80534
1e5908f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -11,16 +11,24 @@ | |||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| #pragma warning disable IDE0051 | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| using Neo.Extensions.IO; | ||||||||||||||||||||||||
| using Neo.Network.P2P.Payloads; | ||||||||||||||||||||||||
| using Neo.Persistence; | ||||||||||||||||||||||||
| using Neo.SmartContract.Iterators; | ||||||||||||||||||||||||
| using System.Diagnostics.CodeAnalysis; | ||||||||||||||||||||||||
| using System.Numerics; | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| namespace Neo.SmartContract.Native; | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| /// <summary> | ||||||||||||||||||||||||
| /// A native contract that manages the system policies. | ||||||||||||||||||||||||
| /// </summary> | ||||||||||||||||||||||||
| [ContractEvent(0, name: WhitelistChangedEventName, | ||||||||||||||||||||||||
| "contract", ContractParameterType.Hash160, | ||||||||||||||||||||||||
| "method", ContractParameterType.String, | ||||||||||||||||||||||||
| "argCount", ContractParameterType.Integer, | ||||||||||||||||||||||||
| "fee", ContractParameterType.Any | ||||||||||||||||||||||||
| )] | ||||||||||||||||||||||||
| public sealed class PolicyContract : NativeContract | ||||||||||||||||||||||||
| { | ||||||||||||||||||||||||
| /// <summary> | ||||||||||||||||||||||||
|
|
@@ -64,8 +72,9 @@ | |||||||||||||||||||||||
| /// </summary> | ||||||||||||||||||||||||
| public const uint MaxStoragePrice = 10000000; | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| private const byte Prefix_BlockedAccount = 15; | ||||||||||||||||||||||||
| private const byte Prefix_FeePerByte = 10; | ||||||||||||||||||||||||
| private const byte Prefix_BlockedAccount = 15; | ||||||||||||||||||||||||
| private const byte Prefix_WhitelistedFeeContracts = 16; | ||||||||||||||||||||||||
| private const byte Prefix_ExecFeeFactor = 18; | ||||||||||||||||||||||||
| private const byte Prefix_StoragePrice = 19; | ||||||||||||||||||||||||
| private const byte Prefix_AttributeFee = 20; | ||||||||||||||||||||||||
|
|
@@ -74,6 +83,8 @@ | |||||||||||||||||||||||
| private readonly StorageKey _execFeeFactor; | ||||||||||||||||||||||||
| private readonly StorageKey _storagePrice; | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| private const string WhitelistChangedEventName = "WhitelistFeeChanged"; | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| internal PolicyContract() | ||||||||||||||||||||||||
| { | ||||||||||||||||||||||||
| _feePerByte = CreateStorageKey(Prefix_FeePerByte); | ||||||||||||||||||||||||
|
|
@@ -237,6 +248,125 @@ | |||||||||||||||||||||||
| return true; | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| internal bool IsWhitelistFeeContract(DataCache snapshot, UInt160 contractHash, string method, int argCount, [NotNullWhen(true)] out long? fixedFee) | ||||||||||||||||||||||||
| { | ||||||||||||||||||||||||
| // Check contract existence | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| var currentContract = ContractManagement.GetContract(snapshot, contractHash); | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| if (currentContract != null) | ||||||||||||||||||||||||
| { | ||||||||||||||||||||||||
| // Check state existence | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| var item = snapshot.TryGet(CreateStorageKey(Prefix_WhitelistedFeeContracts, contractHash, method, argCount)); | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| if (item != null) | ||||||||||||||||||||||||
| { | ||||||||||||||||||||||||
| fixedFee = (long)(BigInteger)item; | ||||||||||||||||||||||||
| return true; | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| fixedFee = null; | ||||||||||||||||||||||||
| return false; | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| /// <summary> | ||||||||||||||||||||||||
| /// Remove whitelisted Fee contracts | ||||||||||||||||||||||||
| /// </summary> | ||||||||||||||||||||||||
| /// <param name="engine">The execution engine.</param> | ||||||||||||||||||||||||
| /// <param name="contractHash">The contract to set the whitelist</param> | ||||||||||||||||||||||||
| /// <param name="method">Method</param> | ||||||||||||||||||||||||
| /// <param name="argCount">Argument count</param> | ||||||||||||||||||||||||
| [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.States | CallFlags.AllowNotify)] | ||||||||||||||||||||||||
| private void RemoveWhitelistFeeContract(ApplicationEngine engine, UInt160 contractHash, string method, int argCount) | ||||||||||||||||||||||||
| { | ||||||||||||||||||||||||
| if (!CheckCommittee(engine)) throw new InvalidOperationException("Invalid committee signature"); | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| var key = CreateStorageKey(Prefix_WhitelistedFeeContracts, contractHash, method, argCount); | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| if (!engine.SnapshotCache.Contains(key)) throw new InvalidOperationException("Whitelist not found"); | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| engine.SnapshotCache.Delete(key); | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| // Emit event | ||||||||||||||||||||||||
| engine.SendNotification(Hash, WhitelistChangedEventName, | ||||||||||||||||||||||||
| [new VM.Types.ByteString(contractHash.ToArray()), new VM.Types.ByteString(method.ToStrictUtf8Bytes()), | ||||||||||||||||||||||||
| new VM.Types.Integer(argCount), VM.Types.StackItem.Null]); | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| internal int CleanWhitelist(ApplicationEngine engine, UInt160 contractHash) | ||||||||||||||||||||||||
| { | ||||||||||||||||||||||||
| var count = 0; | ||||||||||||||||||||||||
| var searchKey = CreateStorageKey(Prefix_WhitelistedFeeContracts, contractHash); | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| foreach ((var key, _) in engine.SnapshotCache.Find(searchKey, SeekDirection.Forward)) | ||||||||||||||||||||||||
| { | ||||||||||||||||||||||||
| engine.SnapshotCache.Delete(key); | ||||||||||||||||||||||||
| count++; | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| // Emit event recovering the values from the Key | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| var keyData = key.ToArray().AsSpan(); | ||||||||||||||||||||||||
| // TODO: Require a unwrap | ||||||||||||||||||||||||
| (var method, var argCount) = StorageKey.ReadMethodAndArgCount(key.ToArray().AsSpan()); | ||||||||||||||||||||||||
|
Check failure on line 312 in src/Neo/SmartContract/Native/PolicyContract.cs
|
||||||||||||||||||||||||
|
||||||||||||||||||||||||
| public class ContractMethodDescriptor : ContractEventDescriptor, IEquatable<ContractMethodDescriptor> | |
| { | |
| /// <summary> | |
| /// Indicates the return type of the method. It can be any value of <see cref="ContractParameterType"/>. | |
| /// </summary> | |
| public ContractParameterType ReturnType { get; set; } | |
| /// <summary> | |
| /// The position of the method in the contract script. | |
| /// </summary> | |
| public int Offset { get; set; } |
Once the contract is updated, all of its whitelists will become invalid. Therefore, storing only the Offset is safe.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It will safe storage, it's a good idea
Uh oh!
There was an error while loading. Please reload this page.