1 | "use strict";
|
2 | var __assign = (this && this.__assign) || function () {
|
3 | __assign = Object.assign || function(t) {
|
4 | for (var s, i = 1, n = arguments.length; i < n; i++) {
|
5 | s = arguments[i];
|
6 | for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
7 | t[p] = s[p];
|
8 | }
|
9 | return t;
|
10 | };
|
11 | return __assign.apply(this, arguments);
|
12 | };
|
13 | Object.defineProperty(exports, "__esModule", { value: true });
|
14 | var ethereumjs_util_1 = require("ethereumjs-util");
|
15 | var ethereumjs_common_1 = require("ethereumjs-common");
|
16 | var buffer_1 = require("buffer");
|
17 |
|
18 | var N_DIV_2 = new ethereumjs_util_1.BN('7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0', 16);
|
19 |
|
20 |
|
21 |
|
22 | var Transaction = (function () {
|
23 | |
24 |
|
25 |
|
26 |
|
27 |
|
28 |
|
29 |
|
30 |
|
31 |
|
32 |
|
33 |
|
34 |
|
35 |
|
36 |
|
37 |
|
38 |
|
39 |
|
40 |
|
41 |
|
42 |
|
43 |
|
44 |
|
45 |
|
46 |
|
47 |
|
48 |
|
49 |
|
50 |
|
51 |
|
52 | function Transaction(data, opts) {
|
53 | if (data === void 0) { data = {}; }
|
54 | if (opts === void 0) { opts = {}; }
|
55 |
|
56 | if (opts.common) {
|
57 | if (opts.chain || opts.hardfork) {
|
58 | throw new Error('Instantiation with both opts.common, and opts.chain and opts.hardfork parameter not allowed!');
|
59 | }
|
60 | this._common = opts.common;
|
61 | }
|
62 | else {
|
63 | var chain = opts.chain ? opts.chain : 'mainnet';
|
64 | var hardfork = opts.hardfork ? opts.hardfork : 'petersburg';
|
65 | this._common = new ethereumjs_common_1.default(chain, hardfork);
|
66 | }
|
67 |
|
68 | var fields = [
|
69 | {
|
70 | name: 'nonce',
|
71 | length: 32,
|
72 | allowLess: true,
|
73 | default: new buffer_1.Buffer([]),
|
74 | },
|
75 | {
|
76 | name: 'gasPrice',
|
77 | length: 32,
|
78 | allowLess: true,
|
79 | default: new buffer_1.Buffer([]),
|
80 | },
|
81 | {
|
82 | name: 'gasLimit',
|
83 | alias: 'gas',
|
84 | length: 32,
|
85 | allowLess: true,
|
86 | default: new buffer_1.Buffer([]),
|
87 | },
|
88 | {
|
89 | name: 'to',
|
90 | allowZero: true,
|
91 | length: 20,
|
92 | default: new buffer_1.Buffer([]),
|
93 | },
|
94 | {
|
95 | name: 'value',
|
96 | length: 32,
|
97 | allowLess: true,
|
98 | default: new buffer_1.Buffer([]),
|
99 | },
|
100 | {
|
101 | name: 'data',
|
102 | alias: 'input',
|
103 | allowZero: true,
|
104 | default: new buffer_1.Buffer([]),
|
105 | },
|
106 | {
|
107 | name: 'v',
|
108 | allowZero: true,
|
109 | default: new buffer_1.Buffer([]),
|
110 | },
|
111 | {
|
112 | name: 'r',
|
113 | length: 32,
|
114 | allowZero: true,
|
115 | allowLess: true,
|
116 | default: new buffer_1.Buffer([]),
|
117 | },
|
118 | {
|
119 | name: 's',
|
120 | length: 32,
|
121 | allowZero: true,
|
122 | allowLess: true,
|
123 | default: new buffer_1.Buffer([]),
|
124 | },
|
125 | ];
|
126 |
|
127 | ethereumjs_util_1.defineProperties(this, fields, data);
|
128 | |
129 |
|
130 |
|
131 |
|
132 |
|
133 | Object.defineProperty(this, 'from', {
|
134 | enumerable: true,
|
135 | configurable: true,
|
136 | get: this.getSenderAddress.bind(this),
|
137 | });
|
138 | this._validateV(this.v);
|
139 | this._overrideVSetterWithValidation();
|
140 | }
|
141 | /**
|
142 | * If the tx's `to` is to the creation address
|
143 | */
|
144 | Transaction.prototype.toCreationAddress = function () {
|
145 | return this.to.toString('hex') === '';
|
146 | };
|
147 | |
148 |
|
149 |
|
150 |
|
151 | Transaction.prototype.hash = function (includeSignature) {
|
152 | if (includeSignature === void 0) { includeSignature = true; }
|
153 | var items;
|
154 | if (includeSignature) {
|
155 | items = this.raw;
|
156 | }
|
157 | else {
|
158 | if (this._implementsEIP155()) {
|
159 | items = this.raw.slice(0, 6).concat([
|
160 | ethereumjs_util_1.toBuffer(this.getChainId()),
|
161 |
|
162 | ethereumjs_util_1.stripZeros(ethereumjs_util_1.toBuffer(0)),
|
163 | ethereumjs_util_1.stripZeros(ethereumjs_util_1.toBuffer(0)),
|
164 | ]);
|
165 | }
|
166 | else {
|
167 | items = this.raw.slice(0, 6);
|
168 | }
|
169 | }
|
170 |
|
171 | return ethereumjs_util_1.rlphash(items);
|
172 | };
|
173 | |
174 |
|
175 |
|
176 | Transaction.prototype.getChainId = function () {
|
177 | return this._common.chainId();
|
178 | };
|
179 | |
180 |
|
181 |
|
182 | Transaction.prototype.getSenderAddress = function () {
|
183 | if (this._from) {
|
184 | return this._from;
|
185 | }
|
186 | var pubkey = this.getSenderPublicKey();
|
187 | this._from = ethereumjs_util_1.publicToAddress(pubkey);
|
188 | return this._from;
|
189 | };
|
190 | |
191 |
|
192 |
|
193 | Transaction.prototype.getSenderPublicKey = function () {
|
194 | if (!this.verifySignature()) {
|
195 | throw new Error('Invalid Signature');
|
196 | }
|
197 |
|
198 | return this._senderPubKey;
|
199 | };
|
200 | |
201 |
|
202 |
|
203 | Transaction.prototype.verifySignature = function () {
|
204 | var msgHash = this.hash(false);
|
205 |
|
206 | if (this._common.gteHardfork('homestead') && new ethereumjs_util_1.BN(this.s).cmp(N_DIV_2) === 1) {
|
207 | return false;
|
208 | }
|
209 | try {
|
210 | var v = ethereumjs_util_1.bufferToInt(this.v);
|
211 | var useChainIdWhileRecoveringPubKey = v >= this.getChainId() * 2 + 35 && this._common.gteHardfork('spuriousDragon');
|
212 | this._senderPubKey = ethereumjs_util_1.ecrecover(msgHash, v, this.r, this.s, useChainIdWhileRecoveringPubKey ? this.getChainId() : undefined);
|
213 | }
|
214 | catch (e) {
|
215 | return false;
|
216 | }
|
217 | return !!this._senderPubKey;
|
218 | };
|
219 | |
220 |
|
221 |
|
222 |
|
223 | Transaction.prototype.sign = function (privateKey) {
|
224 |
|
225 |
|
226 | this.v = new buffer_1.Buffer([]);
|
227 | this.s = new buffer_1.Buffer([]);
|
228 | this.r = new buffer_1.Buffer([]);
|
229 | var msgHash = this.hash(false);
|
230 | var sig = ethereumjs_util_1.ecsign(msgHash, privateKey);
|
231 | if (this._implementsEIP155()) {
|
232 | sig.v += this.getChainId() * 2 + 8;
|
233 | }
|
234 | Object.assign(this, sig);
|
235 | };
|
236 | |
237 |
|
238 |
|
239 | Transaction.prototype.getDataFee = function () {
|
240 | var data = this.raw[5];
|
241 | var cost = new ethereumjs_util_1.BN(0);
|
242 | for (var i = 0; i < data.length; i++) {
|
243 | data[i] === 0
|
244 | ? cost.iaddn(this._common.param('gasPrices', 'txDataZero'))
|
245 | : cost.iaddn(this._common.param('gasPrices', 'txDataNonZero'));
|
246 | }
|
247 | return cost;
|
248 | };
|
249 | |
250 |
|
251 |
|
252 | Transaction.prototype.getBaseFee = function () {
|
253 | var fee = this.getDataFee().iaddn(this._common.param('gasPrices', 'tx'));
|
254 | if (this._common.gteHardfork('homestead') && this.toCreationAddress()) {
|
255 | fee.iaddn(this._common.param('gasPrices', 'txCreation'));
|
256 | }
|
257 | return fee;
|
258 | };
|
259 | |
260 |
|
261 |
|
262 | Transaction.prototype.getUpfrontCost = function () {
|
263 | return new ethereumjs_util_1.BN(this.gasLimit).imul(new ethereumjs_util_1.BN(this.gasPrice)).iadd(new ethereumjs_util_1.BN(this.value));
|
264 | };
|
265 | Transaction.prototype.validate = function (stringError) {
|
266 | if (stringError === void 0) { stringError = false; }
|
267 | var errors = [];
|
268 | if (!this.verifySignature()) {
|
269 | errors.push('Invalid Signature');
|
270 | }
|
271 | if (this.getBaseFee().cmp(new ethereumjs_util_1.BN(this.gasLimit)) > 0) {
|
272 | errors.push(["gas limit is too low. Need at least " + this.getBaseFee()]);
|
273 | }
|
274 | if (stringError === false) {
|
275 | return errors.length === 0;
|
276 | }
|
277 | else {
|
278 | return errors.join(' ');
|
279 | }
|
280 | };
|
281 | |
282 |
|
283 |
|
284 | Transaction.prototype.serialize = function () {
|
285 |
|
286 | return ethereumjs_util_1.rlp.encode(this.raw);
|
287 | };
|
288 | |
289 |
|
290 |
|
291 |
|
292 | Transaction.prototype.toJSON = function (labels) {
|
293 | if (labels === void 0) { labels = false; }
|
294 |
|
295 | return {};
|
296 | };
|
297 | Transaction.prototype._validateV = function (v) {
|
298 | if (v === undefined || v.length === 0) {
|
299 | return;
|
300 | }
|
301 | if (!this._common.gteHardfork('spuriousDragon')) {
|
302 | return;
|
303 | }
|
304 | var vInt = ethereumjs_util_1.bufferToInt(v);
|
305 | if (vInt === 27 || vInt === 28) {
|
306 | return;
|
307 | }
|
308 | var isValidEIP155V = vInt === this.getChainId() * 2 + 35 || vInt === this.getChainId() * 2 + 36;
|
309 | if (!isValidEIP155V) {
|
310 | throw new Error("Incompatible EIP155-based V " + vInt + " and chain id " + this.getChainId() + ". See the second parameter of the Transaction constructor to set the chain id.");
|
311 | }
|
312 | };
|
313 | Transaction.prototype._isSigned = function () {
|
314 | return this.v.length > 0 && this.r.length > 0 && this.s.length > 0;
|
315 | };
|
316 | Transaction.prototype._overrideVSetterWithValidation = function () {
|
317 | var _this = this;
|
318 | var vDescriptor = Object.getOwnPropertyDescriptor(this, 'v');
|
319 | Object.defineProperty(this, 'v', __assign({}, vDescriptor, { set: function (v) {
|
320 | if (v !== undefined) {
|
321 | _this._validateV(ethereumjs_util_1.toBuffer(v));
|
322 | }
|
323 | vDescriptor.set(v);
|
324 | } }));
|
325 | };
|
326 | Transaction.prototype._implementsEIP155 = function () {
|
327 | var onEIP155BlockOrLater = this._common.gteHardfork('spuriousDragon');
|
328 | if (!this._isSigned()) {
|
329 |
|
330 | return onEIP155BlockOrLater;
|
331 | }
|
332 |
|
333 |
|
334 |
|
335 |
|
336 |
|
337 | var v = ethereumjs_util_1.bufferToInt(this.v);
|
338 | var vAndChainIdMeetEIP155Conditions = v === this.getChainId() * 2 + 35 || v === this.getChainId() * 2 + 36;
|
339 | return vAndChainIdMeetEIP155Conditions && onEIP155BlockOrLater;
|
340 | };
|
341 | return Transaction;
|
342 | }());
|
343 | exports.default = Transaction;
|
344 |
|
\ | No newline at end of file |