-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathblockchain
More file actions
106 lines (102 loc) · 3.11 KB
/
blockchain
File metadata and controls
106 lines (102 loc) · 3.11 KB
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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
#!/usr/bin/php
<?php
/**
* A very simple BlockChain implementation intended to illustrate the concept.
*
* The block index simply maps a block to a disk offset for convenience.
* It's not necessary, but it makes it much easier to quickly locate any
* block within the chain.
*
* ISAM index:
* [4] count
* -----------
* [4] offset
* [4] length
* ...
*
* Block format:
* [4] magic
* [1] format (0x01)
* [4] timestamp
* [n] hash of previous block
* [4] data length
* [?] data
*
*
*/
define('_magic', 0xD5E8A97F);
define('_hashalg', 'sha256');
define('_hashlen', 32);
define('_blksize', (13 + _hashlen));
/*
$res = addblock('blockchain.dat','Some data');
if ($res!==TRUE) exit("ERROR: ".$res."\n");
*/
function addblock($fn, $data, $genesis = false)
{
$indexfn = $fn . '.idx';
if (!$genesis) {
if (!file_exists($fn)) {
return ('Missing blockchain data file!');
}
if (!file_exists($indexfn)) {
return ('Missing blockchain index file!');
}
// get disk location of last block from index
if (!$ix = fopen($indexfn, 'r+b')) {
return ("Can't open " . $indexfn);
}
$maxblock = unpack('V', fread($ix, 4))[1];
$zpos = (($maxblock * 8) - 4);
fseek($ix, $zpos, SEEK_SET);
$ofs = unpack('V', fread($ix, 4))[1];
$len = unpack('V', fread($ix, 4))[1];
// read last block and calculate hash
if (!$bc = fopen($fn, 'r+b')) {
return ("Can't open " . $fn);
}
fseek($bc, $ofs, SEEK_SET);
$block = fread($bc, $len);
$hash = hash(_hashalg, $block);
// add new block to the end of the chain
fseek($bc, 0, SEEK_END);
$pos = ftell($bc);
write_block($bc, $data, $hash);
fclose($bc);
// update index
update_index($ix, $pos, strlen($data), ($maxblock + 1));
fclose($ix);
return true;
} else {
if (file_exists($fn)) {
return ('Blockchain data file already exists!');
}
if (file_exists($indexfn)) {
return ('Blockchain index file already exists!');
}
$bc = fopen($fn, 'wb');
$ix = fopen($indexfn, 'wb');
write_block($bc, $data, str_repeat('00', _hashlen));
update_index($ix, 0, strlen($data), 1);
fclose($bc);
fclose($ix);
return true;
}
}
function write_block(&$fp, $data, $prevhash)
{
fwrite($fp, pack('V', _magic), 4); // Magic
fwrite($fp, chr(1), 1); // Version
fwrite($fp, pack('V', time()), 4); // Timestamp
fwrite($fp, hex2bin($prevhash), _hashlen); // Previous Hash
fwrite($fp, pack('V', strlen($data)), 4); // Data Length
fwrite($fp, $data, strlen($data)); // Data
}
function update_index(&$fp, $pos, $datalen, $count)
{
fseek($fp, 0, SEEK_SET);
fwrite($fp, pack('V', $count), 4); // Record count
fseek($fp, 0, SEEK_END);
fwrite($fp, pack('V', $pos), 4); // Offset
fwrite($fp, pack('V', ($datalen + _blksize)), 4); // Length
}