Print signature for proof-of-stake blocks only
[NovacoinLibrary.git] / Novacoin / CBlock.cs
1 \feffusing System;
2 using System.Text;
3 using System.Collections.Generic;
4
5 namespace Novacoin
6 {
7         /// <summary>
8         /// Represents the block. Block consists of header, transaction array and header signature.
9         /// </summary>
10         public class CBlock
11         {
12                 /// <summary>
13                 /// Block header.
14                 /// </summary>
15                 public CBlockHeader header;
16
17                 /// <summary>
18                 /// Transactions array.
19                 /// </summary>
20                 public CTransaction[] vtx;
21
22         /// <summary>
23         /// Block header signature.
24         /// </summary>
25         public byte[] signature = new byte[0];
26
27         public CBlock(CBlock b)
28         {
29             header = new CBlockHeader(b.header);
30
31             for (int i = 0; i < b.vtx.Length; i++)
32             {
33                 vtx[i] = new CTransaction(b.vtx[i]);
34             }
35
36             b.signature.CopyTo(signature, 0);
37         }
38
39         /// <summary>
40         /// Parse byte sequence and initialize new block instance
41         /// </summary>
42         /// <param name="blockBytes"></param>
43                 public CBlock (IList<byte> blockBytes)
44                 {
45             ByteQueue wBytes = new ByteQueue(blockBytes);
46
47             // Fill the block header fields
48             header = new CBlockHeader(wBytes.Get(80));
49
50             // Parse transactions list
51             vtx = CTransaction.ReadTransactionsList(ref wBytes);
52
53             // Read block signature
54             signature = wBytes.Get((int)wBytes.GetVarInt());
55                 }
56
57         public CBlock()
58         {
59             // Initialize empty array of transactions. Please note that such 
60             // configuration is not valid real block since it has to provide 
61             // at least one transaction.
62             vtx = new CTransaction[0];
63         }
64
65         /// <summary>
66         /// Is this a Proof-of-Stake block?
67         /// </summary>
68         public bool IsProofOfStake
69         {
70             get
71             {
72                 return (vtx.Length > 1 && vtx[1].IsCoinStake);
73             }
74         }
75
76         /// <summary>
77         /// Was this signed correctly?
78         /// </summary>
79         public bool SignatureOK
80         {
81             get
82             {
83                 if (IsProofOfStake)
84                 {
85                     if (signature.Length == 0)
86                     {
87                         return false; // No signature
88                     }
89
90                     txnouttype whichType;
91                     IList<IEnumerable<byte>> solutions;
92
93                     if (!ScriptCode.Solver(vtx[1].vout[1].scriptPubKey, out whichType, out solutions))
94                     {
95                         return false; // No solutions found
96                     }
97
98                     if (whichType == txnouttype.TX_PUBKEY)
99                     {
100                         CPubKey pubkey;
101
102                         try
103                         {
104                             pubkey = new CPubKey(solutions[0]);
105                         }
106                         catch (Exception)
107                         {
108                             return false; // Error while loading public key
109                         }
110
111                         return pubkey.VerifySignature(header.Hash, signature);
112                     }
113                 }
114                 else
115                 {
116                     // Proof-of-Work blocks have no signature
117
118                     return true;
119                 }
120
121                 return false;
122             }
123         }
124
125         /// <summary>
126         /// Get current instance as sequence of bytes
127         /// </summary>
128         /// <returns>Byte sequence</returns>
129         public IList<byte> Bytes 
130         {
131             get
132             {
133                 List<byte> r = new List<byte>();
134
135                 r.AddRange(header.Bytes);
136                 r.AddRange(VarInt.EncodeVarInt(vtx.LongLength)); // transactions count
137
138                 foreach (CTransaction tx in vtx)
139                 {
140                     r.AddRange(tx.Bytes);
141                 }
142
143                 r.AddRange(VarInt.EncodeVarInt(signature.LongLength));
144                 r.AddRange(signature);
145
146                 return r;
147             }
148         }
149
150         public override string ToString()
151         {
152             StringBuilder sb = new StringBuilder();
153
154             sb.AppendFormat("CBlock(\n header={0},\n", header.ToString());
155
156             foreach(CTransaction tx in vtx)
157             {
158                 sb.AppendFormat("{0}", tx.ToString());
159             }
160
161             if (IsProofOfStake)
162             {
163                 sb.AppendFormat(", signature={0}, signatureOK={1}\n", Interop.ToHex(signature), SignatureOK);
164             }
165
166             sb.Append(")");
167
168             // TODO
169             return sb.ToString();
170         }
171         }
172 }
173