diff --git a/src/neo/Ledger/MemoryPool.cs b/src/neo/Ledger/MemoryPool.cs index 998b56e3a2..555f79528a 100644 --- a/src/neo/Ledger/MemoryPool.cs +++ b/src/neo/Ledger/MemoryPool.cs @@ -62,6 +62,7 @@ public class MemoryPool : IReadOnlyCollection private int _maxTxPerBlock; private long _feePerByte; + private uint _feeRatio; /// /// Total maximum capacity of transactions the pool can hold. @@ -109,8 +110,10 @@ internal bool LoadPolicy(StoreView snapshot) { _maxTxPerBlock = (int)NativeContract.Policy.GetMaxTransactionsPerBlock(snapshot); long newFeePerByte = NativeContract.Policy.GetFeePerByte(snapshot); - bool policyChanged = newFeePerByte > _feePerByte; + uint newFeeRatio = NativeContract.Policy.GetFeeRatio(snapshot); + bool policyChanged = newFeePerByte > _feePerByte || newFeeRatio > _feeRatio; _feePerByte = newFeePerByte; + _feeRatio = newFeeRatio; return policyChanged; } diff --git a/src/neo/Network/P2P/Payloads/BlockBase.cs b/src/neo/Network/P2P/Payloads/BlockBase.cs index b724f5e074..8d091b075b 100644 --- a/src/neo/Network/P2P/Payloads/BlockBase.cs +++ b/src/neo/Network/P2P/Payloads/BlockBase.cs @@ -1,8 +1,8 @@ -using Neo.Cryptography; using Neo.IO; using Neo.IO.Json; using Neo.Persistence; using Neo.SmartContract; +using Neo.SmartContract.Native; using Neo.Wallets; using System; using System.IO; @@ -118,7 +118,7 @@ public virtual bool Verify(StoreView snapshot) if (prev_header == null) return false; if (prev_header.Index + 1 != Index) return false; if (prev_header.Timestamp >= Timestamp) return false; - if (!this.VerifyWitnesses(snapshot, 1_00000000)) return false; + if (!this.VerifyWitnesses(snapshot, 0_03333333 * NativeContract.Policy.GetFeeRatio(snapshot))) return false; return true; } } diff --git a/src/neo/Network/P2P/Payloads/ConsensusPayload.cs b/src/neo/Network/P2P/Payloads/ConsensusPayload.cs index dbf2732fbc..e55b3ac7b0 100644 --- a/src/neo/Network/P2P/Payloads/ConsensusPayload.cs +++ b/src/neo/Network/P2P/Payloads/ConsensusPayload.cs @@ -124,7 +124,7 @@ public bool Verify(StoreView snapshot) { if (BlockIndex <= snapshot.Height) return false; - return this.VerifyWitnesses(snapshot, 0_02000000); + return this.VerifyWitnesses(snapshot, 0_00066666 * NativeContract.Policy.GetFeeRatio(snapshot)); } } } diff --git a/src/neo/SmartContract/ApplicationEngine.Binary.cs b/src/neo/SmartContract/ApplicationEngine.Binary.cs index 78faa488b5..d7adbc9ec2 100644 --- a/src/neo/SmartContract/ApplicationEngine.Binary.cs +++ b/src/neo/SmartContract/ApplicationEngine.Binary.cs @@ -9,14 +9,14 @@ namespace Neo.SmartContract { partial class ApplicationEngine { - public static readonly InteropDescriptor System_Binary_Serialize = Register("System.Binary.Serialize", nameof(BinarySerialize), 0_00100000, CallFlags.None, true); - public static readonly InteropDescriptor System_Binary_Deserialize = Register("System.Binary.Deserialize", nameof(BinaryDeserialize), 0_00500000, CallFlags.None, true); - public static readonly InteropDescriptor System_Binary_Base64Encode = Register("System.Binary.Base64Encode", nameof(Base64Encode), 0_00100000, CallFlags.None, true); - public static readonly InteropDescriptor System_Binary_Base64Decode = Register("System.Binary.Base64Decode", nameof(Base64Decode), 0_00100000, CallFlags.None, true); - public static readonly InteropDescriptor System_Binary_Base58Encode = Register("System.Binary.Base58Encode", nameof(Base58Encode), 0_00100000, CallFlags.None, true); - public static readonly InteropDescriptor System_Binary_Base58Decode = Register("System.Binary.Base58Decode", nameof(Base58Decode), 0_00100000, CallFlags.None, true); - public static readonly InteropDescriptor System_Binary_Itoa = Register("System.Binary.Itoa", nameof(Itoa), 0_00100000, CallFlags.None, true); - public static readonly InteropDescriptor System_Binary_Atoi = Register("System.Binary.Atoi", nameof(Atoi), 0_00100000, CallFlags.None, true); + public static readonly InteropDescriptor System_Binary_Serialize = Register("System.Binary.Serialize", nameof(BinarySerialize), 0_00003333, CallFlags.None, true); + public static readonly InteropDescriptor System_Binary_Deserialize = Register("System.Binary.Deserialize", nameof(BinaryDeserialize), 0_00016667, CallFlags.None, true); + public static readonly InteropDescriptor System_Binary_Base64Encode = Register("System.Binary.Base64Encode", nameof(Base64Encode), 0_00003333, CallFlags.None, true); + public static readonly InteropDescriptor System_Binary_Base64Decode = Register("System.Binary.Base64Decode", nameof(Base64Decode), 0_00003333, CallFlags.None, true); + public static readonly InteropDescriptor System_Binary_Base58Encode = Register("System.Binary.Base58Encode", nameof(Base58Encode), 0_00003333, CallFlags.None, true); + public static readonly InteropDescriptor System_Binary_Base58Decode = Register("System.Binary.Base58Decode", nameof(Base58Decode), 0_00003333, CallFlags.None, true); + public static readonly InteropDescriptor System_Binary_Itoa = Register("System.Binary.Itoa", nameof(Itoa), 0_00003333, CallFlags.None, true); + public static readonly InteropDescriptor System_Binary_Atoi = Register("System.Binary.Atoi", nameof(Atoi), 0_00003333, CallFlags.None, true); protected internal byte[] BinarySerialize(StackItem item) { diff --git a/src/neo/SmartContract/ApplicationEngine.Blockchain.cs b/src/neo/SmartContract/ApplicationEngine.Blockchain.cs index 191a2322e7..71f5ffe8ae 100644 --- a/src/neo/SmartContract/ApplicationEngine.Blockchain.cs +++ b/src/neo/SmartContract/ApplicationEngine.Blockchain.cs @@ -8,12 +8,12 @@ namespace Neo.SmartContract { partial class ApplicationEngine { - public static readonly InteropDescriptor System_Blockchain_GetHeight = Register("System.Blockchain.GetHeight", nameof(GetBlockchainHeight), 0_00000400, CallFlags.AllowStates, true); - public static readonly InteropDescriptor System_Blockchain_GetBlock = Register("System.Blockchain.GetBlock", nameof(GetBlock), 0_02500000, CallFlags.AllowStates, true); - public static readonly InteropDescriptor System_Blockchain_GetTransaction = Register("System.Blockchain.GetTransaction", nameof(GetTransaction), 0_01000000, CallFlags.AllowStates, true); - public static readonly InteropDescriptor System_Blockchain_GetTransactionHeight = Register("System.Blockchain.GetTransactionHeight", nameof(GetTransactionHeight), 0_01000000, CallFlags.AllowStates, true); - public static readonly InteropDescriptor System_Blockchain_GetTransactionFromBlock = Register("System.Blockchain.GetTransactionFromBlock", nameof(GetTransactionFromBlock), 0_01000000, CallFlags.AllowStates, true); - public static readonly InteropDescriptor System_Blockchain_GetContract = Register("System.Blockchain.GetContract", nameof(GetContract), 0_01000000, CallFlags.AllowStates, true); + public static readonly InteropDescriptor System_Blockchain_GetHeight = Register("System.Blockchain.GetHeight", nameof(GetBlockchainHeight), 0_00000013, CallFlags.AllowStates, true); + public static readonly InteropDescriptor System_Blockchain_GetBlock = Register("System.Blockchain.GetBlock", nameof(GetBlock), 0_00083333, CallFlags.AllowStates, true); + public static readonly InteropDescriptor System_Blockchain_GetTransaction = Register("System.Blockchain.GetTransaction", nameof(GetTransaction), 0_00033333, CallFlags.AllowStates, true); + public static readonly InteropDescriptor System_Blockchain_GetTransactionHeight = Register("System.Blockchain.GetTransactionHeight", nameof(GetTransactionHeight), 0_00033333, CallFlags.AllowStates, true); + public static readonly InteropDescriptor System_Blockchain_GetTransactionFromBlock = Register("System.Blockchain.GetTransactionFromBlock", nameof(GetTransactionFromBlock), 0_00033333, CallFlags.AllowStates, true); + public static readonly InteropDescriptor System_Blockchain_GetContract = Register("System.Blockchain.GetContract", nameof(GetContract), 0_00033333, CallFlags.AllowStates, true); protected internal uint GetBlockchainHeight() { diff --git a/src/neo/SmartContract/ApplicationEngine.Callback.cs b/src/neo/SmartContract/ApplicationEngine.Callback.cs index 10e4191b3d..7d2e8fb83a 100644 --- a/src/neo/SmartContract/ApplicationEngine.Callback.cs +++ b/src/neo/SmartContract/ApplicationEngine.Callback.cs @@ -7,10 +7,10 @@ namespace Neo.SmartContract { partial class ApplicationEngine { - public static readonly InteropDescriptor System_Callback_Create = Register("System.Callback.Create", nameof(CreateCallback), 0_00000400, CallFlags.None, false); - public static readonly InteropDescriptor System_Callback_CreateFromMethod = Register("System.Callback.CreateFromMethod", nameof(CreateCallbackFromMethod), 0_01000000, CallFlags.None, false); - public static readonly InteropDescriptor System_Callback_CreateFromSyscall = Register("System.Callback.CreateFromSyscall", nameof(CreateCallbackFromSyscall), 0_00000400, CallFlags.None, false); - public static readonly InteropDescriptor System_Callback_Invoke = Register("System.Callback.Invoke", nameof(InvokeCallback), 0_01000000, CallFlags.None, false); + public static readonly InteropDescriptor System_Callback_Create = Register("System.Callback.Create", nameof(CreateCallback), 0_00000013, CallFlags.None, false); + public static readonly InteropDescriptor System_Callback_CreateFromMethod = Register("System.Callback.CreateFromMethod", nameof(CreateCallbackFromMethod), 0_00033333, CallFlags.None, false); + public static readonly InteropDescriptor System_Callback_CreateFromSyscall = Register("System.Callback.CreateFromSyscall", nameof(CreateCallbackFromSyscall), 0_00000013, CallFlags.None, false); + public static readonly InteropDescriptor System_Callback_Invoke = Register("System.Callback.Invoke", nameof(InvokeCallback), 0_00033333, CallFlags.None, false); protected internal void InvokeCallback(CallbackBase callback, Array args) { diff --git a/src/neo/SmartContract/ApplicationEngine.Contract.cs b/src/neo/SmartContract/ApplicationEngine.Contract.cs index 8fe9e779a2..931038009a 100644 --- a/src/neo/SmartContract/ApplicationEngine.Contract.cs +++ b/src/neo/SmartContract/ApplicationEngine.Contract.cs @@ -17,16 +17,16 @@ partial class ApplicationEngine public static readonly InteropDescriptor System_Contract_Create = Register("System.Contract.Create", nameof(CreateContract), 0, CallFlags.AllowModifyStates, false); public static readonly InteropDescriptor System_Contract_Update = Register("System.Contract.Update", nameof(UpdateContract), 0, CallFlags.AllowModifyStates, false); - public static readonly InteropDescriptor System_Contract_Destroy = Register("System.Contract.Destroy", nameof(DestroyContract), 0_01000000, CallFlags.AllowModifyStates, false); - public static readonly InteropDescriptor System_Contract_Call = Register("System.Contract.Call", nameof(CallContract), 0_01000000, CallFlags.AllowCall, false); - public static readonly InteropDescriptor System_Contract_CallEx = Register("System.Contract.CallEx", nameof(CallContractEx), 0_01000000, CallFlags.AllowCall, false); - public static readonly InteropDescriptor System_Contract_IsStandard = Register("System.Contract.IsStandard", nameof(IsStandardContract), 0_00030000, CallFlags.AllowStates, true); - public static readonly InteropDescriptor System_Contract_GetCallFlags = Register("System.Contract.GetCallFlags", nameof(GetCallFlags), 0_00030000, CallFlags.None, false); + public static readonly InteropDescriptor System_Contract_Destroy = Register("System.Contract.Destroy", nameof(DestroyContract), 0_00033333, CallFlags.AllowModifyStates, false); + public static readonly InteropDescriptor System_Contract_Call = Register("System.Contract.Call", nameof(CallContract), 0_00033333, CallFlags.AllowCall, false); + public static readonly InteropDescriptor System_Contract_CallEx = Register("System.Contract.CallEx", nameof(CallContractEx), 0_00033333, CallFlags.AllowCall, false); + public static readonly InteropDescriptor System_Contract_IsStandard = Register("System.Contract.IsStandard", nameof(IsStandardContract), 0_00001000, CallFlags.AllowStates, true); + public static readonly InteropDescriptor System_Contract_GetCallFlags = Register("System.Contract.GetCallFlags", nameof(GetCallFlags), 0_00001000, CallFlags.None, false); /// /// Calculate corresponding account scripthash for given public key /// Warning: check first that input public key is valid, before creating the script. /// - public static readonly InteropDescriptor System_Contract_CreateStandardAccount = Register("System.Contract.CreateStandardAccount", nameof(CreateStandardAccount), 0_00010000, CallFlags.None, true); + public static readonly InteropDescriptor System_Contract_CreateStandardAccount = Register("System.Contract.CreateStandardAccount", nameof(CreateStandardAccount), 0_00000333, CallFlags.None, true); protected internal void CreateContract(byte[] script, byte[] manifest) { @@ -35,7 +35,7 @@ protected internal void CreateContract(byte[] script, byte[] manifest) if (manifest.Length == 0 || manifest.Length > ContractManifest.MaxLength) throw new ArgumentException($"Invalid Manifest Length: {manifest.Length}"); - AddGas(StoragePrice * (script.Length + manifest.Length)); + AddGas(StoragePrice * (script.Length + manifest.Length), false); UInt160 hash = script.ToScriptHash(); ContractState contract = Snapshot.Contracts.TryGet(hash); @@ -66,7 +66,7 @@ protected internal void UpdateContract(byte[] script, byte[] manifest) { if (script is null && manifest is null) throw new ArgumentException(); - AddGas(StoragePrice * ((script?.Length ?? 0) + (manifest?.Length ?? 0))); + AddGas(StoragePrice * ((script?.Length ?? 0) + (manifest?.Length ?? 0)), false); var contract = Snapshot.Contracts.TryGet(CurrentScriptHash); if (contract is null) throw new InvalidOperationException($"Updating Contract Does Not Exist: {CurrentScriptHash}"); diff --git a/src/neo/SmartContract/ApplicationEngine.Crypto.cs b/src/neo/SmartContract/ApplicationEngine.Crypto.cs index 2c7a312855..750b4b4625 100644 --- a/src/neo/SmartContract/ApplicationEngine.Crypto.cs +++ b/src/neo/SmartContract/ApplicationEngine.Crypto.cs @@ -9,10 +9,10 @@ namespace Neo.SmartContract { partial class ApplicationEngine { - public const long ECDsaVerifyPrice = 0_01000000; + public const long ECDsaVerifyPrice = 0_00033333; - public static readonly InteropDescriptor Neo_Crypto_RIPEMD160 = Register("Neo.Crypto.RIPEMD160", nameof(RIPEMD160), 0_01000000, CallFlags.None, true); - public static readonly InteropDescriptor Neo_Crypto_SHA256 = Register("Neo.Crypto.SHA256", nameof(Sha256), 0_01000000, CallFlags.None, true); + public static readonly InteropDescriptor Neo_Crypto_RIPEMD160 = Register("Neo.Crypto.RIPEMD160", nameof(RIPEMD160), 0_00033333, CallFlags.None, true); + public static readonly InteropDescriptor Neo_Crypto_SHA256 = Register("Neo.Crypto.SHA256", nameof(Sha256), 0_00033333, CallFlags.None, true); public static readonly InteropDescriptor Neo_Crypto_VerifyWithECDsaSecp256r1 = Register("Neo.Crypto.VerifyWithECDsaSecp256r1", nameof(VerifyWithECDsaSecp256r1), ECDsaVerifyPrice, CallFlags.None, true); public static readonly InteropDescriptor Neo_Crypto_VerifyWithECDsaSecp256k1 = Register("Neo.Crypto.VerifyWithECDsaSecp256k1", nameof(VerifyWithECDsaSecp256k1), ECDsaVerifyPrice, CallFlags.None, true); public static readonly InteropDescriptor Neo_Crypto_CheckMultisigWithECDsaSecp256r1 = Register("Neo.Crypto.CheckMultisigWithECDsaSecp256r1", nameof(CheckMultisigWithECDsaSecp256r1), 0, CallFlags.None, true); diff --git a/src/neo/SmartContract/ApplicationEngine.Enumerator.cs b/src/neo/SmartContract/ApplicationEngine.Enumerator.cs index 4a53381038..b31091aacf 100644 --- a/src/neo/SmartContract/ApplicationEngine.Enumerator.cs +++ b/src/neo/SmartContract/ApplicationEngine.Enumerator.cs @@ -8,10 +8,10 @@ namespace Neo.SmartContract { partial class ApplicationEngine { - public static readonly InteropDescriptor System_Enumerator_Create = Register("System.Enumerator.Create", nameof(CreateEnumerator), 0_00000400, CallFlags.None, false); - public static readonly InteropDescriptor System_Enumerator_Next = Register("System.Enumerator.Next", nameof(EnumeratorNext), 0_01000000, CallFlags.None, false); - public static readonly InteropDescriptor System_Enumerator_Value = Register("System.Enumerator.Value", nameof(EnumeratorValue), 0_00000400, CallFlags.None, false); - public static readonly InteropDescriptor System_Enumerator_Concat = Register("System.Enumerator.Concat", nameof(ConcatEnumerators), 0_00000400, CallFlags.None, false); + public static readonly InteropDescriptor System_Enumerator_Create = Register("System.Enumerator.Create", nameof(CreateEnumerator), 0_00000013, CallFlags.None, false); + public static readonly InteropDescriptor System_Enumerator_Next = Register("System.Enumerator.Next", nameof(EnumeratorNext), 0_00033333, CallFlags.None, false); + public static readonly InteropDescriptor System_Enumerator_Value = Register("System.Enumerator.Value", nameof(EnumeratorValue), 0_00000013, CallFlags.None, false); + public static readonly InteropDescriptor System_Enumerator_Concat = Register("System.Enumerator.Concat", nameof(ConcatEnumerators), 0_00000013, CallFlags.None, false); protected internal IEnumerator CreateEnumerator(StackItem item) { diff --git a/src/neo/SmartContract/ApplicationEngine.Iterator.cs b/src/neo/SmartContract/ApplicationEngine.Iterator.cs index 66d5edf085..55de5a219d 100644 --- a/src/neo/SmartContract/ApplicationEngine.Iterator.cs +++ b/src/neo/SmartContract/ApplicationEngine.Iterator.cs @@ -8,11 +8,11 @@ namespace Neo.SmartContract { partial class ApplicationEngine { - public static readonly InteropDescriptor System_Iterator_Create = Register("System.Iterator.Create", nameof(CreateIterator), 0_00000400, CallFlags.None, false); - public static readonly InteropDescriptor System_Iterator_Key = Register("System.Iterator.Key", nameof(IteratorKey), 0_00000400, CallFlags.None, false); - public static readonly InteropDescriptor System_Iterator_Keys = Register("System.Iterator.Keys", nameof(IteratorKeys), 0_00000400, CallFlags.None, false); - public static readonly InteropDescriptor System_Iterator_Values = Register("System.Iterator.Values", nameof(IteratorValues), 0_00000400, CallFlags.None, false); - public static readonly InteropDescriptor System_Iterator_Concat = Register("System.Iterator.Concat", nameof(ConcatIterators), 0_00000400, CallFlags.None, false); + public static readonly InteropDescriptor System_Iterator_Create = Register("System.Iterator.Create", nameof(CreateIterator), 0_00000013, CallFlags.None, false); + public static readonly InteropDescriptor System_Iterator_Key = Register("System.Iterator.Key", nameof(IteratorKey), 0_00000013, CallFlags.None, false); + public static readonly InteropDescriptor System_Iterator_Keys = Register("System.Iterator.Keys", nameof(IteratorKeys), 0_00000013, CallFlags.None, false); + public static readonly InteropDescriptor System_Iterator_Values = Register("System.Iterator.Values", nameof(IteratorValues), 0_00000013, CallFlags.None, false); + public static readonly InteropDescriptor System_Iterator_Concat = Register("System.Iterator.Concat", nameof(ConcatIterators), 0_00000013, CallFlags.None, false); protected internal IIterator CreateIterator(StackItem item) { diff --git a/src/neo/SmartContract/ApplicationEngine.Json.cs b/src/neo/SmartContract/ApplicationEngine.Json.cs index 48ff632123..b68d17773d 100644 --- a/src/neo/SmartContract/ApplicationEngine.Json.cs +++ b/src/neo/SmartContract/ApplicationEngine.Json.cs @@ -5,8 +5,8 @@ namespace Neo.SmartContract { partial class ApplicationEngine { - public static readonly InteropDescriptor System_Json_Serialize = Register("System.Json.Serialize", nameof(JsonSerialize), 0_00100000, CallFlags.None, true); - public static readonly InteropDescriptor System_Json_Deserialize = Register("System.Json.Deserialize", nameof(JsonDeserialize), 0_00500000, CallFlags.None, true); + public static readonly InteropDescriptor System_Json_Serialize = Register("System.Json.Serialize", nameof(JsonSerialize), 0_00003333, CallFlags.None, true); + public static readonly InteropDescriptor System_Json_Deserialize = Register("System.Json.Deserialize", nameof(JsonDeserialize), 0_00016667, CallFlags.None, true); protected internal byte[] JsonSerialize(StackItem item) { diff --git a/src/neo/SmartContract/ApplicationEngine.OpCodePrices.cs b/src/neo/SmartContract/ApplicationEngine.OpCodePrices.cs index 5237a52bd8..9af012f447 100644 --- a/src/neo/SmartContract/ApplicationEngine.OpCodePrices.cs +++ b/src/neo/SmartContract/ApplicationEngine.OpCodePrices.cs @@ -7,190 +7,190 @@ partial class ApplicationEngine { public static readonly IReadOnlyDictionary OpCodePrices = new Dictionary { - [OpCode.PUSHINT8] = 30, - [OpCode.PUSHINT16] = 30, - [OpCode.PUSHINT32] = 30, - [OpCode.PUSHINT64] = 30, - [OpCode.PUSHINT128] = 120, - [OpCode.PUSHINT256] = 120, - [OpCode.PUSHA] = 120, - [OpCode.PUSHNULL] = 30, - [OpCode.PUSHDATA1] = 180, - [OpCode.PUSHDATA2] = 13000, - [OpCode.PUSHDATA4] = 110000, - [OpCode.PUSHM1] = 30, - [OpCode.PUSH0] = 30, - [OpCode.PUSH1] = 30, - [OpCode.PUSH2] = 30, - [OpCode.PUSH3] = 30, - [OpCode.PUSH4] = 30, - [OpCode.PUSH5] = 30, - [OpCode.PUSH6] = 30, - [OpCode.PUSH7] = 30, - [OpCode.PUSH8] = 30, - [OpCode.PUSH9] = 30, - [OpCode.PUSH10] = 30, - [OpCode.PUSH11] = 30, - [OpCode.PUSH12] = 30, - [OpCode.PUSH13] = 30, - [OpCode.PUSH14] = 30, - [OpCode.PUSH15] = 30, - [OpCode.PUSH16] = 30, - [OpCode.NOP] = 30, - [OpCode.JMP] = 70, - [OpCode.JMP_L] = 70, - [OpCode.JMPIF] = 70, - [OpCode.JMPIF_L] = 70, - [OpCode.JMPIFNOT] = 70, - [OpCode.JMPIFNOT_L] = 70, - [OpCode.JMPEQ] = 70, - [OpCode.JMPEQ_L] = 70, - [OpCode.JMPNE] = 70, - [OpCode.JMPNE_L] = 70, - [OpCode.JMPGT] = 70, - [OpCode.JMPGT_L] = 70, - [OpCode.JMPGE] = 70, - [OpCode.JMPGE_L] = 70, - [OpCode.JMPLT] = 70, - [OpCode.JMPLT_L] = 70, - [OpCode.JMPLE] = 70, - [OpCode.JMPLE_L] = 70, - [OpCode.CALL] = 22000, - [OpCode.CALL_L] = 22000, - [OpCode.CALLA] = 22000, - [OpCode.ABORT] = 30, - [OpCode.ASSERT] = 30, - [OpCode.THROW] = 22000, - [OpCode.TRY] = 100, - [OpCode.TRY_L] = 100, - [OpCode.ENDTRY] = 100, - [OpCode.ENDTRY_L] = 100, - [OpCode.ENDFINALLY] = 100, + [OpCode.PUSHINT8] = 1, + [OpCode.PUSHINT16] = 1, + [OpCode.PUSHINT32] = 1, + [OpCode.PUSHINT64] = 1, + [OpCode.PUSHINT128] = 4, + [OpCode.PUSHINT256] = 4, + [OpCode.PUSHA] = 4, + [OpCode.PUSHNULL] = 1, + [OpCode.PUSHDATA1] = 6, + [OpCode.PUSHDATA2] = 433, + [OpCode.PUSHDATA4] = 3667, + [OpCode.PUSHM1] = 1, + [OpCode.PUSH0] = 1, + [OpCode.PUSH1] = 1, + [OpCode.PUSH2] = 1, + [OpCode.PUSH3] = 1, + [OpCode.PUSH4] = 1, + [OpCode.PUSH5] = 1, + [OpCode.PUSH6] = 1, + [OpCode.PUSH7] = 1, + [OpCode.PUSH8] = 1, + [OpCode.PUSH9] = 1, + [OpCode.PUSH10] = 1, + [OpCode.PUSH11] = 1, + [OpCode.PUSH12] = 1, + [OpCode.PUSH13] = 1, + [OpCode.PUSH14] = 1, + [OpCode.PUSH15] = 1, + [OpCode.PUSH16] = 1, + [OpCode.NOP] = 1, + [OpCode.JMP] = 2, + [OpCode.JMP_L] = 2, + [OpCode.JMPIF] = 2, + [OpCode.JMPIF_L] = 2, + [OpCode.JMPIFNOT] = 2, + [OpCode.JMPIFNOT_L] = 2, + [OpCode.JMPEQ] = 2, + [OpCode.JMPEQ_L] = 2, + [OpCode.JMPNE] = 2, + [OpCode.JMPNE_L] = 2, + [OpCode.JMPGT] = 2, + [OpCode.JMPGT_L] = 2, + [OpCode.JMPGE] = 2, + [OpCode.JMPGE_L] = 2, + [OpCode.JMPLT] = 2, + [OpCode.JMPLT_L] = 2, + [OpCode.JMPLE] = 2, + [OpCode.JMPLE_L] = 2, + [OpCode.CALL] = 733, + [OpCode.CALL_L] = 733, + [OpCode.CALLA] = 733, + [OpCode.ABORT] = 1, + [OpCode.ASSERT] = 1, + [OpCode.THROW] = 733, + [OpCode.TRY] = 3, + [OpCode.TRY_L] = 3, + [OpCode.ENDTRY] = 3, + [OpCode.ENDTRY_L] = 3, + [OpCode.ENDFINALLY] = 3, [OpCode.RET] = 0, [OpCode.SYSCALL] = 0, - [OpCode.DEPTH] = 60, - [OpCode.DROP] = 60, - [OpCode.NIP] = 60, - [OpCode.XDROP] = 400, - [OpCode.CLEAR] = 400, - [OpCode.DUP] = 60, - [OpCode.OVER] = 60, - [OpCode.PICK] = 60, - [OpCode.TUCK] = 60, - [OpCode.SWAP] = 60, - [OpCode.ROT] = 60, - [OpCode.ROLL] = 400, - [OpCode.REVERSE3] = 60, - [OpCode.REVERSE4] = 60, - [OpCode.REVERSEN] = 400, - [OpCode.INITSSLOT] = 400, - [OpCode.INITSLOT] = 1600, - [OpCode.LDSFLD0] = 60, - [OpCode.LDSFLD1] = 60, - [OpCode.LDSFLD2] = 60, - [OpCode.LDSFLD3] = 60, - [OpCode.LDSFLD4] = 60, - [OpCode.LDSFLD5] = 60, - [OpCode.LDSFLD6] = 60, - [OpCode.LDSFLD] = 60, - [OpCode.STSFLD0] = 60, - [OpCode.STSFLD1] = 60, - [OpCode.STSFLD2] = 60, - [OpCode.STSFLD3] = 60, - [OpCode.STSFLD4] = 60, - [OpCode.STSFLD5] = 60, - [OpCode.STSFLD6] = 60, - [OpCode.STSFLD] = 60, - [OpCode.LDLOC0] = 60, - [OpCode.LDLOC1] = 60, - [OpCode.LDLOC2] = 60, - [OpCode.LDLOC3] = 60, - [OpCode.LDLOC4] = 60, - [OpCode.LDLOC5] = 60, - [OpCode.LDLOC6] = 60, - [OpCode.LDLOC] = 60, - [OpCode.STLOC0] = 60, - [OpCode.STLOC1] = 60, - [OpCode.STLOC2] = 60, - [OpCode.STLOC3] = 60, - [OpCode.STLOC4] = 60, - [OpCode.STLOC5] = 60, - [OpCode.STLOC6] = 60, - [OpCode.STLOC] = 60, - [OpCode.LDARG0] = 60, - [OpCode.LDARG1] = 60, - [OpCode.LDARG2] = 60, - [OpCode.LDARG3] = 60, - [OpCode.LDARG4] = 60, - [OpCode.LDARG5] = 60, - [OpCode.LDARG6] = 60, - [OpCode.LDARG] = 60, - [OpCode.STARG0] = 60, - [OpCode.STARG1] = 60, - [OpCode.STARG2] = 60, - [OpCode.STARG3] = 60, - [OpCode.STARG4] = 60, - [OpCode.STARG5] = 60, - [OpCode.STARG6] = 60, - [OpCode.STARG] = 60, - [OpCode.NEWBUFFER] = 80000, - [OpCode.MEMCPY] = 80000, - [OpCode.CAT] = 80000, - [OpCode.SUBSTR] = 80000, - [OpCode.LEFT] = 80000, - [OpCode.RIGHT] = 80000, - [OpCode.INVERT] = 100, - [OpCode.AND] = 200, - [OpCode.OR] = 200, - [OpCode.XOR] = 200, - [OpCode.EQUAL] = 1000, - [OpCode.NOTEQUAL] = 1000, - [OpCode.SIGN] = 100, - [OpCode.ABS] = 100, - [OpCode.NEGATE] = 100, - [OpCode.INC] = 100, - [OpCode.DEC] = 100, - [OpCode.ADD] = 200, - [OpCode.SUB] = 200, - [OpCode.MUL] = 300, - [OpCode.DIV] = 300, - [OpCode.MOD] = 300, - [OpCode.SHL] = 300, - [OpCode.SHR] = 300, - [OpCode.NOT] = 100, - [OpCode.BOOLAND] = 200, - [OpCode.BOOLOR] = 200, - [OpCode.NZ] = 100, - [OpCode.NUMEQUAL] = 200, - [OpCode.NUMNOTEQUAL] = 200, - [OpCode.LT] = 200, - [OpCode.LE] = 200, - [OpCode.GT] = 200, - [OpCode.GE] = 200, - [OpCode.MIN] = 200, - [OpCode.MAX] = 200, - [OpCode.WITHIN] = 200, - [OpCode.PACK] = 15000, - [OpCode.UNPACK] = 15000, - [OpCode.NEWARRAY0] = 400, - [OpCode.NEWARRAY] = 15000, - [OpCode.NEWARRAY_T] = 15000, - [OpCode.NEWSTRUCT0] = 400, - [OpCode.NEWSTRUCT] = 15000, - [OpCode.NEWMAP] = 200, - [OpCode.SIZE] = 150, - [OpCode.HASKEY] = 270000, - [OpCode.KEYS] = 500, - [OpCode.VALUES] = 270000, - [OpCode.PICKITEM] = 270000, - [OpCode.APPEND] = 270000, - [OpCode.SETITEM] = 270000, - [OpCode.REVERSEITEMS] = 270000, - [OpCode.REMOVE] = 500, - [OpCode.CLEARITEMS] = 400, - [OpCode.ISNULL] = 60, - [OpCode.ISTYPE] = 60, - [OpCode.CONVERT] = 80000, + [OpCode.DEPTH] = 2, + [OpCode.DROP] = 2, + [OpCode.NIP] = 2, + [OpCode.XDROP] = 13, + [OpCode.CLEAR] = 13, + [OpCode.DUP] = 2, + [OpCode.OVER] = 2, + [OpCode.PICK] = 2, + [OpCode.TUCK] = 2, + [OpCode.SWAP] = 2, + [OpCode.ROT] = 2, + [OpCode.ROLL] = 13, + [OpCode.REVERSE3] = 2, + [OpCode.REVERSE4] = 2, + [OpCode.REVERSEN] = 13, + [OpCode.INITSSLOT] = 13, + [OpCode.INITSLOT] = 53, + [OpCode.LDSFLD0] = 2, + [OpCode.LDSFLD1] = 2, + [OpCode.LDSFLD2] = 2, + [OpCode.LDSFLD3] = 2, + [OpCode.LDSFLD4] = 2, + [OpCode.LDSFLD5] = 2, + [OpCode.LDSFLD6] = 2, + [OpCode.LDSFLD] = 2, + [OpCode.STSFLD0] = 2, + [OpCode.STSFLD1] = 2, + [OpCode.STSFLD2] = 2, + [OpCode.STSFLD3] = 2, + [OpCode.STSFLD4] = 2, + [OpCode.STSFLD5] = 2, + [OpCode.STSFLD6] = 2, + [OpCode.STSFLD] = 2, + [OpCode.LDLOC0] = 2, + [OpCode.LDLOC1] = 2, + [OpCode.LDLOC2] = 2, + [OpCode.LDLOC3] = 2, + [OpCode.LDLOC4] = 2, + [OpCode.LDLOC5] = 2, + [OpCode.LDLOC6] = 2, + [OpCode.LDLOC] = 2, + [OpCode.STLOC0] = 2, + [OpCode.STLOC1] = 2, + [OpCode.STLOC2] = 2, + [OpCode.STLOC3] = 2, + [OpCode.STLOC4] = 2, + [OpCode.STLOC5] = 2, + [OpCode.STLOC6] = 2, + [OpCode.STLOC] = 2, + [OpCode.LDARG0] = 2, + [OpCode.LDARG1] = 2, + [OpCode.LDARG2] = 2, + [OpCode.LDARG3] = 2, + [OpCode.LDARG4] = 2, + [OpCode.LDARG5] = 2, + [OpCode.LDARG6] = 2, + [OpCode.LDARG] = 2, + [OpCode.STARG0] = 2, + [OpCode.STARG1] = 2, + [OpCode.STARG2] = 2, + [OpCode.STARG3] = 2, + [OpCode.STARG4] = 2, + [OpCode.STARG5] = 2, + [OpCode.STARG6] = 2, + [OpCode.STARG] = 2, + [OpCode.NEWBUFFER] = 2667, + [OpCode.MEMCPY] = 2667, + [OpCode.CAT] = 2667, + [OpCode.SUBSTR] = 2667, + [OpCode.LEFT] = 2667, + [OpCode.RIGHT] = 2667, + [OpCode.INVERT] = 3, + [OpCode.AND] = 7, + [OpCode.OR] = 7, + [OpCode.XOR] = 7, + [OpCode.EQUAL] = 33, + [OpCode.NOTEQUAL] = 33, + [OpCode.SIGN] = 3, + [OpCode.ABS] = 3, + [OpCode.NEGATE] = 3, + [OpCode.INC] = 3, + [OpCode.DEC] = 3, + [OpCode.ADD] = 7, + [OpCode.SUB] = 7, + [OpCode.MUL] = 10, + [OpCode.DIV] = 10, + [OpCode.MOD] = 10, + [OpCode.SHL] = 10, + [OpCode.SHR] = 10, + [OpCode.NOT] = 3, + [OpCode.BOOLAND] = 7, + [OpCode.BOOLOR] = 7, + [OpCode.NZ] = 3, + [OpCode.NUMEQUAL] = 7, + [OpCode.NUMNOTEQUAL] = 7, + [OpCode.LT] = 7, + [OpCode.LE] = 7, + [OpCode.GT] = 7, + [OpCode.GE] = 7, + [OpCode.MIN] = 7, + [OpCode.MAX] = 7, + [OpCode.WITHIN] = 7, + [OpCode.PACK] = 500, + [OpCode.UNPACK] = 500, + [OpCode.NEWARRAY0] = 13, + [OpCode.NEWARRAY] = 500, + [OpCode.NEWARRAY_T] = 500, + [OpCode.NEWSTRUCT0] = 13, + [OpCode.NEWSTRUCT] = 500, + [OpCode.NEWMAP] = 7, + [OpCode.SIZE] = 5, + [OpCode.HASKEY] = 9000, + [OpCode.KEYS] = 17, + [OpCode.VALUES] = 9000, + [OpCode.PICKITEM] = 9000, + [OpCode.APPEND] = 9000, + [OpCode.SETITEM] = 9000, + [OpCode.REVERSEITEMS] = 9000, + [OpCode.REMOVE] = 17, + [OpCode.CLEARITEMS] = 13, + [OpCode.ISNULL] = 2, + [OpCode.ISTYPE] = 2, + [OpCode.CONVERT] = 2667, }; } } diff --git a/src/neo/SmartContract/ApplicationEngine.Runtime.cs b/src/neo/SmartContract/ApplicationEngine.Runtime.cs index 674a0cea9e..9401374e75 100644 --- a/src/neo/SmartContract/ApplicationEngine.Runtime.cs +++ b/src/neo/SmartContract/ApplicationEngine.Runtime.cs @@ -16,19 +16,19 @@ partial class ApplicationEngine public const int MaxEventName = 32; public const int MaxNotificationSize = 1024; - public static readonly InteropDescriptor System_Runtime_Platform = Register("System.Runtime.Platform", nameof(GetPlatform), 0_00000250, CallFlags.None, true); - public static readonly InteropDescriptor System_Runtime_GetTrigger = Register("System.Runtime.GetTrigger", nameof(Trigger), 0_00000250, CallFlags.None, true); - public static readonly InteropDescriptor System_Runtime_GetTime = Register("System.Runtime.GetTime", nameof(GetTime), 0_00000250, CallFlags.AllowStates, true); - public static readonly InteropDescriptor System_Runtime_GetScriptContainer = Register("System.Runtime.GetScriptContainer", nameof(GetScriptContainer), 0_00000250, CallFlags.None, true); - public static readonly InteropDescriptor System_Runtime_GetExecutingScriptHash = Register("System.Runtime.GetExecutingScriptHash", nameof(CurrentScriptHash), 0_00000400, CallFlags.None, true); - public static readonly InteropDescriptor System_Runtime_GetCallingScriptHash = Register("System.Runtime.GetCallingScriptHash", nameof(CallingScriptHash), 0_00000400, CallFlags.None, true); - public static readonly InteropDescriptor System_Runtime_GetEntryScriptHash = Register("System.Runtime.GetEntryScriptHash", nameof(EntryScriptHash), 0_00000400, CallFlags.None, true); - public static readonly InteropDescriptor System_Runtime_CheckWitness = Register("System.Runtime.CheckWitness", nameof(CheckWitness), 0_00030000, CallFlags.None, true); - public static readonly InteropDescriptor System_Runtime_GetInvocationCounter = Register("System.Runtime.GetInvocationCounter", nameof(GetInvocationCounter), 0_00000400, CallFlags.None, true); - public static readonly InteropDescriptor System_Runtime_Log = Register("System.Runtime.Log", nameof(RuntimeLog), 0_01000000, CallFlags.AllowNotify, false); - public static readonly InteropDescriptor System_Runtime_Notify = Register("System.Runtime.Notify", nameof(RuntimeNotify), 0_01000000, CallFlags.AllowNotify, false); - public static readonly InteropDescriptor System_Runtime_GetNotifications = Register("System.Runtime.GetNotifications", nameof(GetNotifications), 0_00010000, CallFlags.None, true); - public static readonly InteropDescriptor System_Runtime_GasLeft = Register("System.Runtime.GasLeft", nameof(GasLeft), 0_00000400, CallFlags.None, true); + public static readonly InteropDescriptor System_Runtime_Platform = Register("System.Runtime.Platform", nameof(GetPlatform), 0_00000008, CallFlags.None, true); + public static readonly InteropDescriptor System_Runtime_GetTrigger = Register("System.Runtime.GetTrigger", nameof(Trigger), 0_00000008, CallFlags.None, true); + public static readonly InteropDescriptor System_Runtime_GetTime = Register("System.Runtime.GetTime", nameof(GetTime), 0_00000008, CallFlags.AllowStates, true); + public static readonly InteropDescriptor System_Runtime_GetScriptContainer = Register("System.Runtime.GetScriptContainer", nameof(GetScriptContainer), 0_00000008, CallFlags.None, true); + public static readonly InteropDescriptor System_Runtime_GetExecutingScriptHash = Register("System.Runtime.GetExecutingScriptHash", nameof(CurrentScriptHash), 0_00000013, CallFlags.None, true); + public static readonly InteropDescriptor System_Runtime_GetCallingScriptHash = Register("System.Runtime.GetCallingScriptHash", nameof(CallingScriptHash), 0_00000013, CallFlags.None, true); + public static readonly InteropDescriptor System_Runtime_GetEntryScriptHash = Register("System.Runtime.GetEntryScriptHash", nameof(EntryScriptHash), 0_00000013, CallFlags.None, true); + public static readonly InteropDescriptor System_Runtime_CheckWitness = Register("System.Runtime.CheckWitness", nameof(CheckWitness), 0_00001000, CallFlags.None, true); + public static readonly InteropDescriptor System_Runtime_GetInvocationCounter = Register("System.Runtime.GetInvocationCounter", nameof(GetInvocationCounter), 0_00000013, CallFlags.None, true); + public static readonly InteropDescriptor System_Runtime_Log = Register("System.Runtime.Log", nameof(RuntimeLog), 0_00033333, CallFlags.AllowNotify, false); + public static readonly InteropDescriptor System_Runtime_Notify = Register("System.Runtime.Notify", nameof(RuntimeNotify), 0_00033333, CallFlags.AllowNotify, false); + public static readonly InteropDescriptor System_Runtime_GetNotifications = Register("System.Runtime.GetNotifications", nameof(GetNotifications), 0_00000333, CallFlags.None, true); + public static readonly InteropDescriptor System_Runtime_GasLeft = Register("System.Runtime.GasLeft", nameof(GasLeft), 0_00000013, CallFlags.None, true); private static bool CheckItemForNotification(StackItem state) { diff --git a/src/neo/SmartContract/ApplicationEngine.Storage.cs b/src/neo/SmartContract/ApplicationEngine.Storage.cs index 92c9d9df74..e70e2dd92f 100644 --- a/src/neo/SmartContract/ApplicationEngine.Storage.cs +++ b/src/neo/SmartContract/ApplicationEngine.Storage.cs @@ -11,14 +11,14 @@ partial class ApplicationEngine public const int MaxStorageKeySize = 64; public const int MaxStorageValueSize = ushort.MaxValue; - public static readonly InteropDescriptor System_Storage_GetContext = Register("System.Storage.GetContext", nameof(GetStorageContext), 0_00000400, CallFlags.AllowStates, false); - public static readonly InteropDescriptor System_Storage_GetReadOnlyContext = Register("System.Storage.GetReadOnlyContext", nameof(GetReadOnlyContext), 0_00000400, CallFlags.AllowStates, false); - public static readonly InteropDescriptor System_Storage_AsReadOnly = Register("System.Storage.AsReadOnly", nameof(AsReadOnly), 0_00000400, CallFlags.AllowStates, false); - public static readonly InteropDescriptor System_Storage_Get = Register("System.Storage.Get", nameof(Get), 0_01000000, CallFlags.AllowStates, false); - public static readonly InteropDescriptor System_Storage_Find = Register("System.Storage.Find", nameof(Find), 0_01000000, CallFlags.AllowStates, false); + public static readonly InteropDescriptor System_Storage_GetContext = Register("System.Storage.GetContext", nameof(GetStorageContext), 0_00000013, CallFlags.AllowStates, false); + public static readonly InteropDescriptor System_Storage_GetReadOnlyContext = Register("System.Storage.GetReadOnlyContext", nameof(GetReadOnlyContext), 0_00000013, CallFlags.AllowStates, false); + public static readonly InteropDescriptor System_Storage_AsReadOnly = Register("System.Storage.AsReadOnly", nameof(AsReadOnly), 0_00000013, CallFlags.AllowStates, false); + public static readonly InteropDescriptor System_Storage_Get = Register("System.Storage.Get", nameof(Get), 0_00033333, CallFlags.AllowStates, false); + public static readonly InteropDescriptor System_Storage_Find = Register("System.Storage.Find", nameof(Find), 0_00033333, CallFlags.AllowStates, false); public static readonly InteropDescriptor System_Storage_Put = Register("System.Storage.Put", nameof(Put), 0, CallFlags.AllowModifyStates, false); public static readonly InteropDescriptor System_Storage_PutEx = Register("System.Storage.PutEx", nameof(PutEx), 0, CallFlags.AllowModifyStates, false); - public static readonly InteropDescriptor System_Storage_Delete = Register("System.Storage.Delete", nameof(Delete), 1 * StoragePrice, CallFlags.AllowModifyStates, false); + public static readonly InteropDescriptor System_Storage_Delete = Register("System.Storage.Delete", nameof(Delete), 1 * StoragePrice, CallFlags.AllowModifyStates, false, false); protected internal StorageContext GetStorageContext() { @@ -105,7 +105,7 @@ private void PutExInternal(StorageContext context, byte[] key, byte[] value, Sto else newDataSize = (item.Value.Length - 1) / 4 + 1 + value.Length - item.Value.Length; } - AddGas(newDataSize * StoragePrice); + AddGas(newDataSize * StoragePrice, false); item.Value = value; item.IsConstant = flags.HasFlag(StorageFlags.Constant); diff --git a/src/neo/SmartContract/ApplicationEngine.cs b/src/neo/SmartContract/ApplicationEngine.cs index a527344570..dea1033de9 100644 --- a/src/neo/SmartContract/ApplicationEngine.cs +++ b/src/neo/SmartContract/ApplicationEngine.cs @@ -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; @@ -35,7 +36,7 @@ private class InvocationState /// /// This constant can be used for testing scripts. /// - private const long TestModeGas = 20_00000000; + private const long TestModeGas = 66666667; public static event EventHandler Notify; public static event EventHandler Log; @@ -47,6 +48,7 @@ private class InvocationState private List disposables; private readonly Dictionary invocationCounter = new Dictionary(); private readonly Dictionary invocationStates = new Dictionary(); + private readonly uint feeRatio; public static IReadOnlyDictionary Services => services; private List Disposables => disposables ??= new List(); @@ -67,10 +69,12 @@ protected ApplicationEngine(TriggerType trigger, IVerifiable container, StoreVie this.ScriptContainer = container; this.Snapshot = snapshot; this.gas_amount = gas; + this.feeRatio = snapshot is null ? 1 : NativeContract.Policy.GetFeeRatio(Snapshot); } - protected internal void AddGas(long gas) + protected internal void AddGas(long gas, bool withRatio = true) { + if (withRatio && Snapshot != null) gas *= feeRatio; GasConsumed = checked(GasConsumed + gas); if (GasConsumed > gas_amount) throw new InvalidOperationException("Insufficient GAS."); @@ -134,8 +138,13 @@ protected override void ContextUnloaded(ExecutionContext context) } } - public static ApplicationEngine Create(TriggerType trigger, IVerifiable container, StoreView snapshot, long gas = TestModeGas) + public static ApplicationEngine Create(TriggerType trigger, IVerifiable container, StoreView snapshot, long gas = -1) { + if (gas == -1) + { + if (snapshot != null) gas = TestModeGas * NativeContract.Policy.GetFeeRatio(snapshot); + else gas = TestModeGas; + } return applicationEngineProvider?.Create(trigger, container, snapshot, gas) ?? new ApplicationEngine(trigger, container, snapshot, gas); } @@ -256,7 +265,7 @@ protected override void OnSysCall(uint method) { InteropDescriptor descriptor = services[method]; ValidateCallFlags(descriptor); - AddGas(descriptor.FixedPrice); + AddGas(descriptor.FixedPrice, descriptor.WithRatio); List parameters = descriptor.Parameters.Count > 0 ? new List() : null; @@ -294,11 +303,11 @@ private static Block CreateDummyBlock(StoreView snapshot) }; } - private static InteropDescriptor Register(string name, string handler, long fixedPrice, CallFlags requiredCallFlags, bool allowCallback) + private static InteropDescriptor Register(string name, string handler, long fixedPrice, CallFlags requiredCallFlags, bool allowCallback, bool withRatio = true) { MethodInfo method = typeof(ApplicationEngine).GetMethod(handler, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance) ?? typeof(ApplicationEngine).GetProperty(handler, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).GetMethod; - InteropDescriptor descriptor = new InteropDescriptor(name, method, fixedPrice, requiredCallFlags, allowCallback); + InteropDescriptor descriptor = new InteropDescriptor(name, method, fixedPrice, requiredCallFlags, allowCallback, withRatio); services ??= new Dictionary(); services.Add(descriptor.Hash, descriptor); return descriptor; @@ -309,7 +318,7 @@ internal static void ResetApplicationEngineProvider() Exchange(ref applicationEngineProvider, null); } - public static ApplicationEngine Run(byte[] script, StoreView snapshot = null, IVerifiable container = null, Block persistingBlock = null, int offset = 0, long gas = TestModeGas) + public static ApplicationEngine Run(byte[] script, StoreView snapshot = null, IVerifiable container = null, Block persistingBlock = null, int offset = 0, long gas = -1) { SnapshotView disposable = null; if (snapshot is null) @@ -317,6 +326,7 @@ public static ApplicationEngine Run(byte[] script, StoreView snapshot = null, IV disposable = Blockchain.Singleton.GetSnapshot(); snapshot = disposable; } + if (gas == -1) gas = TestModeGas * NativeContract.Policy.GetFeeRatio(snapshot); snapshot.PersistingBlock = persistingBlock ?? snapshot.PersistingBlock ?? CreateDummyBlock(snapshot); ApplicationEngine engine = Create(TriggerType.Application, container, snapshot, gas); if (disposable != null) engine.Disposables.Add(disposable); diff --git a/src/neo/SmartContract/Helper.cs b/src/neo/SmartContract/Helper.cs index d3f841b84d..68e9d9fa49 100644 --- a/src/neo/SmartContract/Helper.cs +++ b/src/neo/SmartContract/Helper.cs @@ -14,7 +14,7 @@ namespace Neo.SmartContract { public static class Helper { - private const long MaxVerificationGas = 0_50000000; + private const long MaxVerificationGas = 0_01666667; public static UInt160 GetScriptHash(this ExecutionContext context) { @@ -130,10 +130,18 @@ public static UInt160 ToScriptHash(this ReadOnlySpan script) return new UInt160(Crypto.Hash160(script)); } - internal static bool VerifyWitnesses(this IVerifiable verifiable, StoreView snapshot, long gas, WitnessFlag filter = WitnessFlag.All) + internal static bool VerifyWitnesses(this IVerifiable verifiable, StoreView snapshot, long gas, WitnessFlag filter = WitnessFlag.All, bool withRatio = true) { if (gas < 0) return false; - if (gas > MaxVerificationGas) gas = MaxVerificationGas; + if (snapshot is null) + { + gas = MaxVerificationGas; + } + else + { + long MaxVerificationGasWithRatio = MaxVerificationGas * NativeContract.Policy.GetFeeRatio(snapshot); + if (gas > MaxVerificationGasWithRatio) gas = MaxVerificationGasWithRatio; + } UInt160[] hashes; try @@ -150,7 +158,8 @@ 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; + if (snapshot == null) gas -= verifiable.Witnesses[i].GasConsumed; + else gas -= verifiable.Witnesses[i].GasConsumed * NativeContract.Policy.GetFeeRatio(snapshot); if (gas < 0) return false; continue; } diff --git a/src/neo/SmartContract/InteropDescriptor.cs b/src/neo/SmartContract/InteropDescriptor.cs index 690fac884c..8c5002aa06 100644 --- a/src/neo/SmartContract/InteropDescriptor.cs +++ b/src/neo/SmartContract/InteropDescriptor.cs @@ -16,8 +16,9 @@ public class InteropDescriptor public long FixedPrice { get; } public CallFlags RequiredCallFlags { get; } public bool AllowCallback { get; } + public bool WithRatio { get; } - internal InteropDescriptor(string name, MethodInfo handler, long fixedPrice, CallFlags requiredCallFlags, bool allowCallback) + internal InteropDescriptor(string name, MethodInfo handler, long fixedPrice, CallFlags requiredCallFlags, bool allowCallback, bool withRatio) { this.Name = name; this.Hash = BitConverter.ToUInt32(Encoding.ASCII.GetBytes(name).Sha256(), 0); @@ -26,6 +27,7 @@ internal InteropDescriptor(string name, MethodInfo handler, long fixedPrice, Cal this.FixedPrice = fixedPrice; this.RequiredCallFlags = requiredCallFlags; this.AllowCallback = allowCallback; + this.WithRatio = withRatio; } public static implicit operator uint(InteropDescriptor descriptor) diff --git a/src/neo/SmartContract/Native/Designate/DesignateContract.cs b/src/neo/SmartContract/Native/Designate/DesignateContract.cs index a8180bbea0..63629c1225 100644 --- a/src/neo/SmartContract/Native/Designate/DesignateContract.cs +++ b/src/neo/SmartContract/Native/Designate/DesignateContract.cs @@ -23,7 +23,7 @@ internal DesignateContract() { } - [ContractMethod(0_01000000, CallFlags.AllowStates)] + [ContractMethod(0_00033333, CallFlags.AllowStates)] public ECPoint[] GetDesignatedByRole(StoreView snapshot, Role role, uint index) { if (!Enum.IsDefined(typeof(Role), role)) diff --git a/src/neo/SmartContract/Native/Oracle/OracleContract.cs b/src/neo/SmartContract/Native/Oracle/OracleContract.cs index 18d8ad20a9..be8a6bf01d 100644 --- a/src/neo/SmartContract/Native/Oracle/OracleContract.cs +++ b/src/neo/SmartContract/Native/Oracle/OracleContract.cs @@ -27,7 +27,7 @@ public sealed class OracleContract : NativeContract private const byte Prefix_Request = 7; private const byte Prefix_IdList = 6; - private const long OracleRequestPrice = 0_50000000; + private const long OracleRequestPrice = 0_01666667; public override int Id => -4; public override string Name => "Oracle"; @@ -161,7 +161,7 @@ protected override void PostPersist(ApplicationEngine engine) if (nodes.Length > 0) { int index = (int)(response.Id % (ulong)nodes.Length); - nodes[index].GAS += OracleRequestPrice; + nodes[index].GAS += OracleRequestPrice * Policy.GetFeeRatio(engine.Snapshot); } } if (nodes != null) @@ -180,7 +180,7 @@ private void Request(ApplicationEngine engine, string url, string filter, string if (Utility.StrictUTF8.GetByteCount(url) > MaxUrlLength || (filter != null && Utility.StrictUTF8.GetByteCount(filter) > MaxFilterLength) || Utility.StrictUTF8.GetByteCount(callback) > MaxCallbackLength - || gasForResponse < 0_10000000) + || gasForResponse < 0_00333333 * Policy.GetFeeRatio(engine.Snapshot)) throw new ArgumentException(); //Mint gas for the response @@ -215,7 +215,7 @@ private void Request(ApplicationEngine engine, string url, string filter, string engine.SendNotification(Hash, "OracleRequest", new VM.Types.Array { id, engine.CallingScriptHash.ToArray(), url, filter }); } - [ContractMethod(0_01000000, CallFlags.None)] + [ContractMethod(0_00033333, CallFlags.None)] private bool Verify(ApplicationEngine engine) { Transaction tx = (Transaction)engine.ScriptContainer; diff --git a/src/neo/SmartContract/Native/PolicyContract.cs b/src/neo/SmartContract/Native/PolicyContract.cs index e828bbc94c..47bc17c5f3 100644 --- a/src/neo/SmartContract/Native/PolicyContract.cs +++ b/src/neo/SmartContract/Native/PolicyContract.cs @@ -14,17 +14,19 @@ public sealed class PolicyContract : NativeContract public override string Name => "Policy"; public override int Id => -3; + private const uint MaximumRatio = 1000; private const byte Prefix_MaxTransactionsPerBlock = 23; private const byte Prefix_FeePerByte = 10; private const byte Prefix_BlockedAccount = 15; private const byte Prefix_MaxBlockSize = 12; private const byte Prefix_MaxBlockSystemFee = 17; + private const byte Prefix_FeeRatio = 34; internal PolicyContract() { } - [ContractMethod(0_01000000, CallFlags.AllowStates)] + [ContractMethod(0_00033333, CallFlags.AllowStates)] public uint GetMaxTransactionsPerBlock(StoreView snapshot) { StorageItem item = snapshot.Storages.TryGet(CreateStorageKey(Prefix_MaxTransactionsPerBlock)); @@ -32,7 +34,7 @@ public uint GetMaxTransactionsPerBlock(StoreView snapshot) return (uint)(BigInteger)item; } - [ContractMethod(0_01000000, CallFlags.AllowStates)] + [ContractMethod(0_00033333, CallFlags.AllowStates)] public uint GetMaxBlockSize(StoreView snapshot) { StorageItem item = snapshot.Storages.TryGet(CreateStorageKey(Prefix_MaxBlockSize)); @@ -40,7 +42,7 @@ public uint GetMaxBlockSize(StoreView snapshot) return (uint)(BigInteger)item; } - [ContractMethod(0_01000000, CallFlags.AllowStates)] + [ContractMethod(0_00033333, CallFlags.AllowStates)] public long GetMaxBlockSystemFee(StoreView snapshot) { StorageItem item = snapshot.Storages.TryGet(CreateStorageKey(Prefix_MaxBlockSystemFee)); @@ -48,7 +50,7 @@ public long GetMaxBlockSystemFee(StoreView snapshot) return (long)(BigInteger)item; } - [ContractMethod(0_01000000, CallFlags.AllowStates)] + [ContractMethod(0_00033333, CallFlags.AllowStates)] public long GetFeePerByte(StoreView snapshot) { StorageItem item = snapshot.Storages.TryGet(CreateStorageKey(Prefix_FeePerByte)); @@ -56,13 +58,21 @@ public long GetFeePerByte(StoreView snapshot) return (long)(BigInteger)item; } - [ContractMethod(0_01000000, CallFlags.AllowStates)] + [ContractMethod(0_00033333, CallFlags.AllowStates)] public bool IsBlocked(StoreView snapshot, UInt160 account) { return snapshot.Storages.Contains(CreateStorageKey(Prefix_BlockedAccount).Add(account)); } - [ContractMethod(0_03000000, CallFlags.AllowModifyStates)] + [ContractMethod(0_00033333, CallFlags.AllowStates)] + public uint GetFeeRatio(StoreView snapshot) + { + StorageItem item = snapshot.Storages.TryGet(CreateStorageKey(Prefix_FeeRatio)); + if (item is null) return 30; + return (uint)(BigInteger)item; + } + + [ContractMethod(0_00100000, CallFlags.AllowModifyStates)] private bool SetMaxBlockSize(ApplicationEngine engine, uint value) { if (value > Message.PayloadMaxSize) throw new ArgumentOutOfRangeException(nameof(value)); @@ -72,7 +82,7 @@ private bool SetMaxBlockSize(ApplicationEngine engine, uint value) return true; } - [ContractMethod(0_03000000, CallFlags.AllowModifyStates)] + [ContractMethod(0_00100000, CallFlags.AllowModifyStates)] private bool SetMaxTransactionsPerBlock(ApplicationEngine engine, uint value) { if (value > Block.MaxTransactionsPerBlock) throw new ArgumentOutOfRangeException(nameof(value)); @@ -82,7 +92,7 @@ private bool SetMaxTransactionsPerBlock(ApplicationEngine engine, uint value) return true; } - [ContractMethod(0_03000000, CallFlags.AllowModifyStates)] + [ContractMethod(0_00100000, CallFlags.AllowModifyStates)] private bool SetMaxBlockSystemFee(ApplicationEngine engine, long value) { if (value <= 4007600) throw new ArgumentOutOfRangeException(nameof(value)); @@ -92,7 +102,7 @@ private bool SetMaxBlockSystemFee(ApplicationEngine engine, long value) return true; } - [ContractMethod(0_03000000, CallFlags.AllowModifyStates)] + [ContractMethod(0_00100000, CallFlags.AllowModifyStates)] private bool SetFeePerByte(ApplicationEngine engine, long value) { if (value < 0 || value > 1_00000000) throw new ArgumentOutOfRangeException(nameof(value)); @@ -102,7 +112,7 @@ private bool SetFeePerByte(ApplicationEngine engine, long value) return true; } - [ContractMethod(0_03000000, CallFlags.AllowModifyStates)] + [ContractMethod(0_00100000, CallFlags.AllowModifyStates)] private bool BlockAccount(ApplicationEngine engine, UInt160 account) { if (!CheckCommittee(engine)) return false; @@ -114,7 +124,7 @@ private bool BlockAccount(ApplicationEngine engine, UInt160 account) return true; } - [ContractMethod(0_03000000, CallFlags.AllowModifyStates)] + [ContractMethod(0_00100000, CallFlags.AllowModifyStates)] private bool UnblockAccount(ApplicationEngine engine, UInt160 account) { if (!CheckCommittee(engine)) return false; @@ -125,5 +135,15 @@ private bool UnblockAccount(ApplicationEngine engine, UInt160 account) engine.Snapshot.Storages.Delete(key); return true; } + + [ContractMethod(0_00100000, CallFlags.AllowModifyStates)] + private bool SetFeeRatio(ApplicationEngine engine, uint value) + { + if (value == 0 || value > MaximumRatio) 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; + } } } diff --git a/src/neo/SmartContract/Native/Tokens/NeoToken.cs b/src/neo/SmartContract/Native/Tokens/NeoToken.cs index 956f78d481..56f61d22f4 100644 --- a/src/neo/SmartContract/Native/Tokens/NeoToken.cs +++ b/src/neo/SmartContract/Native/Tokens/NeoToken.cs @@ -181,7 +181,7 @@ protected override void PostPersist(ApplicationEngine engine) } } - [ContractMethod(0_05000000, CallFlags.AllowModifyStates)] + [ContractMethod(0_00166667, CallFlags.AllowModifyStates)] private bool SetGasPerBlock(ApplicationEngine engine, BigInteger gasPerBlock) { if (gasPerBlock < 0 || gasPerBlock > 10 * GAS.Factor) @@ -194,7 +194,7 @@ private bool SetGasPerBlock(ApplicationEngine engine, BigInteger gasPerBlock) return true; } - [ContractMethod(0_01000000, CallFlags.AllowStates)] + [ContractMethod(0_00033333, CallFlags.AllowStates)] public BigInteger GetGasPerBlock(StoreView snapshot) { return GetSortedGasRecords(snapshot, snapshot.PersistingBlock.Index).First().GasPerBlock; @@ -208,7 +208,7 @@ public BigInteger GetGasPerBlock(StoreView snapshot) .Select(u => (BinaryPrimitives.ReadUInt32BigEndian(u.Key.Key.AsSpan(^sizeof(uint))), (BigInteger)u.Value)); } - [ContractMethod(0_03000000, CallFlags.AllowStates)] + [ContractMethod(0_00100000, CallFlags.AllowStates)] public BigInteger UnclaimedGas(StoreView snapshot, UInt160 account, uint end) { StorageItem storage = snapshot.Storages.TryGet(CreateStorageKey(Prefix_Account).Add(account)); @@ -217,7 +217,7 @@ public BigInteger UnclaimedGas(StoreView snapshot, UInt160 account, uint end) return CalculateBonus(snapshot, state.VoteTo, state.Balance, state.BalanceHeight, end); } - [ContractMethod(0_05000000, CallFlags.AllowModifyStates)] + [ContractMethod(0_00166667, CallFlags.AllowModifyStates)] private bool RegisterCandidate(ApplicationEngine engine, ECPoint pubkey) { if (!engine.CheckWitnessInternal(Contract.CreateSignatureRedeemScript(pubkey).ToScriptHash())) @@ -229,7 +229,7 @@ private bool RegisterCandidate(ApplicationEngine engine, ECPoint pubkey) return true; } - [ContractMethod(0_05000000, CallFlags.AllowModifyStates)] + [ContractMethod(0_00166667, CallFlags.AllowModifyStates)] private bool UnregisterCandidate(ApplicationEngine engine, ECPoint pubkey) { if (!engine.CheckWitnessInternal(Contract.CreateSignatureRedeemScript(pubkey).ToScriptHash())) @@ -243,7 +243,7 @@ private bool UnregisterCandidate(ApplicationEngine engine, ECPoint pubkey) return true; } - [ContractMethod(0_05000000, CallFlags.AllowModifyStates)] + [ContractMethod(0_00166667, CallFlags.AllowModifyStates)] private bool Vote(ApplicationEngine engine, UInt160 account, ECPoint voteTo) { if (!engine.CheckWitnessInternal(account)) return false; @@ -281,7 +281,7 @@ private bool Vote(ApplicationEngine engine, UInt160 account, ECPoint voteTo) return true; } - [ContractMethod(1_00000000, CallFlags.AllowStates)] + [ContractMethod(0_03333333, CallFlags.AllowStates)] public (ECPoint PublicKey, BigInteger Votes)[] GetCandidates(StoreView snapshot) { byte[] prefix_key = CreateStorageKey(Prefix_Candidate).ToArray(); @@ -292,7 +292,7 @@ private bool Vote(ApplicationEngine engine, UInt160 account, ECPoint voteTo) )).Where(p => p.Item2.Registered).Select(p => (p.Item1, p.Item2.Votes)).ToArray(); } - [ContractMethod(1_00000000, CallFlags.AllowStates)] + [ContractMethod(0_03333333, CallFlags.AllowStates)] public ECPoint[] GetCommittee(StoreView snapshot) { return GetCommitteeFromCache(snapshot).Select(p => p.PublicKey).OrderBy(p => p).ToArray(); @@ -324,7 +324,7 @@ internal ECPoint[] ComputeNextBlockValidators(StoreView snapshot) return candidates.OrderByDescending(p => p.Votes).ThenBy(p => p.PublicKey).Take(ProtocolSettings.Default.CommitteeMembersCount); } - [ContractMethod(1_00000000, CallFlags.AllowStates)] + [ContractMethod(0_03333333, CallFlags.AllowStates)] public ECPoint[] GetNextBlockValidators(StoreView snapshot) { return GetCommitteeFromCache(snapshot) diff --git a/src/neo/SmartContract/Native/Tokens/Nep5Token.cs b/src/neo/SmartContract/Native/Tokens/Nep5Token.cs index a2337b1c25..6c909bb0d5 100644 --- a/src/neo/SmartContract/Native/Tokens/Nep5Token.cs +++ b/src/neo/SmartContract/Native/Tokens/Nep5Token.cs @@ -88,7 +88,7 @@ internal protected virtual void Burn(ApplicationEngine engine, UInt160 account, engine.SendNotification(Hash, "Transfer", new Array { account.ToArray(), StackItem.Null, amount }); } - [ContractMethod(0_01000000, CallFlags.AllowStates)] + [ContractMethod(0_00033333, CallFlags.AllowStates)] public virtual BigInteger TotalSupply(StoreView snapshot) { StorageItem storage = snapshot.Storages.TryGet(CreateStorageKey(Prefix_TotalSupply)); @@ -96,7 +96,7 @@ public virtual BigInteger TotalSupply(StoreView snapshot) return storage; } - [ContractMethod(0_01000000, CallFlags.AllowStates)] + [ContractMethod(0_00033333, CallFlags.AllowStates)] public virtual BigInteger BalanceOf(StoreView snapshot, UInt160 account) { StorageItem storage = snapshot.Storages.TryGet(CreateStorageKey(Prefix_Account).Add(account)); @@ -104,7 +104,7 @@ public virtual BigInteger BalanceOf(StoreView snapshot, UInt160 account) return storage.GetInteroperable().Balance; } - [ContractMethod(0_08000000, CallFlags.AllowModifyStates)] + [ContractMethod(0_00266667, CallFlags.AllowModifyStates)] protected virtual bool Transfer(ApplicationEngine engine, UInt160 from, UInt160 to, BigInteger amount) { if (amount.Sign < 0) throw new ArgumentOutOfRangeException(nameof(amount)); diff --git a/src/neo/Wallets/AssetDescriptor.cs b/src/neo/Wallets/AssetDescriptor.cs index 9f6a4d4c18..748c682632 100644 --- a/src/neo/Wallets/AssetDescriptor.cs +++ b/src/neo/Wallets/AssetDescriptor.cs @@ -1,4 +1,7 @@ +using Neo.Ledger; +using Neo.Persistence; using Neo.SmartContract; +using Neo.SmartContract.Native; using Neo.VM; using System; @@ -19,7 +22,8 @@ public AssetDescriptor(UInt160 asset_id) sb.EmitAppCall(asset_id, "name"); script = sb.ToArray(); } - using ApplicationEngine engine = ApplicationEngine.Run(script, gas: 3_000_000); + using SnapshotView snapshot = Blockchain.Singleton.GetSnapshot(); + using ApplicationEngine engine = ApplicationEngine.Run(script, snapshot, gas: 100_000 * NativeContract.Policy.GetFeeRatio(snapshot)); if (engine.State.HasFlag(VMState.FAULT)) throw new ArgumentException(); this.AssetId = asset_id; this.AssetName = engine.ResultStack.Pop().GetString(); diff --git a/src/neo/Wallets/Wallet.cs b/src/neo/Wallets/Wallet.cs index 603c6a50a6..5e18964404 100644 --- a/src/neo/Wallets/Wallet.cs +++ b/src/neo/Wallets/Wallet.cs @@ -145,7 +145,8 @@ public BigDecimal GetBalance(UInt160 asset_id, params UInt160[] accounts) sb.EmitAppCall(asset_id, "decimals"); script = sb.ToArray(); } - using ApplicationEngine engine = ApplicationEngine.Run(script, gas: 20000000L * accounts.Length); + using SnapshotView snapshot = Blockchain.Singleton.GetSnapshot(); + using ApplicationEngine engine = ApplicationEngine.Run(script, snapshot, gas: 666667L * NativeContract.Policy.GetFeeRatio(snapshot) * accounts.Length); if (engine.State.HasFlag(VMState.FAULT)) return new BigDecimal(0, 0); byte decimals = (byte)engine.ResultStack.Pop().GetInteger(); @@ -369,6 +370,7 @@ public long CalculateNetworkFee(StoreView snapshot, Transaction tx) // base size for transaction: includes const_header + signers + attributes + script + hashes int size = Transaction.HeaderSize + tx.Signers.GetVarSize() + tx.Attributes.GetVarSize() + tx.Script.GetVarSize() + IO.Helper.GetVarSize(hashes.Length); long networkFee = 0; + long networkFeeWithoutRatio = 0; foreach (UInt160 hash in hashes) { byte[] witness_script = GetAccount(hash)?.Contract?.Script; @@ -411,26 +413,26 @@ public long CalculateNetworkFee(StoreView snapshot, Transaction tx) else if (witness_script.IsSignatureContract()) { size += 67 + witness_script.GetVarSize(); - networkFee += ApplicationEngine.OpCodePrices[OpCode.PUSHDATA1] + ApplicationEngine.OpCodePrices[OpCode.PUSHDATA1] + ApplicationEngine.OpCodePrices[OpCode.PUSHNULL] + ApplicationEngine.ECDsaVerifyPrice; + networkFeeWithoutRatio += ApplicationEngine.OpCodePrices[OpCode.PUSHDATA1] + ApplicationEngine.OpCodePrices[OpCode.PUSHDATA1] + ApplicationEngine.OpCodePrices[OpCode.PUSHNULL] + ApplicationEngine.ECDsaVerifyPrice; } else if (witness_script.IsMultiSigContract(out int m, out int n)) { int size_inv = 66 * m; size += IO.Helper.GetVarSize(size_inv) + size_inv + witness_script.GetVarSize(); - networkFee += ApplicationEngine.OpCodePrices[OpCode.PUSHDATA1] * m; + networkFeeWithoutRatio += ApplicationEngine.OpCodePrices[OpCode.PUSHDATA1] * m; using (ScriptBuilder sb = new ScriptBuilder()) - networkFee += ApplicationEngine.OpCodePrices[(OpCode)sb.EmitPush(m).ToArray()[0]]; - networkFee += ApplicationEngine.OpCodePrices[OpCode.PUSHDATA1] * n; + networkFeeWithoutRatio += ApplicationEngine.OpCodePrices[(OpCode)sb.EmitPush(m).ToArray()[0]]; + networkFeeWithoutRatio += ApplicationEngine.OpCodePrices[OpCode.PUSHDATA1] * n; using (ScriptBuilder sb = new ScriptBuilder()) - networkFee += ApplicationEngine.OpCodePrices[(OpCode)sb.EmitPush(n).ToArray()[0]]; - networkFee += ApplicationEngine.OpCodePrices[OpCode.PUSHNULL] + ApplicationEngine.ECDsaVerifyPrice * n; + networkFeeWithoutRatio += ApplicationEngine.OpCodePrices[(OpCode)sb.EmitPush(n).ToArray()[0]]; + networkFeeWithoutRatio += ApplicationEngine.OpCodePrices[OpCode.PUSHNULL] + ApplicationEngine.ECDsaVerifyPrice * n; } else { //We can support more contract types in the future. } } - networkFee += size * NativeContract.Policy.GetFeePerByte(snapshot); + networkFee += size * NativeContract.Policy.GetFeePerByte(snapshot) + networkFeeWithoutRatio * NativeContract.Policy.GetFeeRatio(snapshot); return networkFee; } diff --git a/tests/neo.UnitTests/Network/P2P/Payloads/UT_Transaction.cs b/tests/neo.UnitTests/Network/P2P/Payloads/UT_Transaction.cs index c8e4c4e028..a64abe056d 100644 --- a/tests/neo.UnitTests/Network/P2P/Payloads/UT_Transaction.cs +++ b/tests/neo.UnitTests/Network/P2P/Payloads/UT_Transaction.cs @@ -176,9 +176,9 @@ public void FeeIsMultiSigContract() } var sizeGas = tx.Size * NativeContract.Policy.GetFeePerByte(snapshot); - Assert.AreEqual(2000810, verificationGas); + Assert.AreEqual(2000790, verificationGas); Assert.AreEqual(347000, sizeGas); - Assert.AreEqual(2347810, tx.NetworkFee); + Assert.AreEqual(2347790, tx.NetworkFee); } } @@ -219,7 +219,7 @@ public void FeeIsSignatureContractDetailed() Assert.IsNull(tx.Witnesses); // check pre-computed network fee (already guessing signature sizes) - tx.NetworkFee.Should().Be(1244390L); + tx.NetworkFee.Should().Be(1244380L); // ---- // Sign @@ -256,7 +256,7 @@ public void FeeIsSignatureContractDetailed() verificationGas += engine.GasConsumed; } } - Assert.AreEqual(verificationGas, 1000390); + Assert.AreEqual(verificationGas, 1000380); // ------------------ // check tx_size cost @@ -285,7 +285,7 @@ public void FeeIsSignatureContractDetailed() // final check: verification_cost and tx_size Assert.AreEqual(244000, sizeGas); - Assert.AreEqual(1000390, verificationGas); + Assert.AreEqual(1000380, verificationGas); // final assert Assert.AreEqual(tx.NetworkFee, verificationGas + sizeGas); @@ -372,7 +372,7 @@ public void FeeIsSignatureContract_TestScope_Global() // get sizeGas var sizeGas = tx.Size * NativeContract.Policy.GetFeePerByte(snapshot); // final check on sum: verification_cost + tx_size - Assert.AreEqual(1244390, verificationGas + sizeGas); + Assert.AreEqual(1244380, verificationGas + sizeGas); // final assert Assert.AreEqual(tx.NetworkFee, verificationGas + sizeGas); } @@ -459,7 +459,7 @@ public void FeeIsSignatureContract_TestScope_CurrentHash_GAS() // get sizeGas var sizeGas = tx.Size * NativeContract.Policy.GetFeePerByte(snapshot); // final check on sum: verification_cost + tx_size - Assert.AreEqual(1265390, verificationGas + sizeGas); + Assert.AreEqual(1265380, verificationGas + sizeGas); // final assert Assert.AreEqual(tx.NetworkFee, verificationGas + sizeGas); } @@ -549,7 +549,7 @@ public void FeeIsSignatureContract_TestScope_CalledByEntry_Plus_GAS() // get sizeGas var sizeGas = tx.Size * NativeContract.Policy.GetFeePerByte(snapshot); // final check on sum: verification_cost + tx_size - Assert.AreEqual(1265390, verificationGas + sizeGas); + Assert.AreEqual(1265380, verificationGas + sizeGas); // final assert Assert.AreEqual(tx.NetworkFee, verificationGas + sizeGas); } @@ -691,7 +691,7 @@ public void FeeIsSignatureContract_TestScope_CurrentHash_NEO_GAS() // get sizeGas var sizeGas = tx.Size * NativeContract.Policy.GetFeePerByte(snapshot); // final check on sum: verification_cost + tx_size - Assert.AreEqual(1285390, verificationGas + sizeGas); + Assert.AreEqual(1285380, verificationGas + sizeGas); // final assert Assert.AreEqual(tx.NetworkFee, verificationGas + sizeGas); } @@ -1041,7 +1041,7 @@ public void FeeIsSignatureContract_TestScope_FeeOnly_Default() // get sizeGas var sizeGas = tx.Size * NativeContract.Policy.GetFeePerByte(snapshot); // final check on sum: verification_cost + tx_size - Assert.AreEqual(1244390, verificationGas + sizeGas); + Assert.AreEqual(1244380, verificationGas + sizeGas); // final assert Assert.AreEqual(tx.NetworkFee, verificationGas + sizeGas); } @@ -1260,9 +1260,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().Balance = 10000 * NativeContract.GAS.Factor; + entry.GetInteroperable().Balance = NativeContract.GAS.Factor / 10; + + snapshot.Commit(); + //Change FeeRatio + StorageItem storage = snapshot.Storages.GetAndChange(new KeyBuilder(-3, 34), () => new StorageItem()); + storage.Set(15); snapshot.Commit(); + NativeContract.Policy.GetFeeRatio(snapshot).Should().Be(15); // Make transaction @@ -1285,6 +1291,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)) + { + 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(30); + snapshot.Commit(); + NativeContract.Policy.GetFeeRatio(snapshot).Should().Be(30); } } } diff --git a/tests/neo.UnitTests/SmartContract/UT_InteropPrices.cs b/tests/neo.UnitTests/SmartContract/UT_InteropPrices.cs index fbea2b839d..7674ad218e 100644 --- a/tests/neo.UnitTests/SmartContract/UT_InteropPrices.cs +++ b/tests/neo.UnitTests/SmartContract/UT_InteropPrices.cs @@ -23,7 +23,7 @@ public void ApplicationEngineFixedPrices() using (ApplicationEngine ae = ApplicationEngine.Create(TriggerType.Application, null, null, 0)) { ae.LoadScript(SyscallSystemRuntimeCheckWitnessHash); - ApplicationEngine.System_Runtime_CheckWitness.FixedPrice.Should().Be(0_00030000L); + ApplicationEngine.System_Runtime_CheckWitness.FixedPrice.Should().Be(0_00001000L); } // System.Storage.GetContext: 9bf667ce (price is 1) @@ -31,7 +31,7 @@ public void ApplicationEngineFixedPrices() using (ApplicationEngine ae = ApplicationEngine.Create(TriggerType.Application, null, null, 0)) { ae.LoadScript(SyscallSystemStorageGetContextHash); - ApplicationEngine.System_Storage_GetContext.FixedPrice.Should().Be(0_00000400L); + ApplicationEngine.System_Storage_GetContext.FixedPrice.Should().Be(0_00000013L); } // System.Storage.Get: 925de831 (price is 100) @@ -39,7 +39,7 @@ public void ApplicationEngineFixedPrices() using (ApplicationEngine ae = ApplicationEngine.Create(TriggerType.Application, null, null, 0)) { ae.LoadScript(SyscallSystemStorageGetHash); - ApplicationEngine.System_Storage_Get.FixedPrice.Should().Be(0_01000000L); + ApplicationEngine.System_Storage_Get.FixedPrice.Should().Be(0_00033333L); } } diff --git a/tests/neo.UnitTests/SmartContract/UT_Syscalls.cs b/tests/neo.UnitTests/SmartContract/UT_Syscalls.cs index b69c5f4759..b757260015 100644 --- a/tests/neo.UnitTests/SmartContract/UT_Syscalls.cs +++ b/tests/neo.UnitTests/SmartContract/UT_Syscalls.cs @@ -287,7 +287,7 @@ public void System_Runtime_GasLeft() CollectionAssert.AreEqual ( engine.ResultStack.Select(u => (int)u.GetInteger()).ToArray(), - new int[] { 99_999_570, 99_999_140, 99_998_650 } + new int[] { 99_999_580, 99_999_160, 99_998_680 } ); } @@ -307,7 +307,7 @@ public void System_Runtime_GasLeft() Assert.AreEqual(engine.Execute(), VMState.HALT); Assert.AreEqual(1, engine.ResultStack.Count); Assert.IsInstanceOfType(engine.ResultStack.Peek(), typeof(Integer)); - Assert.AreEqual(1999999600, engine.ResultStack.Pop().GetInteger()); + Assert.AreEqual(1999999620, engine.ResultStack.Pop().GetInteger()); } }