/** * Used by addmultisigaddress / createmultisig: */ CScript _createmultisig_redeemScript(CWallet * const pwallet, const UniValue& params) { int nRequired = params[0].get_int(); const UniValue& keys = params[1].get_array(); // Gather public keys if (nRequired < 1) throw std::runtime_error("a multisignature address must require at least one key to redeem"); if ((int)keys.size() < nRequired) throw std::runtime_error( strprintf("not enough keys supplied " "(got %u keys, but need at least %d to redeem)", keys.size(), nRequired)); if (keys.size() > 16) throw std::runtime_error("Number of addresses involved in the multisignature address creation > 16\nReduce the number"); std::vector<CPubKey> pubkeys; pubkeys.resize(keys.size()); for (unsigned int i = 0; i < keys.size(); i++) { const std::string& ks = keys[i].get_str(); #ifdef ENABLE_WALLET // Case 1: Bitcoin address and we have full public key: CBitcoinAddress address(ks); if (pwallet && address.IsValid()) { CKeyID keyID; if (!address.GetKeyID(keyID)) throw std::runtime_error( strprintf("%s does not refer to a key",ks)); CPubKey vchPubKey; if (!pwallet->GetPubKey(keyID, vchPubKey)) { throw std::runtime_error( strprintf("no full public key for address %s",ks)); } if (!vchPubKey.IsFullyValid()) throw std::runtime_error(" Invalid public key: "+ks); pubkeys[i] = vchPubKey; } // Case 2: hex public key else #endif if (IsHex(ks)) { CPubKey vchPubKey(ParseHex(ks)); if (!vchPubKey.IsFullyValid()) throw std::runtime_error(" Invalid public key: "+ks); pubkeys[i] = vchPubKey; } else { throw std::runtime_error(" Invalid public key: "+ks); } } CScript result = GetScriptForMultisig(nRequired, pubkeys); if (result.size() > MAX_SCRIPT_ELEMENT_SIZE) throw std::runtime_error( strprintf("redeemScript exceeds size limit: %d > %d", result.size(), MAX_SCRIPT_ELEMENT_SIZE)); return result; }
bool CScriptCompressor::IsToPubKey(CPubKey &pubkey) const { if (script.size() == 35 && script[0] == 33 && script[34] == OP_CHECKSIG && (script[1] == 0x02 || script[1] == 0x03)) { pubkey.Set(&script[1], &script[34]); return true; } if (script.size() == 67 && script[0] == 65 && script[66] == OP_CHECKSIG && script[1] == 0x04) { pubkey.Set(&script[1], &script[66]); // if not fully valid, a case that would not be compressible return pubkey.IsFullyValid(); } return false; }
static bool ExtractPubKey(const CScript &dest, CPubKey& pubKeyOut) { //TODO: Use Solver to extract this? CScript::const_iterator pc = dest.begin(); opcodetype opcode; std::vector<unsigned char> vch; if (!dest.GetOp(pc, opcode, vch) || vch.size() < 33 || vch.size() > 65) return false; pubKeyOut = CPubKey(vch); if (!pubKeyOut.IsFullyValid()) return false; if (!dest.GetOp(pc, opcode, vch) || opcode != OP_CHECKSIG || dest.GetOp(pc, opcode, vch)) return false; return true; }
// Retrieves a public key for an address from the given CKeyStore CPubKey AddrToPubKey(CKeyStore* const keystore, const std::string& addr_in) { CTxDestination dest = DecodeDestination(addr_in); if (!IsValidDestination(dest)) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address: " + addr_in); } CKeyID key = GetKeyForDestination(*keystore, dest); if (key.IsNull()) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("%s does not refer to a key", addr_in)); } CPubKey vchPubKey; if (!keystore->GetPubKey(key, vchPubKey)) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("no full public key for address %s", addr_in)); } if (!vchPubKey.IsFullyValid()) { throw JSONRPCError(RPC_INTERNAL_ERROR, "Wallet contains an invalid public key"); } return vchPubKey; }
bool MultisigDialog::createRedeemScript(int m, vector<string> vKeys, CScript& redeemRet, string& errorRet) { try{ int n = vKeys.size(); //gather pub keys if (n < 1) throw runtime_error("a Multisignature address must require at least one key to redeem"); if (n < m) throw runtime_error( strprintf("not enough keys supplied " "(got %d keys, but need at least %d to redeem)", m, n)); if (n > 15) throw runtime_error("Number of addresses involved in the Multisignature address creation > 15\nReduce the number"); vector<CPubKey> pubkeys; pubkeys.resize(n); int i = 0; for(vector<string>::iterator it = vKeys.begin(); it != vKeys.end(); ++it) { string keyString = *it; #ifdef ENABLE_WALLET // Case 1: PIVX address and we have full public key: CBitcoinAddress address(keyString); if (pwalletMain && address.IsValid()) { CKeyID keyID; if (!address.GetKeyID(keyID)) { throw runtime_error( strprintf("%s does not refer to a key", keyString)); } CPubKey vchPubKey; if (!pwalletMain->GetPubKey(keyID, vchPubKey)) throw runtime_error( strprintf("no full public key for address %s", keyString)); if (!vchPubKey.IsFullyValid()){ string sKey = keyString.empty()?"(empty)":keyString; throw runtime_error(" Invalid public key: " + sKey ); } pubkeys[i++] = vchPubKey; } //case 2: hex pub key else #endif if (IsHex(keyString)) { CPubKey vchPubKey(ParseHex(keyString)); if (!vchPubKey.IsFullyValid()){ throw runtime_error(" Invalid public key: " + keyString); } pubkeys[i++] = vchPubKey; } else { throw runtime_error(" Invalid public key: " + keyString); } } //populate redeem script //OP_N for required signatures redeemRet << redeemRet.EncodeOP_N(m); //public keys for(CPubKey& key : pubkeys){ vector<unsigned char> vKey= ToByteVector(key); redeemRet << vKey; } //OP_N for total pubkeys redeemRet << redeemRet.EncodeOP_N(pubkeys.size()); redeemRet << OP_CHECKMULTISIG; return true; }catch(const runtime_error& e){ errorRet = string(e.what()); return false; } }