// Add in sigops done by pay-to-script-hash inputs;
// this is to prevent a "rogue miner" from creating
// an incredibly-expensive-to-validate block.
- nSigOps += tx.GetP2SHSigOpCount(inputs);
+ nSigOps += tx.GetP2SHSigOpCount(ref inputs);
if (nSigOps > CBlock.nMaxSigOps)
{
return false; // too many sigops
}
- ulong nTxValueIn = tx.GetValueIn(inputs);
+ ulong nTxValueIn = tx.GetValueIn(ref inputs);
ulong nTxValueOut = tx.nValueOut;
nValueIn += nTxValueIn;
namespace Novacoin
{
- public class COutPoint : IComparable<COutPoint>, IEquatable<COutPoint>
+ public class COutPoint : IComparable<COutPoint>, IEquatable<COutPoint>, IEqualityComparer<COutPoint>
{
/// <summary>
/// Hash of parent transaction.
return (o.n == n) && (o.hash == hash);
}
+
+ /// <summary>
+ /// Equality comparer for outpoints.
+ /// </summary>
+ /// <param name="x">First outpoint.</param>
+ /// <param name="y">Second outpoint.</param>
+ /// <returns>Result of comparison.</returns>
+ public bool Equals(COutPoint x, COutPoint y)
+ {
+ return (x.n == y.n) && (x.hash == y.hash);
+ }
+
+ public override int GetHashCode()
+ {
+ return n.GetHashCode() ^ hash.GetHashCode();
+ }
+
+ public int GetHashCode(COutPoint obj)
+ {
+ return obj.GetHashCode();
+ }
}
}
}
return true;
}
-
+
/// <summary>
/// Parse byte sequence and initialize new instance of CTransaction
/// </summary>
public static bool MoneyRange(ulong nValue) { return (nValue <= nMaxMoney); }
- internal uint GetP2SHSigOpCount(Dictionary<COutPoint, TxOutItem> inputs)
+ /// <summary>
+ /// Get total sigops.
+ /// </summary>
+ /// <param name="inputs">Inputs map.</param>
+ /// <returns>Amount of sigops.</returns>
+ public uint GetP2SHSigOpCount(ref Dictionary<COutPoint, TxOutItem> inputs)
+ {
+ if (IsCoinBase)
+ {
+ return 0;
+ }
+
+ uint nSigOps = 0;
+ for (var i = 0; i < vin.Length; i++)
+ {
+ var prevout = GetOutputFor(vin[i], ref inputs);
+ if (prevout.scriptPubKey.IsPayToScriptHash)
+ {
+ nSigOps += prevout.scriptPubKey.GetSigOpCount(vin[i].scriptSig);
+ }
+ }
+
+ return nSigOps;
+ }
+
+ /// <summary>
+ /// Get sum of inputs spent by this transaction.
+ /// </summary>
+ /// <param name="inputs">Reference to innputs map.</param>
+ /// <returns>Sum of inputs.</returns>
+ public ulong GetValueIn(ref Dictionary<COutPoint, TxOutItem> inputs)
{
- throw new NotImplementedException();
+ if (IsCoinBase)
+ {
+ return 0;
+ }
+
+ ulong nResult = 0;
+ for (int i = 0; i < vin.Length; i++)
+ {
+ nResult += GetOutputFor(vin[i], ref inputs).nValue;
+ }
+
+ return nResult;
}
- internal ulong GetValueIn(Dictionary<COutPoint, TxOutItem> inputs)
+ /// <summary>
+ /// Helper method to find output in the map.
+ /// </summary>
+ /// <param name="input">Transaction input.</param>
+ /// <param name="inputs">eference to inuts map.</param>
+ /// <returns>Parent output.</returns>
+ private CTxOut GetOutputFor(CTxIn input, ref Dictionary<COutPoint, TxOutItem> inputs)
{
- throw new NotImplementedException();
+ if (!inputs.ContainsKey(input.prevout))
+ {
+ throw new Exception("No such input");
+ }
+
+ var outItem = inputs[input.prevout];
+
+ return new CTxOut(outItem.nValue, outItem.scriptPubKey);
}
+
}
}