forked from ruqqq/blockchainparser
-
Notifications
You must be signed in to change notification settings - Fork 1
/
block_file.go
133 lines (113 loc) · 2.9 KB
/
block_file.go
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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
package blockchainparser
import (
"bytes"
"encoding/binary"
"fmt"
"os"
)
const (
//! Magic numbers to identify start of block
BLOCK_MAGIC_ID_BITCOIN MagicId = 0xd9b4bef9
BLOCK_MAGIC_ID_TESTNET MagicId = 0x0709110b
)
type BlockFile struct {
file *os.File
FileNum uint32
}
func NewBlockFile(blockchainDataDir string, fileNum uint32) (*BlockFile, error) {
filepath := fmt.Sprintf(blockchainDataDir+"/blocks/blk%05d.dat", fileNum)
//fmt.Printf("Opening file %s...\n", filepath)
file, err := os.OpenFile(filepath, os.O_RDONLY, 0666)
if err != nil {
return nil, err
}
return &BlockFile{file: file, FileNum: fileNum}, nil
}
func (blockFile *BlockFile) Close() {
blockFile.file.Close()
}
func (blockFile *BlockFile) Seek(offset int64, whence int) (int64, error) {
return blockFile.file.Seek(offset, whence)
}
func (blockFile *BlockFile) Size() (int64, error) {
fileInfo, err := blockFile.file.Stat()
if err != nil {
return 0, err
}
return fileInfo.Size(), err
}
func (blockFile *BlockFile) Peek(length int) ([]byte, error) {
pos, err := blockFile.file.Seek(0, 1)
if err != nil {
return nil, err
}
val := make([]byte, length)
blockFile.file.Read(val)
_, err = blockFile.file.Seek(pos, 0)
if err != nil {
return nil, err
}
return val, nil
}
func (blockFile *BlockFile) ReadByte() byte {
val := make([]byte, 1)
blockFile.file.Read(val)
return val[0]
}
func (blockFile *BlockFile) ReadBytes(length uint64) []byte {
val := make([]byte, length)
blockFile.file.Read(val)
return val
}
func (blockFile *BlockFile) ReadUint16() uint16 {
val := make([]byte, 2)
blockFile.file.Read(val)
return binary.LittleEndian.Uint16(val)
}
func (blockFile *BlockFile) ReadInt32() int32 {
raw := make([]byte, 4)
blockFile.file.Read(raw)
var val int32
binary.Read(bytes.NewReader(raw), binary.LittleEndian, &val)
return val
}
func (blockFile *BlockFile) ReadUint32() uint32 {
val := make([]byte, 4)
blockFile.file.Read(val)
return binary.LittleEndian.Uint32(val)
}
func (blockFile *BlockFile) ReadInt64() int64 {
raw := make([]byte, 8)
blockFile.file.Read(raw)
var val int64
binary.Read(bytes.NewReader(raw), binary.LittleEndian, &val)
return val
}
func (blockFile *BlockFile) ReadUint64() uint64 {
val := make([]byte, 8)
blockFile.file.Read(val)
return binary.LittleEndian.Uint64(val)
}
//func (blockFile *BlockFile) ReadVarint() uint64 {
// chSize := blockFile.ReadByte()
// if chSize < 253 {
// return uint64(chSize)
// } else if chSize == 253 {
// return uint64(blockFile.ReadUint16())
// } else if chSize == 254 {
// return uint64(blockFile.ReadUint32())
// } else {
// return blockFile.ReadUint64()
// }
//}
func (blockFile *BlockFile) ReadVarint() uint64 {
intType := blockFile.ReadByte()
if intType == 0xFF {
return blockFile.ReadUint64()
} else if intType == 0xFE {
return uint64(blockFile.ReadUint32())
} else if intType == 0xFD {
return uint64(blockFile.ReadUint16())
}
return uint64(intType)
}