Skip to content

Commit

Permalink
Fix policy check (#1668)
Browse files Browse the repository at this point in the history
* fix policy check

* Rename

* Fix GetCommitteeAddress()

Co-authored-by: erikzhang <erik@neo.org>
  • Loading branch information
Luchuan and erikzhang committed May 26, 2020
1 parent 9cbc025 commit 5c7197f
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 16 deletions.
17 changes: 8 additions & 9 deletions src/neo/SmartContract/Native/PolicyContract.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,10 @@ internal bool CheckPolicy(Transaction tx, StoreView snapshot)
return true;
}

private bool CheckValidators(ApplicationEngine engine)
private bool CheckCommittees(ApplicationEngine engine)
{
UInt256 prev_hash = engine.Snapshot.PersistingBlock.PrevHash;
TrimmedBlock prev_block = engine.Snapshot.Blocks[prev_hash];
return InteropService.Runtime.CheckWitnessInternal(engine, prev_block.NextConsensus);
UInt160 committeeMultiSigAddr = NEO.GetCommitteeAddress(engine.Snapshot);
return InteropService.Runtime.CheckWitnessInternal(engine, committeeMultiSigAddr);
}

internal override bool Initialize(ApplicationEngine engine)
Expand Down Expand Up @@ -114,7 +113,7 @@ public UInt160[] GetBlockedAccounts(StoreView snapshot)
[ContractMethod(0_03000000, ContractParameterType.Boolean, CallFlags.AllowModifyStates, ParameterTypes = new[] { ContractParameterType.Integer }, ParameterNames = new[] { "value" })]
private StackItem SetMaxBlockSize(ApplicationEngine engine, Array args)
{
if (!CheckValidators(engine)) return false;
if (!CheckCommittees(engine)) return false;
uint value = (uint)args[0].GetBigInteger();
if (Network.P2P.Message.PayloadMaxSize <= value) return false;
StorageItem storage = engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_MaxBlockSize));
Expand All @@ -125,7 +124,7 @@ private StackItem SetMaxBlockSize(ApplicationEngine engine, Array args)
[ContractMethod(0_03000000, ContractParameterType.Boolean, CallFlags.AllowModifyStates, ParameterTypes = new[] { ContractParameterType.Integer }, ParameterNames = new[] { "value" })]
private StackItem SetMaxTransactionsPerBlock(ApplicationEngine engine, Array args)
{
if (!CheckValidators(engine)) return false;
if (!CheckCommittees(engine)) return false;
uint value = (uint)args[0].GetBigInteger();
StorageItem storage = engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_MaxTransactionsPerBlock));
storage.Value = BitConverter.GetBytes(value);
Expand All @@ -135,7 +134,7 @@ private StackItem SetMaxTransactionsPerBlock(ApplicationEngine engine, Array arg
[ContractMethod(0_03000000, ContractParameterType.Boolean, CallFlags.AllowModifyStates, ParameterTypes = new[] { ContractParameterType.Integer }, ParameterNames = new[] { "value" })]
private StackItem SetFeePerByte(ApplicationEngine engine, Array args)
{
if (!CheckValidators(engine)) return false;
if (!CheckCommittees(engine)) return false;
long value = (long)args[0].GetBigInteger();
StorageItem storage = engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_FeePerByte));
storage.Value = BitConverter.GetBytes(value);
Expand All @@ -145,7 +144,7 @@ private StackItem SetFeePerByte(ApplicationEngine engine, Array args)
[ContractMethod(0_03000000, ContractParameterType.Boolean, CallFlags.AllowModifyStates, ParameterTypes = new[] { ContractParameterType.Hash160 }, ParameterNames = new[] { "account" })]
private StackItem BlockAccount(ApplicationEngine engine, Array args)
{
if (!CheckValidators(engine)) return false;
if (!CheckCommittees(engine)) return false;
UInt160 account = new UInt160(args[0].GetSpan());
StorageKey key = CreateStorageKey(Prefix_BlockedAccounts);
StorageItem storage = engine.Snapshot.Storages[key];
Expand All @@ -159,7 +158,7 @@ private StackItem BlockAccount(ApplicationEngine engine, Array args)
[ContractMethod(0_03000000, ContractParameterType.Boolean, CallFlags.AllowModifyStates, ParameterTypes = new[] { ContractParameterType.Hash160 }, ParameterNames = new[] { "account" })]
private StackItem UnblockAccount(ApplicationEngine engine, Array args)
{
if (!CheckValidators(engine)) return false;
if (!CheckCommittees(engine)) return false;
UInt160 account = new UInt160(args[0].GetSpan());
StorageKey key = CreateStorageKey(Prefix_BlockedAccounts);
StorageItem storage = engine.Snapshot.Storages[key];
Expand Down
6 changes: 6 additions & 0 deletions src/neo/SmartContract/Native/Tokens/NeoToken.cs
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,12 @@ public ECPoint[] GetCommittee(StoreView snapshot)
return GetCommitteeMembers(snapshot, ProtocolSettings.Default.MaxCommitteeMembersCount).OrderBy(p => p).ToArray();
}

public UInt160 GetCommitteeAddress(StoreView snapshot)
{
ECPoint[] committees = GetCommittee(snapshot);
return Contract.CreateMultiSigRedeemScript(committees.Length - (committees.Length - 1) / 2, committees).ToScriptHash();
}

private IEnumerable<ECPoint> GetCommitteeMembers(StoreView snapshot, int count)
{
return GetCandidates(snapshot).OrderByDescending(p => p.Votes).ThenBy(p => p.PublicKey).Select(p => p.PublicKey).Take(count);
Expand Down
18 changes: 11 additions & 7 deletions tests/neo.UnitTests/SmartContract/Native/UT_PolicyContract.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ public void Check_SetMaxBlockSize()
snapshot.PersistingBlock = new Block() { Index = 1000, PrevHash = UInt256.Zero };
snapshot.Blocks.Add(UInt256.Zero, new Neo.Ledger.TrimmedBlock() { NextConsensus = UInt160.Zero });

UInt160 committeeMultiSigAddr = NativeContract.NEO.GetCommitteeAddress(snapshot);

NativeContract.Policy.Initialize(new ApplicationEngine(TriggerType.Application, null, snapshot, 0)).Should().BeTrue();

// Without signature
Expand All @@ -76,7 +78,7 @@ public void Check_SetMaxBlockSize()

// More than expected

ret = NativeContract.Policy.Call(snapshot, new Nep5NativeContractExtensions.ManualWitness(UInt160.Zero),
ret = NativeContract.Policy.Call(snapshot, new Nep5NativeContractExtensions.ManualWitness(committeeMultiSigAddr),
"setMaxBlockSize", new ContractParameter(ContractParameterType.Integer) { Value = Neo.Network.P2P.Message.PayloadMaxSize });
ret.Should().BeOfType<VM.Types.Boolean>();
ret.ToBoolean().Should().BeFalse();
Expand All @@ -87,7 +89,7 @@ public void Check_SetMaxBlockSize()

// With signature

ret = NativeContract.Policy.Call(snapshot, new Nep5NativeContractExtensions.ManualWitness(UInt160.Zero),
ret = NativeContract.Policy.Call(snapshot, new Nep5NativeContractExtensions.ManualWitness(committeeMultiSigAddr),
"setMaxBlockSize", new ContractParameter(ContractParameterType.Integer) { Value = 1024 });
ret.Should().BeOfType<VM.Types.Boolean>();
ret.ToBoolean().Should().BeTrue();
Expand Down Expand Up @@ -122,7 +124,7 @@ public void Check_SetMaxTransactionsPerBlock()

// With signature

ret = NativeContract.Policy.Call(snapshot, new Nep5NativeContractExtensions.ManualWitness(UInt160.Zero),
ret = NativeContract.Policy.Call(snapshot, new Nep5NativeContractExtensions.ManualWitness(NativeContract.NEO.GetCommitteeAddress(snapshot)),
"setMaxTransactionsPerBlock", new ContractParameter(ContractParameterType.Integer) { Value = 1 });
ret.Should().BeOfType<VM.Types.Boolean>();
ret.ToBoolean().Should().BeTrue();
Expand Down Expand Up @@ -156,8 +158,8 @@ public void Check_SetFeePerByte()
ret.GetBigInteger().Should().Be(1000);

// With signature

ret = NativeContract.Policy.Call(snapshot, new Nep5NativeContractExtensions.ManualWitness(UInt160.Zero),
UInt160 committeeMultiSigAddr = NativeContract.NEO.GetCommitteeAddress(snapshot);
ret = NativeContract.Policy.Call(snapshot, new Nep5NativeContractExtensions.ManualWitness(committeeMultiSigAddr),
"setFeePerByte", new ContractParameter(ContractParameterType.Integer) { Value = 1 });
ret.Should().BeOfType<VM.Types.Boolean>();
ret.ToBoolean().Should().BeTrue();
Expand All @@ -177,6 +179,8 @@ public void Check_Block_UnblockAccount()
snapshot.PersistingBlock = new Block() { Index = 1000, PrevHash = UInt256.Zero };
snapshot.Blocks.Add(UInt256.Zero, new Neo.Ledger.TrimmedBlock() { NextConsensus = UInt160.Zero });

UInt160 committeeMultiSigAddr = NativeContract.NEO.GetCommitteeAddress(snapshot);

NativeContract.Policy.Initialize(new ApplicationEngine(TriggerType.Application, null, snapshot, 0)).Should().BeTrue();

// Block without signature
Expand All @@ -192,7 +196,7 @@ public void Check_Block_UnblockAccount()

// Block with signature

ret = NativeContract.Policy.Call(snapshot, new Nep5NativeContractExtensions.ManualWitness(UInt160.Zero),
ret = NativeContract.Policy.Call(snapshot, new Nep5NativeContractExtensions.ManualWitness(committeeMultiSigAddr),
"blockAccount", new ContractParameter(ContractParameterType.Hash160) { Value = UInt160.Zero });
ret.Should().BeOfType<VM.Types.Boolean>();
ret.ToBoolean().Should().BeTrue();
Expand All @@ -216,7 +220,7 @@ public void Check_Block_UnblockAccount()

// Unblock with signature

ret = NativeContract.Policy.Call(snapshot, new Nep5NativeContractExtensions.ManualWitness(UInt160.Zero),
ret = NativeContract.Policy.Call(snapshot, new Nep5NativeContractExtensions.ManualWitness(committeeMultiSigAddr),
"unblockAccount", new ContractParameter(ContractParameterType.Hash160) { Value = UInt160.Zero });
ret.Should().BeOfType<VM.Types.Boolean>();
ret.ToBoolean().Should().BeTrue();
Expand Down

0 comments on commit 5c7197f

Please sign in to comment.