Skip to content

Commit 31cc896

Browse files
authored
feat: update coinbase payload accroding to changes in Core v20 (#282)
1 parent 2828471 commit 31cc896

File tree

2 files changed

+119
-9
lines changed

2 files changed

+119
-9
lines changed

lib/transaction/payload/coinbasepayload.js

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ var BufferWriter = require('../../encoding/bufferwriter');
77
var BufferReader = require('../../encoding/bufferreader');
88
var AbstractPayload = require('./abstractpayload');
99
var utils = require('../../util/js');
10+
var BN = require('../../crypto/bn');
1011

1112
var isUnsignedInteger = utils.isUnsignedInteger;
1213
var isHexString = utils.isHexaString;
@@ -20,6 +21,9 @@ var HASH_SIZE = constants.SHA256_HASH_SIZE;
2021
* @property {number} height
2122
* @property {string} merkleRootMNList
2223
* @property {string} merkleRootQuorums
24+
* @property {number} bestCLHeight
25+
* @property {Buffer} bestCLSignature
26+
* @property {number} assetLockedAmount
2327
*/
2428

2529
/**
@@ -28,6 +32,9 @@ var HASH_SIZE = constants.SHA256_HASH_SIZE;
2832
* @property {number} height
2933
* @property {string} merkleRootMNList
3034
* @property {string} merkleRootQuorums
35+
* @property {number} bestCLHeight
36+
* @property {Buffer} bestCLSignature
37+
* @property {number} assetLockedAmount
3138
*/
3239
function CoinbasePayload() {
3340
AbstractPayload.call(this);
@@ -60,6 +67,12 @@ CoinbasePayload.fromBuffer = function (rawPayload) {
6067
.toString('hex');
6168
}
6269

70+
if (payload.version >= 3) {
71+
payload.bestCLHeight = payloadBufferReader.readVarintNum();
72+
payload.bestCLSignature = payloadBufferReader.read(96);
73+
payload.assetLockedAmount = payloadBufferReader.readUInt64LEBN();
74+
}
75+
6376
if (!payloadBufferReader.finished()) {
6477
throw new Error(
6578
'Failed to parse payload: raw payload is bigger than expected.'
@@ -84,6 +97,12 @@ CoinbasePayload.fromJSON = function fromJSON(payloadJson) {
8497
payload.merkleRootQuorums = payloadJson.merkleRootQuorums;
8598
}
8699

100+
if (payload.version >= 3) {
101+
payload.bestCLHeight = payloadJson.bestCLHeight;
102+
payload.bestCLSignature = Buffer.from(payloadJson.bestCLSignature, 'hex');
103+
payload.assetLockedAmount = payloadJson.assetLockedAmount;
104+
}
105+
87106
payload.validate();
88107
return payload;
89108
};
@@ -123,6 +142,28 @@ CoinbasePayload.prototype.validate = function () {
123142
'Invalid merkleRootQuorums size'
124143
);
125144
}
145+
if (this.version >= 3) {
146+
Preconditions.checkArgument(
147+
isUnsignedInteger(this.bestCLHeight),
148+
'Expect bestCLHeight to be an unsigned integer'
149+
);
150+
Preconditions.checkArgument(
151+
Buffer.isBuffer(this.bestCLSignature),
152+
'Expect bestCLSignature to be a buffer'
153+
);
154+
Preconditions.checkArgument(
155+
this.bestCLSignature.length === 96,
156+
'Invalid bestCLSignature size'
157+
);
158+
Preconditions.checkArgument(
159+
BN.isBN(this.assetLockedAmount),
160+
'Expect assetLockedAmount to be an instance of BN'
161+
);
162+
Preconditions.checkArgument(
163+
isUnsignedInteger(this.assetLockedAmount.toNumber()),
164+
'Expect assetLockedAmount to be an unsigned integer'
165+
);
166+
}
126167
return true;
127168
};
128169

@@ -140,6 +181,11 @@ CoinbasePayload.prototype.toJSON = function toJSON() {
140181
if (this.version >= 2) {
141182
json.merkleRootQuorums = this.merkleRootQuorums;
142183
}
184+
if (this.version >= 3) {
185+
json.bestCLHeight = this.bestCLHeight;
186+
json.bestCLSignature = this.bestCLSignature.toString('hex');
187+
json.assetLockedAmount = this.assetLockedAmount;
188+
}
143189
return json;
144190
};
145191

@@ -162,6 +208,12 @@ CoinbasePayload.prototype.toBuffer = function toBuffer() {
162208
);
163209
}
164210

