-
-
Notifications
You must be signed in to change notification settings - Fork 203
Expand file tree
/
Copy pathEthereumBlockObject.swift
More file actions
211 lines (166 loc) · 6.69 KB
/
EthereumBlockObject.swift
File metadata and controls
211 lines (166 loc) · 6.69 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
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
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
//
// EthereumBlockObject.swift
// Web3
//
// Created by Koray Koska on 30.12.17.
//
import Foundation
/**
* A block as returned by an Ethereum node.
*/
public struct EthereumBlockObject: Codable {
/// The block number. nil when its a pending block.
public let number: EthereumQuantity?
/// 32 Bytes - hash of the block. nil when its a pending block.
public let hash: EthereumData?
/// 32 Bytes - hash of the parent block.
public let parentHash: EthereumData
/// 8 Bytes - hash of the generated proof-of-work. nil when its a pending block.
public let nonce: EthereumData?
/// 32 Bytes - SHA3 of the uncles data in the block.
public let sha3Uncles: EthereumData
/// 256 Bytes - the bloom filter for the logs of the block. null when its a pending block.
public let logsBloom: EthereumData?
/// 32 Bytes - the root of the transaction trie of the block.
public let transactionsRoot: EthereumData
/// 32 Bytes - the root of the final state trie of the block.
public let stateRoot: EthereumData
/// 32 Bytes - the root of the receipts trie of the block.
public let receiptsRoot: EthereumData
/// 20 Bytes - the address of the beneficiary to whom the mining rewards were given.
public let miner: EthereumAddress
/// Integer of the difficulty for this block.
public let difficulty: EthereumQuantity
/// Integer of the total difficulty of the chain until this block.
public let totalDifficulty: EthereumQuantity?
/// The "extra data" field of this block.
public let extraData: EthereumData
/// Integer the size of this block in bytes.
public let size: EthereumQuantity?
/// The maximum gas allowed in this block.
public let gasLimit: EthereumQuantity
/// The total used gas by all transactions in this block.
public let gasUsed: EthereumQuantity
/// The unix timestamp for when the block was collated.
public let timestamp: EthereumQuantity
/// Array of transaction objects, or 32 Bytes transaction hashes depending on the last given parameter.
public let transactions: [Transaction]?
/// Array of uncle hashes.
public let uncles: [EthereumData]?
/// The block base fees per gas (EIP-1559)
public let baseFeePerGas: EthereumQuantity?
/**
* Represents a transaction as either a hash or an object.
*/
public struct Transaction: Codable {
/// The transaction as an object
public let object: EthereumTransactionObject?
/// The transaction as an hash
public let hash: EthereumData?
/**
* Initialize this Transaction as an object.
*
* - parameter object: The Transaction as an object.
*/
public init(object: EthereumTransactionObject) {
self.object = object
self.hash = nil
}
/**
* Initialize this Transaction as an hash.
*
* - parameter hash: The transaction hash.
*/
public init(hash: EthereumData) {
self.hash = hash
self.object = nil
}
public init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
if let tx = try? container.decode(EthereumTransactionObject.self) {
self.init(object: tx)
} else if let tx = try? container.decode(EthereumData.self) {
self.init(hash: tx)
} else {
throw Error.unsupportedType
}
}
public func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
if let object = object {
try container.encode(object)
} else if let hash = hash {
try container.encode(hash)
} else {
// This will never happen, but to be consistent...
try container.encodeNil()
}
}
/// Encoding and Decoding errors specific to EthereumValue
public enum Error: Swift.Error {
/// The type set is not convertible to EthereumValue
case unsupportedType
}
}
}
// MARK: - Equatable
extension EthereumBlockObject.Transaction: Equatable {
public static func ==(_ lhs: EthereumBlockObject.Transaction, _ rhs: EthereumBlockObject.Transaction) -> Bool {
return lhs.object == rhs.object && lhs.hash == rhs.hash
}
}
extension EthereumBlockObject: Equatable {
public static func ==(_ lhs: EthereumBlockObject, _ rhs: EthereumBlockObject) -> Bool {
return lhs.number == rhs.number
&& lhs.hash == rhs.hash
&& lhs.parentHash == rhs.parentHash
&& lhs.nonce == rhs.nonce
&& lhs.sha3Uncles == rhs.sha3Uncles
&& lhs.logsBloom == rhs.logsBloom
&& lhs.transactionsRoot == rhs.transactionsRoot
&& lhs.stateRoot == rhs.stateRoot
&& lhs.receiptsRoot == rhs.receiptsRoot
&& lhs.miner == rhs.miner
&& lhs.difficulty == rhs.difficulty
&& lhs.totalDifficulty == rhs.totalDifficulty
&& lhs.extraData == rhs.extraData
&& lhs.size == rhs.size
&& lhs.gasLimit == rhs.gasLimit
&& lhs.gasUsed == rhs.gasUsed
&& lhs.timestamp == rhs.timestamp
&& lhs.transactions == rhs.transactions
&& lhs.uncles == rhs.uncles
}
}
// MARK: - Hashable
extension EthereumBlockObject.Transaction: Hashable {
public func hash(into hasher: inout Hasher) {
hasher.combine(hash)
hasher.combine(object?.hashValue ?? 0)
}
}
extension EthereumBlockObject: Hashable {
public func hash(into hasher: inout Hasher) {
// As of now we don't include transactions and uncles into the hashValue. This should be sufficiently fast for
// the average case, which is enough for now. (Normally there are no block objects which have exact same values
// but different transactions and uncles unless they were requested to include only tx hashes/complete objects.
// We should test those cases and change this function if it makes a huge difference)
hasher.combine(number)
hasher.combine(hash)
hasher.combine(parentHash)
hasher.combine(nonce)
hasher.combine(sha3Uncles)
hasher.combine(logsBloom)
hasher.combine(transactionsRoot)
hasher.combine(stateRoot)
hasher.combine(receiptsRoot)
hasher.combine(miner)
hasher.combine(difficulty)
hasher.combine(totalDifficulty)
hasher.combine(extraData)
hasher.combine(size)
hasher.combine(gasLimit)
hasher.combine(gasUsed)
hasher.combine(timestamp)
}
}