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 Fee Ratio #2032

Closed
wants to merge 29 commits into from
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
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
3 changes: 2 additions & 1 deletion src/neo/Ledger/Blockchain.cs
Original file line number Diff line number Diff line change
Expand Up @@ -446,6 +446,7 @@ private void Persist(Block block)
all_application_executed.Add(application_executed);
}
snapshot.Blocks.Add(block.Hash, block.Trim());
uint ratio = NativeContract.Policy.GetFeeRatio(snapshot);
StoreView clonedSnapshot = snapshot.Clone();
// Warning: Do not write into variable snapshot directly. Write into variable clonedSnapshot and commit instead.
foreach (Transaction tx in block.Transactions)
Expand All @@ -459,7 +460,7 @@ private void Persist(Block block)
clonedSnapshot.Transactions.Add(tx.Hash, state);
clonedSnapshot.Transactions.Commit();

using (ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Application, tx, clonedSnapshot, tx.SystemFee))
using (ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Application, tx, clonedSnapshot, tx.SystemFee * ratio))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very good. I like this design.
Thus, ratio 0.5 makes the network more expensive.

{
engine.LoadScript(tx.Script);
state.VMState = engine.Execute();
Expand Down
2 changes: 1 addition & 1 deletion src/neo/Network/P2P/Payloads/Transaction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ public virtual VerifyResult VerifyStateDependent(StoreView snapshot, Transaction
foreach (TransactionAttribute attribute in Attributes)
if (!attribute.Verify(snapshot, this))
return VerifyResult.Invalid;
long net_fee = NetworkFee - Size * NativeContract.Policy.GetFeePerByte(snapshot);
long net_fee = NetworkFee * NativeContract.Policy.GetFeeRatio(snapshot) - Size * NativeContract.Policy.GetFeePerByte(snapshot);
Copy link
Member

@vncoelho vncoelho Oct 28, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is the same, but maybe:
(NetworkFee * NativeContract.Policy.GetFeeRatio(snapshot)) - (Size * NativeContract.Policy.GetFeePerByte(snapshot)), to make it clear.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have fixed, please have a check

if (!this.VerifyWitnesses(snapshot, net_fee, WitnessFlag.StateDependent))
return VerifyResult.Invalid;
return VerifyResult.Succeed;
Expand Down
2 changes: 1 addition & 1 deletion src/neo/Network/P2P/Payloads/Witness.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public class Witness : ISerializable
public byte[] InvocationScript;
public byte[] VerificationScript;

internal long GasConsumed { get; set; }
internal long GasConsumedWithRatio { get; set; }

private UInt160 _scriptHash;
public virtual UInt160 ScriptHash
Expand Down
14 changes: 8 additions & 6 deletions src/neo/SmartContract/ApplicationEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using Neo.Network.P2P.Payloads;
using Neo.Persistence;
using Neo.Plugins;
using Neo.SmartContract.Native;
using Neo.VM;
using Neo.VM.Types;
using System;
Expand Down Expand Up @@ -42,7 +43,7 @@ private class InvocationState

private static IApplicationEngineProvider applicationEngineProvider;
private static Dictionary<uint, InteropDescriptor> services;
private readonly long gas_amount;
private readonly long gas_amount_with_ratio;
private List<NotifyEventArgs> notifications;
private List<IDisposable> disposables;
private readonly Dictionary<UInt160, int> invocationCounter = new Dictionary<UInt160, int>();
Expand All @@ -53,8 +54,9 @@ private class InvocationState
public TriggerType Trigger { get; }
public IVerifiable ScriptContainer { get; }
public StoreView Snapshot { get; }
public long GasConsumed { get; private set; } = 0;
public long GasLeft => gas_amount - GasConsumed;
public long GasConsumedWithRatio = 0;
public long GasConsumed => GasConsumedWithRatio / NativeContract.Policy.GetFeeRatio(Snapshot);
public long GasLeft => (gas_amount_with_ratio - GasConsumedWithRatio) / NativeContract.Policy.GetFeeRatio(Snapshot);
public Exception FaultException { get; private set; }
public UInt160 CurrentScriptHash => CurrentContext?.GetScriptHash();
public UInt160 CallingScriptHash => CurrentContext?.GetState<ExecutionContextState>().CallingScriptHash;
Expand All @@ -66,13 +68,13 @@ protected ApplicationEngine(TriggerType trigger, IVerifiable container, StoreVie
this.Trigger = trigger;
this.ScriptContainer = container;
this.Snapshot = snapshot;
this.gas_amount = gas;
this.gas_amount_with_ratio = gas;
}

protected internal void AddGas(long gas)
{
GasConsumed = checked(GasConsumed + gas);
if (GasConsumed > gas_amount)
GasConsumedWithRatio = checked(GasConsumedWithRatio + gas);
if (GasConsumedWithRatio > gas_amount_with_ratio)
throw new InvalidOperationException("Insufficient GAS.");
}

Expand Down
9 changes: 5 additions & 4 deletions src/neo/SmartContract/Helper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,8 @@ public static UInt160 ToScriptHash(this ReadOnlySpan<byte> script)
internal static bool VerifyWitnesses(this IVerifiable verifiable, StoreView snapshot, long gas, WitnessFlag filter = WitnessFlag.All)
{
if (gas < 0) return false;
if (gas > MaxVerificationGas) gas = MaxVerificationGas;
if (snapshot is null) gas = MaxVerificationGas;
else if (gas > MaxVerificationGas) gas = MaxVerificationGas;

UInt160[] hashes;
try
Expand All @@ -150,7 +151,7 @@ internal static bool VerifyWitnesses(this IVerifiable verifiable, StoreView snap
WitnessFlag flag = verifiable.Witnesses[i].StateDependent ? WitnessFlag.StateDependent : WitnessFlag.StateIndependent;
if (!filter.HasFlag(flag))
{
gas -= verifiable.Witnesses[i].GasConsumed;
gas -= verifiable.Witnesses[i].GasConsumedWithRatio;
if (gas < 0) return false;
continue;
}
Expand Down Expand Up @@ -192,8 +193,8 @@ internal static bool VerifyWitnesses(this IVerifiable verifiable, StoreView snap
engine.LoadScript(verifiable.Witnesses[i].InvocationScript, CallFlags.None);
if (engine.Execute() == VMState.FAULT) return false;
if (engine.ResultStack.Count != 1 || !engine.ResultStack.Pop().GetBoolean()) return false;
gas -= engine.GasConsumed;
verifiable.Witnesses[i].GasConsumed = engine.GasConsumed;
gas -= engine.GasConsumedWithRatio;
verifiable.Witnesses[i].GasConsumedWithRatio = engine.GasConsumedWithRatio;
}
}
return true;
Expand Down
19 changes: 19 additions & 0 deletions src/neo/SmartContract/Native/PolicyContract.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public sealed class PolicyContract : NativeContract
private const byte Prefix_BlockedAccount = 15;
private const byte Prefix_MaxBlockSize = 12;
private const byte Prefix_MaxBlockSystemFee = 17;
private const byte Prefix_FeeRatio = 34;

public PolicyContract()
{
Expand Down Expand Up @@ -64,6 +65,14 @@ public bool IsBlocked(StoreView snapshot, UInt160 account)
return snapshot.Storages.Contains(CreateStorageKey(Prefix_BlockedAccount).Add(account));
}

[ContractMethod(0_01000000, CallFlags.AllowStates)]
public uint GetFeeRatio(StoreView snapshot)
{
StorageItem item = snapshot.Storages.TryGet(CreateStorageKey(Prefix_FeeRatio));
if (item is null) return 1;
return (uint)(BigInteger)item;
}

[ContractMethod(0_03000000, CallFlags.AllowModifyStates)]
private bool SetMaxBlockSize(ApplicationEngine engine, uint value)
{
Expand Down Expand Up @@ -127,5 +136,15 @@ private bool UnblockAccount(ApplicationEngine engine, UInt160 account)
engine.Snapshot.Storages.Delete(key);
return true;
}

[ContractMethod(0_03000000, CallFlags.AllowModifyStates)]
private bool SetFeeRatio(ApplicationEngine engine, uint value)
shargon marked this conversation as resolved.
Show resolved Hide resolved
{
if (value == 0) throw new ArgumentOutOfRangeException(nameof(value));
if (!CheckCommittee(engine)) return false;
StorageItem storage = engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_FeeRatio), () => new StorageItem());
storage.Set(value);
return true;
}
}
}
4 changes: 2 additions & 2 deletions src/neo/Wallets/Wallet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -405,7 +405,7 @@ public long CalculateNetworkFee(StoreView snapshot, Transaction tx)
if (engine.Execute() == VMState.FAULT) throw new ArgumentException($"Smart contract {contract.ScriptHash} verification fault.");
if (engine.ResultStack.Count != 1 || !engine.ResultStack.Pop().GetBoolean()) throw new ArgumentException($"Smart contract {contract.ScriptHash} returns false.");

