HmacSha256Key PeerAuth::getSendingMacKey(Curve25519Public const& remotePublic, uint256 const& localNonce, uint256 const& remoteNonce, Peer::PeerRole role) { std::vector<uint8_t> buf; if (role == Peer::WE_CALLED_REMOTE) { // If WE_CALLED_REMOTE then sending key is K_AB, // and A is local and B is remote. buf.push_back(0); buf.insert(buf.end(), localNonce.begin(), localNonce.end()); buf.insert(buf.end(), remoteNonce.begin(), remoteNonce.end()); } else { // If REMOTE_CALLED_US then sending key is K_BA, // and B is local and A is remote. buf.push_back(1); buf.insert(buf.end(), localNonce.begin(), localNonce.end()); buf.insert(buf.end(), remoteNonce.begin(), remoteNonce.end()); } auto k = getSharedKey(remotePublic, role); return hkdfExpand(k, buf); }
uint256 JoinSplit<NumInputs, NumOutputs>::h_sig( const uint256& randomSeed, const boost::array<uint256, NumInputs>& nullifiers, const uint256& pubKeyHash ) { const unsigned char personalization[crypto_generichash_blake2b_PERSONALBYTES] = {'Z','c','a','s','h','C','o','m','p','u','t','e','h','S','i','g'}; std::vector<unsigned char> block(randomSeed.begin(), randomSeed.end()); for (size_t i = 0; i < NumInputs; i++) { block.insert(block.end(), nullifiers[i].begin(), nullifiers[i].end()); } block.insert(block.end(), pubKeyHash.begin(), pubKeyHash.end()); uint256 output; if (crypto_generichash_blake2b_salt_personal(output.begin(), 32, &block[0], block.size(), NULL, 0, // No key. NULL, // No salt. personalization ) != 0) { throw std::logic_error("hash function failure"); } return output; }
uint32_t operator()(const uint256& key) const { static_assert(hash_select <8, "SignatureCacheHasher only has 8 hashes available."); uint32_t u; std::memcpy(&u, key.begin() + 4 * hash_select, 4); return u; }
std::array<unsigned char, 11> default_diversifier(const uint256& sk) { std::array<unsigned char, 11> res; unsigned char blob[34]; memcpy(&blob[0], sk.begin(), 32); blob[32] = 3; blob[33] = 0; while (true) { crypto_generichash_blake2b_state state; crypto_generichash_blake2b_init_salt_personal(&state, nullptr, 0, 64, nullptr, ZCASH_EXPANDSEED_PERSONALIZATION); crypto_generichash_blake2b_update(&state, blob, 34); crypto_generichash_blake2b_final(&state, res.data(), 11); if (librustzcash_check_diversifier(res.data())) { break; } else if (blob[33] == 255) { throw std::runtime_error("librustzcash_check_diversifier did not return valid diversifier"); } blob[33] += 1; } return res; }
// Which branch would contain the specified hash int SHAMapNodeID::selectBranch (uint256 const& hash) const { #if RIPPLE_VERIFY_NODEOBJECT_KEYS if (mDepth >= 64) { assert (false); return -1; } if ((hash & Masks(mDepth)) != mNodeID) { std::cerr << "selectBranch(" << getString () << std::endl; std::cerr << " " << hash << " off branch" << std::endl; assert (false); return -1; // does not go under this node } #endif int branch = * (hash.begin () + (mDepth / 2)); if (mDepth & 1) branch &= 0xf; else branch >>= 4; assert ((branch >= 0) && (branch < 16)); return branch; }
std::uint64_t ProofOfWork::getDifficulty (uint256 const& target, int iterations) { // calculate the approximate number of hashes required to solve this proof of work if ((iterations > kMaxIterations) || (target < sMinTarget)) { WriteLog (lsINFO, ProofOfWork) << "Iterations:" << iterations; WriteLog (lsINFO, ProofOfWork) << "MaxIterat: " << kMaxIterations; WriteLog (lsINFO, ProofOfWork) << "Target: " << target; WriteLog (lsINFO, ProofOfWork) << "MinTarget: " << sMinTarget; throw std::runtime_error ("invalid proof of work target/iteration"); } // more iterations means more hashes per iteration but also a larger final hash std::uint64_t difficulty = iterations + (iterations / 8); // Multiply the number of hashes needed by 256 for each leading zero byte in the difficulty const unsigned char* ptr = target.begin (); while (*ptr == 0) { difficulty *= 256; ++ptr; } difficulty = (difficulty * 256) / (*ptr + 1); return difficulty; }
std::vector<std::pair<arith_uint256, CDeterministicMNCPtr>> CDeterministicMNList::CalculateScores(const uint256& modifier) const { std::vector<std::pair<arith_uint256, CDeterministicMNCPtr>> scores; scores.reserve(GetAllMNsCount()); ForEachMN(true, [&](const CDeterministicMNCPtr& dmn) { if (dmn->pdmnState->confirmedHash.IsNull()) { // we only take confirmed MNs into account to avoid hash grinding on the ProRegTxHash to sneak MNs into a // future quorums return; } // calculate sha256(sha256(proTxHash, confirmedHash), modifier) per MN // Please note that this is not a double-sha256 but a single-sha256 // The first part is already precalculated (confirmedHashWithProRegTxHash) // TODO When https://github.com/bitcoin/bitcoin/pull/13191 gets backported, implement something that is similar but for single-sha256 uint256 h; CSHA256 sha256; sha256.Write(dmn->pdmnState->confirmedHashWithProRegTxHash.begin(), dmn->pdmnState->confirmedHashWithProRegTxHash.size()); sha256.Write(modifier.begin(), modifier.size()); sha256.Finalize(h.begin()); scores.emplace_back(UintToArith256(h), dmn); }); return scores; }
bool CZMQPublishHashBlockNotifier::NotifyBlock(const uint256 &hash) { LogPrint("zmq", "Publish hash block %s\n", hash.GetHex()); char data[32]; for (unsigned int i = 0; i < 32; i++) data[31 - i] = hash.begin()[i]; int rc = zmq_send_multipart(psocket, "hashblock", 9, data, 32, 0); return rc == 0; }
void RippleAddress::sign(uint256 const& message, Blob& retSignature) const { assert(vchData.size() == 64); const unsigned char *key = vchData.data(); retSignature.resize(crypto_sign_BYTES); crypto_sign_detached(&retSignature[0], NULL, (unsigned char*)message.begin(), message.size(), key); }
int PrimeWorker::CheckReqNonce(const uint256& nonce) { const uint32_t* limbs = (uint32_t*)nonce.begin(); uint32_t tmp = limbs[0]; for(int i = 1; i < 7; ++i) tmp *= limbs[i]; tmp += limbs[7]; return !tmp; }
void PaysharesPrivateKey::sign(uint256 const& message, Blob& retSignature) const { unsigned char out[crypto_sign_BYTES + message.bytes]; unsigned long long len; const unsigned char *key = mPair.mPrivateKey.data(); // contrary to the docs it puts the signature in front crypto_sign(out, &len, (unsigned char*)message.begin(), message.size(), key); retSignature.resize(crypto_sign_BYTES); memcpy(&retSignature[0], out, crypto_sign_BYTES); }
// Sapling std::array<unsigned char, 64> PRF_expand(const uint256& sk, unsigned char t) { std::array<unsigned char, 64> res; unsigned char blob[33]; memcpy(&blob[0], sk.begin(), 32); blob[32] = t; crypto_generichash_blake2b_state state; crypto_generichash_blake2b_init_salt_personal(&state, nullptr, 0, 64, nullptr, ZCASH_EXPANDSEED_PERSONALIZATION); crypto_generichash_blake2b_update(&state, blob, 33); crypto_generichash_blake2b_final(&state, res.data(), 64); return res; }
void dumpKeyInfo(uint256 secret) { CKey key; CAnoncoinSecret b58secret; printf(" * secret (hex): %s\n", secret.GetHex().c_str()); for (int nCompressed=0; nCompressed<2; nCompressed++) { bool fCompressed = nCompressed == 1; printf(" * %s:\n", fCompressed ? "compressed" : "uncompressed"); key.Set( secret.begin(), secret.end(), fCompressed ); b58secret.SetKey( key ); printf(" * secret (base58): %s\n", b58secret.ToString().c_str()); CPubKey pubkey = key.GetPubKey(); printf(" * address (base58): %s\n", CAnoncoinAddress(CTxDestination(pubkey.GetID())).ToString().c_str() ); } }
// Sprout uint256 PRF(bool a, bool b, bool c, bool d, const uint252& x, const uint256& y) { uint256 res; unsigned char blob[64]; memcpy(&blob[0], x.begin(), 32); memcpy(&blob[32], y.begin(), 32); blob[0] &= 0x0F; blob[0] |= (a ? 1 << 7 : 0) | (b ? 1 << 6 : 0) | (c ? 1 << 5 : 0) | (d ? 1 << 4 : 0); CSHA256 hasher; hasher.Write(blob, 64); hasher.FinalizeNoPadding(res.begin()); return res; }
ec_key ECDSAPrivateKey (uint256 const& serialized) { BIGNUM* bn = BN_bin2bn (serialized.begin(), serialized.size(), nullptr); if (bn == nullptr) { throw std::runtime_error ("ec_key::ec_key: BN_bin2bn failed"); } EC_KEY* key = new_initialized_EC_KEY(); const bool ok = EC_KEY_set_private_key (key, bn); BN_clear_free (bn); if (! ok) { EC_KEY_free (key); } return ec_key::acquire ((ec_key::pointer_t) key); }
void CAuxPow::initAuxPow (CBlockHeader& header) { /* Set auxpow flag right now, since we take the block hash below. */ header.SetAuxpowVersion(true); /* Build a minimal coinbase script input for merge-mining. */ const uint256 blockHash = header.GetHash (); valtype inputData(blockHash.begin (), blockHash.end ()); std::reverse (inputData.begin (), inputData.end ()); inputData.push_back (1); inputData.insert (inputData.end (), 7, 0); /* Fake a parent-block coinbase with just the required input script and no outputs. */ CMutableTransaction coinbase; coinbase.vin.resize (1); coinbase.vin[0].prevout.SetNull (); coinbase.vin[0].scriptSig = (CScript () << inputData); assert (coinbase.vout.empty ()); CTransactionRef coinbaseRef = MakeTransactionRef (coinbase); /* Build a fake parent block with the coinbase. */ CBlock parent; parent.nVersion = 1; parent.vtx.resize (1); parent.vtx[0] = coinbaseRef; parent.hashMerkleRoot = BlockMerkleRoot (parent); /* Construct the auxpow object. */ header.SetAuxpow (new CAuxPow (coinbaseRef)); assert (header.auxpow->vChainMerkleBranch.empty ()); header.auxpow->nChainIndex = 0; assert (header.auxpow->vMerkleBranch.empty ()); header.auxpow->nIndex = 0; header.auxpow->parentBlock = parent; }
void RippleAddress::setAccountPrivate(uint256 hash256) { SetData(VER_ACCOUNT_PRIVATE, hash256.begin(), 32); }
void RippleAddress::setNodePrivate(uint256 hash256) { SetData(VER_NODE_PRIVATE, hash256.begin(), 32); }
bool CAuxPow::check (const uint256& hashAuxBlock, int nChainId, const Consensus::Params& params) const { if (nIndex != 0) return error("AuxPow is not a generate"); if (params.fStrictChainId && parentBlock.GetChainId () == nChainId) return error("Aux POW parent has our chain ID"); if (vChainMerkleBranch.size() > 30) return error("Aux POW chain merkle branch too long"); // Check that the chain merkle root is in the coinbase const uint256 nRootHash = CheckMerkleBranch (hashAuxBlock, vChainMerkleBranch, nChainIndex); valtype vchRootHash(nRootHash.begin (), nRootHash.end ()); std::reverse (vchRootHash.begin (), vchRootHash.end ()); // correct endian // Check that we are in the parent block merkle tree if (CheckMerkleBranch(GetHash(), vMerkleBranch, nIndex) != parentBlock.hashMerkleRoot) return error("Aux POW merkle root incorrect"); const CScript script = tx->vin[0].scriptSig; // Check that the same work is not submitted twice to our chain. // CScript::const_iterator pcHead = std::search(script.begin(), script.end(), UBEGIN(pchMergedMiningHeader), UEND(pchMergedMiningHeader)); CScript::const_iterator pc = std::search(script.begin(), script.end(), vchRootHash.begin(), vchRootHash.end()); if (pc == script.end()) return error("Aux POW missing chain merkle root in parent coinbase"); if (pcHead != script.end()) { // Enforce only one chain merkle root by checking that a single instance of the merged // mining header exists just before. if (script.end() != std::search(pcHead + 1, script.end(), UBEGIN(pchMergedMiningHeader), UEND(pchMergedMiningHeader))) return error("Multiple merged mining headers in coinbase"); if (pcHead + sizeof(pchMergedMiningHeader) != pc) return error("Merged mining header is not just before chain merkle root"); } else { // For backward compatibility. // Enforce only one chain merkle root by checking that it starts early in the coinbase. // 8-12 bytes are enough to encode extraNonce and nBits. if (pc - script.begin() > 20) return error("Aux POW chain merkle root must start in the first 20 bytes of the parent coinbase"); } // Ensure we are at a deterministic point in the merkle leaves by hashing // a nonce and our chain ID and comparing to the index. pc += vchRootHash.size(); if (script.end() - pc < 8) return error("Aux POW missing chain merkle tree size and nonce in parent coinbase"); uint32_t nSize; memcpy(&nSize, &pc[0], 4); nSize = le32toh (nSize); const unsigned merkleHeight = vChainMerkleBranch.size (); if (nSize != (1u << merkleHeight)) return error("Aux POW merkle branch size does not match parent coinbase"); uint32_t nNonce; memcpy(&nNonce, &pc[4], 4); nNonce = le32toh (nNonce); if (nChainIndex != getExpectedIndex (nNonce, nChainId, merkleHeight)) return error("Aux POW wrong index"); return true; }
/** insecure_GetRandHash fills in a uint256 from insecure_rand */ void insecure_GetRandHash(uint256& t) { uint32_t* ptr = (uint32_t*)t.begin(); for (uint8_t j = 0; j < 8; ++j) *(ptr++) = insecure_rand.rand32(); }
SproutProof prove( bool makeGrothProof, const std::array<JSInput, NumInputs>& inputs, const std::array<JSOutput, NumOutputs>& outputs, std::array<SproutNote, NumOutputs>& out_notes, std::array<ZCNoteEncryption::Ciphertext, NumOutputs>& out_ciphertexts, uint256& out_ephemeralKey, const uint256& joinSplitPubKey, uint256& out_randomSeed, std::array<uint256, NumInputs>& out_macs, std::array<uint256, NumInputs>& out_nullifiers, std::array<uint256, NumOutputs>& out_commitments, uint64_t vpub_old, uint64_t vpub_new, const uint256& rt, bool computeProof, uint256 *out_esk // Payment disclosure ) { if (vpub_old > MAX_MONEY) { throw std::invalid_argument("nonsensical vpub_old value"); } if (vpub_new > MAX_MONEY) { throw std::invalid_argument("nonsensical vpub_new value"); } uint64_t lhs_value = vpub_old; uint64_t rhs_value = vpub_new; for (size_t i = 0; i < NumInputs; i++) { // Sanity checks of input { // If note has nonzero value if (inputs[i].note.value() != 0) { // The witness root must equal the input root. if (inputs[i].witness.root() != rt) { throw std::invalid_argument("joinsplit not anchored to the correct root"); } // The tree must witness the correct element if (inputs[i].note.cm() != inputs[i].witness.element()) { throw std::invalid_argument("witness of wrong element for joinsplit input"); } } // Ensure we have the key to this note. if (inputs[i].note.a_pk != inputs[i].key.address().a_pk) { throw std::invalid_argument("input note not authorized to spend with given key"); } // Balance must be sensical if (inputs[i].note.value() > MAX_MONEY) { throw std::invalid_argument("nonsensical input note value"); } lhs_value += inputs[i].note.value(); if (lhs_value > MAX_MONEY) { throw std::invalid_argument("nonsensical left hand size of joinsplit balance"); } } // Compute nullifier of input out_nullifiers[i] = inputs[i].nullifier(); } // Sample randomSeed out_randomSeed = random_uint256(); // Compute h_sig uint256 h_sig = this->h_sig(out_randomSeed, out_nullifiers, joinSplitPubKey); // Sample phi uint252 phi = random_uint252(); // Compute notes for outputs for (size_t i = 0; i < NumOutputs; i++) { // Sanity checks of output { if (outputs[i].value > MAX_MONEY) { throw std::invalid_argument("nonsensical output value"); } rhs_value += outputs[i].value; if (rhs_value > MAX_MONEY) { throw std::invalid_argument("nonsensical right hand side of joinsplit balance"); } } // Sample r uint256 r = random_uint256(); out_notes[i] = outputs[i].note(phi, r, i, h_sig); } if (lhs_value != rhs_value) { throw std::invalid_argument("invalid joinsplit balance"); } // Compute the output commitments for (size_t i = 0; i < NumOutputs; i++) { out_commitments[i] = out_notes[i].cm(); } // Encrypt the ciphertexts containing the note // plaintexts to the recipients of the value. { ZCNoteEncryption encryptor(h_sig); for (size_t i = 0; i < NumOutputs; i++) { SproutNotePlaintext pt(out_notes[i], outputs[i].memo); out_ciphertexts[i] = pt.encrypt(encryptor, outputs[i].addr.pk_enc); } out_ephemeralKey = encryptor.get_epk(); // !!! Payment disclosure START if (out_esk != nullptr) { *out_esk = encryptor.get_esk(); } // !!! Payment disclosure END } // Authenticate h_sig with each of the input // spending keys, producing macs which protect // against malleability. for (size_t i = 0; i < NumInputs; i++) { out_macs[i] = PRF_pk(inputs[i].key, i, h_sig); } if (makeGrothProof) { if (!computeProof) { return GrothProof(); } GrothProof proof; CDataStream ss1(SER_NETWORK, PROTOCOL_VERSION); ss1 << inputs[0].witness.path(); std::vector<unsigned char> auth1(ss1.begin(), ss1.end()); CDataStream ss2(SER_NETWORK, PROTOCOL_VERSION); ss2 << inputs[1].witness.path(); std::vector<unsigned char> auth2(ss2.begin(), ss2.end()); librustzcash_sprout_prove( proof.begin(), phi.begin(), rt.begin(), h_sig.begin(), inputs[0].key.begin(), inputs[0].note.value(), inputs[0].note.rho.begin(), inputs[0].note.r.begin(), auth1.data(), inputs[1].key.begin(), inputs[1].note.value(), inputs[1].note.rho.begin(), inputs[1].note.r.begin(), auth2.data(), out_notes[0].a_pk.begin(), out_notes[0].value(), out_notes[0].r.begin(), out_notes[1].a_pk.begin(), out_notes[1].value(), out_notes[1].r.begin(), vpub_old, vpub_new ); return proof; } if (!computeProof) { return PHGRProof(); } protoboard<FieldT> pb; { joinsplit_gadget<FieldT, NumInputs, NumOutputs> g(pb); g.generate_r1cs_constraints(); g.generate_r1cs_witness( phi, rt, h_sig, inputs, out_notes, vpub_old, vpub_new ); } // The constraint system must be satisfied or there is an unimplemented // or incorrect sanity check above. Or the constraint system is broken! assert(pb.is_satisfied()); // TODO: These are copies, which is not strictly necessary. std::vector<FieldT> primary_input = pb.primary_input(); std::vector<FieldT> aux_input = pb.auxiliary_input(); // Swap A and B if it's beneficial (less arithmetic in G2) // In our circuit, we already know that it's beneficial // to swap, but it takes so little time to perform this // estimate that it doesn't matter if we check every time. pb.constraint_system.swap_AB_if_beneficial(); std::ifstream fh(pkPath, std::ios::binary); if(!fh.is_open()) { throw std::runtime_error(strprintf("could not load param file at %s", pkPath)); } return PHGRProof(r1cs_ppzksnark_prover_streaming<ppzksnark_ppT>( fh, primary_input, aux_input, pb.constraint_system )); }