-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathTransaction.js
More file actions
100 lines (93 loc) · 2.7 KB
/
Copy pathTransaction.js
File metadata and controls
100 lines (93 loc) · 2.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
const EC = require('elliptic').ec;
const ec = new EC('secp256k1');
const crypto = require('crypto')
/**
* Transaction class
* @class
*/
class Transaction {
/**
* Create a new transaction
* @param {string} from
* @param {string} to
* @param {number} amount
* @param {string} body
* @param {number} nonce
*/
constructor(from, to, amount, body, nonce) {
this.from = from;
this.to = to;
this.amount = amount;
this.body = body;
this.nonce = nonce;
this.timestamp = Math.floor(Date.now()/1000);
}
/**
* Serializes the transaction to JSON string
* @param {boolean} nosign
* @returns {string}
*/
serialize(nosign=false) {
if (!nosign && this.signature) {
return JSON.stringify({
from: this.from,
to: this.to,
amount: this.amount,
timestamp: this.timestamp,
nonce: this.nonce,
body: this.body,
signature: this.signature
});
}
return JSON.stringify({
from: this.from,
to: this.to,
amount: this.amount,
timestamp: this.timestamp,
nonce: this.nonce,
body: this.body
});
}
/**
* Deserializes the transaction from JSON
* @param {string} data
* @returns {Transaction}
*/
static deserialize(data) {
const json = JSON.parse(data);
const transaction = new this(json.from, json.to, json.amount, json.body, json.nonce);
transaction.signature = json.signature;
transaction.timestamp = json.timestamp;
return transaction
}
/**
* Signs the transaction
* @param {string} privateKey
*/
sign(privateKey) {
const keyPair = ec.keyFromPrivate(privateKey, 'hex');
if (keyPair.getPublic('hex') != this.from) throw new Error("Invalid private key");
const hash = this.hash();
this.signature = keyPair.sign(hash).toDER('hex');
}
/**
* Verifies the transaction by signature
* @returns {boolean}
*/
verify() {
if (!this.signature || !this.from) return false;
const keyPair = ec.keyFromPublic(this.from, 'hex');
if (keyPair.getPublic('hex') != this.from) throw new Error("Invalid private key")
const hash = this.hash();
return keyPair.verify(hash, this.signature);
}
/**
* SHA256 Hash of transaction
* @param {boolean} nosign
* @returns {Buffer}
*/
hash(nosign=true) {
return crypto.createHash('sha256').update(this.serialize(nosign)).digest();
}
}
module.exports = Transaction