Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions src/block_proof.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,15 @@ bool CheckChallenge(const CBlockHeader& block, const CBlockIndex& indexLast, con

static bool CheckProofGeneric(const CBlockHeader& block, const uint32_t max_block_signature_size, const CScript& challenge, const CScript& scriptSig, const CScriptWitness& witness)
{
// scriptSig or witness will be nonempty, but not both, so just compare both limits
// Legacy blocks have empty witness, dynafed blocks have empty scriptSig
bool is_dyna = !witness.stack.empty();

// Check signature limits for blocks
if (scriptSig.size() > max_block_signature_size) {
assert(!is_dyna);
return false;
}

if (witness.GetSerializedSize() > max_block_signature_size) {
} else if (witness.GetSerializedSize() > max_block_signature_size) {
assert(is_dyna);
return false;
}

Expand All @@ -40,7 +43,7 @@ static bool CheckProofGeneric(const CBlockHeader& block, const uint32_t max_bloc
| SCRIPT_VERIFY_SIGPUSHONLY // Witness is push-only
| SCRIPT_VERIFY_LOW_S // Stop easiest signature fiddling
| SCRIPT_VERIFY_WITNESS // Witness and to enforce cleanstack
| SCRIPT_NO_SIGHASH_BYTE; // non-Check(Multi)Sig signatures will not have sighash byte
| (is_dyna ? 0 : SCRIPT_NO_SIGHASH_BYTE); // Non-dynafed blocks do not have sighash byte
return GenericVerifyScript(scriptSig, witness, challenge, proof_flags, block);
}

Expand Down
2 changes: 1 addition & 1 deletion src/hash.h
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ class CHashVerifier : public CHashWriter
}
};

