OpenCBDC Transaction Processor
Loading...
Searching...
No Matches
transaction.cpp
Go to the documentation of this file.
1// Copyright (c) 2021 MIT Digital Currency Initiative,
2// Federal Reserve Bank of Boston
3// Distributed under the MIT software license, see the accompanying
4// file COPYING or http://www.opensource.org/licenses/mit-license.php.
5
6#include "transaction.hpp"
7
8#include "crypto/sha256.h"
9#include "messages.hpp"
12
14 auto out_point::operator==(const out_point& rhs) const -> bool {
15 return m_tx_id == rhs.m_tx_id && m_index == rhs.m_index;
16 }
17
18 auto out_point::operator<(const out_point& rhs) const -> bool {
19 return std::tie(m_tx_id, m_index) < std::tie(rhs.m_tx_id, rhs.m_index);
20 }
21
22 out_point::out_point(const hash_t& hash, const uint64_t index)
23 : m_tx_id(hash),
24 m_index(index) {}
25
26 auto output::operator==(const output& rhs) const -> bool {
27 return m_witness_program_commitment == rhs.m_witness_program_commitment
28 && m_value == rhs.m_value;
29 }
30
31 auto output::operator!=(const output& rhs) const -> bool {
32 return !(*this == rhs);
33 }
34
35 output::output(hash_t witness_program_commitment, uint64_t value)
36 : m_witness_program_commitment(witness_program_commitment),
37 m_value(value) {}
38
39 auto input::operator==(const input& rhs) const -> bool {
40 return m_prevout == rhs.m_prevout
41 && m_prevout_data == rhs.m_prevout_data;
42 }
43
44 auto input::operator!=(const input& rhs) const -> bool {
45 return !(*this == rhs);
46 }
47
48 auto input::hash() const -> hash_t {
49 auto buf = cbdc::make_buffer(*this);
50
51 CSHA256 sha;
52 hash_t result;
53
54 sha.Write(buf.c_ptr(), buf.size());
55 sha.Finalize(result.data());
56
57 return result;
58 }
59
60 auto full_tx::operator==(const full_tx& rhs) const -> bool {
61 return rhs.m_inputs == m_inputs && rhs.m_outputs == m_outputs
62 && rhs.m_witness == m_witness;
63 }
64
65 auto compact_tx_hasher::operator()(const compact_tx& tx) const noexcept
66 -> size_t {
67 size_t ret{};
68 std::memcpy(&ret, tx.m_id.data(), sizeof(ret));
69 return ret;
70 }
71
72 auto tx_id(const full_tx& tx) noexcept -> hash_t {
73 CSHA256 sha;
74
75 auto inp_buf = cbdc::make_buffer(tx.m_inputs);
76 sha.Write(inp_buf.c_ptr(), inp_buf.size());
77
78 auto out_buf = cbdc::make_buffer(tx.m_outputs);
79 sha.Write(out_buf.c_ptr(), out_buf.size());
80
81 hash_t ret;
82 sha.Finalize(ret.data());
83
84 return ret;
85 }
86
87 auto input_from_output(const full_tx& tx, size_t i, const hash_t& txid)
88 -> std::optional<input> {
89 input ret;
90 if(i >= tx.m_outputs.size()) {
91 return std::nullopt;
92 }
93 ret.m_prevout_data = tx.m_outputs[i];
94 ret.m_prevout.m_index = i;
95 ret.m_prevout.m_tx_id = txid;
96 return ret;
97 }
98
99 auto input_from_output(const full_tx& tx, size_t i)
100 -> std::optional<input> {
101 const auto id = tx_id(tx);
102 return input_from_output(tx, i, id);
103 }
104
105 auto uhs_id_from_output(const hash_t& entropy,
106 uint64_t i,
107 const output& output) -> hash_t {
108 CSHA256 sha;
109 hash_t ret;
110 sha.Write(entropy.data(), entropy.size());
111 std::array<unsigned char, sizeof(i)> index_arr{};
112 std::memcpy(index_arr.data(), &i, sizeof(i));
113 sha.Write(index_arr.data(), sizeof(i));
114
115 auto buf = cbdc::make_buffer(output);
116
117 sha.Write(buf.c_ptr(), buf.size());
118 sha.Finalize(ret.data());
119 return ret;
120 }
121
122 auto compact_tx::operator==(const compact_tx& tx) const noexcept -> bool {
123 return m_id == tx.m_id;
124 }
125
127 m_id = tx_id(tx);
128 for(const auto& inp : tx.m_inputs) {
129 m_inputs.push_back(inp.hash());
130 }
131 for(uint64_t i = 0; i < tx.m_outputs.size(); i++) {
132 m_uhs_outputs.push_back(
134 }
135 }
136
137 auto compact_tx::sign(secp256k1_context* ctx, const privkey_t& key) const
139 auto payload = hash();
140 auto pubkey = pubkey_from_privkey(key, ctx);
141 secp256k1_keypair keypair{};
142 [[maybe_unused]] const auto ret
143 = secp256k1_keypair_create(ctx, &keypair, key.data());
144 assert(ret == 1);
145
146 auto sig = signature_t();
147 [[maybe_unused]] const auto sign_ret
148 = secp256k1_schnorrsig_sign(ctx,
149 sig.data(),
150 payload.data(),
151 &keypair,
152 nullptr,
153 nullptr);
154 assert(sign_ret == 1);
155 return {pubkey, sig};
156 }
157
158 auto compact_tx::hash() const -> hash_t {
159 // Don't include the attesations in the hash
160 auto ctx = *this;
161 ctx.m_attestations.clear();
162 auto buf = make_buffer(ctx);
163 auto sha = CSHA256();
164 sha.Write(buf.c_ptr(), buf.size());
165 auto ret = hash_t();
166 sha.Finalize(ret.data());
167 return ret;
168 }
169
171 const sentinel_attestation& att) const -> bool {
172 auto payload = hash();
173 secp256k1_xonly_pubkey pubkey{};
174 if(secp256k1_xonly_pubkey_parse(ctx, &pubkey, att.first.data()) != 1) {
175 return false;
176 }
177
178 if(secp256k1_schnorrsig_verify(ctx,
179 att.second.data(),
180 payload.data(),
181 &pubkey)
182 != 1) {
183 return false;
184 }
185
186 return true;
187 }
188}
struct secp256k1_context_struct secp256k1_context
Definition keys.hpp:14
auto uhs_id_from_output(const hash_t &entropy, uint64_t i, const output &output) -> hash_t
std::pair< pubkey_t, signature_t > sentinel_attestation
Sentinel attestation type.
auto tx_id(const full_tx &tx) noexcept -> hash_t
Calculates the unique hash of a full transaction.
auto input_from_output(const full_tx &tx, size_t i, const hash_t &txid) -> std::optional< input >
Converts the output at the specified index to an input.
std::array< unsigned char, cbdc::hash_size > hash_t
SHA256 hash container.
std::array< unsigned char, pubkey_len > privkey_t
A private key of a public/private keypair.
Definition keys.hpp:23
std::array< unsigned char, sig_len > signature_t
A signature.
Definition keys.hpp:29
auto make_buffer(const T &obj) -> std::enable_if_t< std::is_same_v< B, nuraft::ptr< nuraft::buffer > >, nuraft::ptr< nuraft::buffer > >
Serialize object into nuraft::buffer using a cbdc::nuraft_serializer.
auto pubkey_from_privkey(const privkey_t &privkey, secp256k1_context *ctx) -> pubkey_t
Generates a public key from the specified private key.
Definition keys.cpp:12
auto operator()(compact_tx const &tx) const noexcept -> size_t
A condensed, hash-only transaction representation.
std::vector< hash_t > m_inputs
The set of hashes of the transaction's inputs.
hash_t m_id
The hash of the full transaction returned by tx_id.
std::vector< hash_t > m_uhs_outputs
The set of hashes of the new outputs created in the transaction.
auto hash() const -> hash_t
Return the hash of the compact transaction, without the sentinel attestations included.
auto operator==(const compact_tx &tx) const noexcept -> bool
Equality of two compact transactions.
auto verify(secp256k1_context *ctx, const sentinel_attestation &att) const -> bool
Verify the given attestation contains a valid signature that matches the compact transaction.
auto sign(secp256k1_context *ctx, const privkey_t &key) const -> sentinel_attestation
Sign the compact transaction and return the signature.
A complete transaction.
std::vector< input > m_inputs
The set of inputs for the transaction.
std::vector< output > m_outputs
The set of new outputs created by the transaction.
auto operator==(const full_tx &rhs) const -> bool
An input for a new transaction.
out_point m_prevout
The unique identifier of the output.
auto hash() const -> hash_t
output m_prevout_data
The output's data.
auto operator==(const input &rhs) const -> bool
auto operator!=(const input &rhs) const -> bool
The unique identifier of a specific output from a transaction.
hash_t m_tx_id
The hash of the transaction which created the out_point.
auto operator==(const out_point &rhs) const -> bool
uint64_t m_index
The index of the output in the transaction's output list.
auto operator<(const out_point &rhs) const -> bool
An output of a transaction.
auto operator!=(const output &rhs) const -> bool
auto operator==(const output &rhs) const -> bool