mirror of
https://github.com/benjamin-wilson/public-pool.git
synced 2026-09-29 09:05:06 -07:00
test nonce work
This commit is contained in:
Generated
+18
@@ -13,6 +13,7 @@
|
|||||||
"@nestjs/config": "^2.3.2",
|
"@nestjs/config": "^2.3.2",
|
||||||
"@nestjs/core": "^9.0.0",
|
"@nestjs/core": "^9.0.0",
|
||||||
"@nestjs/platform-fastify": "^9.4.2",
|
"@nestjs/platform-fastify": "^9.4.2",
|
||||||
|
"big.js": "^6.2.1",
|
||||||
"class-transformer": "^0.5.1",
|
"class-transformer": "^0.5.1",
|
||||||
"class-validator": "^0.14.0",
|
"class-validator": "^0.14.0",
|
||||||
"merkletreejs": "^0.3.10",
|
"merkletreejs": "^0.3.10",
|
||||||
@@ -2856,6 +2857,18 @@
|
|||||||
"tweetnacl": "^0.14.3"
|
"tweetnacl": "^0.14.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/big.js": {
|
||||||
|
"version": "6.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/big.js/-/big.js-6.2.1.tgz",
|
||||||
|
"integrity": "sha512-bCtHMwL9LeDIozFn+oNhhFoq+yQ3BNdnsLSASUxLciOb1vgvpHsIO1dsENiGMgbb4SkP5TrzWzRiLddn8ahVOQ==",
|
||||||
|
"engines": {
|
||||||
|
"node": "*"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/bigjs"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/bignumber.js": {
|
"node_modules/bignumber.js": {
|
||||||
"version": "9.1.1",
|
"version": "9.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.1.tgz",
|
||||||
@@ -11090,6 +11103,11 @@
|
|||||||
"tweetnacl": "^0.14.3"
|
"tweetnacl": "^0.14.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"big.js": {
|
||||||
|
"version": "6.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/big.js/-/big.js-6.2.1.tgz",
|
||||||
|
"integrity": "sha512-bCtHMwL9LeDIozFn+oNhhFoq+yQ3BNdnsLSASUxLciOb1vgvpHsIO1dsENiGMgbb4SkP5TrzWzRiLddn8ahVOQ=="
|
||||||
|
},
|
||||||
"bignumber.js": {
|
"bignumber.js": {
|
||||||
"version": "9.1.1",
|
"version": "9.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.1.tgz",
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
"@nestjs/config": "^2.3.2",
|
"@nestjs/config": "^2.3.2",
|
||||||
"@nestjs/core": "^9.0.0",
|
"@nestjs/core": "^9.0.0",
|
||||||
"@nestjs/platform-fastify": "^9.4.2",
|
"@nestjs/platform-fastify": "^9.4.2",
|
||||||
|
"big.js": "^6.2.1",
|
||||||
"class-transformer": "^0.5.1",
|
"class-transformer": "^0.5.1",
|
||||||
"class-validator": "^0.14.0",
|
"class-validator": "^0.14.0",
|
||||||
"merkletreejs": "^0.3.10",
|
"merkletreejs": "^0.3.10",
|
||||||
|
|||||||
+1
-1
@@ -3,6 +3,6 @@ import { Injectable } from '@nestjs/common';
|
|||||||
@Injectable()
|
@Injectable()
|
||||||
export class AppService {
|
export class AppService {
|
||||||
getHello(): string {
|
getHello(): string {
|
||||||
return 'Hello World!@';
|
return 'Hello World!';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ export class MiningJob {
|
|||||||
public method: eResponseMethod.MINING_NOTIFY;
|
public method: eResponseMethod.MINING_NOTIFY;
|
||||||
public params: string[];
|
public params: string[];
|
||||||
|
|
||||||
public target: string;
|
public target: number;
|
||||||
public merkleRoot: string;
|
public merkleRoot: string;
|
||||||
|
|
||||||
public job_id: string; // ID of the job. Use this ID while submitting share generated from this job.
|
public job_id: string; // ID of the job. Use this ID while submitting share generated from this job.
|
||||||
@@ -22,24 +22,26 @@ export class MiningJob {
|
|||||||
public coinb1: string; // The hex-encoded prefix of the coinbase transaction (to precede extra nonce 2).
|
public coinb1: string; // The hex-encoded prefix of the coinbase transaction (to precede extra nonce 2).
|
||||||
public coinb2: string; //The hex-encoded suffix of the coinbase transaction (to follow extra nonce 2).
|
public coinb2: string; //The hex-encoded suffix of the coinbase transaction (to follow extra nonce 2).
|
||||||
public merkle_branch: string[]; // List of hashes, will be used for calculation of merkle root. This is not a list of all transactions, it only contains prepared hashes of steps of merkle tree algorithm.
|
public merkle_branch: string[]; // List of hashes, will be used for calculation of merkle root. This is not a list of all transactions, it only contains prepared hashes of steps of merkle tree algorithm.
|
||||||
public version: string; // The hex-encoded block version.
|
public version: number; // The hex-encoded block version.
|
||||||
public nbits: string; // The hex-encoded network difficulty required for the block.
|
public nbits: string; // The hex-encoded network difficulty required for the block.
|
||||||
public ntime: string; // Current ntime/
|
public ntime: number; // Current ntime/
|
||||||
public clean_jobs: boolean; // When true, server indicates that submitting shares from previous jobs don't have a sense and such shares will be rejected. When this flag is set, miner should also drop all previous jobs too.
|
public clean_jobs: boolean; // When true, server indicates that submitting shares from previous jobs don't have a sense and such shares will be rejected. When this flag is set, miner should also drop all previous jobs too.
|
||||||
|
|
||||||
public response: string;
|
public response: string;
|
||||||
|
|
||||||
|
public versionMask: number;
|
||||||
|
|
||||||
constructor(blockTemplate: IBlockTemplate) {
|
constructor(blockTemplate: IBlockTemplate) {
|
||||||
|
|
||||||
console.log(blockTemplate);
|
console.log(blockTemplate);
|
||||||
|
|
||||||
this.job_id = randomUUID();
|
this.job_id = randomUUID();
|
||||||
this.target = blockTemplate.target;
|
this.target = Number(blockTemplate.target);
|
||||||
this.prevhash = blockTemplate.previousblockhash;
|
this.prevhash = blockTemplate.previousblockhash;
|
||||||
|
|
||||||
this.version = blockTemplate.version.toString();
|
this.version = blockTemplate.version;
|
||||||
this.nbits = blockTemplate.bits;
|
this.nbits = blockTemplate.bits;
|
||||||
this.ntime = Math.floor(new Date().getTime() / 1000).toString();
|
this.ntime = Math.floor(new Date().getTime() / 1000);
|
||||||
this.clean_jobs = false;
|
this.clean_jobs = false;
|
||||||
|
|
||||||
const transactions = blockTemplate.transactions.map(tx => tx.hash);
|
const transactions = blockTemplate.transactions.map(tx => tx.hash);
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
import { plainToInstance } from 'class-transformer';
|
import { plainToInstance } from 'class-transformer';
|
||||||
import { validate, ValidatorOptions } from 'class-validator';
|
import { validate, ValidatorOptions } from 'class-validator';
|
||||||
import { Socket } from 'net';
|
import { Socket } from 'net';
|
||||||
import { BehaviorSubject, combineLatest, concat, merge, Observable, takeUntil } from 'rxjs';
|
import { BehaviorSubject, merge, Observable, takeUntil } from 'rxjs';
|
||||||
|
|
||||||
import { EasyUnsubscribe } from '../utils/AutoUnsubscribe';
|
import { EasyUnsubscribe } from '../utils/AutoUnsubscribe';
|
||||||
import { eRequestMethod } from './enums/eRequestMethod';
|
import { eRequestMethod } from './enums/eRequestMethod';
|
||||||
|
import { MiningJob } from './MiningJob';
|
||||||
import { AuthorizationMessage } from './stratum-messages/AuthorizationMessage';
|
import { AuthorizationMessage } from './stratum-messages/AuthorizationMessage';
|
||||||
import { ConfigurationMessage } from './stratum-messages/ConfigurationMessage';
|
import { ConfigurationMessage } from './stratum-messages/ConfigurationMessage';
|
||||||
import { MiningSubmitMessage } from './stratum-messages/MiningSubmitMessage';
|
import { MiningSubmitMessage } from './stratum-messages/MiningSubmitMessage';
|
||||||
import { SubscriptionMessage } from './stratum-messages/SubscriptionMessage';
|
import { SubscriptionMessage } from './stratum-messages/SubscriptionMessage';
|
||||||
import { SuggestDifficulty } from './stratum-messages/SuggestDifficultyMessage';
|
import { SuggestDifficulty } from './stratum-messages/SuggestDifficultyMessage';
|
||||||
import { MiningJob } from './MiningJob';
|
|
||||||
|
|
||||||
export class StratumV1Client extends EasyUnsubscribe {
|
export class StratumV1Client extends EasyUnsubscribe {
|
||||||
|
|
||||||
@@ -24,6 +24,7 @@ export class StratumV1Client extends EasyUnsubscribe {
|
|||||||
|
|
||||||
public onInitialized: BehaviorSubject<void> = new BehaviorSubject(null);
|
public onInitialized: BehaviorSubject<void> = new BehaviorSubject(null);
|
||||||
public localMiningJobEmitter: BehaviorSubject<MiningJob> = new BehaviorSubject(null);
|
public localMiningJobEmitter: BehaviorSubject<MiningJob> = new BehaviorSubject(null);
|
||||||
|
public blockFoundEmitter: BehaviorSubject<any> = new BehaviorSubject(null);
|
||||||
|
|
||||||
|
|
||||||
private currentJob: MiningJob;
|
private currentJob: MiningJob;
|
||||||
@@ -216,8 +217,11 @@ export class StratumV1Client extends EasyUnsubscribe {
|
|||||||
|
|
||||||
|
|
||||||
private handleMiningSubmission(submission: MiningSubmitMessage) {
|
private handleMiningSubmission(submission: MiningSubmitMessage) {
|
||||||
const diff = submission.testNonceValue(this.currentJob, submission.nonce);
|
const networkDifficulty = 0;
|
||||||
console.log(diff);
|
const diff = submission.testNonceValue(this.currentJob, parseInt(submission.nonce, 16));
|
||||||
|
if (networkDifficulty < diff) {
|
||||||
|
this.blockFoundEmitter.next(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// private miningNotify() {
|
// private miningNotify() {
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
import { MiningJob } from '../MiningJob';
|
||||||
|
import { MiningSubmitMessage } from './MiningSubmitMessage';
|
||||||
|
|
||||||
|
describe('MiningSubmitMessage', () => {
|
||||||
|
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('root', () => {
|
||||||
|
|
||||||
|
const value = new MiningSubmitMessage().testNonceValue({
|
||||||
|
version: 0x20000004,
|
||||||
|
prevhash: "0c859545a3498373a57452fac22eb7113df2a465000543520000000000000000",
|
||||||
|
merkleRoot: "5bdc1968499c3393873edf8e07a1c3a50a97fc3a9d1a376bbf77087dd63778eb",
|
||||||
|
ntime: 0x647025b5,
|
||||||
|
target: 0x1705ae3a,
|
||||||
|
} as MiningJob, 0x0a029ed1);
|
||||||
|
|
||||||
|
it('should be correct difficulty', () => {
|
||||||
|
expect(value).toEqual(683);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -1,18 +1,17 @@
|
|||||||
|
import Big from 'big.js';
|
||||||
import { ArrayMaxSize, ArrayMinSize, IsArray } from 'class-validator';
|
import { ArrayMaxSize, ArrayMinSize, IsArray } from 'class-validator';
|
||||||
|
|
||||||
import { eRequestMethod } from '../enums/eRequestMethod';
|
|
||||||
import { StratumBaseMessage } from './StratumBaseMessage';
|
|
||||||
import { MiningJob } from '../MiningJob';
|
|
||||||
import * as crypto from 'crypto';
|
import * as crypto from 'crypto';
|
||||||
|
|
||||||
|
import { eRequestMethod } from '../enums/eRequestMethod';
|
||||||
|
import { MiningJob } from '../MiningJob';
|
||||||
|
import { StratumBaseMessage } from './StratumBaseMessage';
|
||||||
|
|
||||||
const trueDiffOne = Number('26959535291011309493156476344723991336010898738574164086137773096960');
|
|
||||||
export class MiningSubmitMessage extends StratumBaseMessage {
|
export class MiningSubmitMessage extends StratumBaseMessage {
|
||||||
|
|
||||||
@IsArray()
|
@IsArray()
|
||||||
@ArrayMinSize(5)
|
@ArrayMinSize(5)
|
||||||
@ArrayMaxSize(5)
|
@ArrayMaxSize(5)
|
||||||
params: string[];
|
public params: string[];
|
||||||
|
|
||||||
public userId: string;
|
public userId: string;
|
||||||
public jobId: string;
|
public jobId: string;
|
||||||
@@ -43,48 +42,60 @@ export class MiningSubmitMessage extends StratumBaseMessage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
testNonceValue(job: MiningJob, nonce: string): number {
|
testNonceValue(job: MiningJob, nonce: number, midstateIndex: number = 0): string {
|
||||||
|
const truediffone = Big('26959535291011309493156476344723991336010898738574164086137773096960');
|
||||||
|
let s64: Big, ds: number;
|
||||||
const header = Buffer.alloc(80);
|
const header = Buffer.alloc(80);
|
||||||
|
|
||||||
// TODO: Use the midstate hash instead of hashing the whole header
|
// TODO: Use the midstate hash instead of hashing the whole header
|
||||||
|
|
||||||
// Copy data from job to header
|
// Copy data from job to header
|
||||||
|
|
||||||
|
let rolledVersion = job.version;
|
||||||
|
for (let i = 0; i < midstateIndex; i++) {
|
||||||
|
rolledVersion = this.incrementBitmask(rolledVersion, job.versionMask);
|
||||||
|
}
|
||||||
|
|
||||||
header.set(Buffer.from(job.version, 'hex').subarray(0, 4), 0);
|
header.writeUInt32LE(rolledVersion, 0);
|
||||||
header.set(Buffer.from(job.prevhash, 'hex').subarray(0, 32), 4);
|
Buffer.from(job.prevhash, 'hex').copy(header, 4);
|
||||||
header.set(Buffer.from(job.merkleRoot, 'hex').subarray(0, 32), 36);
|
Buffer.from(job.merkleRoot, 'hex').copy(header, 36);
|
||||||
header.set(Buffer.from(job.ntime).subarray(0, 4), 68);
|
header.writeUInt32LE(job.ntime, 68);
|
||||||
header.set(Buffer.from(job.target, 'hex').subarray(0, 4), 72);
|
header.writeUInt32LE(job.target, 72);
|
||||||
header.set(Buffer.from(nonce, 'hex').subarray(0, 4), 76);
|
header.writeUInt32LE(nonce, 76);
|
||||||
|
|
||||||
|
console.log(header);
|
||||||
|
|
||||||
const hashBuffer = crypto.createHash('sha256').update(header).digest();
|
const hashBuffer: Buffer = crypto.createHash('sha256').update(header).digest();
|
||||||
const hashResult = crypto.createHash('sha256').update(hashBuffer).digest();
|
const hashResult: Buffer = crypto.createHash('sha256').update(hashBuffer).digest();
|
||||||
|
|
||||||
const d64 = 1.0;
|
s64 = this.le256todouble(hashResult);
|
||||||
const s64 = this.littleEndianToDouble(hashResult);
|
ds = truediffone.div(s64);
|
||||||
const ds = d64 / s64;
|
|
||||||
|
|
||||||
return ds;
|
return ds.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private littleEndianToDouble(buffer: Buffer): number {
|
|
||||||
// Reverse the byte order to big-endian
|
|
||||||
const reversedBytes = Buffer.from(buffer).reverse();
|
|
||||||
|
|
||||||
// Convert the reversed bytes to a hexadecimal string
|
private le256todouble(target: Buffer): Big {
|
||||||
const hexString = `0x${reversedBytes.toString('hex')}`;
|
|
||||||
|
|
||||||
// Interpret the hexadecimal string as a double
|
const bits192 = new Big(6277101735386680763835789423207666416102355444464034512896);
|
||||||
const doubleValue = Number(hexString);
|
const bits128 = new Big(340282366920938463463374607431768211456);
|
||||||
|
const bits64 = new Big(18446744073709551616);
|
||||||
|
|
||||||
// Check for NaN and Infinity
|
const data64_3 = target.readBigUInt64LE(24);
|
||||||
if (!Number.isFinite(doubleValue)) {
|
const data64_2 = target.readBigUInt64LE(16);
|
||||||
throw new Error('Conversion resulted in NaN or Infinity');
|
const data64_1 = target.readBigUInt64LE(8);
|
||||||
|
const data64_0 = target.readBigUInt64LE(0);
|
||||||
|
|
||||||
|
const dcut64 = new Big(data64_3).times(bits192)
|
||||||
|
.plus(new Big(data64_2).times(bits128))
|
||||||
|
.plus(new Big(data64_1).times(bits64))
|
||||||
|
.plus(new Big(data64_0));
|
||||||
|
|
||||||
|
return dcut64;
|
||||||
}
|
}
|
||||||
|
|
||||||
return doubleValue;
|
public incrementBitmask(rolledVersion: number, versionMask: number) {
|
||||||
|
return (rolledVersion + 1) | versionMask;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user