persistence for the blockchain + everything through the chain instead of broadcasting

This commit is contained in:
Josip Milovac 2022-12-05 16:00:26 +11:00
parent 1cb1070d45
commit ea81105df6
5 changed files with 127 additions and 61 deletions

View file

@ -1,4 +1,9 @@
const Websocket = require('ws');
const N3 = require('n3');
const parser = new N3.Parser(); //({format: 'application/n-quads'});
const DataFactory = require('n3').DataFactory;
const fs = require('fs');
const process = require('process');
const P2P_PORT = process.env.P2P_PORT || 5000;
const peers = process.env.PEERS ? process.env.PEERS.split(',') : [];
@ -10,10 +15,21 @@ const MESSAGE_TYPES = {
};
class P2pServer {
constructor(blockchain, transactionPool) {
constructor(blockchain, transactionPool,chainStorageLocation) {
this.blockchain = blockchain;
this.transactionPool = transactionPool;
this.sockets = [];
this.store = new N3.Store();
this.chainStorageLocation = chainStorageLocation;
//possible race if deleted after check, but we live with it I guess
if (fs.existsSync(this.chainStorageLocation)) {
const rawPersistedChain = fs.readFileSync(this.chainStorageLocation, 'utf8');
const chain = JSON.parse(rawPersistedChain);
this.newChain(chain, false);
} else {
console.log("Didn't find a persisted chain, starting from genesis");
}
}
listen() {
@ -47,7 +63,7 @@ class P2pServer {
const data = JSON.parse(message);
switch(data.type) {
case MESSAGE_TYPES.chain:
this.blockchain.replaceChain(data.chain);
newChain(data.chain);
break;
case MESSAGE_TYPES.transaction:
this.transactionPool.updateOrAddTransaction(data.transaction);
@ -62,6 +78,67 @@ class P2pServer {
});
}
newBlock(block) {
this.onNewBlock(block.data);
this.syncChains();
this.persistChain(this.blockchain.chain);
}
newChain(chain,persist) {
if (!this.blockchain.replaceChain(chain)) {
//failed to replace
return;
}
if (typeof persist === "undefined" || persist) {
this.persistChain(chain);
}
//dirty clear
this.store = new N3.Store();
for (var block in this.blockchain.chain) {
this.onNewBlock(block);
}
}
persistChain(chain) {
try {
fs.writeFileSync(
this.chainStorageLocation,
JSON.stringify(chain));
} catch (err) {
console.error("Couldn't persist chain, aborting");
process.exit(-1);
}
}
onNewBlock(block) {
//block data is of form [transactions,metadatas]
if (block.length != 2) {
//assert?
return;
}
const metadatas = block[1];
for (var metadata in metadatas) {
if (!(SSNmetadata in metadata)) {
//assert?
return;
}
var ssn = metadata.SSNmetadata;
parser.parse(
ssn,
(error, quadN, prefixes) => {
if (quadN) {
store.addQuad(DataFactory.quad(
DataFactory.namedNode(quadN.subject.id),
DataFactory.namedNode(quadN.predicate.id),
DataFactory.namedNode(quadN.object.id)));
}
});
}
}
sendChain(socket) {
socket.send(JSON.stringify({
type: MESSAGE_TYPES.chain,
@ -69,36 +146,36 @@ class P2pServer {
}));
}
sendTransaction(socket, transaction) {
socket.send(JSON.stringify({
type: MESSAGE_TYPES.transaction,
transaction
}));
}
//sendTransaction(socket, transaction) {
// socket.send(JSON.stringify({
// type: MESSAGE_TYPES.transaction,
// transaction
// }));
//}
sendMetadata(socket, metadata) {
socket.send(JSON.stringify({
type: MESSAGE_TYPES.metadata,
metadata
}));
}
//sendMetadata(socket, metadata) {
// socket.send(JSON.stringify({
// type: MESSAGE_TYPES.metadata,
// metadata
// }));
//}
syncChains() {
this.sockets.forEach(socket => this.sendChain(socket));
}
broadcastTransaction(transaction) {
this.sockets.forEach(socket => this.sendTransaction(socket, transaction));
}
//broadcastTransaction(transaction) {
// this.sockets.forEach(socket => this.sendTransaction(socket, transaction));
//}
broadcastMetadata(metadata) {
this.sockets.forEach(socket => this.sendMetadata(socket, metadata));
}
//broadcastMetadata(metadata) {
// this.sockets.forEach(socket => this.sendMetadata(socket, metadata));
//}
broadcastClearTransactions() {
this.sockets.forEach(socket => socket.send(JSON.stringify({
type: MESSAGE_TYPES.clear_transactions
})));
}
//broadcastClearTransactions() {
// this.sockets.forEach(socket => socket.send(JSON.stringify({
// type: MESSAGE_TYPES.clear_transactions
// })));
//}
}
module.exports = P2pServer;