ZIP 244 transaction digests
This commit is contained in:
parent
bad7f7eadb
commit
bd1fd2eaca
|
@ -9,6 +9,8 @@
|
|||
#include "tinyformat.h"
|
||||
#include "utilstrencodings.h"
|
||||
|
||||
#include <rust/transaction.h>
|
||||
|
||||
SaplingBundle::SaplingBundle(
|
||||
const std::vector<SpendDescription>& vShieldedSpend,
|
||||
const std::vector<OutputDescription>& vShieldedOutput,
|
||||
|
@ -138,12 +140,39 @@ CMutableTransaction::CMutableTransaction(const CTransaction& tx) : nVersion(tx.n
|
|||
|
||||
uint256 CMutableTransaction::GetHash() const
|
||||
{
|
||||
return SerializeHash(*this);
|
||||
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
|
||||
ss << *this;
|
||||
uint256 hash;
|
||||
assert(zcash_transaction_digests(
|
||||
reinterpret_cast<const unsigned char*>(ss.data()),
|
||||
ss.size(),
|
||||
hash.begin(),
|
||||
nullptr));
|
||||
return hash;
|
||||
}
|
||||
|
||||
uint256 CMutableTransaction::GetAuthDigest() const
|
||||
{
|
||||
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
|
||||
ss << *this;
|
||||
uint256 authDigest;
|
||||
assert(zcash_transaction_digests(
|
||||
reinterpret_cast<const unsigned char*>(ss.data()),
|
||||
ss.size(),
|
||||
nullptr,
|
||||
authDigest.begin()));
|
||||
return authDigest;
|
||||
}
|
||||
|
||||
void CTransaction::UpdateHash() const
|
||||
{
|
||||
*const_cast<uint256*>(&hash) = SerializeHash(*this);
|
||||
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
|
||||
ss << *this;
|
||||
assert(zcash_transaction_digests(
|
||||
reinterpret_cast<const unsigned char*>(ss.data()),
|
||||
ss.size(),
|
||||
const_cast<uint256*>(&hash)->begin(),
|
||||
const_cast<uint256*>(&authDigest)->begin()));
|
||||
}
|
||||
|
||||
CTransaction::CTransaction() : nVersion(CTransaction::SPROUT_MIN_CURRENT_VERSION),
|
||||
|
|
|
@ -714,6 +714,8 @@ private:
|
|||
|
||||
/** Memory only. */
|
||||
const uint256 hash;
|
||||
/** Memory only. */
|
||||
const uint256 authDigest;
|
||||
void UpdateHash() const;
|
||||
|
||||
protected:
|
||||
|
@ -899,6 +901,15 @@ public:
|
|||
return hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the authorizing data commitment for this transaction.
|
||||
*
|
||||
* For v1-v4 transactions, this returns the null hash (i.e. all-zeroes).
|
||||
*/
|
||||
const uint256& GetAuthDigest() const {
|
||||
return authDigest;
|
||||
}
|
||||
|
||||
uint32_t GetHeader() const {
|
||||
// When serializing v1 and v2, the 4 byte header is nVersion
|
||||
uint32_t header = this->nVersion;
|
||||
|
@ -1093,6 +1104,14 @@ struct CMutableTransaction
|
|||
* fly, as opposed to GetHash() in CTransaction, which uses a cached result.
|
||||
*/
|
||||
uint256 GetHash() const;
|
||||
|
||||
/** Compute the authentication digest of this CMutableTransaction. This is
|
||||
* computed on the fly, as opposed to GetAuthDigest() in CTransaction, which
|
||||
* uses a cached result.
|
||||
*
|
||||
* For v1-v4 transactions, this returns the null hash (i.e. all-zeroes).
|
||||
*/
|
||||
uint256 GetAuthDigest() const;
|
||||
};
|
||||
|
||||
#endif // BITCOIN_PRIMITIVES_TRANSACTION_H
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
// Copyright (c) 2020 The Zcash developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or https://www.opensource.org/licenses/mit-license.php .
|
||||
|
||||
#ifndef ZCASH_RUST_INCLUDE_RUST_TRANSACTION_H
|
||||
#define ZCASH_RUST_INCLUDE_RUST_TRANSACTION_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/// Calculates identifying and authorizing digests for the given transaction.
|
||||
///
|
||||
/// If either `txid_ret` or `authDigest_ret` is `nullptr`, the corresponding
|
||||
/// digest will not be calculated.
|
||||
///
|
||||
/// Returns `false` if the transaction is invalid.
|
||||
bool zcash_transaction_digests(
|
||||
const unsigned char* txBytes,
|
||||
size_t txBytes_len,
|
||||
unsigned char* txid_ret,
|
||||
unsigned char* authDigest_ret);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // ZCASH_RUST_INCLUDE_RUST_TRANSACTION_H
|
|
@ -70,6 +70,7 @@ mod streams_ffi;
|
|||
mod tracing_ffi;
|
||||
|
||||
mod orchard_ffi;
|
||||
mod transaction_ffi;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
use std::slice;
|
||||
|
||||
use libc::{c_uchar, size_t};
|
||||
use tracing::error;
|
||||
use zcash_primitives::{
|
||||
consensus::BranchId,
|
||||
transaction::{Transaction, TxVersion},
|
||||
};
|
||||
|
||||
/// Calculates identifying and authorizing digests for the given transaction.
|
||||
///
|
||||
/// If either `txid_ret` or `auth_digest_ret` is `nullptr`, the corresponding digest will
|
||||
/// not be calculated.
|
||||
///
|
||||
/// Returns `false` if the transaction is invalid.
|
||||
#[no_mangle]
|
||||
pub extern "C" fn zcash_transaction_digests(
|
||||
tx_bytes: *const c_uchar,
|
||||
tx_bytes_len: size_t,
|
||||
txid_ret: *mut [u8; 32],
|
||||
auth_digest_ret: *mut [u8; 32],
|
||||
) -> bool {
|
||||
let tx_bytes = unsafe { slice::from_raw_parts(tx_bytes, tx_bytes_len) };
|
||||
|
||||
// We use a placeholder branch ID here, since it is not used for anything.
|
||||
let tx = match Transaction::read(tx_bytes, BranchId::Canopy) {
|
||||
Ok(tx) => tx,
|
||||
Err(e) => {
|
||||
error!("Failed to parse transaction: {}", e);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
if let Some(txid_ret) = unsafe { txid_ret.as_mut() } {
|
||||
*txid_ret = *tx.txid().as_ref();
|
||||
}
|
||||
if let Some(auth_digest_ret) = unsafe { auth_digest_ret.as_mut() } {
|
||||
match tx.version() {
|
||||
// Pre-NU5 transaction formats don't have auth digests; leave it empty so we
|
||||
// don't need to know the correct consensus branch ID for them.
|
||||
TxVersion::Sprout(_) | TxVersion::Overwinter | TxVersion::Sapling => (),
|
||||
_ => auth_digest_ret.copy_from_slice(tx.auth_commitment().as_bytes()),
|
||||
}
|
||||
}
|
||||
|
||||
true
|
||||
}
|
|
@ -868,6 +868,10 @@ BOOST_AUTO_TEST_CASE(TxV5)
|
|||
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
|
||||
ss << tx;
|
||||
BOOST_CHECK_EQUAL(HexStr(ss.begin(), ss.end()), transaction);
|
||||
|
||||
// ZIP 244: Check the transaction digests.
|
||||
BOOST_CHECK_EQUAL(tx.GetHash().GetHex(), test[1].getValStr());
|
||||
BOOST_CHECK_EQUAL(tx.GetAuthDigest().GetHex(), test[2].getValStr());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue