From: CryptoManiac Date: Fri, 21 Aug 2015 12:15:34 +0000 (+0300) Subject: COutPoint class, coinbase/coinstake properties X-Git-Url: https://git.novaco.in/?p=NovacoinLibrary.git;a=commitdiff_plain;h=12a559c6cb61ae1c22e2859742ea0edd552eca07 COutPoint class, coinbase/coinstake properties --- diff --git a/Novacoin/COutPoint.cs b/Novacoin/COutPoint.cs new file mode 100644 index 0000000..4c9f17a --- /dev/null +++ b/Novacoin/COutPoint.cs @@ -0,0 +1,73 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Novacoin +{ + public class COutPoint + { + /// + /// Hash of parent transaction. + /// + public Hash256 hash; + + /// + /// Parent input number. + /// + public uint n; + + public COutPoint() + { + hash = new Hash256(); + n = uint.MaxValue; + } + + public COutPoint(Hash256 hashIn, uint nIn) + { + hash = hashIn; + n = nIn; + } + + public COutPoint(COutPoint o) + { + hash = new Hash256(o.hash); + n = o.n; + } + + public COutPoint(IEnumerable bytes) + { + hash = new Hash256(bytes.Take(32)); + n = BitConverter.ToUInt32(bytes.Skip(32).Take(4).ToArray(), 0); + } + + public bool IsNull + { + get { return hash.IsZero && n == uint.MaxValue; } + } + + public IList Bytes + { + get + { + List r = new List(); + r.AddRange(hash.hashBytes); + r.AddRange(BitConverter.GetBytes(n)); + + return r; + } + } + + public override string ToString() + { + StringBuilder sb = new StringBuilder(); + sb.AppendFormat("COutPoint({0}, {1})", hash.ToString(), n); + + return sb.ToString(); + } + + + } + +} diff --git a/Novacoin/CScript.cs b/Novacoin/CScript.cs index 835c53d..4223791 100644 --- a/Novacoin/CScript.cs +++ b/Novacoin/CScript.cs @@ -174,7 +174,6 @@ namespace Novacoin /// /// Is it true that script doesn't contain anything except push value operations? /// - /// Checking result public bool IsPushonly { get @@ -201,7 +200,6 @@ namespace Novacoin /// /// Is it true that script doesn't contain non-canonical push operations? /// - /// Checking result public bool HasOnlyCanonicalPushes { get @@ -245,7 +243,6 @@ namespace Novacoin /// /// Quick test for pay-to-script-hash CScripts /// - /// Checking result public bool IsPayToScriptHash { get @@ -262,7 +259,6 @@ namespace Novacoin /// /// Quick test for pay-to-pubkeyhash CScripts /// - /// Checking result public bool IsPayToPubKeyHash { get @@ -279,6 +275,14 @@ namespace Novacoin } /// + /// Quick test for Null destination + /// + public bool IsNull + { + get { return codeBytes.Count == 0; } + } + + /// /// Pre-version-0.6, Bitcoin always counted CHECKMULTISIGs /// as 20 sigops. With pay-to-script-hash, that changed: /// CHECKMULTISIGs serialized in scriptSigs are diff --git a/Novacoin/CTransaction.cs b/Novacoin/CTransaction.cs index 8fba084..1c58089 100644 --- a/Novacoin/CTransaction.cs +++ b/Novacoin/CTransaction.cs @@ -4,35 +4,35 @@ using System.Collections.Generic; namespace Novacoin { - /// - /// Represents the transaction. Any transaction must provide one input and one output at least. - /// - public class CTransaction - { - /// - /// Version of transaction schema. - /// - public uint nVersion = 1; - - /// - /// Transaction timestamp. - /// - public uint nTime = 0; - - /// - /// Array of transaction inputs - /// - public CTxIn[] vin; - - /// - /// Array of transaction outputs - /// - public CTxOut[] vout; - - /// - /// Block height or timestamp when transaction is final - /// - public uint nLockTime = 0; + /// + /// Represents the transaction. Any transaction must provide one input and one output at least. + /// + public class CTransaction + { + /// + /// Version of transaction schema. + /// + public uint nVersion = 1; + + /// + /// Transaction timestamp. + /// + public uint nTime = 0; + + /// + /// Array of transaction inputs + /// + public CTxIn[] vin; + + /// + /// Array of transaction outputs + /// + public CTxOut[] vout; + + /// + /// Block height or timestamp when transaction is final + /// + public uint nLockTime = 0; /// /// Initialize an empty instance @@ -77,12 +77,12 @@ namespace Novacoin /// Parse byte sequence and initialize new instance of CTransaction /// /// Byte sequence - public CTransaction (IList txBytes) - { + public CTransaction(IList txBytes) + { WrappedList wBytes = new WrappedList(txBytes); - nVersion = BitConverter.ToUInt32(wBytes.GetItems(4),0); - nTime = BitConverter.ToUInt32(wBytes.GetItems(4),0); + nVersion = BitConverter.ToUInt32(wBytes.GetItems(4), 0); + nTime = BitConverter.ToUInt32(wBytes.GetItems(4), 0); int nInputs = (int)VarInt.ReadVarInt(ref wBytes); vin = new CTxIn[nInputs]; @@ -92,8 +92,7 @@ namespace Novacoin // Fill inputs array vin[nCurrentInput] = new CTxIn(); - vin[nCurrentInput].txID = new Hash256(wBytes.GetItems(32)); - vin[nCurrentInput].n = BitConverter.ToUInt32(wBytes.GetItems(4), 0); + vin[nCurrentInput].prevout = new COutPoint(wBytes.GetItems(36)); int nScriptSigLen = (int)VarInt.ReadVarInt(ref wBytes); vin[nCurrentInput].scriptSig = new CScript(wBytes.GetItems(nScriptSigLen)); @@ -107,14 +106,14 @@ namespace Novacoin { // Fill outputs array vout[nCurrentOutput] = new CTxOut(); - vout[nCurrentOutput].nValue = BitConverter.ToUInt64(wBytes.GetItems(8), 0); + vout[nCurrentOutput].nValue = BitConverter.ToInt64(wBytes.GetItems(8), 0); int nScriptPKLen = (int)VarInt.ReadVarInt(ref wBytes); vout[nCurrentOutput].scriptPubKey = new CScript(wBytes.GetItems(nScriptPKLen)); } nLockTime = BitConverter.ToUInt32(wBytes.GetItems(4), 0); - } + } /// /// Read transactions array which is encoded in the block body. @@ -124,9 +123,9 @@ namespace Novacoin public static CTransaction[] ReadTransactionsList(ref WrappedList wTxBytes) { CTransaction[] tx; - + // Read amount of transactions - int nTransactions = (int) VarInt.ReadVarInt(ref wTxBytes); + int nTransactions = (int)VarInt.ReadVarInt(ref wTxBytes); tx = new CTransaction[nTransactions]; for (int nTx = 0; nTx < nTransactions; nTx++) @@ -149,6 +148,20 @@ namespace Novacoin return tx; } + public bool IsCoinBase + { + get { return (vin.Length == 1 && vin[0].prevout.IsNull && vout.Length >= 1); } + } + + public bool IsCoinStake + { + get + { + return (vin.Length > 0 && (!vin[0].prevout.IsNull) && vout.Length >= 2 && vout[0].IsEmpty); + } + } + + public IList Bytes { get diff --git a/Novacoin/CTxIn.cs b/Novacoin/CTxIn.cs index 9983c65..671a0a1 100644 --- a/Novacoin/CTxIn.cs +++ b/Novacoin/CTxIn.cs @@ -9,15 +9,10 @@ namespace Novacoin /// public class CTxIn { - /// - /// Hash of parent transaction. - /// - public Hash256 txID; - - /// - /// Parent input number. - /// - public uint n = 0; + /// + /// Previous input data + /// + public COutPoint prevout; /// /// First half of script, signatures for the scriptPubKey @@ -35,8 +30,7 @@ namespace Novacoin /// CTxIn instance. public CTxIn(CTxIn i) { - txID = i.txID; - n = i.n; + prevout = new COutPoint(i.prevout); scriptSig = i.scriptSig; nSequence = i.nSequence; } @@ -46,7 +40,7 @@ namespace Novacoin /// public CTxIn() { - txID = new Hash256(); + prevout = new COutPoint(); scriptSig = new CScript(); } @@ -67,9 +61,7 @@ namespace Novacoin { // Fill inputs array vin[nIndex] = new CTxIn(); - - vin[nIndex].txID = new Hash256(wBytes.GetItems(32)); - vin[nIndex].n = BitConverter.ToUInt32(wBytes.GetItems(4), 0); + vin[nIndex].prevout = new COutPoint(wBytes.GetItems(36)); vin[nIndex].scriptSig = new CScript(wBytes.GetItems((int)VarInt.ReadVarInt(ref wBytes))); vin[nIndex].nSequence = BitConverter.ToUInt32(wBytes.GetItems(4), 0); } @@ -88,8 +80,7 @@ namespace Novacoin { List inputBytes = new List(); - inputBytes.AddRange(txID.hashBytes); // Input transaction id - inputBytes.AddRange(BitConverter.GetBytes(n)); // Output number + inputBytes.AddRange(prevout.Bytes); // prevout List s = new List(scriptSig.Bytes); @@ -101,15 +92,15 @@ namespace Novacoin } } - public bool IsCoinBase + public bool IsFinal { - get { return txID.IsZero; } + get { return (nSequence == uint.MaxValue); } } - - public override string ToString () + public override string ToString () { StringBuilder sb = new StringBuilder (); + /* if (IsCoinBase) { sb.AppendFormat("CTxIn(txId={0}, coinbase={2}, nSequence={3})", txID.ToString(), n, Interop.ToHex(scriptSig.Bytes), nSequence); @@ -118,8 +109,30 @@ namespace Novacoin { sb.AppendFormat("CTxIn(txId={0}, n={1}, scriptSig={2}, nSequence={3})", txID.ToString(), n, scriptSig.ToString(), nSequence); } + */ + + + sb.AppendFormat("CTxIn("); + sb.Append(prevout.ToString()); + + if(prevout.IsNull) + { + sb.AppendFormat(", coinbase={0}", Interop.ToHex(scriptSig.Bytes)); + } + else + { + sb.AppendFormat(", scriptsig={0}", scriptSig.ToString()); + } + + if (nSequence != uint.MaxValue) + { + sb.AppendFormat(", nSequence={0}", nSequence); + } + + sb.Append(")"); + - return sb.ToString (); + return sb.ToString (); } } diff --git a/Novacoin/CTxOut.cs b/Novacoin/CTxOut.cs index 920fcd5..3e3d4c1 100644 --- a/Novacoin/CTxOut.cs +++ b/Novacoin/CTxOut.cs @@ -12,7 +12,7 @@ namespace Novacoin /// /// Input value. /// - public ulong nValue; + public long nValue = -1; /// /// Second half of script which contains spending instructions. @@ -81,6 +81,28 @@ namespace Novacoin } } + public void SetNull() + { + nValue = -1; + scriptPubKey.SetNullDestination(); + } + + public void SetEmpty() + { + nValue = 0; + scriptPubKey.SetNullDestination(); + } + + public bool IsNull + { + get { return (nValue == -1); } + } + + public bool IsEmpty + { + get { return nValue == 0 && scriptPubKey.IsNull; } + } + public override string ToString () { StringBuilder sb = new StringBuilder (); diff --git a/Novacoin/Hash.cs b/Novacoin/Hash.cs index 8cf0b55..fbff17f 100644 --- a/Novacoin/Hash.cs +++ b/Novacoin/Hash.cs @@ -53,6 +53,7 @@ namespace Novacoin public Hash(Hash h) { + _hashBytes = new byte[h.hashSize]; h._hashBytes.CopyTo(_hashBytes, 0); } diff --git a/Novacoin/Novacoin.csproj b/Novacoin/Novacoin.csproj index 6f13cc7..0c94140 100644 --- a/Novacoin/Novacoin.csproj +++ b/Novacoin/Novacoin.csproj @@ -42,6 +42,7 @@ +