bool CMasternodeBroadcast::Create(const COutPoint& outpoint, const CService& service, const CKey& keyCollateralAddressNew, const CPubKey& pubKeyCollateralAddressNew, const CKey& keyMasternodeNew, const CPubKey& pubKeyMasternodeNew, std::string& strErrorRet, CMasternodeBroadcast& mnbRet) { // wait for reindex and/or import to finish if (fImporting || fReindex) return false; LogPrint(MCLog::MN, "CMasternodeBroadcast::Create -- pubKeyCollateralAddressNew = %s, pubKeyMasternodeNew.GetID() = %s\n", EncodeDestination(CScriptID(GetScriptForDestination(WitnessV0KeyHash(pubKeyCollateralAddressNew.GetID())))), EncodeDestination(CScriptID(GetScriptForDestination(WitnessV0KeyHash(pubKeyMasternodeNew.GetID()))))); auto Log = [&strErrorRet, &mnbRet](std::string sErr) -> bool { strErrorRet = sErr; mnbRet = CMasternodeBroadcast(); return false; }; CMasternodePing mnp(outpoint); if (!mnp.Sign(keyMasternodeNew, pubKeyMasternodeNew)) return Log(strprintf("Failed to sign ping, masternode=%s", outpoint.ToStringShort())); mnbRet = CMasternodeBroadcast(service, outpoint, pubKeyCollateralAddressNew, pubKeyMasternodeNew, PROTOCOL_VERSION); if (!mnbRet.IsValidNetAddr()) return Log(strprintf("Invalid IP address, masternode=%s", outpoint.ToStringShort())); mnbRet.lastPing = mnp; if (!mnbRet.Sign(keyCollateralAddressNew)) return Log(strprintf("Failed to sign broadcast, masternode=%s", outpoint.ToStringShort())); return true; }
CScript GetScriptForWitness(const CScript& redeemscript) { txnouttype typ; std::vector<std::vector<unsigned char> > vSolutions; if (Solver(redeemscript, typ, vSolutions)) { if (typ == TX_PUBKEY) { return GetScriptForDestination(WitnessV0KeyHash(Hash160(vSolutions[0].begin(), vSolutions[0].end()))); } else if (typ == TX_PUBKEYHASH) { return GetScriptForDestination(WitnessV0KeyHash(vSolutions[0])); } } return GetScriptForDestination(WitnessV0ScriptHash(redeemscript)); }
CScript GetScriptForWitness(const CScript& redeemscript) { CScript ret; txnouttype typ; std::vector<std::vector<unsigned char> > vSolutions; if (Solver(redeemscript, typ, vSolutions)) { if (typ == TX_PUBKEY) { return GetScriptForDestination(WitnessV0KeyHash(Hash160(vSolutions[0].begin(), vSolutions[0].end()))); } else if (typ == TX_PUBKEYHASH) { return GetScriptForDestination(WitnessV0KeyHash(vSolutions[0])); } } uint256 hash; CSHA256().Write(&redeemscript[0], redeemscript.size()).Finalize(hash.begin()); return GetScriptForDestination(WitnessV0ScriptHash(hash)); }
std::vector<CTxDestination> GetAllDestinationsForKey(const CPubKey& key) { CKeyID keyid = key.GetID(); if (key.IsCompressed()) { CTxDestination segwit = WitnessV0KeyHash(keyid); CTxDestination p2sh = CScriptID(GetScriptForDestination(segwit)); return std::vector<CTxDestination>{std::move(keyid), std::move(p2sh), std::move(segwit)}; } else { return std::vector<CTxDestination>{std::move(keyid)}; } }
void CMasternode::UpdateLastPaid(const CBlockIndex* pindex, int nMaxBlocksToScanBack) { if (!pindex) return; const CBlockIndex* pindexActive = chainActive.Tip(); assert(pindexActive); CDiskBlockPos blockPos = pindexActive->GetBlockPos(); CScript mnpayee = GetScriptForDestination(CScriptID(GetScriptForDestination(WitnessV0KeyHash(pubKeyCollateralAddress.GetID())))); //LogPrint(MCLog::MN, "CMasternode::UpdateLastPaidBlock -- searching for block with payment to %s\n", outpoint.ToStringShort()); LOCK(cs_mapMasternodeBlocks); for (int i = 0; pindexActive->nHeight > nBlockLastPaid && i < nMaxBlocksToScanBack; i++) { if (mnpayments.mapMasternodeBlocks.count(pindexActive->nHeight) && mnpayments.mapMasternodeBlocks[pindexActive->nHeight].HasPayeeWithVotes(mnpayee, 2)) { if (blockPos.IsNull() == true) { return; } CBlock block; if (!ReadBlockFromDisk(block, blockPos, Params().GetConsensus())) continue; CAmount nMasternodePayment = GetMasternodePayment(pindexActive->nHeight, block.vtx[0]->GetValueOut()); for (const auto& txout : block.vtx[0]->vout) if (mnpayee == txout.scriptPubKey && nMasternodePayment == txout.nValue) { nBlockLastPaid = pindexActive->nHeight; nTimeLastPaid = pindexActive->nTime; LogPrint(MCLog::MN, "CMasternode::UpdateLastPaidBlock -- searching for block with payment to %s -- found new %d\n", outpoint.ToStringShort(), nBlockLastPaid); return; } } if (pindexActive->pprev == nullptr) { assert(pindexActive); break; } pindexActive = pindexActive->pprev; } // Last payment for this masternode wasn't found in latest mnpayments blocks // or it was found in mnpayments blocks but wasn't found in the blockchain. LogPrint(MCLog::MN, "CMasternode::UpdateLastPaidBlock -- searching for block with payment to %s -- keeping old %d\n", outpoint.ToStringShort(), nBlockLastPaid); }
CTxDestination GetDestinationForKey(const CPubKey& key, OutputType type) { switch (type) { case OutputType::LEGACY: return key.GetID(); case OutputType::P2SH_SEGWIT: case OutputType::BECH32: { if (!key.IsCompressed()) return key.GetID(); CTxDestination witdest = WitnessV0KeyHash(key.GetID()); CScript witprog = GetScriptForDestination(witdest); if (type == OutputType::P2SH_SEGWIT) { return CScriptID(witprog); } else { return witdest; } } default: assert(false); } }
void CBasicKeyStore::ImplicitlyLearnRelatedKeyScripts(const CPubKey& pubkey) { AssertLockHeld(cs_KeyStore); CKeyID key_id = pubkey.GetID(); // We must actually know about this key already. assert(HaveKey(key_id) || mapWatchKeys.count(key_id)); // This adds the redeemscripts necessary to detect P2WPKH and P2SH-P2WPKH // outputs. Technically P2WPKH outputs don't have a redeemscript to be // spent. However, our current IsMine logic requires the corresponding // P2SH-P2WPKH redeemscript to be present in the wallet in order to accept // payment even to P2WPKH outputs. // Also note that having superfluous scripts in the keystore never hurts. // They're only used to guide recursion in signing and IsMine logic - if // a script is present but we can't do anything with it, it has no effect. // "Implicitly" refers to fact that scripts are derived automatically from // existing keys, and are present in memory, even without being explicitly // loaded (e.g. from a file). if (pubkey.IsCompressed()) { CScript script = GetScriptForDestination(WitnessV0KeyHash(key_id)); // This does not use AddCScript, as it may be overridden. CScriptID id(script); mapScripts[id] = std::move(script); } }
CMasternode::CollateralStatus CMasternode::CheckCollateral(const COutPoint& outpoint, const CPubKey& pubkey, int& nHeightRet) { AssertLockHeld(cs_main); Coin coin; if (!GetUTXOCoin(outpoint, coin)) { return COLLATERAL_UTXO_NOT_FOUND; } if (coin.out.nValue != 25000 * COIN) { return COLLATERAL_INVALID_AMOUNT; } if (pubkey == CPubKey() || coin.out.scriptPubKey != GetScriptForDestination(CScriptID(GetScriptForDestination(WitnessV0KeyHash(pubkey.GetID()))))) { return COLLATERAL_INVALID_PUBKEY; } nHeightRet = coin.nHeight; return COLLATERAL_OK; }