Basic infrastructure for remote peering

This commit is contained in:
Garrett Mills 2021-04-10 13:00:29 -05:00
parent 46131e2219
commit 313fdb65e9
Signed by: garrettmills
GPG Key ID: D2BF5FBA8298F246
4 changed files with 73 additions and 7 deletions

View File

@ -81,7 +81,7 @@ export class FirebaseResource<T extends FirebaseResourceItem> extends Iterable<T
// @ts-ignore
delete item.firebaseID
collection.push(item)
collection.push(this.filter(item))
return collection
})
@ -123,4 +123,22 @@ export class FirebaseResource<T extends FirebaseResourceItem> extends Iterable<T
inst.refName = this.refName
return inst
}
filter(obj: {[key: string]: any}) {
for (let key in obj) {
if (obj[key] === undefined) {
delete obj[key]
continue
}
if (obj[key] && typeof obj[key] === "object") {
this.filter(obj[key])
if (!Object.keys(obj[key]).length) {
delete obj[key]
}
}
}
return obj
}
}

View File

@ -6,6 +6,10 @@ export default {
base_url: env('BASE_URL', 'http://localhost:8000/'),
peers: [
// 'http://127.0.0.1:8100/',
],
session: {
/* The implementation of @extollo/lib.Session that serves as the session backend. */
driver: MemorySession,

View File

@ -22,11 +22,11 @@ export class ServerGPGTokenVerify extends Middleware {
}
// if single string
if (typeof(value) === 'string') {
this.verifyToken(value)
this.verifyToken(Buffer.from(value, 'base64').toString('utf-8'))
return
} else { // else an array of strings
for (const item of value) {
if (await this.verifyToken(item)) {
if (await this.verifyToken(Buffer.from(item, 'base64').toString('utf-8'))) {
return
}
}

View File

@ -144,6 +144,15 @@ export class Blockchain extends Unit {
protected isSubmitting: boolean = false
async up() {
const peers = this.config.get('server.peers')
for ( const peer of peers ) {
await this.registerPeer({
host: peer,
})
}
}
/**
* Returns true if the given host is registered as a peer.
* @param host
@ -166,7 +175,7 @@ export class Blockchain extends Unit {
*/
public async getPeerSubmit(peer: Peer): Promise<Block[] | undefined> {
try {
const result = await axios.get(peer.host)
const result = await axios.get(`${peer.host}api/v1/chain/submit`)
const blocks: unknown = result.data?.data?.records
if ( Array.isArray(blocks) && blocks.every(isBlockResourceItem) ) {
return blocks.map(x => new Block(x))
@ -182,6 +191,7 @@ export class Blockchain extends Unit {
*/
public async registerPeer(peer: Peer) {
if (!(await this.hasPeer(peer.host))) {
this.logging.info(`Registering peer: ${peer.host}`)
await (<PeerResource> this.make(PeerResource)).push({
firebaseID: '',
seqID: -1,
@ -189,7 +199,28 @@ export class Blockchain extends Unit {
host: peer.host,
})
this.refresh()
const header = this.config.get('app.api_server_header')
try {
console.log('return peering', [`${peer.host}api/v1/peer`, {
host: this.getBaseURL(),
}, {
headers: {
[header]: await this.getPeerToken(),
}
}])
await axios.post(`${peer.host}api/v1/peer`, {
host: this.getBaseURL(),
}, {
headers: {
[header]: await this.getPeerToken(),
}
})
this.refresh()
} catch (e) {
this.logging.error(e)
}
}
}
@ -289,7 +320,7 @@ export class Blockchain extends Unit {
await (<BlockResource>this.app().make(BlockResource)).push(block)
} else {
await this.firebase.ref('block').transaction((_) => {
return time_x_blocks[min].map(x => x.toItem())
return (time_x_blocks[min] || []).map(x => x.toItem())
})
this.pendingSubmit = undefined
@ -307,6 +338,7 @@ export class Blockchain extends Unit {
blocks.push(submit.toItem())
}
this.refresh()
return blocks
}
@ -404,6 +436,18 @@ export class Blockchain extends Unit {
return new Block(block)*/
}
public async getPeerToken() {
const message = openpgp.Message.fromText("0000")
const privateKey = this.config.get("app.gpg.key.private")
return Buffer.from((await openpgp.sign({
message,
privateKeys: await openpgp.readKey({
armoredKey: privateKey
}),
})), 'utf-8').toString('base64')
}
/**
* Instantiate the genesis block of the entire chain.
*/
@ -513,7 +557,7 @@ export class Blockchain extends Unit {
*/
protected getBaseURL(): string {
const base = this.config.get('server.base_url')
return `${base}${base.endsWith('/') ? '' : '/'}api/v1/chain/submit`
return `${base}${base.endsWith('/') ? '' : '/'}`
}
/** Sleep for (roughly) the given number of milliseconds. */