211+
if (this.version >= 3) {
212+
payloadBufferWriter.writeVarintNum(this.bestCLHeight);
213+
payloadBufferWriter.write(this.bestCLSignature);
214+
payloadBufferWriter.writeUInt64LEBN(new BN(this.assetLockedAmount));
215+
}
216+
165217
return payloadBufferWriter.toBuffer();
166218
};
167219

test/transaction/payload/coinbasepayload.js

Lines changed: 67 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,28 +6,32 @@ var sinon = require('sinon');
66

77
var DashcoreLib = require('../../../index');
88

9+
var BN = require('../../../lib/crypto/bn');
10+
911
var CoinbasePayload = DashcoreLib.Transaction.Payload.CoinbasePayload;
1012

1113
var merkleRootMNList =
1214
'a1d4f77f5c85a9d56293878edda45ba6fb3e433e6b9bc278c0f4c5799748b975';
1315
var merkleRootQuorums =
1416
'9491099bb93b789d8628acce8f8a84c0f4af8196d3dd6c2427aca0ee702fcc90';
17+
var bestCLHeight = 42;
18+
var bestCLSignature = Buffer.alloc(96, 1);
19+
var assetLockedAmount = new BN(1000);
1520

1621
var validCoinbasePayloadJSON = {
17-
version: 2,
22+
version: 3,
1823
height: 80672,
1924
merkleRootMNList: merkleRootMNList,
2025
merkleRootQuorums: merkleRootQuorums,
26+
bestCLHeight: bestCLHeight,
27+
bestCLSignature: bestCLSignature,
28+
assetLockedAmount: assetLockedAmount,
2129
};
2230
// Contains same data as JSON above
2331
// 0200 is 16-bit unsigned 2, 203b0100 is 32 bit unsigned 80672, everything else is a hash.
24-
var validCoinbasePayloadHexString =
25-
'0200203b010075b9489779c5f4c078c29b6b3e433efba65ba4dd8e879362d5a9855c7ff7d4a190cc2f70eea0ac27246cddd39681aff4c0848a8fceac28869d783bb99b099194';
26-
var validCoinbasePayloadBuffer = Buffer.from(
27-
validCoinbasePayloadHexString,
28-
'hex'
29-
);
3032
var validCoinbasePayload = CoinbasePayload.fromJSON(validCoinbasePayloadJSON);
33+
var validCoinbasePayloadBuffer = validCoinbasePayload.toBuffer();
34+
var validCoinbasePayloadHexString = validCoinbasePayloadBuffer.toString('hex');
3135

