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 "ParamsBuilder.h"
8
#include "Data.h"
9
#include "OpCode.h"
10

11
#include <TrezorCrypto/bignum.h>
12
#include <TrezorCrypto/ecdsa.h>
13
#include <TrezorCrypto/nist256p1.h>
14

15
#include <list>
16

17
using namespace TW;
18
using namespace TW::Ontology;
19

20 1
void ParamsBuilder::buildNeoVmParam(ParamsBuilder& builder, const boost::any& param) {
21 1
    if (param.type() == typeid(std::string)) {
22 0
        builder.push(boost::any_cast<std::string>(param));
23 1
    } else if (param.type() == typeid(std::array<uint8_t, 20>)) {
24 1
        builder.push(boost::any_cast<std::array<uint8_t, 20>>(param));
25 1
    } else if (param.type() == typeid(Data)) {
26 1
        builder.push(boost::any_cast<Data>(param));
27 1
    } else if (param.type() == typeid(uint64_t)) {
28 1
        builder.push(boost::any_cast<uint64_t>(param));
29 1
    } else if (param.type() == typeid(std::vector<boost::any>)) {
30 1
        auto paramVec = boost::any_cast<std::vector<boost::any>>(param);
31 1
        for (const auto& item : paramVec) {
32 1
            ParamsBuilder::buildNeoVmParam(builder, item);
33
        }
34 1
        builder.push(static_cast<uint8_t>(paramVec.size()));
35 1
        builder.pushBack(PACK);
36 1
    } else if (param.type() == typeid(std::list<boost::any>)) {
37 1
        builder.pushBack(PUSH0);
38 1
        builder.pushBack(NEW_STRUCT);
39 1
        builder.pushBack(TO_ALT_STACK);
40 1
        for (auto const& p : boost::any_cast<std::list<boost::any>>(param)) {
41 1
            ParamsBuilder::buildNeoVmParam(builder, p);
42 1
            builder.pushBack(DUP_FROM_ALT_STACK);
43 1
            builder.pushBack(SWAP);
44 1
            builder.pushBack(HAS_KEY);
45
        }
46 1
        builder.pushBack(FROM_ALT_STACK);
47 1
    } else {
48 0
        throw std::runtime_error("Unsupported param type.");
49
    }
50
}
51

52 0
void ParamsBuilder::buildNeoVmParam(ParamsBuilder& builder, const std::string& param) {
53 0
    builder.pushBack(param);
54
}
55

56 0
void ParamsBuilder::buildNeoVmParam(ParamsBuilder& builder, const std::array<uint8_t, 20>& param) {
57 0
    builder.pushBack(Data(param.begin(), param.end()));
58
}
59

60 0
void ParamsBuilder::buildNeoVmParam(ParamsBuilder& builder, const Data& param) {
61 0
    builder.push(param);
62
}
63

64 1
void ParamsBuilder::pushVar(const Data& data) {
65 1
    pushVar(data.size());
66 1
    bytes.insert(bytes.end(), data.begin(), data.end());
67
}
68

69 1
void ParamsBuilder::pushVar(std::size_t value) {
70 1
    if (value < 0xFD) {
71 1
        ParamsBuilder::pushBack(static_cast<uint8_t>(value));
72 1
    } else if (value < 0xFFFF) {
73 0
        bytes.push_back(0xFD);
74 0
        encode16LE(static_cast<uint16_t>(value), bytes);
75 0
    } else if (value < 0xFFFFFFFF) {
76 0
        bytes.push_back(0xFE);
77 0
        encode32LE(static_cast<uint32_t>(value), bytes);
78 0
    } else {
79 0
        bytes.push_back(0xFF);
80 0
        encode64LE(value, bytes);
81
    }
82
}
83

84 0
void ParamsBuilder::push(const std::string& data) {
85 0
    push(Data(data.begin(), data.end()));
86
}
87

88 1
void ParamsBuilder::push(const std::array<uint8_t, 20>& data) {
89 1
    push(Data(data.begin(), data.end()));
90
}
91

92 1
void ParamsBuilder::push(const Data& data) {
93 1
    auto dataSize = data.size();
94 1
    if (dataSize < 75) {
95 1
        bytes.push_back(static_cast<uint8_t>(dataSize));
96 1
    } else if (dataSize < 256) {
97 0
        bytes.push_back(PUSH_DATA1);
98 0
        bytes.push_back(static_cast<uint8_t>(dataSize));
99 0
    } else if (dataSize < 65536) {
100 0
        bytes.push_back(PUSH_DATA2);
101 0
        encode16LE(static_cast<uint16_t>(dataSize), bytes);
102 0
    } else {
103 0
        bytes.push_back(PUSH_DATA4);
104 0
        encode32LE(static_cast<uint16_t>(dataSize), bytes);
105
    }
106 1
    bytes.insert(bytes.end(), data.begin(), data.end());
107
}
108

109 1
void ParamsBuilder::push(uint64_t num, uint8_t len) {
110 1
    Data data;
111 1
    for (auto i = 0; i < len; i++) {
112 1
        data.push_back(static_cast<uint8_t>(num));
113 1
        num >>= 8;
114
    }
115 1
    if (data.back() >> 7 == 1) {
116 1
        data.push_back(0x00);
117
    }
118 1
    push(data);
119
}
120

