mirror of
https://github.com/hackku21/loc-chain-backend.git
synced 2024-10-27 20:34:03 +00:00
Fix logic for validating blockchain and expose debugging endpoint
This commit is contained in:
parent
f0005a9ed3
commit
a3c60a1951
@ -2,7 +2,7 @@ import {Controller} from "@extollo/lib"
|
||||
import {Injectable, Inject} from "@extollo/di"
|
||||
import {TransactionResource, TransactionResourceItem} from "../../../rtdb/TransactionResource"
|
||||
import {many, one} from "@extollo/util"
|
||||
import {Blockchain as BlockchainService} from "../../../units/Blockchain"
|
||||
import {Block, Blockchain as BlockchainService} from "../../../units/Blockchain"
|
||||
import {ExposureResource, ExposureResourceItem} from "../../../rtdb/ExposureResource";
|
||||
|
||||
/**
|
||||
@ -26,6 +26,13 @@ export class Blockchain extends Controller {
|
||||
}))
|
||||
}
|
||||
|
||||
public async validate() {
|
||||
const blocks = (await this.blockchain.read()).map(x => new Block(x))
|
||||
return {
|
||||
is_valid: await this.blockchain.validate(blocks)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Post a new transaction to the blockchain. This is only intended for testing.
|
||||
*/
|
||||
|
@ -9,5 +9,8 @@ Route.group('/api/v1', () => {
|
||||
.pre('DebugOnly')
|
||||
.pre('api:ValidateExposureTransaction')
|
||||
|
||||
Route.post('/validate', 'api:Blockchain.validate')
|
||||
.pre('DebugOnly')
|
||||
|
||||
Route.get('/chain', 'api:Blockchain.readBlockchain')
|
||||
})
|
||||
|
@ -44,15 +44,17 @@ export class Block implements BlockResourceItem {
|
||||
}
|
||||
const proof = this.proof
|
||||
const publicKey = this.config.get("app.gpg.key.public")
|
||||
const message = openpgp.Message.fromText(proof)
|
||||
|
||||
// Verify the signature
|
||||
const verified = await (await openpgp.verify({
|
||||
message,
|
||||
publicKeys: publicKey
|
||||
})).signatures[0].verified
|
||||
const result = await openpgp.verify({
|
||||
publicKeys: await openpgp.readKey({
|
||||
armoredKey: publicKey,
|
||||
}),
|
||||
message: await openpgp.readMessage({
|
||||
armoredMessage: proof,
|
||||
}),
|
||||
})
|
||||
|
||||
return !!verified
|
||||
return !!(await result.signatures?.[0]?.verified)
|
||||
}
|
||||
|
||||
/** Generate the hash for this block. */
|
||||
@ -80,7 +82,7 @@ export class Block implements BlockResourceItem {
|
||||
toString() {
|
||||
return [
|
||||
this.uuid,
|
||||
JSON.stringify(this.transactions),
|
||||
JSON.stringify(this.transactions || [], undefined, 0),
|
||||
this.lastBlockHash,
|
||||
this.lastBlockUUID,
|
||||
].join('%')
|
||||
@ -145,7 +147,43 @@ export class Blockchain extends Unit {
|
||||
*/
|
||||
public async validate(chain: Block[]) {
|
||||
const blocks = collect<Block>(chain)
|
||||
return (await blocks.promiseMap((block: Block) => block.isGenesis())).every(Boolean)
|
||||
return (
|
||||
await blocks.promiseMap(async (block, idx) => {
|
||||
if ( await block.isGenesis() ) {
|
||||
return true
|
||||
}
|
||||
|
||||
const previous: Block | undefined = blocks.at(idx - 1)
|
||||
if ( !previous ) {
|
||||
this.logging.debug(`Chain is invalid: block ${idx} is missing previous ${idx - 1}.`)
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( !(await this.validateProofOfWork(block, previous)) ) {
|
||||
this.logging.debug(`Chain is invalid: block ${idx} failed proof of work validation`)
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
const pass = (
|
||||
block.lastBlockUUID === previous.uuid
|
||||
&& block.lastBlockHash === previous.hash()
|
||||
)
|
||||
|
||||
if ( !pass ) {
|
||||
this.logging.debug(`Chain is invalid: block ${idx} does not match previous.`)
|
||||
this.logging.debug({
|
||||
lastBlockUUID: block.lastBlockUUID,
|
||||
computedLastUUID: previous.uuid,
|
||||
lastBlockHash: block.lastBlockHash,
|
||||
computedLastHash: previous.hash(),
|
||||
})
|
||||
}
|
||||
|
||||
return pass
|
||||
})
|
||||
).every(Boolean)
|
||||
}
|
||||
|
||||
public async refresh() {
|
||||
@ -276,7 +314,7 @@ export class Blockchain extends Unit {
|
||||
privateKeys: await openpgp.readKey({
|
||||
armoredKey: privateKey,
|
||||
})
|
||||
})).toString()
|
||||
}))
|
||||
}
|
||||
|
||||
/**
|
||||
@ -288,14 +326,16 @@ export class Blockchain extends Unit {
|
||||
protected async validateProofOfWork(currentBlock: Block, lastBlock: Block): Promise<boolean> {
|
||||
const proof = lastBlock.proof
|
||||
const publicKey = this.config.get("app.gpg.key.public")
|
||||
const message = openpgp.Message.fromText(proof)
|
||||
|
||||
// Verify the signature
|
||||
const verified = await (await openpgp.verify({
|
||||
message,
|
||||
publicKeys: publicKey
|
||||
})).signatures[0].verified
|
||||
const result = await openpgp.verify({
|
||||
publicKeys: await openpgp.readKey({
|
||||
armoredKey: publicKey,
|
||||
}),
|
||||
message: await openpgp.readMessage({
|
||||
armoredMessage: proof,
|
||||
}),
|
||||
})
|
||||
|
||||
return !!verified
|
||||
return !!(await result.signatures?.[0]?.verified)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user