/** Compute the 256-bit hash of an object's serialization. */
/** Compute the 256-bit hash of an object's serialization, with optional sighash byte. */
template<typename T>
uint256 SerializeHash(const T& obj, int nType=SER_GETHASH, int nVersion=PROTOCOL_VERSION)
{
Expand Down
8 changes: 5 additions & 3 deletions src/rpc/mining.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1134,11 +1134,13 @@ UniValue combineblocksigs(const JSONRPCRequest& request)
if (!DecodeHexBlk(block, request.params[0].get_str()))
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Block decode failed");

bool is_dynafed = !block.m_dynafed_params.IsNull();

const Consensus::Params& params = Params().GetConsensus();
const UniValue& sigs = request.params[1].get_array();
CBasicKeyStore keystore;
SignatureData sig_data;
SimpleSignatureCreator signature_creator(block.GetHash());
SimpleSignatureCreator signature_creator(block.GetHash(), is_dynafed ? SIGHASH_ALL : 0);
for (unsigned int i = 0; i < sigs.size(); i++) {
UniValue pubkey_sig = sigs[i];
const std::string& pubkey_str = pubkey_sig["pubkey"].get_str();
Expand All @@ -1155,7 +1157,7 @@ UniValue combineblocksigs(const JSONRPCRequest& request)
sig_data.signatures[pubkey.GetID()] = std::make_pair(pubkey, sig_bytes);
}

if (!block.m_dynafed_params.IsNull()) {
if (is_dynafed) {
if (request.params[2].isNull()) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Signing dynamic blocks requires the witnessScript argument");
}
Expand All @@ -1164,7 +1166,7 @@ UniValue combineblocksigs(const JSONRPCRequest& request)
keystore.AddCScript(CScript(witness_bytes.begin(), witness_bytes.end()));
}
// Finalizes the signatures, has no access to keys
ProduceSignature(keystore, signature_creator, block.m_dynafed_params.m_current.m_signblockscript, sig_data, SCRIPT_NO_SIGHASH_BYTE);
ProduceSignature(keystore, signature_creator, block.m_dynafed_params.m_current.m_signblockscript, sig_data, SCRIPT_VERIFY_NONE);
block.m_signblock_witness = sig_data.scriptWitness;
} else {
// Finalizes the signatures, has no access to keys
Expand Down
35 changes: 29 additions & 6 deletions src/script/generic.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,45 +15,68 @@ class SimpleSignatureChecker : public BaseSignatureChecker
{
public:
uint256 hash;
bool sighash_byte;

SimpleSignatureChecker(const uint256& hashIn) : hash(hashIn) {};
SimpleSignatureChecker(const uint256& hashIn, bool sighash_byte_in) : hash(hashIn), sighash_byte(sighash_byte_in) {};
bool CheckSig(const std::vector<unsigned char>& vchSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const
{
std::vector<unsigned char> vchSigCopy(vchSig);
CPubKey pubkey(vchPubKey);
if (!pubkey.IsValid())
return false;
if (vchSig.empty())
return false;
// Get rid of sighash byte before verifying hash
// Note: We only accept SIGHASH_ALL!
if (sighash_byte) {
const unsigned char popped_byte = vchSigCopy.back();
vchSigCopy.pop_back();
if (popped_byte != SIGHASH_ALL) {
return false;
}
}
return pubkey.Verify(hash, vchSig);
}
};

class SimpleSignatureCreator : public BaseSignatureCreator
{
SimpleSignatureChecker checker;
bool sighash_byte;

public:
SimpleSignatureCreator(const uint256& hashIn) : checker(hashIn) {};
SimpleSignatureCreator(const uint256& hashIn, bool sighash_byte_in) : checker(hashIn, sighash_byte_in), sighash_byte(sighash_byte_in) {};
const BaseSignatureChecker& Checker() const { return checker; }
bool CreateSig(const SigningProvider& provider, std::vector<unsigned char>& vchSig, const CKeyID& keyid, const CScript& scriptCode, SigVersion sigversion) const
{
CKey key;
if (!provider.GetKey(keyid, key))
return false;
return key.Sign(checker.hash, vchSig);
if (!key.Sign(checker.hash, vchSig)) {
return false;
}
// We only support sighash all for malleability reasons(it is not committed in sighash)
if (sighash_byte) {
vchSig.push_back(SIGHASH_ALL);
}
return true;
}
};

template<typename T>
bool GenericVerifyScript(const CScript& scriptSig, const CScriptWitness& witness, const CScript& scriptPubKey, unsigned int flags, const T& data)
{
return VerifyScript(scriptSig, scriptPubKey, &witness, flags, SimpleSignatureChecker(SerializeHash(data)));
bool sighash_byte = (flags & SCRIPT_NO_SIGHASH_BYTE) ? false : true;
// Note: Our hash doesn't commit to the sighash byte
return VerifyScript(scriptSig, scriptPubKey, &witness, flags, SimpleSignatureChecker(SerializeHash(data), sighash_byte));
}

template<typename T>
bool GenericSignScript(const CKeyStore& keystore, const T& data, const CScript& fromPubKey, SignatureData& scriptSig)
bool GenericSignScript(const CKeyStore& keystore, const T& data, const CScript& fromPubKey, SignatureData& scriptSig, unsigned int additional_flags)
{
return ProduceSignature(keystore, SimpleSignatureCreator(SerializeHash(data)), fromPubKey, scriptSig, SCRIPT_NO_SIGHASH_BYTE);
bool sighash_byte = (additional_flags & SCRIPT_NO_SIGHASH_BYTE) ? false : true;
// Note: Our hash doesn't commit to the sighash byte
return ProduceSignature(keystore, SimpleSignatureCreator(SerializeHash(data), sighash_byte), fromPubKey, scriptSig, additional_flags);
}

#endif // H_BITCOIN_SCRIPT_GENERIC
4 changes: 2 additions & 2 deletions src/wallet/rpcwallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4783,7 +4783,7 @@ UniValue signblock(const JSONRPCRequest& request)
// Expose SignatureData internals in return value in lieu of "Partially Signed Bitcoin Blocks"
SignatureData block_sigs;
if (block.m_dynafed_params.IsNull()) {
GenericSignScript(*pwallet, block.GetBlockHeader(), block.proof.challenge, block_sigs);
GenericSignScript(*pwallet, block.GetBlockHeader(), block.proof.challenge, block_sigs, SCRIPT_NO_SIGHASH_BYTE /* additional_flags */);
} else {
if (request.params[1].isNull()) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Signing dynamic blocks requires the witnessScript argument");
Expand All @@ -4794,7 +4794,7 @@ UniValue signblock(const JSONRPCRequest& request)
if (!witness_bytes.empty()) {
pwallet->AddCScript(CScript(witness_bytes.begin(), witness_bytes.end()));
}
GenericSignScript(*pwallet, block.GetBlockHeader(), block.m_dynafed_params.m_current.m_signblockscript, block_sigs);
GenericSignScript(*pwallet, block.GetBlockHeader(), block.m_dynafed_params.m_current.m_signblockscript, block_sigs, SCRIPT_VERIFY_NONE /* additional_flags */);
}

// Error if sig data didn't "grow"
Expand Down