mirror of
https://github.com/benjamin-wilson/public-pool.git
synced 2026-09-29 17:15:03 -07:00
189 lines
6.5 KiB
TypeScript
189 lines
6.5 KiB
TypeScript
import { BufferReader } from './sv2-binary-codec';
|
|
import {
|
|
Sv2OpenExtendedMiningChannel,
|
|
serializeOpenExtendedMiningChannel,
|
|
deserializeOpenExtendedMiningChannel,
|
|
Sv2OpenExtendedMiningChannelSuccess,
|
|
serializeOpenExtendedMiningChannelSuccess,
|
|
deserializeOpenExtendedMiningChannelSuccess,
|
|
Sv2NewExtendedMiningJob,
|
|
serializeNewExtendedMiningJob,
|
|
deserializeNewExtendedMiningJob,
|
|
Sv2SubmitSharesExtended,
|
|
serializeSubmitSharesExtended,
|
|
deserializeSubmitSharesExtended,
|
|
Sv2SetExtranoncePrefix,
|
|
serializeSetExtranoncePrefix,
|
|
deserializeSetExtranoncePrefix,
|
|
Sv2SetGroupChannel,
|
|
serializeSetGroupChannel,
|
|
deserializeSetGroupChannel,
|
|
} from './sv2-extended-messages';
|
|
|
|
function roundTrip<T>(
|
|
msg: T,
|
|
serialize: (m: T) => Buffer,
|
|
deserialize: (r: BufferReader) => T,
|
|
): T {
|
|
const buf = serialize(msg);
|
|
return deserialize(new BufferReader(buf));
|
|
}
|
|
|
|
describe('SV2 Extended Mining Channel Messages', () => {
|
|
it('OpenExtendedMiningChannel round-trips', () => {
|
|
const maxTarget = Buffer.alloc(32, 0x00);
|
|
maxTarget[0] = 0xff;
|
|
const msg: Sv2OpenExtendedMiningChannel = {
|
|
requestId: 1,
|
|
userIdentity: 'bc1qtest.worker1',
|
|
nominalHashRate: 500000.0,
|
|
maxTarget,
|
|
minExtranonceSize: 8,
|
|
};
|
|
const result = roundTrip(msg, serializeOpenExtendedMiningChannel, deserializeOpenExtendedMiningChannel);
|
|
expect(result.requestId).toBe(msg.requestId);
|
|
expect(result.userIdentity).toBe(msg.userIdentity);
|
|
expect(result.nominalHashRate).toBeCloseTo(msg.nominalHashRate, 0);
|
|
expect(result.maxTarget).toEqual(msg.maxTarget);
|
|
expect(result.minExtranonceSize).toBe(msg.minExtranonceSize);
|
|
});
|
|
|
|
it('OpenExtendedMiningChannelSuccess round-trips', () => {
|
|
const target = Buffer.alloc(32);
|
|
target[0] = 0xff;
|
|
const msg: Sv2OpenExtendedMiningChannelSuccess = {
|
|
requestId: 1,
|
|
channelId: 42,
|
|
target,
|
|
extranonceSize: 8,
|
|
extranoncePrefix: Buffer.from([0x00, 0x00, 0x00, 0x01]),
|
|
groupChannelId: 0,
|
|
};
|
|
const result = roundTrip(
|
|
msg,
|
|
serializeOpenExtendedMiningChannelSuccess,
|
|
deserializeOpenExtendedMiningChannelSuccess,
|
|
);
|
|
expect(result.requestId).toBe(msg.requestId);
|
|
expect(result.channelId).toBe(msg.channelId);
|
|
expect(result.target).toEqual(msg.target);
|
|
expect(result.extranonceSize).toBe(msg.extranonceSize);
|
|
expect(result.extranoncePrefix).toEqual(msg.extranoncePrefix);
|
|
expect(result.groupChannelId).toBe(msg.groupChannelId);
|
|
});
|
|
|
|
it('NewExtendedMiningJob round-trips with minNtime (mine immediately)', () => {
|
|
const hash1 = Buffer.alloc(32, 0xaa);
|
|
const hash2 = Buffer.alloc(32, 0xbb);
|
|
const msg: Sv2NewExtendedMiningJob = {
|
|
channelId: 1,
|
|
jobId: 100,
|
|
minNtime: 1700000000,
|
|
version: 0x20000000,
|
|
versionRollingAllowed: true,
|
|
merklePath: [hash1, hash2],
|
|
coinbasePrefix: Buffer.from('deadbeef', 'hex'),
|
|
coinbaseSuffix: Buffer.from('cafebabe', 'hex'),
|
|
};
|
|
const result = roundTrip(msg, serializeNewExtendedMiningJob, deserializeNewExtendedMiningJob);
|
|
expect(result.channelId).toBe(msg.channelId);
|
|
expect(result.jobId).toBe(msg.jobId);
|
|
expect(result.minNtime).toBe(msg.minNtime);
|
|
expect(result.version).toBe(msg.version);
|
|
expect(result.versionRollingAllowed).toBe(msg.versionRollingAllowed);
|
|
expect(result.merklePath).toHaveLength(2);
|
|
expect(result.merklePath[0]).toEqual(hash1);
|
|
expect(result.merklePath[1]).toEqual(hash2);
|
|
expect(result.coinbasePrefix).toEqual(msg.coinbasePrefix);
|
|
expect(result.coinbaseSuffix).toEqual(msg.coinbaseSuffix);
|
|
});
|
|
|
|
it('NewExtendedMiningJob with null minNtime (future job)', () => {
|
|
const msg: Sv2NewExtendedMiningJob = {
|
|
channelId: 1,
|
|
jobId: 1,
|
|
minNtime: null,
|
|
version: 0x20000000,
|
|
versionRollingAllowed: false,
|
|
merklePath: [],
|
|
coinbasePrefix: Buffer.alloc(0),
|
|
coinbaseSuffix: Buffer.alloc(0),
|
|
};
|
|
const result = roundTrip(msg, serializeNewExtendedMiningJob, deserializeNewExtendedMiningJob);
|
|
expect(result.merklePath).toHaveLength(0);
|
|
expect(result.minNtime).toBeNull();
|
|
expect(result.versionRollingAllowed).toBe(false);
|
|
});
|
|
|
|
it('SubmitSharesExtended round-trips', () => {
|
|
const msg: Sv2SubmitSharesExtended = {
|
|
channelId: 1,
|
|
sequenceNumber: 42,
|
|
jobId: 100,
|
|
nonce: 0xdeadbeef,
|
|
ntime: 1700000000,
|
|
version: 0x20000000,
|
|
extranonce: Buffer.from([0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07]),
|
|
};
|
|
const result = roundTrip(msg, serializeSubmitSharesExtended, deserializeSubmitSharesExtended);
|
|
expect(result.channelId).toBe(msg.channelId);
|
|
expect(result.sequenceNumber).toBe(msg.sequenceNumber);
|
|
expect(result.jobId).toBe(msg.jobId);
|
|
expect(result.nonce).toBe(msg.nonce);
|
|
expect(result.ntime).toBe(msg.ntime);
|
|
expect(result.version).toBe(msg.version);
|
|
expect(result.extranonce).toEqual(msg.extranonce);
|
|
});
|
|
|
|
it('SubmitSharesExtended with short extranonce', () => {
|
|
const msg: Sv2SubmitSharesExtended = {
|
|
channelId: 1,
|
|
sequenceNumber: 1,
|
|
jobId: 1,
|
|
nonce: 0,
|
|
ntime: 1700000000,
|
|
version: 0x20000000,
|
|
extranonce: Buffer.from([0xab]),
|
|
};
|
|
const result = roundTrip(msg, serializeSubmitSharesExtended, deserializeSubmitSharesExtended);
|
|
expect(result.extranonce).toEqual(Buffer.from([0xab]));
|
|
});
|
|
|
|
it('SetExtranoncePrefix round-trips', () => {
|
|
const msg: Sv2SetExtranoncePrefix = {
|
|
channelId: 5,
|
|
extranoncePrefix: Buffer.from([0x00, 0x00, 0x00, 0x02]),
|
|
};
|
|
const result = roundTrip(msg, serializeSetExtranoncePrefix, deserializeSetExtranoncePrefix);
|
|
expect(result.channelId).toBe(msg.channelId);
|
|
expect(result.extranoncePrefix).toEqual(msg.extranoncePrefix);
|
|
});
|
|
|
|
it('SetGroupChannel round-trips', () => {
|
|
const msg: Sv2SetGroupChannel = {
|
|
groupChannelId: 10,
|
|
channelIds: [42, 43, 44],
|
|
};
|
|
const result = roundTrip(msg, serializeSetGroupChannel, deserializeSetGroupChannel);
|
|
expect(result).toEqual(msg);
|
|
});
|
|
|
|
it('serialized SubmitSharesExtended has correct byte layout', () => {
|
|
const msg: Sv2SubmitSharesExtended = {
|
|
channelId: 1,
|
|
sequenceNumber: 2,
|
|
jobId: 3,
|
|
nonce: 4,
|
|
ntime: 5,
|
|
version: 6,
|
|
extranonce: Buffer.from([0xab, 0xcd]),
|
|
};
|
|
const buf = serializeSubmitSharesExtended(msg);
|
|
// 6 * U32(4) = 24 + B0_32(1+2) = 27
|
|
expect(buf.length).toBe(27);
|
|
expect(buf.readUInt32LE(0)).toBe(1);
|
|
expect(buf.readUInt32LE(4)).toBe(2);
|
|
expect(buf.readUInt32LE(8)).toBe(3);
|
|
});
|
|
});
|