Skip to content

Instantly share code, notes, and snippets.

@harshvishu
Last active January 8, 2019 15:58
Show Gist options
  • Save harshvishu/e6e0353e77588f8a0835306f31088e48 to your computer and use it in GitHub Desktop.
Save harshvishu/e6e0353e77588f8a0835306f31088e48 to your computer and use it in GitHub Desktop.
Swift-Blockchain-Node
class Blockchain: Chain {
// MARK: - Properties
...
var nodes: Set<String>
// MARK: - Initializers
init() {
...
nodes = Set()
// Create the genesis block
self.newBlock(previous_hash: "1", proof: 100)
}
// MARK: - Methods
...
// Generate a globally unique address for this node
var node_identifier: String {
return ProcessInfo().globallyUniqueString.replacingOccurrences(of: "-", with: "")
}
/**
Add a new node to the list of nodes
- Parameter address: Address of node. Eg. 'http://192.168.0.5:5000'
*/
func registerNode(address: String) -> Bool {
let options = ClientRequest.parse(address)
for option in options {
if case let ClientRequest.Options.hostname(host) = option, !host.isEmpty {
self.nodes.insert(host)
return true
}
}
print("Invalid URL")
return false
}
/**
Determine if a given blockchain is valid
- Parameter chain: A blockchain
- returns: True if valid, False if not
*/
func validChain(_ chain: [Block]) -> Bool {
var last_block = chain[0]
var current_index = 1
while current_index < chain.count {
let block = chain[current_index]
print("\(last_block)")
print("\(block)")
print("\n----------\n")
// Check the hash of the block is correct
let last_block_hash = self.hash(block: last_block)
if block.previous_hash != last_block_hash {
return false
}
// Check that the Proof of Work is correct
if !self.validProof(last_proof: last_block.proof, proof: block.proof) {
return false
}
last_block = block
current_index += 1
}
return true
}
/**
This is our Consensus Algorithm, it resolves conflicts
by replacing our chain with the longest one in the network.
- returns: True if our chain was replaced, False if not
*/
func resolveConflicts() -> Bool {
let neighbours = self.nodes
var new_chain: [Block]?
// We're only looking for chains longer than ours
var max_length = self.chain.count
// Grab and verify the chains from all the nodes in our network
for node in neighbours {
let semaphore = DispatchSemaphore(value: 0)
struct ResponseData: Decodable {
let chain: [Block]
let length: Int
}
let request = RestRequest(method: .get, url: "http://\(node):5000/chain")
request.responseObject { (response: RestResponse<ResponseData>) in
switch response.result {
case .success(let response_data):
let length = response_data.length
let chain = response_data.chain
if length > max_length && self.validChain(chain) {
max_length = length
new_chain = chain
}
case .failure(let error):
print(error)
}
semaphore.signal()
}
_ = semaphore.wait(timeout: .distantFuture)
}
// Replace our chain if we discovered a new, valid chain longer than ours
if let new_chain = new_chain {
self.chain = new_chain
return true
}
return false
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment