Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[0.17] Add Elements-style witness structure #494

Merged
merged 9 commits into from
Feb 13, 2019
2 changes: 2 additions & 0 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,8 @@ libbitcoin_consensus_a_SOURCES = \
prevector.h \
primitives/block.cpp \
primitives/block.h \
primitives/txwitness.cpp \
primitives/txwitness.h \
primitives/transaction.cpp \
primitives/transaction.h \
primitives/pak.cpp \
Expand Down
3 changes: 2 additions & 1 deletion src/bench/block_assemble.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,8 @@ static void AssembleBlock(benchmark::State& state)
for (size_t b{0}; b < NUM_BLOCKS; ++b) {
CMutableTransaction tx;
tx.vin.push_back(MineBlock(SCRIPT_PUB));
tx.vin.back().scriptWitness = witness;
tx.witness.vtxinwit.resize(1);
tx.witness.vtxinwit.back().scriptWitness = witness;
tx.vout.emplace_back(1337, SCRIPT_PUB);
if (NUM_BLOCKS - b >= COINBASE_MATURITY)
txs.at(b) = MakeTransactionRef(tx);
Expand Down
34 changes: 23 additions & 11 deletions src/bench/mempool_eviction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#include <list>
#include <vector>
#include <primitives/transaction.h>

static void AddTx(const CTransactionRef& tx, const CAmount& nFee, CTxMemPool& pool) EXCLUSIVE_LOCKS_REQUIRED(pool.cs)
{
Expand All @@ -30,15 +31,17 @@ static void MempoolEviction(benchmark::State& state)
CMutableTransaction tx1 = CMutableTransaction();
tx1.vin.resize(1);
tx1.vin[0].scriptSig = CScript() << OP_1;
tx1.vin[0].scriptWitness.stack.push_back({1});
tx1.witness.vtxinwit.resize(1);
tx1.witness.vtxinwit[0].scriptWitness.stack.push_back({1});
tx1.vout.resize(1);
tx1.vout[0].scriptPubKey = CScript() << OP_1 << OP_EQUAL;
tx1.vout[0].nValue = 10 * COIN;

CMutableTransaction tx2 = CMutableTransaction();
tx2.vin.resize(1);
tx2.vin[0].scriptSig = CScript() << OP_2;
tx2.vin[0].scriptWitness.stack.push_back({2});
tx2.witness.vtxinwit.resize(1);
tx2.witness.vtxinwit[0].scriptWitness.stack.push_back({2});
tx2.vout.resize(1);
tx2.vout[0].scriptPubKey = CScript() << OP_2 << OP_EQUAL;
tx2.vout[0].nValue = 10 * COIN;
Expand All @@ -47,7 +50,8 @@ static void MempoolEviction(benchmark::State& state)
tx3.vin.resize(1);
tx3.vin[0].prevout = COutPoint(tx2.GetHash(), 0);
tx3.vin[0].scriptSig = CScript() << OP_2;
tx3.vin[0].scriptWitness.stack.push_back({3});
tx3.witness.vtxinwit.resize(1);
tx3.witness.vtxinwit[0].scriptWitness.stack.push_back({3});
tx3.vout.resize(1);
tx3.vout[0].scriptPubKey = CScript() << OP_3 << OP_EQUAL;
tx3.vout[0].nValue = 10 * COIN;
Expand All @@ -56,10 +60,12 @@ static void MempoolEviction(benchmark::State& state)
tx4.vin.resize(2);
tx4.vin[0].prevout.SetNull();
tx4.vin[0].scriptSig = CScript() << OP_4;
tx4.vin[0].scriptWitness.stack.push_back({4});
tx4.witness.vtxinwit.resize(1);
tx4.witness.vtxinwit[0].scriptWitness.stack.push_back({4});
tx4.vin[1].prevout.SetNull();
tx4.vin[1].scriptSig = CScript() << OP_4;
tx4.vin[1].scriptWitness.stack.push_back({4});
tx4.witness.vtxinwit.resize(2);
tx4.witness.vtxinwit[1].scriptWitness.stack.push_back({4});
tx4.vout.resize(2);
tx4.vout[0].scriptPubKey = CScript() << OP_4 << OP_EQUAL;
tx4.vout[0].nValue = 10 * COIN;
Expand All @@ -70,10 +76,12 @@ static void MempoolEviction(benchmark::State& state)
tx5.vin.resize(2);
tx5.vin[0].prevout = COutPoint(tx4.GetHash(), 0);
tx5.vin[0].scriptSig = CScript() << OP_4;
tx5.vin[0].scriptWitness.stack.push_back({4});
tx5.witness.vtxinwit.resize(1);
tx5.witness.vtxinwit[0].scriptWitness.stack.push_back({4});
tx5.vin[1].prevout.SetNull();
tx5.vin[1].scriptSig = CScript() << OP_5;
tx5.vin[1].scriptWitness.stack.push_back({5});
tx5.witness.vtxinwit.resize(2);
tx5.witness.vtxinwit[1].scriptWitness.stack.push_back({5});
tx5.vout.resize(2);
tx5.vout[0].scriptPubKey = CScript() << OP_5 << OP_EQUAL;
tx5.vout[0].nValue = 10 * COIN;
Expand All @@ -84,10 +92,12 @@ static void MempoolEviction(benchmark::State& state)
tx6.vin.resize(2);
tx6.vin[0].prevout = COutPoint(tx4.GetHash(), 1);
tx6.vin[0].scriptSig = CScript() << OP_4;
tx6.vin[0].scriptWitness.stack.push_back({4});
tx6.witness.vtxinwit.resize(1);
tx6.witness.vtxinwit[0].scriptWitness.stack.push_back({4});
tx6.vin[1].prevout.SetNull();
tx6.vin[1].scriptSig = CScript() << OP_6;
tx6.vin[1].scriptWitness.stack.push_back({6});
tx6.witness.vtxinwit.resize(2);
tx6.witness.vtxinwit[1].scriptWitness.stack.push_back({6});
tx6.vout.resize(2);
tx6.vout[0].scriptPubKey = CScript() << OP_6 << OP_EQUAL;
tx6.vout[0].nValue = 10 * COIN;
Expand All @@ -98,10 +108,12 @@ static void MempoolEviction(benchmark::State& state)
tx7.vin.resize(2);
tx7.vin[0].prevout = COutPoint(tx5.GetHash(), 0);
tx7.vin[0].scriptSig = CScript() << OP_5;
tx7.vin[0].scriptWitness.stack.push_back({5});
tx7.witness.vtxinwit.resize(1);
tx7.witness.vtxinwit[0].scriptWitness.stack.push_back({5});
tx7.vin[1].prevout = COutPoint(tx6.GetHash(), 0);
tx7.vin[1].scriptSig = CScript() << OP_6;
tx7.vin[1].scriptWitness.stack.push_back({6});
tx7.witness.vtxinwit.resize(2);
tx7.witness.vtxinwit[1].scriptWitness.stack.push_back({6});
tx7.vout.resize(2);
tx7.vout[0].scriptPubKey = CScript() << OP_7 << OP_EQUAL;
tx7.vout[0].nValue = 10 * COIN;
Expand Down
5 changes: 3 additions & 2 deletions src/bench/verify_script.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@ static void VerifyScriptBench(benchmark::State& state)
CScript witScriptPubkey = CScript() << OP_DUP << OP_HASH160 << ToByteVector(pubkeyHash) << OP_EQUALVERIFY << OP_CHECKSIG;
const CMutableTransaction& txCredit = BuildCreditingTransaction(scriptPubKey);
CMutableTransaction txSpend = BuildSpendingTransaction(scriptSig, txCredit);
CScriptWitness& witness = txSpend.vin[0].scriptWitness;
txSpend.witness.vtxinwit.resize(1);
CScriptWitness& witness = txSpend.witness.vtxinwit[0].scriptWitness;
witness.stack.emplace_back();
key.Sign(SignatureHash(witScriptPubkey, txSpend, 0, SIGHASH_ALL, txCredit.vout[0].nValue, SigVersion::WITNESS_V0), witness.stack.back());
witness.stack.back().push_back(static_cast<unsigned char>(SIGHASH_ALL));
Expand All @@ -86,7 +87,7 @@ static void VerifyScriptBench(benchmark::State& state)
bool success = VerifyScript(
txSpend.vin[0].scriptSig,
txCredit.vout[0].scriptPubKey,
&txSpend.vin[0].scriptWitness,
&txSpend.witness.vtxinwit[0].scriptWitness,
flags,
MutableTransactionSignatureChecker(&txSpend, 0, txCredit.vout[0].nValue),
&err);
Expand Down
2 changes: 1 addition & 1 deletion src/bitcoin-tx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -649,7 +649,7 @@ static void MutateTxSign(CMutableTransaction& tx, const std::string& flagStr)
if (!fHashSingle || (i < mergedTx.vout.size()))
ProduceSignature(keystore, MutableTransactionSignatureCreator(&mergedTx, i, amount, nHashType), prevPubKey, sigdata);

UpdateInput(txin, sigdata);
UpdateTransaction(mergedTx, i, sigdata);
}

tx = mergedTx;
Expand Down
6 changes: 4 additions & 2 deletions src/chainparams.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include <chainparamsseeds.h>
#include <consensus/merkle.h>
#include <primitives/transaction.h>
#include <tinyformat.h>
#include <util.h>
#include <utilstrencodings.h>
Expand Down Expand Up @@ -523,9 +524,10 @@ class CCustomParams : public CRegTestParams {
consensus.max_block_signature_size = gArgs.GetArg("-con_max_block_sig_size", 74);
g_signed_blocks = gArgs.GetBoolArg("-con_signed_blocks", true);

// Note: This global is needed to avoid circular dependency
// Defaults to true for custom chains.
// Note: These globals are needed to avoid circular dependencies.
// Default to true for custom chains.
g_con_blockheightinheader = args.GetBoolArg("-con_blockheightinheader", true);
g_con_elementswitness = args.GetBoolArg("-con_elementswitness", true);

// No subsidy for custom chains by default
consensus.genesis_subsidy = args.GetArg("-con_blocksubsidy", 0);
Expand Down
1 change: 1 addition & 0 deletions src/chainparamsbase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ void SetupChainParamsBaseOptions()
gArgs.AddArg("-con_mandatorycoinbase", "All non-zero valued coinbase outputs must go to this scriptPubKey, if set.", false, OptionsCategory::ELEMENTS);
gArgs.AddArg("-con_blocksubsidy", "Defines the amount of block subsidy to start with, at genesis block.", false, OptionsCategory::ELEMENTS);
gArgs.AddArg("-con_connect_coinbase", "Connect outputs in genesis block to utxo database.", false, OptionsCategory::ELEMENTS);
gArgs.AddArg("-con_elementswitness", "Use Elements-like instead of Core-like witness encoding. This is required for CA/CT. (default: true)", false, OptionsCategory::ELEMENTS);
gArgs.AddArg("-con_blockheightinheader", "Whether the chain includes the block height directly in the header, for easier validation of block height in low-resource environments. (default: true)", false, OptionsCategory::CHAINPARAMS);
gArgs.AddArg("-con_genesis_style=<style>", "Use genesis style <style> (default: elements). Results in genesis block compatibility with various networks. Allowed values: elements, bitcoin", true, OptionsCategory::ELEMENTS);
gArgs.AddArg("-con_signed_blocks", "Signed blockchain. Uses input of `-signblockscript` to define what signatures are necessary to solve it.", false, OptionsCategory::CHAINPARAMS);
Expand Down
7 changes: 5 additions & 2 deletions src/consensus/merkle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,11 @@ uint256 BlockWitnessMerkleRoot(const CBlock& block, bool* mutated)
leaves.resize(block.vtx.size());
leaves[0].SetNull(); // The witness hash of the coinbase is 0.
for (size_t s = 1; s < block.vtx.size(); s++) {
leaves[s] = block.vtx[s]->GetWitnessHash();
if (g_con_elementswitness) {
leaves[s] = block.vtx[s]->GetWitnessOnlyHash();
} else {
leaves[s] = block.vtx[s]->GetWitnessHash();
}
}
return ComputeMerkleRoot(std::move(leaves), mutated);
}

1 change: 0 additions & 1 deletion src/consensus/merkle.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
#include <stdint.h>
#include <vector>

#include <primitives/transaction.h>
#include <primitives/block.h>
#include <uint256.h>

Expand Down
21 changes: 11 additions & 10 deletions src/consensus/tx_verify.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -159,20 +159,21 @@ int64_t GetTransactionSigOpCost(const CTransaction& tx, const CCoinsViewCache& i

for (unsigned int i = 0; i < tx.vin.size(); i++)
{
std::string err;
if (tx.vin[i].m_is_pegin && !IsValidPeginWitness(tx.vin[i].m_pegin_witness, tx.vin[i].prevout, err, true)) {
continue;
}

CTxOut prevout;
if (tx.vin[i].m_is_pegin) {
prevout = GetPeginOutputFromWitness(tx.vin[i].m_pegin_witness);
std::string err;
if (tx.witness.vtxinwit.size() <= i || !IsValidPeginWitness(tx.witness.vtxinwit[i].m_pegin_witness, tx.vin[i].prevout, err, true)) {
continue;
}
prevout = GetPeginOutputFromWitness(tx.witness.vtxinwit[i].m_pegin_witness);
} else {
const Coin& coin = inputs.AccessCoin(tx.vin[i].prevout);
assert(!coin.IsSpent());
prevout = coin.out;
}
nSigOps += CountWitnessSigOps(tx.vin[i].scriptSig, prevout.scriptPubKey, &tx.vin[i].scriptWitness, flags);

const CScriptWitness* pScriptWitness = tx.witness.vtxinwit.size() > i ? &tx.witness.vtxinwit[i].scriptWitness : NULL;
nSigOps += CountWitnessSigOps(tx.vin[i].scriptSig, prevout.scriptPubKey, pScriptWitness, flags);
}
return nSigOps;
}
Expand Down Expand Up @@ -241,10 +242,10 @@ bool CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoins
if (tx.vin[i].m_is_pegin) {
// Check existence and validity of pegin witness
std::string err;
if (!IsValidPeginWitness(tx.vin[i].m_pegin_witness, prevout, err, true)) {
if (tx.witness.vtxinwit.size() <= i || !IsValidPeginWitness(tx.witness.vtxinwit[i].m_pegin_witness, prevout, err, true)) {
return state.DoS(0, false, REJECT_PEGIN, "bad-pegin-witness");
}
std::pair<uint256, COutPoint> pegin = std::make_pair(uint256(tx.vin[i].m_pegin_witness.stack[2]), prevout);
std::pair<uint256, COutPoint> pegin = std::make_pair(uint256(tx.witness.vtxinwit[i].m_pegin_witness.stack[2]), prevout);
if (inputs.IsPeginSpent(pegin)) {
return state.Invalid(false, REJECT_INVALID, "bad-txns-double-pegin", strprintf("Double-pegin of %s:%d", prevout.hash.ToString(), prevout.n));
}
Expand All @@ -255,7 +256,7 @@ bool CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoins
setPeginsSpent.insert(pegin);

// Tally the input amount.
const CTxOut out = GetPeginOutputFromWitness(tx.vin[i].m_pegin_witness);
const CTxOut out = GetPeginOutputFromWitness(tx.witness.vtxinwit[i].m_pegin_witness);
if (!MoneyRange(out.nValue)) {
return state.DoS(100, false, REJECT_INVALID, "bad-txns-pegin-inputvalue-outofrange");
}
Expand Down
10 changes: 8 additions & 2 deletions src/consensus/validation.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,10 +103,16 @@ static inline int64_t GetBlockWeight(const CBlock& block)
{
return ::GetSerializeSize(block, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) * (WITNESS_SCALE_FACTOR - 1) + ::GetSerializeSize(block, PROTOCOL_VERSION);
}
static inline int64_t GetTransactionInputWeight(const CTxIn& txin)

static inline int64_t GetTransactionInputWeight(const CTransaction& tx, const size_t nIn)
{
// scriptWitness size is added here because witnesses and txins are split up in segwit serialization.
return ::GetSerializeSize(txin, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) * (WITNESS_SCALE_FACTOR - 1) + ::GetSerializeSize(txin, PROTOCOL_VERSION) + ::GetSerializeSize(txin.scriptWitness.stack, PROTOCOL_VERSION);
assert(tx.witness.vtxinwit.size() > nIn);
//TODO(rebase) only count CA/CT witnesses when g_con_elementswitness is true
return ::GetSerializeSize(tx.vin[nIn], PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) * (WITNESS_SCALE_FACTOR - 1)
+ ::GetSerializeSize(tx.vin[nIn], PROTOCOL_VERSION)
+ ::GetSerializeSize(tx.witness.vtxinwit[nIn].scriptWitness.stack, PROTOCOL_VERSION)
+ ::GetSerializeSize(tx.witness.vtxinwit[nIn].m_pegin_witness.stack, PROTOCOL_VERSION);
}

#endif // BITCOIN_CONSENSUS_VALIDATION_H
34 changes: 31 additions & 3 deletions src/core_memusage.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,37 @@ static inline size_t RecursiveDynamicUsage(const COutPoint& out) {
}

static inline size_t RecursiveDynamicUsage(const CTxIn& in) {
size_t mem = RecursiveDynamicUsage(in.scriptSig) + RecursiveDynamicUsage(in.prevout) + memusage::DynamicUsage(in.scriptWitness.stack);
for (std::vector<std::vector<unsigned char> >::const_iterator it = in.scriptWitness.stack.begin(); it != in.scriptWitness.stack.end(); it++) {
mem += memusage::DynamicUsage(*it);
size_t mem = RecursiveDynamicUsage(in.scriptSig) + RecursiveDynamicUsage(in.prevout);
return mem;
}

static inline size_t RecursiveDynamicUsage(const CScriptWitness& scriptWit) {
size_t mem = memusage::DynamicUsage(scriptWit.stack);
for (std::vector<std::vector<unsigned char> >::const_iterator it = scriptWit.stack.begin(); it != scriptWit.stack.end(); it++) {
mem += memusage::DynamicUsage(*it);
}
return mem;
}

static inline size_t RecursiveDynamicUsage(const CTxInWitness& txInWit) {
size_t mem = RecursiveDynamicUsage(txInWit.scriptWitness);
mem += RecursiveDynamicUsage(txInWit.m_pegin_witness);
return mem;
}

static inline size_t RecursiveDynamicUsage(const CTxOutWitness& txOutWit) {
size_t mem = memusage::DynamicUsage(txOutWit.vchRangeproof);
mem += memusage::DynamicUsage(txOutWit.vchSurjectionproof);
return mem;
}

static inline size_t RecursiveDynamicUsage(const CTxWitness& wit) {
size_t mem = memusage::DynamicUsage(wit.vtxinwit) + memusage::DynamicUsage(wit.vtxoutwit);
for (const auto& txInWit: wit.vtxinwit) {
mem += RecursiveDynamicUsage(txInWit);
}
for (const auto& txOutWit: wit.vtxoutwit) {
mem += RecursiveDynamicUsage(txOutWit);
}
return mem;
}
Expand Down
21 changes: 14 additions & 7 deletions src/core_write.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,10 @@ void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry,
{
entry.pushKV("txid", tx.GetHash().GetHex());
entry.pushKV("hash", tx.GetWitnessHash().GetHex());
if (g_con_elementswitness) {
entry.pushKV("wtxid", tx.GetWitnessHash().GetHex());
entry.pushKV("withash", tx.GetWitnessOnlyHash().GetHex());
}
entry.pushKV("version", tx.nVersion);
entry.pushKV("size", (int)::GetSerializeSize(tx, PROTOCOL_VERSION));
entry.pushKV("vsize", (GetTransactionWeight(tx) + WITNESS_SCALE_FACTOR - 1) / WITNESS_SCALE_FACTOR);
Expand All @@ -220,19 +224,22 @@ void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry,
o.pushKV("hex", HexStr(txin.scriptSig.begin(), txin.scriptSig.end()));
in.pushKV("scriptSig", o);

if (!tx.vin[i].scriptWitness.IsNull()) {
UniValue txinwitness(UniValue::VARR);
for (const auto& item : tx.vin[i].scriptWitness.stack) {
txinwitness.push_back(HexStr(item.begin(), item.end()));
if (tx.witness.vtxinwit.size() > i) {
const CScriptWitness &scriptWitness = tx.witness.vtxinwit[i].scriptWitness;
if (!scriptWitness.IsNull()) {
UniValue txinwitness(UniValue::VARR);
for (const auto &item : scriptWitness.stack) {
txinwitness.push_back(HexStr(item.begin(), item.end()));
}
in.pushKV("txinwitness", txinwitness);
}
in.pushKV("txinwitness", txinwitness);
}

// ELEMENTS:
in.pushKV("is_pegin", txin.m_is_pegin);
if (!tx.vin[i].m_pegin_witness.IsNull()) {
if (tx.witness.vtxinwit.size() > i && !tx.witness.vtxinwit[i].m_pegin_witness.IsNull()) {
UniValue pegin_witness(UniValue::VARR);
for (const auto& item : tx.vin[i].m_pegin_witness.stack) {
for (const auto& item : tx.witness.vtxinwit[i].m_pegin_witness.stack) {
pegin_witness.push_back(HexStr(item.begin(), item.end()));
}
in.pushKV("pegin_witness", pegin_witness);
Expand Down
28 changes: 28 additions & 0 deletions src/crypto/sha256.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -670,6 +670,23 @@ CSHA256& CSHA256::Write(const unsigned char* data, size_t len)
}
return *this;
}
//
//void CSHA256::Finalize(unsigned char hash[OUTPUT_SIZE])
//{
// static const unsigned char pad[64] = {0x80};
// unsigned char sizedesc[8];
// WriteBE64(sizedesc, bytes << 3);
// Write(pad, 1 + ((119 - (bytes % 64)) % 64));
// Write(sizedesc, 8);
// WriteBE32(hash, s[0]);
// WriteBE32(hash + 4, s[1]);
// WriteBE32(hash + 8, s[2]);
// WriteBE32(hash + 12, s[3]);
// WriteBE32(hash + 16, s[4]);
// WriteBE32(hash + 20, s[5]);
// WriteBE32(hash + 24, s[6]);
// WriteBE32(hash + 28, s[7]);
//}

void CSHA256::Finalize(unsigned char hash[OUTPUT_SIZE])
{
Expand All @@ -678,6 +695,11 @@ void CSHA256::Finalize(unsigned char hash[OUTPUT_SIZE])
WriteBE64(sizedesc, bytes << 3);
Write(pad, 1 + ((119 - (bytes % 64)) % 64));
Write(sizedesc, 8);
Midstate(hash, NULL, NULL);
}

void CSHA256::Midstate(unsigned char hash[OUTPUT_SIZE], uint64_t* len, unsigned char *buffer)
{
WriteBE32(hash, s[0]);
WriteBE32(hash + 4, s[1]);
WriteBE32(hash + 8, s[2]);
Expand All @@ -686,6 +708,12 @@ void CSHA256::Finalize(unsigned char hash[OUTPUT_SIZE])
WriteBE32(hash + 20, s[5]);
WriteBE32(hash + 24, s[6]);
WriteBE32(hash + 28, s[7]);
if (len) {
*len = bytes << 3;
}
if (buffer) {
memcpy(buffer, buf, bytes % 64);
}
}

CSHA256& CSHA256::Reset()
Expand Down
Loading