diff --git a/src/Neo/SmartContract/Native/ContractManagement.cs b/src/Neo/SmartContract/Native/ContractManagement.cs
index 051e9305fc..cf62b3cbf6 100644
--- a/src/Neo/SmartContract/Native/ContractManagement.cs
+++ b/src/Neo/SmartContract/Native/ContractManagement.cs
@@ -140,7 +140,7 @@ private long GetMinimumDeploymentFee(IReadOnlyStore snapshot)
private void SetMinimumDeploymentFee(ApplicationEngine engine, BigInteger value/* In the unit of datoshi, 1 datoshi = 1e-8 GAS*/)
{
if (value < 0) throw new ArgumentOutOfRangeException(nameof(value), "cannot be negative");
- if (!CheckCommittee(engine)) throw new InvalidOperationException();
+ AssertCommittee(engine);
engine.SnapshotCache.GetAndChange(CreateStorageKey(Prefix_MinimumDeploymentFee)).Set(value);
}
diff --git a/src/Neo/SmartContract/Native/NativeContract.cs b/src/Neo/SmartContract/Native/NativeContract.cs
index e2e3d640db..d6af3b7c19 100644
--- a/src/Neo/SmartContract/Native/NativeContract.cs
+++ b/src/Neo/SmartContract/Native/NativeContract.cs
@@ -348,12 +348,20 @@ public bool IsActive(ProtocolSettings settings, uint blockHeight)
///
/// The that is executing the contract.
/// if the committee has witnessed the current transaction; otherwise, .
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
protected static bool CheckCommittee(ApplicationEngine engine)
{
- UInt160 committeeMultiSigAddr = NEO.GetCommitteeAddress(engine.SnapshotCache);
+ var committeeMultiSigAddr = NEO.GetCommitteeAddress(engine.SnapshotCache);
return engine.CheckWitnessInternal(committeeMultiSigAddr);
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ protected static void AssertCommittee(ApplicationEngine engine)
+ {
+ if (!CheckCommittee(engine))
+ throw new InvalidOperationException("Invalid committee signature. It should be a multisig(len(committee) - (len(committee) - 1) / 2)).");
+ }
+
#region Storage keys
[MethodImpl(MethodImplOptions.AggressiveInlining)]
diff --git a/src/Neo/SmartContract/Native/NeoToken.cs b/src/Neo/SmartContract/Native/NeoToken.cs
index ac597a2eb1..2612da731f 100644
--- a/src/Neo/SmartContract/Native/NeoToken.cs
+++ b/src/Neo/SmartContract/Native/NeoToken.cs
@@ -286,7 +286,7 @@ private void SetGasPerBlock(ApplicationEngine engine, BigInteger gasPerBlock)
{
if (gasPerBlock < 0 || gasPerBlock > 10 * GAS.Factor)
throw new ArgumentOutOfRangeException(nameof(gasPerBlock), $"GasPerBlock must be between [0, {10 * GAS.Factor}]");
- if (!CheckCommittee(engine)) throw new InvalidOperationException();
+ AssertCommittee(engine);
var index = engine.PersistingBlock.Index + 1;
var entry = engine.SnapshotCache.GetAndChange(CreateStorageKey(Prefix_GasPerBlock, index), () => new StorageItem(gasPerBlock));
@@ -314,7 +314,8 @@ private void SetRegisterPrice(ApplicationEngine engine, long registerPrice)
{
if (registerPrice <= 0)
throw new ArgumentOutOfRangeException(nameof(registerPrice), "RegisterPrice must be positive");
- if (!CheckCommittee(engine)) throw new InvalidOperationException();
+ AssertCommittee(engine);
+
engine.SnapshotCache.GetAndChange(_registerPrice).Set(registerPrice);
}
diff --git a/src/Neo/SmartContract/Native/Notary.cs b/src/Neo/SmartContract/Native/Notary.cs
index 7c3c89dc2c..76e7a6050a 100644
--- a/src/Neo/SmartContract/Native/Notary.cs
+++ b/src/Neo/SmartContract/Native/Notary.cs
@@ -257,9 +257,12 @@ private void SetMaxNotValidBeforeDelta(ApplicationEngine engine, uint value)
{
var maxVUBIncrement = engine.SnapshotCache.GetMaxValidUntilBlockIncrement(engine.ProtocolSettings);
if (value > maxVUBIncrement / 2 || value < ProtocolSettings.Default.ValidatorsCount)
+ {
throw new FormatException(string.Format("MaxNotValidBeforeDelta cannot be more than {0} or less than {1}",
- maxVUBIncrement / 2, ProtocolSettings.Default.ValidatorsCount));
- if (!CheckCommittee(engine)) throw new InvalidOperationException();
+ maxVUBIncrement / 2, ProtocolSettings.Default.ValidatorsCount));
+ }
+ AssertCommittee(engine);
+
engine.SnapshotCache.GetAndChange(CreateStorageKey(Prefix_MaxNotValidBeforeDelta))!.Set(value);
}
diff --git a/src/Neo/SmartContract/Native/OracleContract.cs b/src/Neo/SmartContract/Native/OracleContract.cs
index 0f6c15221d..7ab60f2595 100644
--- a/src/Neo/SmartContract/Native/OracleContract.cs
+++ b/src/Neo/SmartContract/Native/OracleContract.cs
@@ -59,9 +59,9 @@ internal OracleContract() : base() { }
[ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.States)]
private void SetPrice(ApplicationEngine engine, long price)
{
- if (price <= 0)
- throw new ArgumentOutOfRangeException(nameof(price), "Price must be positive");
- if (!CheckCommittee(engine)) throw new InvalidOperationException();
+ if (price <= 0) throw new ArgumentOutOfRangeException(nameof(price), "Price must be positive");
+ AssertCommittee(engine);
+
engine.SnapshotCache.GetAndChange(CreateStorageKey(Prefix_Price)).Set(price);
}
diff --git a/src/Neo/SmartContract/Native/PolicyContract.cs b/src/Neo/SmartContract/Native/PolicyContract.cs
index b9bcc1e22d..bddcb70e73 100644
--- a/src/Neo/SmartContract/Native/PolicyContract.cs
+++ b/src/Neo/SmartContract/Native/PolicyContract.cs
@@ -269,8 +269,8 @@ public bool IsBlocked(IReadOnlyStore snapshot, UInt160 account)
public void SetMillisecondsPerBlock(ApplicationEngine engine, uint value)
{
if (value == 0 || value > MaxMillisecondsPerBlock)
- throw new ArgumentOutOfRangeException(nameof(value), $"MillisecondsPerBlock must be between 1 and {MaxMillisecondsPerBlock}, got {value}");
- if (!CheckCommittee(engine)) throw new InvalidOperationException("Invalid committee signature");
+ throw new ArgumentOutOfRangeException(nameof(value), $"MillisecondsPerBlock must be between [1, {MaxMillisecondsPerBlock}], got {value}");
+ AssertCommittee(engine);
var oldTime = GetMillisecondsPerBlock(engine.SnapshotCache);
engine.SnapshotCache.GetAndChange(_millisecondsPerBlock).Set(value);
@@ -325,7 +325,7 @@ private void SetAttributeFee(ApplicationEngine engine, byte attributeType, uint
if (value > MaxAttributeFee)
throw new ArgumentOutOfRangeException(nameof(value), $"AttributeFee must be less than {MaxAttributeFee}");
- if (!CheckCommittee(engine)) throw new InvalidOperationException();
+ AssertCommittee(engine);
engine.SnapshotCache.GetAndChange(CreateStorageKey(Prefix_AttributeFee, attributeType), () => new StorageItem(DefaultAttributeFee)).Set(value);
}
@@ -335,7 +335,8 @@ private void SetFeePerByte(ApplicationEngine engine, long value)
{
if (value < 0 || value > 1_00000000)
throw new ArgumentOutOfRangeException(nameof(value), $"FeePerByte must be between [0, 100000000], got {value}");
- if (!CheckCommittee(engine)) throw new InvalidOperationException();
+ AssertCommittee(engine);
+
engine.SnapshotCache.GetAndChange(_feePerByte).Set(value);
}
@@ -344,7 +345,8 @@ private void SetExecFeeFactor(ApplicationEngine engine, uint value)
{
if (value == 0 || value > MaxExecFeeFactor)
throw new ArgumentOutOfRangeException(nameof(value), $"ExecFeeFactor must be between [1, {MaxExecFeeFactor}], got {value}");
- if (!CheckCommittee(engine)) throw new InvalidOperationException();
+ AssertCommittee(engine);
+
engine.SnapshotCache.GetAndChange(_execFeeFactor).Set(value);
}
@@ -353,7 +355,8 @@ private void SetStoragePrice(ApplicationEngine engine, uint value)
{
if (value == 0 || value > MaxStoragePrice)
throw new ArgumentOutOfRangeException(nameof(value), $"StoragePrice must be between [1, {MaxStoragePrice}], got {value}");
- if (!CheckCommittee(engine)) throw new InvalidOperationException();
+ AssertCommittee(engine);
+
engine.SnapshotCache.GetAndChange(_storagePrice).Set(value);
}
@@ -365,7 +368,8 @@ private void SetMaxValidUntilBlockIncrement(ApplicationEngine engine, uint value
var mtb = GetMaxTraceableBlocks(engine.SnapshotCache);
if (value >= mtb)
throw new InvalidOperationException($"MaxValidUntilBlockIncrement must be lower than MaxTraceableBlocks ({value} vs {mtb})");
- if (!CheckCommittee(engine)) throw new InvalidOperationException();
+ AssertCommittee(engine);
+
engine.SnapshotCache.GetAndChange(_maxValidUntilBlockIncrement).Set(value);
}
@@ -379,26 +383,31 @@ private void SetMaxTraceableBlocks(ApplicationEngine engine, uint value)
{
if (value == 0 || value > MaxMaxTraceableBlocks)
throw new ArgumentOutOfRangeException(nameof(value), $"MaxTraceableBlocks must be between [1, {MaxMaxTraceableBlocks}], got {value}");
+
var oldVal = GetMaxTraceableBlocks(engine.SnapshotCache);
if (value > oldVal)
throw new InvalidOperationException($"MaxTraceableBlocks can not be increased (old {oldVal}, new {value})");
+
var mVUBIncrement = GetMaxValidUntilBlockIncrement(engine.SnapshotCache);
if (value <= mVUBIncrement)
throw new InvalidOperationException($"MaxTraceableBlocks must be larger than MaxValidUntilBlockIncrement ({value} vs {mVUBIncrement})");
- if (!CheckCommittee(engine)) throw new InvalidOperationException("Invalid committee signature");
+
+ AssertCommittee(engine);
+
engine.SnapshotCache.GetAndChange(_maxTraceableBlocks).Set(value);
}
[ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.States)]
private bool BlockAccount(ApplicationEngine engine, UInt160 account)
{
- if (!CheckCommittee(engine)) throw new InvalidOperationException();
+ AssertCommittee(engine);
+
return BlockAccount(engine.SnapshotCache, account);
}
internal bool BlockAccount(DataCache snapshot, UInt160 account)
{
- if (IsNative(account)) throw new InvalidOperationException("It's impossible to block a native contract.");
+ if (IsNative(account)) throw new InvalidOperationException("Cannot block a native contract.");
var key = CreateStorageKey(Prefix_BlockedAccount, account);
if (snapshot.Contains(key)) return false;
@@ -410,7 +419,8 @@ internal bool BlockAccount(DataCache snapshot, UInt160 account)
[ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.States)]
private bool UnblockAccount(ApplicationEngine engine, UInt160 account)
{
- if (!CheckCommittee(engine)) throw new InvalidOperationException();
+ AssertCommittee(engine);
+
var key = CreateStorageKey(Prefix_BlockedAccount, account);
if (!engine.SnapshotCache.Contains(key)) return false;
diff --git a/src/Neo/SmartContract/Native/RoleManagement.cs b/src/Neo/SmartContract/Native/RoleManagement.cs
index c045b5c237..25afa552f5 100644
--- a/src/Neo/SmartContract/Native/RoleManagement.cs
+++ b/src/Neo/SmartContract/Native/RoleManagement.cs
@@ -68,14 +68,15 @@ private void DesignateAsRole(ApplicationEngine engine, Role role, ECPoint[] node
throw new ArgumentException($"Nodes count {nodes.Length} must be between 1 and 32", nameof(nodes));
if (!Enum.IsDefined(typeof(Role), role))
throw new ArgumentOutOfRangeException(nameof(role), $"Role {role} is not valid");
- if (!CheckCommittee(engine))
- throw new InvalidOperationException("Invalid committee signature");
+ AssertCommittee(engine);
+
if (engine.PersistingBlock is null)
throw new InvalidOperationException("Persisting block is null");
var index = engine.PersistingBlock.Index + 1;
var key = CreateStorageKey((byte)role, index);
if (engine.SnapshotCache.Contains(key))
- throw new InvalidOperationException();
+ throw new InvalidOperationException("Role already designated");
+
NodeList list = new();
list.AddRange(nodes);
list.Sort();