-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathblockchain.js
92 lines (81 loc) · 2.67 KB
/
blockchain.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
// This is a blockchain example app, written in Javascript
// generate a new blockchain with only a genesis block
function generateBlockChain() {
return [
{
value: '[Genesis Block]',
hashOfPreviousBlock: 'genesis'
}
]
}
// take a simple hash of a block. this is a very simple (read: insecure) hash
// function lifted from SO. If you were doing this for real, you'd definitely
// choose a proper hashing library
function hashBlock(block) {
var s = JSON.stringify(block)
return s.split("").reduce(function(a,b){a=((a<<5)-a)+b.charCodeAt(0);return a&a},0);
}
// given a string content, adds it to a block and appends to the given blockchain
function writeToChain(content, blockChain) {
var lastBlock = blockChain[blockChain.length - 1]
blockChain.push({
value: content,
hashOfPreviousBlock: hashBlock(lastBlock)
})
}
// returns all the values in the given blockchain
function readFromChain(blockChain) {
return blockChain.map(function(block) {
return block.value
}).join(', ')
}
// re-hashes the given blockchain and checks the hashes are valid
function isValidChain(blockChain) {
var isValid = true
blockChain.reduce(function(prevBlock, block) {
if (hashBlock(prevBlock) != block.hashOfPreviousBlock) {
isValid = false
}
return block
})
return isValid
}
// given a current chain and a new chain, returns the new chain
// if it's a (valid) longer continuation of the current chain
function chooseBetweenChains(currentChain, newChain) {
// make sure new chain is longer than our current one
if (currentChain.length >= newChain.length) {
return currentChain
}
// make sure the new chain's hashes all match
if (!isValidChain(newChain)) {
return currentChain
}
// make sure the new chain is a continuation of our chain
var firstNewBlock = newChain[currentChain.length]
var lastCurrentBlock = currentChain[currentChain.length - 1]
if (firstNewBlock.hashOfPreviousBlock != hashBlock(lastCurrentBlock)) {
return currentChain
}
return newChain
}
// simple client for interacting with the above blockchain functions
function blockChainClient() {
var currentBlockChain = generateBlockChain()
return {
write: function(content) {
writeToChain(content, currentBlockChain)
// here you would broadcast `this.serializeChain()` to your P2P network
},
read: function() {
return readFromChain(currentBlockChain)
},
encounterNewChain: function(serializedNewChain) {
var newChain = JSON.parse(serializedNewChain)
currentBlockChain = chooseBetweenChains(currentBlockChain, newChain)
},
serializeChain: function() {
return JSON.stringify(currentBlockChain)
}
}
}