22#include <glog/logging.h>
34 :
config_(config), wallet_(wallet) {
35 tx_mempool_ = std::make_unique<TxMempool>();
36 for (
const UTXO& trans : config_.genesis_transactions().transactions()) {
37 int64_t transaction_id = tx_mempool_->AddUTXO(trans);
39 for (
const UTXOOut& output : trans.out()) {
40 int ret = wallet_->
AddCoin(output.address(), output.value());
42 LOG(ERROR) <<
"add coin fail";
47 LOG(ERROR) <<
"get genesis utxo:" << trans.DebugString()
48 <<
" transaction id:" << transaction_id;
55 absl::StatusOr<std::vector<UTXOOut>> ins_or = GetInput(utxo);
57 LOG(ERROR) <<
"get input fail:" << ins_or.status().message();
61 if (!VerifyUTXO(utxo, *ins_or)) {
62 LOG(ERROR) <<
"transaction is not valid";
67 LOG(ERROR) <<
"add coin fail";
70 return tx_mempool_->AddUTXO(utxo);
75 if (!utxo.ParseFromString(utxo_str)) {
76 LOG(ERROR) <<
"parse utxo fail";
82absl::StatusOr<std::vector<UTXOOut>> Transaction::GetInput(
const UTXO& utxo) {
83 std::vector<UTXOOut> utxos;
84 if (utxo.in_size() == 0) {
85 if (utxo.address() ==
"0000") {
90 int64_t verify_nonce = 0;
91 std::string public_key;
92 for (
const UTXOIn& input : utxo.in()) {
93 absl::StatusOr<UTXOOut> utxo_or =
94 tx_mempool_->GetUTXO(input.prev_id(), input.out_idx(), utxo.address());
96 LOG(ERROR) <<
"get pre utxo id fail:" << input.prev_id();
97 return utxo_or.status();
99 utxos.push_back(*utxo_or);
100 if (public_key.empty()) {
101 public_key = (*utxo_or).pub_key();
103 verify_nonce += input.prev_id();
107 LOG(ERROR) <<
"no input";
108 return absl::InvalidArgumentError(
"Input invalid.");
111 if (utxo.sig().empty()) {
112 LOG(ERROR) <<
"utxo no sig, invalid";
113 return absl::InvalidArgumentError(
"Input invalid.");
116 LOG(ERROR) <<
"get public key:" << public_key <<
" nonce:" << verify_nonce;
119 utxo.address() + std::to_string(verify_nonce), public_key, utxo.sig());
121 LOG(ERROR) <<
"key not valid";
122 return absl::InvalidArgumentError(
"Key invalid.");
125 for (
const UTXOOut& utxo : utxos) {
126 if (utxo.pub_key() != public_key) {
127 LOG(ERROR) <<
"public key not match";
128 return absl::InvalidArgumentError(
"Key invalid.");
135bool Transaction::VerifyUTXO(
const UTXO& utxo,
136 const std::vector<UTXOOut>& inputs) {
137 int64_t total_input_v = 0;
138 for (
const UTXOOut& input : inputs) {
139 int64_t value = input.value();
140 total_input_v += value;
143 for (
const UTXOOut& output : utxo.out()) {
144 total_input_v -= output.value();
147 if (total_input_v <= 0) {
148 LOG(ERROR) <<
"input is not enough";
155int64_t Transaction::GetUTXOOutValue(int64_t transaction_id,
int out_idx,
156 const std::string& address) {
157 return tx_mempool_->GetUTXOOutValue(transaction_id, out_idx, address);
160int Transaction::AddCoin(
const UTXO& utxo) {
161 int64_t total_value = 0;
162 for (
const UTXOIn& input : utxo.in()) {
163 int64_t value = tx_mempool_->MarkSpend(input.prev_id(), input.out_idx(),
166 total_value += value;
169 int ret = wallet_->
AddCoin(utxo.address(), -total_value);
171 LOG(ERROR) <<
"add coin fail";
175 for (
const UTXOOut& output : utxo.out()) {
176 int ret = wallet_->
AddCoin(output.address(), output.value());
178 LOG(ERROR) <<
"add coin fail";
186 return tx_mempool_->GetUTXO(end_id, num);
std::vector< UTXO > GetUTXO(int64_t end_id, int num)
int64_t AddTransaction(const std::string &utxo_string)
Transaction(const Config &config, Wallet *wallet)
int AddCoin(const std::string &address, int64_t value)
bool ECDSAVerifyString(const std::string &message, const std::string &public_key, const std::string &signature)
std::unique_ptr< ResDBConfig > config_