91 lines
2.9 KiB
C++
91 lines
2.9 KiB
C++
// Copyright (c) 2017-2019 The PIVX developers
|
|
// Distributed under the MIT software license, see the accompanying
|
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|
|
|
#include "blocksignature.h"
|
|
#include "main.h"
|
|
#include "zagrchain.h"
|
|
|
|
bool SignBlockWithKey(CBlock& block, const CKey& key)
|
|
{
|
|
if (!key.Sign(block.GetHash(), block.vchBlockSig))
|
|
return error("%s: failed to sign block hash with key", __func__);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool GetKeyIDFromUTXO(const CTxOut& txout, CKeyID& keyID)
|
|
{
|
|
std::vector<valtype> vSolutions;
|
|
txnouttype whichType;
|
|
if (!Solver(txout.scriptPubKey, whichType, vSolutions))
|
|
return false;
|
|
if (whichType == TX_PUBKEY) {
|
|
keyID = CPubKey(vSolutions[0]).GetID();
|
|
} else if (whichType == TX_PUBKEYHASH) {
|
|
keyID = CKeyID(uint160(vSolutions[0]));
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool SignBlock(CBlock& block, const CKeyStore& keystore)
|
|
{
|
|
CKeyID keyID;
|
|
if (block.IsProofOfWork()) {
|
|
bool fFoundID = false;
|
|
for (const CTxOut& txout :block.vtx[0].vout) {
|
|
if (!GetKeyIDFromUTXO(txout, keyID))
|
|
continue;
|
|
fFoundID = true;
|
|
break;
|
|
}
|
|
if (!fFoundID)
|
|
return error("%s: failed to find key for PoW", __func__);
|
|
} else {
|
|
if (!GetKeyIDFromUTXO(block.vtx[1].vout[1], keyID))
|
|
return error("%s: failed to find key for PoS", __func__);
|
|
}
|
|
|
|
CKey key;
|
|
if (!keystore.GetKey(keyID, key))
|
|
return error("%s: failed to get key from keystore", __func__);
|
|
|
|
return SignBlockWithKey(block, key);
|
|
}
|
|
|
|
bool CheckBlockSignature(const CBlock& block)
|
|
{
|
|
if (block.IsProofOfWork())
|
|
return block.vchBlockSig.empty();
|
|
|
|
if (block.vchBlockSig.empty())
|
|
return error("%s: vchBlockSig is empty!", __func__);
|
|
|
|
/** Each block is signed by the private key of the input that is staked. This can be either zAGR or normal UTXO
|
|
* zAGR: Each zAGR has a keypair associated with it. The serial number is a hash of the public key.
|
|
* UTXO: The public key that signs must match the public key associated with the first utxo of the coinstake tx.
|
|
*/
|
|
CPubKey pubkey;
|
|
bool fzAGRStake = block.vtx[1].vin[0].IsZerocoinSpend();
|
|
if (fzAGRStake) {
|
|
libzerocoin::CoinSpend spend = TxInToZerocoinSpend(block.vtx[1].vin[0]);
|
|
pubkey = spend.getPubKey();
|
|
} else {
|
|
txnouttype whichType;
|
|
std::vector<valtype> vSolutions;
|
|
const CTxOut& txout = block.vtx[1].vout[1];
|
|
if (!Solver(txout.scriptPubKey, whichType, vSolutions))
|
|
return false;
|
|
if (whichType == TX_PUBKEY || whichType == TX_PUBKEYHASH) {
|
|
valtype& vchPubKey = vSolutions[0];
|
|
pubkey = CPubKey(vchPubKey);
|
|
}
|
|
}
|
|
|
|
if (!pubkey.IsValid())
|
|
return error("%s: invalid pubkey %s", __func__, HexStr(pubkey));
|
|
|
|
return pubkey.Verify(block.GetHash(), block.vchBlockSig);
|
|
}
|