3236
describe('CoinbasePayload', function () {
3337
describe('.fromBuffer', function () {
@@ -43,10 +47,13 @@ describe('CoinbasePayload', function () {
4347
var payload = CoinbasePayload.fromBuffer(validCoinbasePayloadBuffer);
4448

4549
expect(payload).to.be.an.instanceOf(CoinbasePayload);
46-
expect(payload.version).to.be.equal(2);
50+
expect(payload.version).to.be.equal(3);
4751
expect(payload.height).to.be.equal(80672);
4852
expect(payload.merkleRootMNList).to.be.equal(merkleRootMNList);
4953
expect(payload.merkleRootQuorums).to.be.equal(merkleRootQuorums);
54+
expect(payload.bestCLHeight).to.be.equal(bestCLHeight);
55+
expect(payload.bestCLSignature).to.be.deep.equal(bestCLSignature);
56+
expect(payload.assetLockedAmount).to.be.deep.equal(assetLockedAmount);
5057
expect(payload.validate.callCount).to.be.equal(1);
5158
});
5259

@@ -73,9 +80,12 @@ describe('CoinbasePayload', function () {
7380
var payload = CoinbasePayload.fromJSON(validCoinbasePayloadJSON);
7481

7582
expect(payload).to.be.an.instanceOf(CoinbasePayload);
76-
expect(payload.version).to.be.equal(2);
83+
expect(payload.version).to.be.equal(3);
7784
expect(payload.height).to.be.equal(80672);
7885
expect(payload.merkleRootMNList).to.be.equal(merkleRootMNList);
86+
expect(payload.bestCLHeight).to.be.equal(bestCLHeight);
87+
expect(payload.bestCLSignature).to.be.deep.equal(bestCLSignature);
88+
expect(payload.assetLockedAmount).to.be.deep.equal(assetLockedAmount);
7989
expect(payload.validate.callCount).to.be.equal(1);
8090
});
8191

@@ -231,6 +241,42 @@ describe('CoinbasePayload', function () {
231241
}).not.to.throw;
232242
}
233243
});
244+
it('Should allow only unsigned integer as bestCLHeight', function () {
245+
var payload = validCoinbasePayload.copy();
246+
247+
payload.bestCLHeight = -10;
248+
249+
expect(function () {
250+
payload.validate();
251+
}).to.throw('Invalid Argument: Expect bestCLHeight to be an unsigned integer');
252+
});
253+
it('Should allow only 96 bytes as bestCLSignature', function () {
254+
var payload = validCoinbasePayload.copy();
255+
256+
payload.bestCLSignature = Buffer.alloc(95, 1);
257+
258+
expect(function () {
259+
payload.validate();
260+
}).to.throw('Invalid Argument: Invalid bestCLSignature size');
261+
});
262+
it('Should allow only BN as assetLockedAmount', function () {
263+
var payload = validCoinbasePayload.copy();
264+
265+
payload.assetLockedAmount = 10;
266+
267+
expect(function () {
268+
payload.validate();
269+
}).to.throw('Invalid Argument: Expect assetLockedAmount to be an instance of BN');
270+
});
271+
it('Should allow only unsigned integer as assetLockedAmount', function () {
272+
var payload = validCoinbasePayload.copy();
273+
274+
payload.assetLockedAmount = new BN(-10);
275+
276+
expect(function () {
277+
payload.validate();
278+
}).to.throw('Invalid Argument: Expect assetLockedAmount to be an unsigned integer');
279+
});
234280
});
235281

236282
describe('#toJSON', function () {
@@ -252,6 +298,11 @@ describe('CoinbasePayload', function () {
252298
expect(payloadJSON.merkleRootMNList).to.be.equal(
253299
payload.merkleRootMNList
254300
);
301+
expect(payloadJSON.bestCLHeight).to.be.equal(payload.bestCLHeight);
302+
expect(payloadJSON.bestCLSignature).to.be.equal(payload.bestCLSignature.toString('hex'));
303+
expect(payloadJSON.assetLockedAmount).to.be.deep.equal(
304+
payload.assetLockedAmount
305+
);
255306
});
256307
it('Should call #validate', function () {
257308
var payload = CoinbasePayload.fromJSON(validCoinbasePayloadJSON);
@@ -281,6 +332,13 @@ describe('CoinbasePayload', function () {
281332
expect(restoredPayload.merkleRootMNList).to.be.equal(
282333
payload.merkleRootMNList
283334
);
335+
expect(restoredPayload.bestCLHeight).to.be.equal(payload.bestCLHeight);
336+
expect(restoredPayload.bestCLSignature).to.be.deep.equal(
337+
payload.bestCLSignature
338+
);
339+
expect(restoredPayload.assetLockedAmount).to.be.deep.equal(
340+
payload.assetLockedAmount
341+
);
284342
});
285343
it('Should call #validate', function () {
286344
var payload = CoinbasePayload.fromJSON(validCoinbasePayloadJSON);

0 commit comments

Comments
 (0)