1
// Copyright © 2017-2020 Trust Wallet.
2
//
3
// This file is part of Trust. The full Trust copyright notice, including
4
// terms governing use, modification, and redistribution, is contained in the
5
// file LICENSE at the root of the source code distribution tree.
6

7
#include "Signer.h"
8

9
#include "Address.h"
10
#include "BinaryCoding.h"
11
#include "../Hash.h"
12
#include "../PrivateKey.h"
13

14
using namespace TW;
15
using namespace TW::NULS;
16

17 1
Proto::SigningOutput Signer::sign(const Proto::SigningInput& input) noexcept {
18 1
    auto output = Proto::SigningOutput();
19
    try {
20 1
        auto signer = Signer(input);
21 1
        auto data = signer.sign();
22 1
        output.set_encoded(data.data(), data.size());
23
    }
24 0
    catch(...) {}
25 1
    return output;
26
}
27

28 1
Signer::Signer(const Proto::SigningInput& input) : input(input) {
29 1
    Proto::TransactionCoinFrom coinFrom;
30 1
    coinFrom.set_from_address(input.from());
31 1
    coinFrom.set_assets_chainid(input.chain_id());
32 1
    coinFrom.set_assets_id(input.idassets_id());
33
    //need to update with amount + fee
34 1
    coinFrom.set_id_amount(input.amount());
35 1
    coinFrom.set_nonce(input.nonce());
36
    //default unlocked
37 1
    coinFrom.set_locked(0);
38 1
    *tx.mutable_input() = coinFrom;
39

40 1
    Proto::TransactionCoinTo coinTo;
41 1
    coinTo.set_to_address(input.to());
42 1
    coinTo.set_id_amount(input.amount());
43 1
    coinTo.set_assets_chainid(input.chain_id());
44 1
    coinTo.set_assets_id(input.idassets_id());
45 1
    coinTo.set_lock_time(0);
46 1
    *tx.mutable_output() = coinTo;
47

48 1
    tx.set_remark(input.remark());
49 1
    tx.set_type(TX_TYPE);
50 1
    tx.set_timestamp(input.timestamp());
51 1
    tx.set_tx_data("");
52
}
53

54 1
Data Signer::sign() const {
55 1
    if (input.private_key().empty()) {
56 0
        throw std::invalid_argument("Must have private key string");
57
    }
58

59 1
    uint32_t txSize = CalculatorTransactionSize(1, 1, static_cast<uint32_t>(tx.remark().size()));
60 1
    uint256_t fee = (uint256_t)CalculatorTransactionFee(txSize);
61 1
    uint256_t txAmount = load(input.amount());
62 1
    uint256_t balance = load(input.balance());
63 1
    uint256_t fromAmount = txAmount + fee;
64 1
    if (fromAmount > balance) {
65 0
        throw std::invalid_argument("User account balance not sufficient");
66
    }
67

68 1
    Proto::TransactionCoinFrom& coinFrom = (Proto::TransactionCoinFrom&)tx.input();
69 1
    Data amount;
70 1
    amount = store(fromAmount);
71 1
    std::reverse(amount.begin(), amount.end());
72 1
    std::string amountStr;
73 1
    amountStr.insert(amountStr.begin(), amount.begin(), amount.end());
74 1
    amountStr.append(static_cast<unsigned long>(amount.capacity() - amount.size()), '\0');
75 1
    coinFrom.set_id_amount(amountStr);
76

77 1
    Proto::TransactionCoinTo& coinTo = (Proto::TransactionCoinTo&)tx.output();
78 1
    Data amountTo;
79 1
    amountTo = store(txAmount);
80 1
    std::reverse(amountTo.begin(), amountTo.end());
81 1
    std::string amountToStr;
82 1
    amountToStr.insert(amountToStr.begin(), amountTo.begin(), amountTo.end());
83 1
    amountToStr.append(static_cast<unsigned long>(amountTo.capacity() - amountTo.size()), '\0');
84 1
    coinTo.set_id_amount(amountToStr);
85

86 1
    auto dataRet = Data();
87
    // Transaction Type
88 1
    encode16LE(static_cast<uint16_t>(tx.type()), dataRet);
89
    // Timestamp
90 1
    encode32LE(tx.timestamp(), dataRet);
91
     // Remark
92 1
    std::string remark = tx.remark();
93 1
    serializerRemark(remark, dataRet);
94
    // txData
95 1
    encodeVarInt(0, dataRet);
96

97
    //coinFrom and coinTo size
98 1
    encodeVarInt(TRANSACTION_INPUT_SIZE + TRANSACTION_OUTPUT_SIZE, dataRet);
99

100
    // CoinData Input
101 1
    serializerInput(tx.input(), dataRet);
102

103
    // CoinData Output
104 1
    serializerOutput(tx.output(), dataRet);
105

106
    // Calc transaction hash
107 1
    Data txHash = calcTransactionDigest(dataRet);
108
   
109 1
    Data privKey = data(input.private_key());
110 1
    auto priv = PrivateKey(privKey);
111 1
    auto transactionSignature = makeTransactionSignature(priv, txHash);
112 1
    encodeVarInt(transactionSignature.size(), dataRet);
113 1
    std::copy(transactionSignature.begin(), transactionSignature.end(), std::back_inserter(dataRet));
114

115 1
    return dataRet;
116
}
117

118 1
uint32_t Signer::CalculatorTransactionSize(uint32_t inputCount, uint32_t outputCount, uint32_t remarkSize) const {
119 1
    uint32_t size = TRANSACTION_FIX_SIZE + TRANSACTION_SIG_MAX_SIZE + TRANSACTION_INPUT_SIZE * inputCount +
120 1
                        TRANSACTION_OUTPUT_SIZE * outputCount + remarkSize;
121 1
    return size;
122
}
123

124 1
uint64_t Signer::CalculatorTransactionFee(uint64_t size) const {
125 1
    uint64_t fee = (size / 1024) * MIN_PRICE_PRE_1024_BYTES;
126 1
    if (size % 1024 > 0) {
127 1
        fee += MIN_PRICE_PRE_1024_BYTES;
128
    }
129 1
    return fee;
130
}

Read our documentation on viewing source code .

Loading