From c4aad1332d39a5bdd66e9e8004932dc99baf44e5 Mon Sep 17 00:00:00 2001 From: CryptoManiac Date: Tue, 8 Sep 2015 00:30:19 +0300 Subject: [PATCH] GetMinTxFee & use unsigned int for sizes. --- Novacoin/CBlock.cs | 10 +++--- Novacoin/CBlockStore.cs | 3 +- Novacoin/CScript.cs | 6 ++-- Novacoin/CTransaction.cs | 82 ++++++++++++++++++++++++++++++++++++++++-- Novacoin/CTxIn.cs | 4 +- Novacoin/CTxOut.cs | 2 +- Novacoin/DatabaseObjects.cs | 6 ++-- Novacoin/VarInt.cs | 2 +- 8 files changed, 94 insertions(+), 21 deletions(-) diff --git a/Novacoin/CBlock.cs b/Novacoin/CBlock.cs index 6c10d6e..afc3e48 100644 --- a/Novacoin/CBlock.cs +++ b/Novacoin/CBlock.cs @@ -382,18 +382,18 @@ namespace Novacoin /// /// Serialized size /// - public int Size + public uint Size { get { - int nSize = 80 + VarInt.GetEncodedSize(vtx.Length); // CBlockHeader + NumTx + uint nSize = 80 + VarInt.GetEncodedSize(vtx.Length); // CBlockHeader + NumTx foreach (var tx in vtx) { nSize += tx.Size; } - nSize += VarInt.GetEncodedSize(signature.Length) + signature.Length; + nSize += VarInt.GetEncodedSize(signature.Length) + (uint)signature.Length; return nSize; } @@ -404,11 +404,11 @@ namespace Novacoin /// /// Transaction index. /// Offset in bytes from the beginning of block header. - public int GetTxOffset(int nTx) + public uint GetTxOffset(int nTx) { Contract.Requires(nTx >= 0 && nTx < vtx.Length, "Transaction index you've specified is incorrect."); - int nOffset = 80 + VarInt.GetEncodedSize(vtx.Length); // CBlockHeader + NumTx + uint nOffset = 80 + VarInt.GetEncodedSize(vtx.Length); // CBlockHeader + NumTx for (int i = 0; i < nTx; i++) { diff --git a/Novacoin/CBlockStore.cs b/Novacoin/CBlockStore.cs index 97ce54e..e1d1994 100644 --- a/Novacoin/CBlockStore.cs +++ b/Novacoin/CBlockStore.cs @@ -904,10 +904,9 @@ namespace Novacoin return false; // unable to get coin age for coinstake } - int nTxSize = (tx.nTime > NetInfo.nStakeValidationSwitchTime) ? tx.Size : 0; ulong nReward = tx.nValueOut - nValueIn; - ulong nCalculatedReward = CBlock.GetProofOfStakeReward(nCoinAge, cursorBlock.nBits, tx.nTime) - CTransaction.GetMinFee(1, false, CTransaction.MinFeeMode.GMF_BLOCK, nTxSize) + CTransaction.nCent; + ulong nCalculatedReward = CBlock.GetProofOfStakeReward(nCoinAge, cursorBlock.nBits, tx.nTime) - tx.GetMinFee(1, false, CTransaction.MinFeeMode.GMF_BLOCK) + CTransaction.nCent; if (nReward > nCalculatedReward) { diff --git a/Novacoin/CScript.cs b/Novacoin/CScript.cs index d27b337..2ac0c73 100644 --- a/Novacoin/CScript.cs +++ b/Novacoin/CScript.cs @@ -402,7 +402,7 @@ namespace Novacoin // get the last item that the scriptSig // pushes onto the stack: InstructionQueue wScriptSig = scriptSig.GetInstructionQueue(); - int nScriptSigSize = scriptSig.Size; + uint nScriptSigSize = scriptSig.Size; instruction opcode; // Current instruction byte[] pushArgs = new byte[0]; // OP_PUSHDATAn argument @@ -512,9 +512,9 @@ namespace Novacoin /// /// Script size /// - public int Size + public uint Size { - get { return codeBytes.Count; } + get { return (uint) codeBytes.Count; } } public CScriptID ScriptID diff --git a/Novacoin/CTransaction.cs b/Novacoin/CTransaction.cs index b0d4f08..3ebde5f 100644 --- a/Novacoin/CTransaction.cs +++ b/Novacoin/CTransaction.cs @@ -57,11 +57,16 @@ namespace Novacoin /// One coin = 1000000 satoshis. /// public const ulong nCoin = 1000000; + /// /// Sanity checking threshold. /// public const ulong nMaxMoney = 2000000000 * nCoin; + public const ulong nMinTxFee = nCent / 10; + public const ulong nMinRelayTxFee = nCent / 50; + public const ulong nMinTxoutAmount = nCent / 100; + /// /// Maximum transaction size is 250Kb /// @@ -334,11 +339,11 @@ namespace Novacoin /// /// Serialized size /// - public int Size + public uint Size { get { - int nSize = 12; // nVersion, nTime, nLockLime + uint nSize = 12; // nVersion, nTime, nLockLime nSize += VarInt.GetEncodedSize(vin.Length); nSize += VarInt.GetEncodedSize(vout.Length); @@ -557,9 +562,78 @@ namespace Novacoin throw new NotImplementedException(); } - internal static ulong GetMinFee(int v1, bool v2, MinFeeMode gMF_BLOCK, int nTxSize) + public ulong GetMinFee(uint nBlockSize, bool fAllowFree, MinFeeMode mode) { - throw new NotImplementedException(); + ulong nMinTxFee = CTransaction.nMinTxFee, nMinRelayTxFee = CTransaction.nMinRelayTxFee; + uint nBytes = Size; + + if (IsCoinStake) + { + // Enforce 0.01 as minimum fee for old approach or coinstake + nMinTxFee = nCent; + nMinRelayTxFee = nCent; + + if (nTime < NetInfo.nStakeValidationSwitchTime) + { + // Enforce zero size for compatibility with old blocks. + nBytes = 0; + } + } + + // Base fee is either nMinTxFee or nMinRelayTxFee + ulong nBaseFee = (mode == MinFeeMode.GMF_RELAY) ? nMinRelayTxFee : nMinTxFee; + + uint nNewBlockSize = nBlockSize + nBytes; + ulong nMinFee = (1 + (ulong)nBytes / 1000) * nBaseFee; + + if (fAllowFree) + { + if (nBlockSize == 1) + { + // Transactions under 1K are free + if (nBytes < 1000) + nMinFee = 0; + } + else + { + // Free transaction area + if (nNewBlockSize < 27000) + nMinFee = 0; + } + } + + // To limit dust spam, require additional MIN_TX_FEE/MIN_RELAY_TX_FEE for + // each non empty output which is less than 0.01 + // + // It's safe to ignore empty outputs here, because these inputs are allowed + // only for coinbase and coinstake transactions. + foreach (var txout in vout) + { + if (txout.nValue < nCent && !txout.IsEmpty) + { + nMinFee += nBaseFee; + } + } + + var nMaxBlockSizeGen = CBlock.nMaxBlockSize / 2; + + // Raise the price as the block approaches full + if (nBlockSize != 1 && nNewBlockSize >= nMaxBlockSizeGen / 2) + { + if (nNewBlockSize >= nMaxBlockSizeGen) + { + return nMaxMoney; + } + + nMinFee *= nMaxBlockSizeGen / (nMaxBlockSizeGen - nNewBlockSize); + } + + if (!MoneyRange(nMinFee)) + { + nMinFee = nMaxMoney; + } + + return nMinFee; } } } diff --git a/Novacoin/CTxIn.cs b/Novacoin/CTxIn.cs index 94cd8b1..480e1d1 100644 --- a/Novacoin/CTxIn.cs +++ b/Novacoin/CTxIn.cs @@ -115,10 +115,10 @@ namespace Novacoin /// /// Serialized size /// - public int Size + public uint Size { get { - int nSize = 40; // COutPoint, nSequence + uint nSize = 40; // COutPoint, nSequence nSize += VarInt.GetEncodedSize(scriptSig.Size); nSize += scriptSig.Size; diff --git a/Novacoin/CTxOut.cs b/Novacoin/CTxOut.cs index 3017fea..36f4817 100644 --- a/Novacoin/CTxOut.cs +++ b/Novacoin/CTxOut.cs @@ -183,7 +183,7 @@ namespace Novacoin /// /// Serialized size /// - public int Size + public uint Size { get { diff --git a/Novacoin/DatabaseObjects.cs b/Novacoin/DatabaseObjects.cs index a78f93b..b297f6d 100644 --- a/Novacoin/DatabaseObjects.cs +++ b/Novacoin/DatabaseObjects.cs @@ -612,7 +612,7 @@ namespace Novacoin { reader.Seek(nBlockPos + nTxOffset, SeekOrigin.Begin); // Seek to transaction offset - if (nTxSize != reader.Read(buffer, 0, nTxSize)) + if (nTxSize != reader.Read(buffer, 0, (int)nTxSize)) { return false; } @@ -647,9 +647,9 @@ namespace Novacoin /// Transaction size accessor /// [Ignore] - public int nTxSize + public uint nTxSize { - get { return (int)VarInt.DecodeVarInt(TxSize); } + get { return (uint)VarInt.DecodeVarInt(TxSize); } private set { TxSize = VarInt.EncodeVarInt(value); } } diff --git a/Novacoin/VarInt.cs b/Novacoin/VarInt.cs index 614e3c6..ba174e9 100644 --- a/Novacoin/VarInt.cs +++ b/Novacoin/VarInt.cs @@ -83,7 +83,7 @@ namespace Novacoin return EncodeVarInt((ulong)n); } - public static int GetEncodedSize(long n) + public static uint GetEncodedSize(long n) { if (n <= 0xfc) { -- 1.7.1