BinaryData CryptoECDSA::ECAddPoints(BinaryData const & Ax, BinaryData const & Ay, BinaryData const & Bx, BinaryData const & By) { CryptoPP::ECP ecp = Get_secp256k1_ECP(); CryptoPP::Integer intAx, intAy, intBx, intBy, intCx, intCy; intAx.Decode(Ax.getPtr(), Ax.getSize(), UNSIGNED); intAy.Decode(Ay.getPtr(), Ay.getSize(), UNSIGNED); intBx.Decode(Bx.getPtr(), Bx.getSize(), UNSIGNED); intBy.Decode(By.getPtr(), By.getSize(), UNSIGNED); BTC_ECPOINT A(intAx, intAy); BTC_ECPOINT B(intBx, intBy); BTC_ECPOINT C = ecp.Add(A,B); BinaryData Cbd(64); C.x.Encode(Cbd.getPtr(), 32, UNSIGNED); C.y.Encode(Cbd.getPtr()+32, 32, UNSIGNED); return Cbd; }
CryptoPP::ECP CryptoECDSA::Get_secp256k1_ECP(void) { static bool firstRun = true; static CryptoPP::Integer intN; static CryptoPP::Integer inta; static CryptoPP::Integer intb; static BinaryData N; static BinaryData a; static BinaryData b; if(firstRun) { firstRun = false; N = BinaryData::CreateFromHex( "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f"); a = BinaryData::CreateFromHex( "0000000000000000000000000000000000000000000000000000000000000000"); b = BinaryData::CreateFromHex( "0000000000000000000000000000000000000000000000000000000000000007"); intN.Decode( N.getPtr(), N.getSize(), UNSIGNED); inta.Decode( a.getPtr(), a.getSize(), UNSIGNED); intb.Decode( b.getPtr(), b.getSize(), UNSIGNED); } return CryptoPP::ECP(intN, inta, intb); }
bool BinaryData::startsWith(BinaryData const & matchStr) const { if(matchStr.getSize() > getSize()) return false; for(uint32_t i=0; i<matchStr.getSize(); i++) if(matchStr[i] != (*this)[i]) return false; return true; }
void TxOut::unserialize( BinaryData const & str, uint32_t nbytes, TxRef parent, uint32_t idx) { unserialize_checked(str.getPtr(), str.getSize(), nbytes, parent, idx); }
BinaryData CryptoECDSA::ECMultiplyScalars(BinaryData const & A, BinaryData const & B) { // Hardcode the order of the secp256k1 EC group static BinaryData N = BinaryData::CreateFromHex( "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141"); CryptoPP::Integer intA, intB, intC, intN; intA.Decode(A.getPtr(), A.getSize(), UNSIGNED); intB.Decode(B.getPtr(), B.getSize(), UNSIGNED); intN.Decode(N.getPtr(), N.getSize(), UNSIGNED); intC = a_times_b_mod_c(intA, intB, intN); BinaryData C(32); intC.Encode(C.getPtr(), 32, UNSIGNED); return C; }
bool CryptoECDSA::ECVerifyPoint(BinaryData const & x, BinaryData const & y) { BTC_PUBKEY cppPubKey; CryptoPP::Integer pubX; CryptoPP::Integer pubY; pubX.Decode(x.getPtr(), x.getSize(), UNSIGNED); pubY.Decode(y.getPtr(), y.getSize(), UNSIGNED); BTC_ECPOINT publicPoint(pubX, pubY); // Initialize the public key with the ECP point just created cppPubKey.Initialize(CryptoPP::ASN1::secp256k1(), publicPoint); // Validate the public key -- not sure why this needs a PRNG BTC_PRNG prng; return cppPubKey.Validate(prng, 3); }
BinaryData CryptoECDSA::ECInverse(BinaryData const & Ax, BinaryData const & Ay) { CryptoPP::ECP ecp = Get_secp256k1_ECP(); CryptoPP::Integer intAx, intAy, intCx, intCy; intAx.Decode(Ax.getPtr(), Ax.getSize(), UNSIGNED); intAy.Decode(Ay.getPtr(), Ay.getSize(), UNSIGNED); BTC_ECPOINT A(intAx, intAy); BTC_ECPOINT C = ecp.Inverse(A); BinaryData Cbd(64); C.x.Encode(Cbd.getPtr(), 32, UNSIGNED); C.y.Encode(Cbd.getPtr()+32, 32, UNSIGNED); return Cbd; }
BinaryData CryptoECDSA::ECMultiplyPoint(BinaryData const & A, BinaryData const & Bx, BinaryData const & By) { CryptoPP::ECP ecp = Get_secp256k1_ECP(); CryptoPP::Integer intA, intBx, intBy, intCx, intCy; intA.Decode( A.getPtr(), A.getSize(), UNSIGNED); intBx.Decode(Bx.getPtr(), Bx.getSize(), UNSIGNED); intBy.Decode(By.getPtr(), By.getSize(), UNSIGNED); BTC_ECPOINT B(intBx, intBy); BTC_ECPOINT C = ecp.ScalarMultiply(B, intA); BinaryData Cbd(64); C.x.Encode(Cbd.getPtr(), 32, UNSIGNED); C.y.Encode(Cbd.getPtr()+32, 32, UNSIGNED); return Cbd; }
bool BinaryData::endsWith(BinaryData const & matchStr) const { uint32_t sz = matchStr.getSize(); if(sz > getSize()) return false; for(uint32_t i=0; i<sz; i++) if(matchStr[sz-(i+1)] != (*this)[getSize()-(i+1)]) return false; return true; }
SecureBinaryData CryptoECDSA::InvMod(const SecureBinaryData& m) { static BinaryData N = BinaryData::CreateFromHex( "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141"); CryptoPP::Integer cppM; CryptoPP::Integer cppModulo; cppM.Decode(m.getPtr(), m.getSize(), UNSIGNED); cppModulo.Decode(N.getPtr(), N.getSize(), UNSIGNED); CryptoPP::Integer cppResult = cppM.InverseMod(cppModulo); SecureBinaryData result(32); cppResult.Encode(result.getPtr(), result.getSize(), UNSIGNED); return result; }
TxOut BlockDataViewer::getTxOutCopy( const BinaryData& txHash, uint16_t index) const { LMDBEnv::Transaction tx; db_->beginDBTransaction(&tx, STXO, LMDB::ReadOnly); BinaryData bdkey = db_->getDBKeyForHash(txHash); if (bdkey.getSize() == 0) return TxOut(); return db_->getTxOutCopy(bdkey, index); }
TxOut BlockDataViewer::getTxOutCopy( const BinaryData& txHash, uint16_t index) const { LMDBEnv::Transaction tx; db_->beginDBTransaction(&tx, HISTORY, LMDB::ReadOnly); BinaryData bdkey; db_->getStoredTx_byHash(txHash, nullptr, &bdkey); if (bdkey.getSize() == 0) return TxOut(); return db_->getTxOutCopy(bdkey, index); }
bool TxIOPair::setTxOut(const BinaryData& dbKey8B) { if (dbKey8B.getSize() == 8) { BinaryRefReader brr(dbKey8B); BinaryDataRef txKey6B = brr.get_BinaryDataRef(6); uint16_t txOutIdx = brr.get_uint16_t(BIGENDIAN); return setTxOut(TxRef(txKey6B), (uint32_t)txOutIdx); } else { //pass 0 byte dbkey to reset the txout setTxOut(TxRef(), 0); return false; } }
void ScrAddrFilter::getScrAddrCurrentSyncState( BinaryData const & scrAddr) { if (scrAddr.getSize() == 0) return; uint32_t shard = lmdb_->getShard(scrAddr); //grab SSH for scrAddr LMDBEnv::Transaction tx; lmdb_->beginShardTransaction(tx, shard, LMDB::ReadOnly); StoredScriptHistory ssh; lmdb_->getStoredScriptHistorySummary(ssh, scrAddr); //update scrAddrData lowest scanned block setScrAddrLastScanned(scrAddr, ssh.alreadyScannedUpToBlk_); }
void BlockDataViewer::flagRefresh(BDV_refresh refresh, const BinaryData& refreshID) { if (saf_->bdmIsRunning() == false) return; unique_lock<mutex> lock(refreshLock_); if (refresh_ != BDV_refreshAndRescan) { if (refresh == BDV_refreshAndRescan) refresh_ = BDV_refreshAndRescan; else refresh_ = BDV_refreshSkipRescan; } if (refreshID.getSize()) refreshIDSet_.insert(refreshID); if (refresh == BDV_filterChanged) refreshIDSet_.insert(BinaryData("wallet_filter_changed")); notifyMainThread(); }
map<BinaryData, map<BinaryData, TxIOPair> > ZeroConfContainer::ZCisMineBulkFilter(const Tx & tx, const BinaryData & ZCkey, uint32_t txtime, function<bool(const BinaryData&)> filter, bool withSecondOrderMultisig) { // Since 99.999%+ of all transactions are not ours, let's do the // fastest bulk filter possible, even though it will add // redundant computation to the tx that are ours. In fact, // we will skip the TxIn/TxOut convenience methods and follow the // pointers directly to the data we want /***filter is a pointer to a function that takes in a scrAddr (21 bytes, including the prefix) and returns a bool. For supernode, it should return true all the time. ***/ map<BinaryData, map<BinaryData, TxIOPair> > processedTxIO; BinaryData txHash = tx.getThisHash(); TxRef txref = db_->getTxRef(txHash); if (txref.isInitialized()) { //Found this tx in the db. It is already part of a block thus //is invalid as a ZC return processedTxIO; } uint8_t const * txStartPtr = tx.getPtr(); for (uint32_t iin = 0; iin<tx.getNumTxIn(); iin++) { // We have the txin, now check if it contains one of our TxOuts OutPoint op; op.unserialize(txStartPtr + tx.getTxInOffset(iin), 36); //check ZC txhash first, always cheaper than grabing a stxo from DB, //and will always be checked if the tx doesn't hit in DB outpoints. { BinaryData opZcKey; if (getKeyForTxHash(op.getTxHash(), opZcKey)) { TxRef outPointRef(opZcKey); uint16_t outPointId = op.getTxOutIndex(); TxIOPair txio(outPointRef, outPointId, TxRef(ZCkey), iin); Tx chainedZC = getTxByHash(op.getTxHash()); const TxOut& chainedTxOut = chainedZC.getTxOutCopy(outPointId); txio.setTxHashOfOutput(op.getTxHash()); txio.setTxHashOfInput(txHash); txio.setValue(chainedTxOut.getValue()); txio.setTxTime(txtime); BinaryData spentSA = chainedTxOut.getScrAddressStr(); auto& key_txioPair = processedTxIO[spentSA]; key_txioPair[txio.getDBKeyOfOutput()] = txio; auto& wltIdVec = keyToSpentScrAddr_[ZCkey]; wltIdVec.push_back(spentSA); txOutsSpentByZC_.insert(txio.getDBKeyOfOutput()); continue; } } //fetch the TxOut from DB BinaryData opKey = op.getDBkey(db_); if (opKey.getSize() == 8) { //found outPoint DBKey, grab the StoredTxOut StoredTxOut stxOut; if (db_->getStoredTxOut(stxOut, opKey)) { BinaryData sa = stxOut.getScrAddress(); if (filter(sa)) { TxIOPair txio(TxRef(opKey.getSliceRef(0, 6)), op.getTxOutIndex(), TxRef(ZCkey), iin); txio.setTxHashOfOutput(op.getTxHash()); txio.setTxHashOfInput(txHash); txio.setValue(stxOut.getValue()); txio.setTxTime(txtime); auto& key_txioPair = processedTxIO[sa]; key_txioPair[opKey] = txio; auto& wltIdVec = keyToSpentScrAddr_[ZCkey]; wltIdVec.push_back(sa); txOutsSpentByZC_.insert(opKey); } } } } // Simply convert the TxOut scripts to scrAddrs and check if registered for (uint32_t iout = 0; iout<tx.getNumTxOut(); iout++) { TxOut txout = tx.getTxOutCopy(iout); BinaryData scrAddr = txout.getScrAddressStr(); if (filter(scrAddr)) { TxIOPair txio(TxRef(ZCkey), iout); txio.setValue(txout.getValue()); txio.setTxHashOfOutput(txHash); txio.setTxTime(txtime); txio.setUTXO(true); auto& key_txioPair = processedTxIO[scrAddr]; key_txioPair[txio.getDBKeyOfOutput()] = txio; continue; } // It's still possible this is a multisig addr involving one of our // existing scrAddrs, even if we aren't explicitly looking for this multisig if (withSecondOrderMultisig && txout.getScriptType() == TXOUT_SCRIPT_MULTISIG) { BinaryRefReader brrmsig(scrAddr); uint8_t PREFIX = brrmsig.get_uint8_t(); (void)PREFIX; uint8_t M = brrmsig.get_uint8_t(); (void)M; uint8_t N = brrmsig.get_uint8_t(); for (uint8_t a = 0; a<N; a++) if (filter(HASH160PREFIX + brrmsig.get_BinaryDataRef(20))) { TxIOPair txio(TxRef(ZCkey), iout); txio.setTxHashOfOutput(txHash); txio.setValue(txout.getValue()); txio.setTxTime(txtime); txio.setUTXO(true); txio.setMultisig(true); auto& key_txioPair = processedTxIO[scrAddr]; key_txioPair[txio.getDBKeyOfOutput()] = txio; } } } // If we got here, it's either non std or not ours return processedTxIO; }
BinaryData SigHashDataLegacy::getDataForSigHashAll(const TransactionStub& stub, BinaryDataRef subScript, unsigned inputIndex) { //grab subscript auto lastCSoffset = stub.getLastCodeSeparatorOffset(inputIndex); auto subScriptLen = subScript.getSize() - lastCSoffset; auto&& presubscript = subScript.getSliceRef(lastCSoffset, subScriptLen); //tokenize op_cs chunks auto&& tokens = tokenize(presubscript, OP_CODESEPARATOR); BinaryData subscript; if (tokens.size() == 1) { subscript = move(presubscript); } else { for (auto& token : tokens) { subscript.append(token); } } //isolate outputs auto&& serializedOutputs = stub.getSerializedOutputScripts(); //isolate inputs auto&& txinsData = stub.getTxInsData(); auto txin_count = txinsData.size(); BinaryWriter strippedTxins; for (unsigned i=0; i < txin_count; i++) { strippedTxins.put_BinaryData(txinsData[i].outputHash_); strippedTxins.put_uint32_t(txinsData[i].outputIndex_); if (inputIndex != i) { //put empty varint strippedTxins.put_var_int(0); //and sequence strippedTxins.put_uint32_t(txinsData[i].sequence_); } else { //scriptsig strippedTxins.put_var_int(subscript.getSize()); strippedTxins.put_BinaryData(subscript); //sequence strippedTxins.put_uint32_t(txinsData[i].sequence_); } } //wrap it up BinaryWriter scriptSigData; //version scriptSigData.put_uint32_t(stub.getVersion()); //txin count scriptSigData.put_var_int(txin_count); //txins scriptSigData.put_BinaryData(strippedTxins.getData()); //txout count scriptSigData.put_var_int(stub.getTxOutCount()); //txouts scriptSigData.put_BinaryData(serializedOutputs); //locktime scriptSigData.put_uint32_t(stub.getLockTime()); //sighashall scriptSigData.put_uint32_t(1); return BinaryData(scriptSigData.getData()); }
void OutPoint::unserialize(BinaryData const & bd) { unserialize(bd.getPtr(), bd.getSize()); }