Merge branch 'main' of github.com:hackku21/loc-chain-backend into main

This commit is contained in:
QiTao Weng 2021-04-10 07:17:23 +00:00
commit e569841356
4 changed files with 169 additions and 1 deletions

View File

@ -17,6 +17,7 @@ export default {
refs: { refs: {
peers: 'chain/server/peers', peers: 'chain/server/peers',
transaction: 'chain/pending/transactions', transaction: 'chain/pending/transactions',
block: 'chain/local/block',
}, },
}, },
} }

View File

@ -0,0 +1,57 @@
import {FirebaseResource, FirebaseResourceItem} from "../FirebaseResource"
import {Injectable} from "@extollo/di"
import {RTDBRef} from "../units/FirebaseUnit"
import {AsyncCollection} from "@extollo/util"
export interface BlockEncounterTransaction {
combinedHash: string;
timestamp: number;
encodedGPSLocation: string;
}
export interface BlockInfectionTransaction {
clientID: string;
timestamp: number;
}
export type BlockTransaction = BlockInfectionTransaction | BlockEncounterTransaction
export function isBlockEncounterTransaction(what: any): what is BlockEncounterTransaction {
return (
what
&& typeof what.combinedHash === 'string'
&& typeof what.timestamp === 'number'
&& typeof what.encodedGPSLocation === 'string'
)
}
export function isBlockInfectionTransaction(what: any): what is BlockInfectionTransaction {
return (
what
&& typeof what.clientID === 'string'
&& typeof what.timestamp === 'number'
)
}
export function isBlockTransaction(what: any): what is BlockTransaction {
return isBlockEncounterTransaction(what) || isBlockInfectionTransaction(what)
}
export interface BlockResourceItem extends FirebaseResourceItem {
uuid: string;
combinedHash: string;
timestamp: number;
encodedGPSLocation: string;
transactions: BlockTransaction[];
lastBlockHash: string;
lastBlockUUID: string;
}
@Injectable()
export class BlockResource extends FirebaseResource<BlockResourceItem> {
public static collect(): AsyncCollection<BlockResourceItem> {
return new AsyncCollection<BlockResourceItem>(new BlockResource())
}
protected refName: RTDBRef = 'block'
}

110
src/app/units/Blockchain.ts Normal file
View File

@ -0,0 +1,110 @@
import {Singleton, Inject} from "@extollo/di"
import {Unit, Logging} from "@extollo/lib"
import {FirebaseUnit} from "./FirebaseUnit"
import {BlockResource, BlockResourceItem, BlockTransaction} from "../rtdb/BlockResource"
import {TransactionResourceItem} from "../rtdb/TransactionResource"
import * as crypto from "crypto"
export class Block implements BlockResourceItem {
seqID: number;
uuid: string;
combinedHash: string;
timestamp: number;
encodedGPSLocation: string;
transactions: BlockTransaction[];
lastBlockHash: string;
lastBlockUUID: string;
constructor(rec: BlockResourceItem) {
this.seqID = rec.seqID
this.uuid = rec.uuid
this.combinedHash = rec.combinedHash
this.timestamp = rec.timestamp
this.encodedGPSLocation = rec.encodedGPSLocation
this.transactions = rec.transactions
this.lastBlockHash = rec.lastBlockHash
this.lastBlockUUID = rec.lastBlockUUID
}
hash() {
return crypto.createHash('sha256')
.update(this.toString(), 'utf-8')
.digest('hex')
}
toString() {
return [
this.uuid,
this.combinedHash,
this.timestamp.toString(),
this.encodedGPSLocation,
JSON.stringify(this.transactions),
this.lastBlockHash,
this.lastBlockUUID,
].join('%')
}
}
export interface Peer {
host: string,
name?: string,
}
/**
* Blockchain Unit
* ---------------------------------------
* Main service for interacting with the contact blockchain.
*/
@Singleton()
export class Blockchain extends Unit {
@Inject()
protected readonly logging!: Logging
@Inject()
protected readonly firebase!: FirebaseUnit
public async hasPeer(host: string): Promise<boolean> {
const peers = await this.getPeers()
return peers.some(peer => peer.host.toLowerCase() === host.toLowerCase())
}
public async getPeers(): Promise<Peer[]> {
const data = await this.firebase.ref('peers').once('value')
return (data.val() as Peer[]) || []
}
public async registerPeer(peer: Peer) {
if ( !(await this.hasPeer(peer.host)) ) {
await this.firebase.ref('peers').push().set(peer)
}
}
public async validate(chain: Block[]) {
}
public async refresh() {
}
public async submitBlock(afterBlock: Block, proofToken: string) {
}
public async submitTransactions(group: [TransactionResourceItem, TransactionResourceItem]) {
// Not sure yet
}
public async getLastBlock(): Promise<Block | undefined> {
const rec: BlockResourceItem | undefined = await BlockResource.collect().last()
return rec ? new Block(rec) : undefined
}
public async up() {
}
public async down() {
}
}

View File

@ -2,7 +2,7 @@ import {Singleton, Inject} from "@extollo/di"
import {Unit, Logging, Config} from "@extollo/lib" import {Unit, Logging, Config} from "@extollo/lib"
import * as firebase from "firebase-admin" import * as firebase from "firebase-admin"
export type RTDBRef = 'peers' | 'transaction' export type RTDBRef = 'peers' | 'transaction' | 'block'
/** /**
* FirebaseUnit Unit * FirebaseUnit Unit