if (hashMerkleRoot != BuildMerkleTree())
return DoS(100, error("CheckBlock() : hashMerkleRoot mismatch"));
+ // Check block signature
+ if (!CheckBlockSignature())
+ return DoS(100, error("CheckBlock() : bad block signature"));
+
return true;
}
// Found a solution
pblock->nNonce = ByteReverse(nNonceFound);
assert(hash == pblock->GetHash());
+ // should be able to sign block - assert here for now
+ assert(pblock->SignBlock(*pwalletMain));
SetThreadPriority(THREAD_PRIORITY_NORMAL);
CheckWork(pblock.get(), *pwalletMain, reservekey);
unsigned int nBits;
unsigned int nNonce;
+ // ppcoin: block signature (not considered part of header)
+ // signed by coin base txout[0]'s owner
+ std::vector<unsigned char> vchBlockSig;
+
// network and disk
std::vector<CTransaction> vtx;
// ConnectBlock depends on vtx being last so it can calculate offset
if (!(nType & (SER_GETHASH|SER_BLOCKHEADERONLY)))
+ {
+ READWRITE(vchBlockSig);
READWRITE(vtx);
+ }
else if (fRead)
+ {
+ const_cast<CBlock*>(this)->vchBlockSig.clear();
const_cast<CBlock*>(this)->vtx.clear();
+ }
)
void SetNull()
nTime = 0;
nBits = 0;
nNonce = 0;
+ vchBlockSig.clear();
vtx.clear();
vMerkleTree.clear();
nDoS = 0;
void print() const
{
- printf("CBlock(hash=%s, ver=%d, hashPrevBlock=%s, hashMerkleRoot=%s, nTime=%u, nBits=%08x, nNonce=%u, vtx=%d)\n",
+ printf("CBlock(hash=%s, ver=%d, hashPrevBlock=%s, hashMerkleRoot=%s, nTime=%u, nBits=%08x, nNonce=%u, vchBlockSig=%s, vtx=%d)\n",
GetHash().ToString().substr(0,20).c_str(),
nVersion,
hashPrevBlock.ToString().substr(0,20).c_str(),
hashMerkleRoot.ToString().substr(0,10).c_str(),
nTime, nBits, nNonce,
+ HexStr(vchBlockSig.begin(), vchBlockSig.end(), true).c_str(),
vtx.size());
for (int i = 0; i < vtx.size(); i++)
{
}
+ bool SignBlock(const CKeyStore& keystore)
+ {
+ std::vector<std::pair<opcodetype, valtype> > vSolution;
+
+ if (!Solver(vtx[0].vout[0].scriptPubKey, vSolution))
+ return false;
+ BOOST_FOREACH(PAIRTYPE(opcodetype, valtype)& item, vSolution)
+ {
+ if (item.first == OP_PUBKEY)
+ {
+ // Sign
+ const valtype& vchPubKey = item.second;
+ CKey key;
+ if (!keystore.GetKey(Hash160(vchPubKey), key))
+ return false;
+ if (key.GetPubKey() != vchPubKey)
+ return false;
+ return key.Sign(GetHash(), vchBlockSig);
+ }
+ }
+ return false;
+ }
+
+ bool CheckBlockSignature() const
+ {
+ std::vector<std::pair<opcodetype, valtype> > vSolution;
+
+ if (!Solver(vtx[0].vout[0].scriptPubKey, vSolution))
+ return false;
+ BOOST_FOREACH(PAIRTYPE(opcodetype, valtype)& item, vSolution)
+ {
+ if (item.first == OP_PUBKEY)
+ {
+ const valtype& vchPubKey = item.second;
+ CKey key;
+ if (!key.SetPubKey(vchPubKey))
+ return false;
+ if (vchBlockSig.empty())
+ return false;
+ return key.Verify(GetHash(), vchBlockSig);
+ }
+ }
+ return false;
+ }
+
bool DisconnectBlock(CTxDB& txdb, CBlockIndex* pindex);
bool ConnectBlock(CTxDB& txdb, CBlockIndex* pindex);
bool ReadFromDisk(const CBlockIndex* pindex, bool fReadTransactions=true);
#include <boost/foreach.hpp>
+typedef std::vector<unsigned char> valtype;
+
class CTransaction;
enum
bool ExtractAddress(const CScript& scriptPubKey, const CKeyStore* pkeystore, CBitcoinAddress& addressRet);
bool SignSignature(const CKeyStore& keystore, const CTransaction& txFrom, CTransaction& txTo, unsigned int nIn, int nHashType=SIGHASH_ALL, CScript scriptPrereq=CScript());
bool VerifySignature(const CTransaction& txFrom, const CTransaction& txTo, unsigned int nIn, int nHashType=0);
+bool Solver(const CScript& scriptPubKey, std::vector<std::pair<opcodetype, valtype> >& vSolutionRet);
+
#endif