Skip to content

Instantly share code, notes, and snippets.

@justmoon
Created December 29, 2011 16:35
Show Gist options
  • Save justmoon/1534875 to your computer and use it in GitHub Desktop.
Save justmoon/1534875 to your computer and use it in GitHub Desktop.
BlockChain, main processing sequence, Step example
/**
* Connect a block and store it.
*
* This function takes over once add() has ascertained that the block passed
* intrinsic checks and there is no reorg currently in progress.
*/
var processBlock = this.processBlock = function processBlock(bw) {
// Shorthand
var block = bw.block;
Step(
function prepare() {
isProcessing = true;
// Index block while it is being connected
connectingBlockIndex.add(bw);
lastRecvBlock = block;
// See if any orphans were waiting for this block
var childBws = connectingBlockIndex.getByParent(bw.hash64);
if (childBws) {
// Remove those orphans as chain heads and add us instead
connectingBlockIndex.removeHeads(childBws);
connectingBlockIndex.addHead(bw, bw.parent64);
// This will cause our children to be added once we are processed
bw.children = childBws;
}
this(null);
},
function connect(err) {
if (err) throw err;
connectBlock(bw, this);
},
function verifyConnection(err) {
if (err) throw err;
bw.parent.verifyChild(self, bw.block, this);
},
function applyParent(err) {
if (err) throw err;
switch (bw.mode) {
case 'main':
connectToMainChain(bw, this);
break;
case 'side':
connectToSideChain(bw, bw.parent, this);
break;
}
},
function prepareTxs(err) {
if (err) throw err;
var txList = [];
bw.txs = bw.txs.map(function (tx) {
if (!(tx instanceof Transaction)) {
tx = new Transaction(tx);
}
// Calculate the hash
tx.getHash();
txList.push(tx.hash);
return tx;
});
bw.block.txs = txList;
this(null);
},
function verifyBlockStep(err) {
if (err) throw err;
verifyBlock(bw, this);
},
function reorganize(err) {
if (err) throw err;
if (bw.mode == "side" && bw.block.moreWorkThan(currentTopBlock)) {
self.reorganize(currentTopBlock, bw.block, this);
} else {
this(null);
}
},
function saveTransactions(err) {
if (err) throw err;
self.saveTransactions(bw.block, bw.txs, this);
},
function saveBlock(err) {
if (err) throw err;
self.saveBlock(bw, this);
},
function connectTransactions(err) {
if (err) throw err;
if (bw.mode == "main") {
self.connectTransactions(bw.block, bw.txs, this);
} else {
this();
}
},
function queueDependents(err) {
if (err) throw err;
// Children of this block can now be processed as well
// TODO: In case this block failed to be added, we should discard
// its children as well.
if (bw.children) {
bw.children.forEach(function (childBw) {
childBw.block.attachTo(bw.block);
});
if (bw.mode == "main") {
// Main chain blocks are processed with priority
incomingBlockQueue = bw.children.concat(incomingBlockQueue);
} else {
// Side chain blocks are processed last
incomingBlockQueue = incomingBlockQueue.concat(bw.children);
}
}
this();
},
function finalize(err) {
// The codes "orphan" and "discard" are special error codes used to
// skip to this point.
if (err === "orphan" || err === "discard") {
err = null;
}
// If block failed processing, remove from caches
if (err) {
// If this block was connected to the main chain, we need to undo
// the updating of currentTopBlock
if (bw.mode == "main") {
currentTopBlock = bw.parent;
}
connectingBlockIndex.remove(bw);
recentBlockIndex.remove(bw.hash64);
}
bw.callback(err);
bw = null;
if (incomingBlockQueue.length) {
var next = incomingBlockQueue.shift();
process.nextTick(self.processBlock.bind(self, next));
//self.processBlock(next);
} else {
isProcessing = false;
self.emit('queueDone', {chain: self});
}
}
);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment