Scala
2018/11/10 Scala Summit 2018
• @itohiro73
• FOLIO
• Reladomo in Scala Scala
Summit 2017
• 2009 Satoshi Nakamoto
Bitcoin https://bitcoin.org/bitcoin.pdf
• Bitcoin
•
• 2017
•
•
•
🙋
👍
0
🤔
•
✓
• Proof of Work
✓
✓nonse Proof of Work
✓mining
•
•
•
•
import java.math.BigInteger
import java.security.MessageDigest
object HashFunction {
val MD_SHA256 = MessageDigest.getInstance("SHA-256")
def sha256(input: String): String =
{
String.format("%064x", new BigInteger(1,
MD_SHA256.digest(input.getBytes("UTF-8"))))
}
}
scala> HashFunction.sha256("a")
res0: String =
ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785
afee48bb
scala> HashFunction.sha256("test")
res1: String =
9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15
b0f00a08
scala> HashFunction.sha256("same input")
res2: String =
c2f991739d5824b4e1d8bafaffb735b9e4061f801d82c4aaf57aea02
495f750c
scala> HashFunction.sha256("same input")
res3: String =
c2f991739d5824b4e1d8bafaffb735b9e4061f801d82c4aaf57aea02
495f750c
??? =
f0157537806d0ec6fd86455f6603bbaf1efed378798bcb43377456bc
6a8bfd78
scala> HashFunction.sha256("random input1")
res5: String =
3ef129a908f6b5e0c11cade17bb27691f6bd8cfffbb18622448a5fb229ca724d
scala> HashFunction.sha256("random input2")
res6: String =
dac708dccfe5ccbf009c9e5cd43ee9bf592abd0c7c04b421d8fe79f7518784c3
scala> HashFunction.sha256("random input3")
res7: String =
30b9b0875d568d926cf653f2360e95c86e8b798574a0ec95ceb7ef43cc9768ad
class Block(val timestamp: LocalDateTime, val data:
String, val previousHash: String) {
val hash = calculateHash()
def calculateHash(): String = {
val value = timestamp.toString + data + previousHash
HashFunction.sha256(value)
}
}
override def toString: String = {
"{ntTimestamp: " + this.timestamp +
"ntData: " + this.data +
"ntPrevious Hash: " + this.previousHash +
"ntHash:" + this.hash +
"n}"
}
class Blockchain(){
var chain = Seq[Block](createGenesisBlock())
def createGenesisBlock(): Block = {
new Block(LocalDateTime.now(), "A genesis block")
}
def addBlock(block: Block): Unit = {
this.chain = this.chain :+ block
}
def getLastBlock(): Block = {
this.chain.last
}
}
override def toString: String = {
this.chain.mkString("n")
}
def isChainValid(): Boolean = {
for(i <- 1 until this.chain.length) {
val currentBlock = this.chain(i)
val previousBlock = this.chain(i-1)
if(currentBlock.hash != currentBlock.calculateHash())
return false
if(currentBlock.previousHash != previousBlock.hash)
return false
}
return true
}
•Bitcoin Proof of
Work
•Proof of Work
0
✓ Satoshi Nakamoto
•
• nonce
• mining
• =difficulty
✓Bitcoin 10 difficulty
• nonce
• nonce
class Block(val timestamp: LocalDateTime, val data: String, val previousHash: String = "") {
var hash = calculateHash()
var nonce = 0
def calculateHash(): String = {
val value = timestamp.toString + data + previousHash + nonce
HashFunction.sha256(value)
}
def mineBlock(difficulty: Int): Unit = {
while(this.hash.substring(0, difficulty) != Array.fill(difficulty)("0").mkString ) {
this.nonce += 1
this.hash = calculateHash()
}
println("Block mined: " + this.hash)
}
class Blockchain {
var chain = Seq[Block](createGenesisBlock())
val difficulty = 4
def createGenesisBlock(): Block = {
new Block(LocalDateTime.now(), "A genesis block.")
}
def addBlock(block: Block): Unit = {
block.mineBlock(difficulty)
this.chain = this.chain :+ block
}
•nonce
Proof of Work
•Blockchain Block
class Transaction(val fromAddress: String, val
toAddress: String, val amount: Double) {
override def toString: String = {
"From Address: " + fromAddress + ", To Address: " +
toAddress + ", Amount: " + amount
}
}
import java.time.LocalDateTime
class Block(val timestamp: LocalDateTime, val transactions: Seq[Transaction], val previousHash: String = "") {
var hash = this.calculateHash()
var nonce = 0
def calculateHash(): String = {
val value = this.timestamp + this.transactions.mkString + this.previousHash + this.nonce
HashFunction.sha256(value)
}
def mineBlock(difficulty: Int): Unit = {
while(this.hash.substring(0, difficulty) != Array.fill(difficulty)("0").mkString) {
this.nonce += 1
this.hash = this.calculateHash()
}
}
override def toString: String = {
"{ntTimestamp: " + this.timestamp +
"ntTransaction: " + this.transactions.mkString("ntt{nttt", "nttt", "ntt}") +
"ntPrevious Hash: " + this.previousHash +
"ntHash: " + this.hash +
"ntNonse: " + this.nonce +
"n}"
}
class Blockchain {
var chain = Seq[Block](createGenesisBlock())
val difficulty = 4
var pendingTransactions = Seq[Transaction]()
val miningReward = 100
def createGenesisBlock(): Block = {
new Block(LocalDateTime.now(), Seq(new
Transaction("", "Initial Pool Address", 500)))
}
def addTransaction(transaction: Transaction): Unit = {
this.pendingTransactions = this.pendingTransactions :+ transaction
}
def minePendingTransactions(rewardAddress: String): Unit = {
val newBlock = new Block(LocalDateTime.now(), this.pendingTransactions)
newBlock.mineBlock(this.difficulty)
println("Block successfully mined: " + newBlock)
this.chain = this.chain :+ newBlock
this.pendingTransactions = Seq[Transaction](new Transaction("Reward",
rewardAddress, this.miningReward))
}
def getBalanceOfAddress(address: String): Double = {
var balance = 0.0
this.chain.flatMap(block =>
block.transactions).foreach(transaction => {
if(transaction.fromAddress == address)
balance -= transaction.amount
if(transaction.toAddress == address)
balance += transaction.amount
})
balance
}
•
✓
• Proof of Work
✓
✓nonse Proof of Work
✓mining
https://github.com/itohiro73/blockchain-scala
Satoshi Nakamoto (2009) Bitcoin: A Peer-to-Peer Electronic Cash System
2017
2018
Building a blockchain with Javascript

Scalaで実装してみる簡易ブロックチェーン

  • 1.
  • 2.
    • @itohiro73 • FOLIO •Reladomo in Scala Scala Summit 2017
  • 4.
    • 2009 SatoshiNakamoto Bitcoin https://bitcoin.org/bitcoin.pdf • Bitcoin • • 2017
  • 5.
  • 9.
  • 12.
  • 14.
  • 15.
  • 18.
    • ✓ • Proof ofWork ✓ ✓nonse Proof of Work ✓mining
  • 20.
  • 21.
    import java.math.BigInteger import java.security.MessageDigest objectHashFunction { val MD_SHA256 = MessageDigest.getInstance("SHA-256") def sha256(input: String): String = { String.format("%064x", new BigInteger(1, MD_SHA256.digest(input.getBytes("UTF-8")))) } }
  • 22.
    scala> HashFunction.sha256("a") res0: String= ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785 afee48bb scala> HashFunction.sha256("test") res1: String = 9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15 b0f00a08
  • 23.
    scala> HashFunction.sha256("same input") res2:String = c2f991739d5824b4e1d8bafaffb735b9e4061f801d82c4aaf57aea02 495f750c scala> HashFunction.sha256("same input") res3: String = c2f991739d5824b4e1d8bafaffb735b9e4061f801d82c4aaf57aea02 495f750c
  • 24.
  • 25.
    scala> HashFunction.sha256("random input1") res5:String = 3ef129a908f6b5e0c11cade17bb27691f6bd8cfffbb18622448a5fb229ca724d scala> HashFunction.sha256("random input2") res6: String = dac708dccfe5ccbf009c9e5cd43ee9bf592abd0c7c04b421d8fe79f7518784c3 scala> HashFunction.sha256("random input3") res7: String = 30b9b0875d568d926cf653f2360e95c86e8b798574a0ec95ceb7ef43cc9768ad
  • 31.
    class Block(val timestamp:LocalDateTime, val data: String, val previousHash: String) { val hash = calculateHash() def calculateHash(): String = { val value = timestamp.toString + data + previousHash HashFunction.sha256(value) } }
  • 32.
    override def toString:String = { "{ntTimestamp: " + this.timestamp + "ntData: " + this.data + "ntPrevious Hash: " + this.previousHash + "ntHash:" + this.hash + "n}" }
  • 33.
    class Blockchain(){ var chain= Seq[Block](createGenesisBlock()) def createGenesisBlock(): Block = { new Block(LocalDateTime.now(), "A genesis block") } def addBlock(block: Block): Unit = { this.chain = this.chain :+ block } def getLastBlock(): Block = { this.chain.last } }
  • 34.
    override def toString:String = { this.chain.mkString("n") }
  • 35.
    def isChainValid(): Boolean= { for(i <- 1 until this.chain.length) { val currentBlock = this.chain(i) val previousBlock = this.chain(i-1) if(currentBlock.hash != currentBlock.calculateHash()) return false if(currentBlock.previousHash != previousBlock.hash) return false } return true }
  • 40.
    •Bitcoin Proof of Work •Proofof Work 0 ✓ Satoshi Nakamoto
  • 41.
    • • nonce • mining •=difficulty ✓Bitcoin 10 difficulty
  • 43.
  • 44.
    class Block(val timestamp:LocalDateTime, val data: String, val previousHash: String = "") { var hash = calculateHash() var nonce = 0 def calculateHash(): String = { val value = timestamp.toString + data + previousHash + nonce HashFunction.sha256(value) } def mineBlock(difficulty: Int): Unit = { while(this.hash.substring(0, difficulty) != Array.fill(difficulty)("0").mkString ) { this.nonce += 1 this.hash = calculateHash() } println("Block mined: " + this.hash) }
  • 45.
    class Blockchain { varchain = Seq[Block](createGenesisBlock()) val difficulty = 4 def createGenesisBlock(): Block = { new Block(LocalDateTime.now(), "A genesis block.") } def addBlock(block: Block): Unit = { block.mineBlock(difficulty) this.chain = this.chain :+ block }
  • 47.
  • 56.
    class Transaction(val fromAddress:String, val toAddress: String, val amount: Double) { override def toString: String = { "From Address: " + fromAddress + ", To Address: " + toAddress + ", Amount: " + amount } }
  • 57.
    import java.time.LocalDateTime class Block(valtimestamp: LocalDateTime, val transactions: Seq[Transaction], val previousHash: String = "") { var hash = this.calculateHash() var nonce = 0 def calculateHash(): String = { val value = this.timestamp + this.transactions.mkString + this.previousHash + this.nonce HashFunction.sha256(value) } def mineBlock(difficulty: Int): Unit = { while(this.hash.substring(0, difficulty) != Array.fill(difficulty)("0").mkString) { this.nonce += 1 this.hash = this.calculateHash() } } override def toString: String = { "{ntTimestamp: " + this.timestamp + "ntTransaction: " + this.transactions.mkString("ntt{nttt", "nttt", "ntt}") + "ntPrevious Hash: " + this.previousHash + "ntHash: " + this.hash + "ntNonse: " + this.nonce + "n}" }
  • 58.
    class Blockchain { varchain = Seq[Block](createGenesisBlock()) val difficulty = 4 var pendingTransactions = Seq[Transaction]() val miningReward = 100 def createGenesisBlock(): Block = { new Block(LocalDateTime.now(), Seq(new Transaction("", "Initial Pool Address", 500))) }
  • 59.
    def addTransaction(transaction: Transaction):Unit = { this.pendingTransactions = this.pendingTransactions :+ transaction } def minePendingTransactions(rewardAddress: String): Unit = { val newBlock = new Block(LocalDateTime.now(), this.pendingTransactions) newBlock.mineBlock(this.difficulty) println("Block successfully mined: " + newBlock) this.chain = this.chain :+ newBlock this.pendingTransactions = Seq[Transaction](new Transaction("Reward", rewardAddress, this.miningReward)) }
  • 60.
    def getBalanceOfAddress(address: String):Double = { var balance = 0.0 this.chain.flatMap(block => block.transactions).foreach(transaction => { if(transaction.fromAddress == address) balance -= transaction.amount if(transaction.toAddress == address) balance += transaction.amount }) balance }
  • 63.
    • ✓ • Proof ofWork ✓ ✓nonse Proof of Work ✓mining
  • 64.
  • 65.
    Satoshi Nakamoto (2009)Bitcoin: A Peer-to-Peer Electronic Cash System 2017 2018 Building a blockchain with Javascript