This repository has been archived by the owner on Oct 28, 2022. It is now read-only.
/
BlockHeader.swift
165 lines (145 loc) · 6.68 KB
/
BlockHeader.swift
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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
import GRDB
class BlockHeader: Record {
static let EMPTY_TRIE_HASH = CryptoUtils.shared.sha3(RLP.encode([]))
var hashHex: Data
var totalDifficulty: BInt = 0 // Scalar value corresponding to the sum of difficulty values of all previous blocks
var parentHash: Data // 256-bit Keccak-256 hash of parent block
let unclesHash: Data // 256-bit Keccak-256 hash of uncles portion of this block
let coinbase: Data // 160-bit address for fees collected from successful mining
let stateRoot: Data // 256-bit state trie root hash
let transactionsRoot: Data // 256-bit transactions trie root hash
let receiptsRoot: Data // 256-bit receipts trie root hash
let logsBloom: Data /* The Bloom filter composed from indexable information
* (logger address and log topics) contained in each log entry
* from the receipt of each transaction in the transactions list */
let difficulty: BInt /* A scalar value corresponding to the difficulty level of this block.
* This can be calculated from the previous block’s difficulty level
* and the timestamp */
var height: Int
let gasLimit: Int // A scalar value equal to the current limit of gas expenditure per block
let gasUsed: Int // A scalar value equal to the total gas used in transactions in this block
let timestamp: Int // A scalar value equal to the reasonable output of Unix's time() at this block's inception
let extraData: Data /* An arbitrary byte array containing data relevant to this block.
* With the exception of the genesis block, this must be 32 bytes or fewer */
let mixHash: Data /* A 256-bit hash which proves that together with nonce a sufficient amount
* of computation has been carried out on this block */
let nonce: Data /* A 64-bit hash which proves that a sufficient amount
* of computation has been carried out on this block */
init(hashHex: Data, totalDifficulty: BInt, parentHash: Data, unclesHash: Data, coinbase: Data,
stateRoot: Data, transactionsRoot: Data, receiptsRoot: Data, logsBloom: Data,
difficulty: BInt, height: Int, gasLimit: Int, gasUsed: Int, timestamp: Int,
extraData: Data, mixHash: Data, nonce: Data) {
self.hashHex = hashHex
self.totalDifficulty = totalDifficulty
self.parentHash = parentHash
self.unclesHash = unclesHash
self.coinbase = coinbase
self.stateRoot = stateRoot
self.transactionsRoot = transactionsRoot
self.receiptsRoot = receiptsRoot
self.logsBloom = logsBloom
self.difficulty = difficulty
self.height = height
self.gasLimit = gasLimit
self.gasUsed = gasUsed
self.timestamp = timestamp
self.extraData = extraData
self.mixHash = mixHash
self.nonce = nonce
super.init()
}
init(rlp: RLPElement) throws {
let rlpList = try rlp.listValue()
self.parentHash = rlpList[0].dataValue
self.unclesHash = rlpList[1].dataValue
self.coinbase = rlpList[2].dataValue
self.stateRoot = rlpList[3].dataValue
let transactionsRoot = rlpList[4].dataValue
if transactionsRoot.count == 0 {
self.transactionsRoot = BlockHeader.EMPTY_TRIE_HASH
} else {
self.transactionsRoot = transactionsRoot
}
let receiptsRoot = rlpList[5].dataValue
if receiptsRoot.count == 0 {
self.receiptsRoot = BlockHeader.EMPTY_TRIE_HASH
} else {
self.receiptsRoot = receiptsRoot
}
self.logsBloom = rlpList[6].dataValue
self.difficulty = try rlpList[7].bIntValue()
self.height = try rlpList[8].intValue()
self.gasLimit = try rlpList[9].intValue()
self.gasUsed = try rlpList[10].intValue()
self.timestamp = try rlpList[11].intValue()
self.extraData = rlpList[12].dataValue
self.mixHash = rlpList[13].dataValue
self.nonce = rlpList[14].dataValue
self.hashHex = CryptoUtils.shared.sha3(rlp.dataValue)
super.init()
}
override class var databaseTableName: String {
return "block_headers"
}
enum Columns: String, ColumnExpression {
case hashHex
case totalDifficulty
case parentHash
case unclesHash
case coinbase
case stateRoot
case transactionsRoot
case receiptsRoot
case logsBloom
case difficulty
case height
case gasLimit
case gasUsed
case timestamp
case extraData
case mixHash
case nonce
}
required init(row: Row) {
hashHex = row[Columns.hashHex]
totalDifficulty = row[Columns.totalDifficulty]
parentHash = row[Columns.parentHash]
unclesHash = row[Columns.unclesHash]
coinbase = row[Columns.coinbase]
stateRoot = row[Columns.stateRoot]
transactionsRoot = row[Columns.transactionsRoot]
receiptsRoot = row[Columns.receiptsRoot]
logsBloom = row[Columns.logsBloom]
difficulty = row[Columns.difficulty]
height = row[Columns.height]
gasLimit = row[Columns.gasLimit]
gasUsed = row[Columns.gasUsed]
timestamp = row[Columns.timestamp]
extraData = row[Columns.extraData]
mixHash = row[Columns.mixHash]
nonce = row[Columns.nonce]
super.init(row: row)
}
override func encode(to container: inout PersistenceContainer) {
container[Columns.hashHex] = hashHex
container[Columns.totalDifficulty] = totalDifficulty
container[Columns.parentHash] = parentHash
container[Columns.unclesHash] = unclesHash
container[Columns.coinbase] = coinbase
container[Columns.stateRoot] = stateRoot
container[Columns.transactionsRoot] = transactionsRoot
container[Columns.receiptsRoot] = receiptsRoot
container[Columns.logsBloom] = logsBloom
container[Columns.difficulty] = difficulty
container[Columns.height] = height
container[Columns.gasLimit] = gasLimit
container[Columns.gasUsed] = gasUsed
container[Columns.timestamp] = timestamp
container[Columns.extraData] = extraData
container[Columns.mixHash] = mixHash
container[Columns.nonce] = nonce
}
func toString() -> String {
return "(hash: \(hashHex.toHexString()); height: \(height); parentHash: \(parentHash.toHexString()))"
}
}