networkFee += engine.GasConsumed;
networkFee += engine.GasConsumedWithRatio;
}
else if (witness_script.IsSignatureContract())
{
Expand All @@ -430,7 +430,7 @@ public long CalculateNetworkFee(StoreView snapshot, Transaction tx)
}
}
networkFee += size * NativeContract.Policy.GetFeePerByte(snapshot);
return networkFee;
return networkFee / NativeContract.Policy.GetFeeRatio(snapshot);
}

public bool Sign(ContractParametersContext context)
Expand Down
22 changes: 21 additions & 1 deletion tests/neo.UnitTests/Network/P2P/Payloads/UT_Transaction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using Neo.IO.Json;
using Neo.Ledger;
using Neo.Network.P2P.Payloads;
using Neo.Persistence;
using Neo.SmartContract;
using Neo.SmartContract.Native;
using Neo.SmartContract.Native.Tokens;
Expand Down Expand Up @@ -1260,9 +1261,15 @@ public void Test_Verify()
var key = NativeContract.GAS.CreateStorageKey(20, acc.ScriptHash);
var entry = snapshot.Storages.GetAndChange(key, () => new StorageItem(new AccountState()));

entry.GetInteroperable<AccountState>().Balance = 10000 * NativeContract.GAS.Factor;
entry.GetInteroperable<AccountState>().Balance = NativeContract.GAS.Factor / 10;

snapshot.Commit();

//Change FeeRatio
StorageItem storage = snapshot.Storages.GetAndChange(new KeyBuilder(-3, 34), () => new StorageItem());
storage.Set(2);
snapshot.Commit();
NativeContract.Policy.GetFeeRatio(snapshot).Should().Be(2);

// Make transaction

Expand All @@ -1285,6 +1292,19 @@ public void Test_Verify()

tx.Witnesses = data.GetWitnesses();
tx.Verify(snapshot, new TransactionVerificationContext()).Should().Be(VerifyResult.Succeed);

using (ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Application, tx, snapshot, tx.SystemFee * NativeContract.Policy.GetFeeRatio(snapshot)))
{
engine.LoadScript(tx.Script);
VMState state = engine.Execute();
Assert.AreEqual(state, VMState.HALT);
}

//Revert FeeRatio
storage = snapshot.Storages.GetAndChange(new KeyBuilder(-3, 34), () => new StorageItem());
storage.Set(1);
snapshot.Commit();
NativeContract.Policy.GetFeeRatio(snapshot).Should().Be(1);
}
}
}
Expand Down