mirror of
https://github.com/benjamin-wilson/public-pool.git
synced 2026-09-29 09:05:06 -07:00
fix the merkle branches
This commit is contained in:
@@ -0,0 +1,15 @@
|
|||||||
|
import { Column, Entity, PrimaryColumn } from 'typeorm';
|
||||||
|
|
||||||
|
import { TrackedEntity } from '../utils/TrackedEntity.entity';
|
||||||
|
|
||||||
|
@Entity()
|
||||||
|
export class AddressSettingsEntity extends TrackedEntity {
|
||||||
|
|
||||||
|
@PrimaryColumn({ length: 62, type: 'varchar' })
|
||||||
|
address: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
miscCoinbaseScriptData: string;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import { Global, Module } from '@nestjs/common';
|
||||||
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||||
|
|
||||||
|
import { AddressSettingsEntity } from './address-settings.entity';
|
||||||
|
import { AddressSettingsService } from './address-settings.service';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Global()
|
||||||
|
@Module({
|
||||||
|
imports: [TypeOrmModule.forFeature([AddressSettingsEntity])],
|
||||||
|
providers: [AddressSettingsService],
|
||||||
|
exports: [TypeOrmModule, AddressSettingsService],
|
||||||
|
})
|
||||||
|
export class AddressSettingsModule { }
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import { InjectRepository } from '@nestjs/typeorm';
|
||||||
|
import { Repository } from 'typeorm';
|
||||||
|
|
||||||
|
import { AddressSettingsEntity } from './address-settings.entity';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class AddressSettingsService {
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
@InjectRepository(AddressSettingsEntity)
|
||||||
|
private addressSettingsRepository: Repository<AddressSettingsEntity>
|
||||||
|
) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+4
-65
@@ -1,6 +1,5 @@
|
|||||||
import { Controller, Get, NotFoundException, Param } from '@nestjs/common';
|
import { Controller, Get } from '@nestjs/common';
|
||||||
|
|
||||||
import { ClientStatisticsService } from './ORM/client-statistics/client-statistics.service';
|
|
||||||
import { ClientService } from './ORM/client/client.service';
|
import { ClientService } from './ORM/client/client.service';
|
||||||
|
|
||||||
|
|
||||||
@@ -8,72 +7,12 @@ import { ClientService } from './ORM/client/client.service';
|
|||||||
@Controller()
|
@Controller()
|
||||||
export class AppController {
|
export class AppController {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly clientService: ClientService,
|
private clientService: ClientService
|
||||||
private readonly clientStatisticsService: ClientStatisticsService
|
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
|
@Get('info')
|
||||||
@Get('client/:address')
|
public info() {
|
||||||
async getClientInfo(@Param('address') address: string) {
|
|
||||||
|
|
||||||
const workers = await this.clientService.getByAddress(address);
|
|
||||||
|
|
||||||
const chartData = await this.clientStatisticsService.getChartDataForAddress(address);
|
|
||||||
|
|
||||||
return {
|
|
||||||
workersCount: workers.length,
|
|
||||||
workers: await Promise.all(
|
|
||||||
workers.map(async (worker) => {
|
|
||||||
return {
|
|
||||||
sessionId: worker.sessionId,
|
|
||||||
name: worker.clientName,
|
|
||||||
bestDifficulty: Math.floor(worker.bestDifficulty),
|
|
||||||
hashRate: Math.floor(await this.clientStatisticsService.getHashRateForSession(worker.address, worker.clientName, worker.sessionId)),
|
|
||||||
startTime: worker.startTime
|
|
||||||
};
|
|
||||||
})
|
|
||||||
),
|
|
||||||
chartData
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Get('client/:address/:workerName')
|
|
||||||
async getWorkerGroupInfo(@Param('address') address: string, @Param('workerName') workerName: string) {
|
|
||||||
|
|
||||||
const workers = await this.clientService.getByName(address, workerName);
|
|
||||||
|
|
||||||
const bestDifficulty = workers.reduce((pre, cur, idx, arr) => {
|
|
||||||
if (cur.bestDifficulty > pre) {
|
|
||||||
return cur.bestDifficulty;
|
|
||||||
}
|
|
||||||
return pre;
|
|
||||||
}, 0);
|
|
||||||
|
|
||||||
const chartData = await this.clientStatisticsService.getChartDataForGroup(address, workerName);
|
|
||||||
return {
|
|
||||||
|
|
||||||
name: workerName,
|
|
||||||
bestDifficulty: Math.floor(bestDifficulty),
|
|
||||||
chartData: chartData,
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Get('client/:address/:workerName/:sessionId')
|
|
||||||
async getWorkerInfo(@Param('address') address: string, @Param('workerName') workerName: string, @Param('sessionId') sessionId: string) {
|
|
||||||
|
|
||||||
const worker = await this.clientService.getBySessionId(address, workerName, sessionId);
|
|
||||||
if (worker == null) {
|
|
||||||
return new NotFoundException();
|
|
||||||
}
|
|
||||||
const chartData = await this.clientStatisticsService.getChartDataForSession(worker.address, worker.clientName, worker.sessionId);
|
|
||||||
|
|
||||||
return {
|
|
||||||
sessionId: worker.sessionId,
|
|
||||||
name: worker.clientName,
|
|
||||||
bestDifficulty: Math.floor(worker.bestDifficulty),
|
|
||||||
chartData: chartData,
|
|
||||||
startTime: worker.startTime
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-3
@@ -4,6 +4,9 @@ import { ScheduleModule } from '@nestjs/schedule';
|
|||||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||||
|
|
||||||
import { AppController } from './app.controller';
|
import { AppController } from './app.controller';
|
||||||
|
import { AddressController } from './controllers/address/address.controller';
|
||||||
|
import { ClientController } from './controllers/client/client.controller';
|
||||||
|
import { AddressSettingsModule } from './ORM/address-settings/address-settings.module';
|
||||||
import { ClientStatisticsModule } from './ORM/client-statistics/client-statistics.module';
|
import { ClientStatisticsModule } from './ORM/client-statistics/client-statistics.module';
|
||||||
import { ClientModule } from './ORM/client/client.module';
|
import { ClientModule } from './ORM/client/client.module';
|
||||||
import { BitcoinRpcService } from './services/bitcoin-rpc.service';
|
import { BitcoinRpcService } from './services/bitcoin-rpc.service';
|
||||||
@@ -11,10 +14,10 @@ import { BlockTemplateService } from './services/block-template.service';
|
|||||||
import { CleanupService } from './services/cleanup.service';
|
import { CleanupService } from './services/cleanup.service';
|
||||||
import { StratumV1Service } from './services/stratum-v1.service';
|
import { StratumV1Service } from './services/stratum-v1.service';
|
||||||
|
|
||||||
|
|
||||||
const ORMModules = [
|
const ORMModules = [
|
||||||
ClientStatisticsModule,
|
ClientStatisticsModule,
|
||||||
ClientModule
|
ClientModule,
|
||||||
|
AddressSettingsModule
|
||||||
]
|
]
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
@@ -30,7 +33,11 @@ const ORMModules = [
|
|||||||
ScheduleModule.forRoot(),
|
ScheduleModule.forRoot(),
|
||||||
...ORMModules
|
...ORMModules
|
||||||
],
|
],
|
||||||
controllers: [AppController],
|
controllers: [
|
||||||
|
AppController,
|
||||||
|
ClientController,
|
||||||
|
AddressController
|
||||||
|
],
|
||||||
providers: [
|
providers: [
|
||||||
|
|
||||||
CleanupService,
|
CleanupService,
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
import { Test, TestingModule } from '@nestjs/testing';
|
||||||
|
import { AddressController } from './address.controller';
|
||||||
|
|
||||||
|
describe('AddressController', () => {
|
||||||
|
let controller: AddressController;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
const module: TestingModule = await Test.createTestingModule({
|
||||||
|
controllers: [AddressController],
|
||||||
|
}).compile();
|
||||||
|
|
||||||
|
controller = module.get<AddressController>(AddressController);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be defined', () => {
|
||||||
|
expect(controller).toBeDefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
import { Controller } from '@nestjs/common';
|
||||||
|
|
||||||
|
@Controller('address')
|
||||||
|
export class AddressController {}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
import { Test, TestingModule } from '@nestjs/testing';
|
||||||
|
import { ClientController } from './client.controller';
|
||||||
|
|
||||||
|
describe('ClientController', () => {
|
||||||
|
let controller: ClientController;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
const module: TestingModule = await Test.createTestingModule({
|
||||||
|
controllers: [ClientController],
|
||||||
|
}).compile();
|
||||||
|
|
||||||
|
controller = module.get<ClientController>(ClientController);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be defined', () => {
|
||||||
|
expect(controller).toBeDefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
import { Controller, Get, NotFoundException, Param } from '@nestjs/common';
|
||||||
|
import { ClientStatisticsService } from 'src/ORM/client-statistics/client-statistics.service';
|
||||||
|
import { ClientService } from 'src/ORM/client/client.service';
|
||||||
|
|
||||||
|
@Controller('client')
|
||||||
|
export class ClientController {
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private readonly clientService: ClientService,
|
||||||
|
private readonly clientStatisticsService: ClientStatisticsService
|
||||||
|
) { }
|
||||||
|
|
||||||
|
|
||||||
|
@Get(':address')
|
||||||
|
async getClientInfo(@Param('address') address: string) {
|
||||||
|
|
||||||
|
const workers = await this.clientService.getByAddress(address);
|
||||||
|
|
||||||
|
const chartData = await this.clientStatisticsService.getChartDataForAddress(address);
|
||||||
|
|
||||||
|
return {
|
||||||
|
workersCount: workers.length,
|
||||||
|
workers: await Promise.all(
|
||||||
|
workers.map(async (worker) => {
|
||||||
|
return {
|
||||||
|
sessionId: worker.sessionId,
|
||||||
|
name: worker.clientName,
|
||||||
|
bestDifficulty: Math.floor(worker.bestDifficulty),
|
||||||
|
hashRate: Math.floor(await this.clientStatisticsService.getHashRateForSession(worker.address, worker.clientName, worker.sessionId)),
|
||||||
|
startTime: worker.startTime
|
||||||
|
};
|
||||||
|
})
|
||||||
|
),
|
||||||
|
chartData
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Get(':address/:workerName')
|
||||||
|
async getWorkerGroupInfo(@Param('address') address: string, @Param('workerName') workerName: string) {
|
||||||
|
|
||||||
|
const workers = await this.clientService.getByName(address, workerName);
|
||||||
|
|
||||||
|
const bestDifficulty = workers.reduce((pre, cur, idx, arr) => {
|
||||||
|
if (cur.bestDifficulty > pre) {
|
||||||
|
return cur.bestDifficulty;
|
||||||
|
}
|
||||||
|
return pre;
|
||||||
|
}, 0);
|
||||||
|
|
||||||
|
const chartData = await this.clientStatisticsService.getChartDataForGroup(address, workerName);
|
||||||
|
return {
|
||||||
|
|
||||||
|
name: workerName,
|
||||||
|
bestDifficulty: Math.floor(bestDifficulty),
|
||||||
|
chartData: chartData,
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Get(':address/:workerName/:sessionId')
|
||||||
|
async getWorkerInfo(@Param('address') address: string, @Param('workerName') workerName: string, @Param('sessionId') sessionId: string) {
|
||||||
|
|
||||||
|
const worker = await this.clientService.getBySessionId(address, workerName, sessionId);
|
||||||
|
if (worker == null) {
|
||||||
|
return new NotFoundException();
|
||||||
|
}
|
||||||
|
const chartData = await this.clientStatisticsService.getChartDataForSession(worker.address, worker.clientName, worker.sessionId);
|
||||||
|
|
||||||
|
return {
|
||||||
|
sessionId: worker.sessionId,
|
||||||
|
name: worker.clientName,
|
||||||
|
bestDifficulty: Math.floor(worker.bestDifficulty),
|
||||||
|
chartData: chartData,
|
||||||
|
startTime: worker.startTime
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+7
-10
@@ -79,7 +79,7 @@ export class MiningJob {
|
|||||||
const merkleBranches: Buffer[] = merkleProof(merkleTree, transactionBuffers[0]).filter(h => h != null);
|
const merkleBranches: Buffer[] = merkleProof(merkleTree, transactionBuffers[0]).filter(h => h != null);
|
||||||
this.block.merkleRoot = merkleBranches.pop();
|
this.block.merkleRoot = merkleBranches.pop();
|
||||||
|
|
||||||
this.merkle_branch = merkleBranches.map(b => b.toString('hex'))
|
this.merkle_branch = merkleBranches.slice(1, merkleBranches.length).map(b => b.toString('hex'))
|
||||||
|
|
||||||
this.block.transactions[0] = coinbaseTransaction;
|
this.block.transactions[0] = coinbaseTransaction;
|
||||||
|
|
||||||
@@ -101,22 +101,19 @@ export class MiningJob {
|
|||||||
|
|
||||||
testBlock.transactions[0].ins[0].script = Buffer.from(`${nonceFreeScript.substring(0, nonceFreeScript.length - 16)}${extraNonce}${extraNonce2}`, 'hex');
|
testBlock.transactions[0].ins[0].script = Buffer.from(`${nonceFreeScript.substring(0, nonceFreeScript.length - 16)}${extraNonce}${extraNonce2}`, 'hex');
|
||||||
|
|
||||||
//@ts-ignore
|
//recompute the roots
|
||||||
//recompute the root
|
testBlock.merkleRoot = this.calculateMerkleRootHash(testBlock.transactions[0].getHash(false), this.merkle_branch);
|
||||||
testBlock.merkleRoot = this.calculateMerkleRootHash(testBlock.transactions[0].__toBuffer(), this.merkle_branch);
|
testBlock.witnessCommit = bitcoinjs.Block.calculateMerkleRoot(this.block.transactions, true);
|
||||||
|
|
||||||
testBlock.timestamp = timestamp
|
testBlock.timestamp = timestamp;
|
||||||
|
|
||||||
return testBlock;
|
return testBlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
private calculateMerkleRootHash(coinbaseTx: string, merkleBranches: string[]): Buffer {
|
private calculateMerkleRootHash(newRoot: Buffer, merkleBranches: string[]): Buffer {
|
||||||
|
|
||||||
let coinbaseTxBuf = Buffer.from(coinbaseTx, 'hex');
|
|
||||||
|
|
||||||
const bothMerkles = Buffer.alloc(64);
|
const bothMerkles = Buffer.alloc(64);
|
||||||
let test = this.sha256(coinbaseTxBuf)
|
|
||||||
let newRoot = this.sha256(test);
|
|
||||||
bothMerkles.set(newRoot);
|
bothMerkles.set(newRoot);
|
||||||
|
|
||||||
for (let i = 0; i < merkleBranches.length; i++) {
|
for (let i = 0; i < merkleBranches.length; i++) {
|
||||||
|
|||||||
@@ -306,7 +306,7 @@ export class StratumV1Client extends EasyUnsubscribe {
|
|||||||
const job = new MiningJob(this.stratumV1JobsService.getNextId(), payoutInformation, blockTemplate, clearJobs);
|
const job = new MiningJob(this.stratumV1JobsService.getNextId(), payoutInformation, blockTemplate, clearJobs);
|
||||||
|
|
||||||
this.stratumV1JobsService.addJob(job, clearJobs);
|
this.stratumV1JobsService.addJob(job, clearJobs);
|
||||||
;
|
|
||||||
|
|
||||||
await this.promiseSocket.write(job.response());
|
await this.promiseSocket.write(job.response());
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user