121 1
void ParamsBuilder::push(uint64_t num) {
122 1
    if (num == 0) {
123 1
        bytes.push_back(PUSH0);
124 1
    } else if (num < 16) {
125 1
        num += 80;
126 1
        bytes.push_back(static_cast<uint8_t>(num));
127 1
    } else if (num < 128) {
128 1
        push(Data{static_cast<uint8_t>(num)});
129 1
    } else if (num <= 0xFFFF) {
130 1
        push(num, 2);
131 1
    } else if (num <= 0xFFFFFF) {
132 1
        push(num, 3);
133 1
    } else if (num <= 0xFFFFFFFF) {
134 1
        push(num, 4);
135 1
    } else if (num <= 0xFFFFFFFFFF) {
136 1
        push(num, 5);
137 1
    } else if (num <= 0xFFFFFFFFFFFF) {
138 0
        push(num, 6);
139 1
    } else if (num <= 0xFFFFFFFFFFFFFF) {
140 1
        push(num, 7);
141 1
    } else {
142 1
        push(num, 8);
143
    }
144
}
145

146 1
void ParamsBuilder::pushBack(uint8_t data) {
147 1
    bytes.push_back(data);
148
}
149

150 1
void ParamsBuilder::pushBack(uint32_t data) {
151 1
    encode32LE(data, bytes);
152
}
153

154 1
void ParamsBuilder::pushBack(uint64_t data) {
155 1
    encode64LE(data, bytes);
156
}
157

158 0
void ParamsBuilder::pushBack(const std::string& data) {
159 0
    bytes.insert(bytes.end(), data.begin(), data.end());
160
}
161

162 1
void ParamsBuilder::pushBack(const std::array<uint8_t, 20>& data) {
163 1
    bytes.insert(bytes.end(), data.begin(), data.end());
164
}
165

166 1
void ParamsBuilder::push(uint8_t num) {
167 1
    if (num == 0) {
168 1
        bytes.push_back(PUSH0);
169 1
    } else if (num < 16) {
170 1
        num += 80;
171 1
        bytes.push_back(static_cast<uint8_t>(num));
172 1
    } else if (num < 128) {
173 0
        push(Data{num});
174 0
    } else {
175 0
        push(Data{num, PUSH0});
176
    }
177
}
178

179 1
Data ParamsBuilder::fromSigs(const std::vector<Data>& sigs) {
180 1
    ParamsBuilder builder;
181 1
    for (auto const& sig : sigs) {
182 1
        builder.push(sig);
183
    }
184 1
    return builder.getBytes();
185
}
186

187 1
Data ParamsBuilder::fromPubkey(const Data& publicKey) {
188 1
    ParamsBuilder builder;
189 1
    builder.push(publicKey);
190 1
    builder.pushBack(CHECK_SIG);
191 1
    return builder.getBytes();
192
}
193

194 1
Data ParamsBuilder::fromMultiPubkey(uint8_t m, const std::vector<Data>& pubKeys) {
195 1
    if (m > pubKeys.size()) {
196 0
        throw std::runtime_error("Invalid m in signature data.");
197
    }
198 1
    if (pubKeys.size() > MAX_PK_SIZE) {
199 0
        throw std::runtime_error("Too many public key found.");
200
    }
201 1
    ParamsBuilder builder;
202 1
    builder.push(m);
203 1
    auto sortedPubKeys = pubKeys;
204 1
    std::sort(sortedPubKeys.begin(), sortedPubKeys.end(), [](Data& o1, Data& o2) -> int {
205
        curve_point p1, p2;
206 1
        ecdsa_read_pubkey(&nist256p1, o1.data(), &p1);
207 1
        ecdsa_read_pubkey(&nist256p1, o2.data(), &p2);
208 1
        auto result = bn_is_less(&p1.x, &p2.x);
209 1
        if (result != 0) {
210 1
            return result;
211
        }
212 1
        return bn_is_less(&p1.y, &p2.y);
213 1
    });
214 1
    for (auto const& pk : sortedPubKeys) {
215 1
        builder.push(pk);
216
    }
217 1
    builder.push((uint8_t)sortedPubKeys.size());
218 1
    builder.pushBack(CHECK_MULTI_SIG);
219 1
    return builder.getBytes();
220
}
221

222 1
Data ParamsBuilder::buildNativeInvokeCode(const Data& contractAddress, uint8_t version,
223
                                          const std::string& method, const boost::any& params) {
224 1
    ParamsBuilder builder;
225 1
    ParamsBuilder::buildNeoVmParam(builder, params);
226 1
    builder.push(Data(method.begin(), method.end()));
227 1
    builder.push(contractAddress);
228 1
    builder.push(version);
229 1
    builder.pushBack(SYS_CALL);
230 1
    std::string nativeInvoke = "Ontology.Native.Invoke";
231 1
    builder.push(Data(nativeInvoke.begin(), nativeInvoke.end()));
232 1
    return builder.getBytes();
233
}

Read our documentation on viewing source code .

Loading