Skip to content

Commit

Permalink
add tome TODOs & hash functions
Browse files Browse the repository at this point in the history
  • Loading branch information
fluency03 committed May 12, 2018
1 parent 46be579 commit 019d5f3
Show file tree
Hide file tree
Showing 9 changed files with 63 additions and 10 deletions.
26 changes: 26 additions & 0 deletions src/main/scala/com/github/fluency03/blockchain/Serde.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.github.fluency03.blockchain

import java.io.{ByteArrayInputStream, ByteArrayOutputStream, ObjectInputStream, ObjectOutputStream}

/**
* Ser(ialization) and De(serialization)
*/
object Serde {

def serialize[T](value: T): Bytes = {
val stream: ByteArrayOutputStream = new ByteArrayOutputStream()
val oos = new ObjectOutputStream(stream)
oos.writeObject(value)
oos.close()
stream.close()
stream.toByteArray
}

def deserialize[T](bytes: Array[Byte]): T = {
val ois = new ObjectInputStream(new ByteArrayInputStream(bytes))
val value = ois.readObject
ois.close()
value.asInstanceOf[T]
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ object Block {
0, ZERO64, "Welcome to Blockchain in Scala!", genesisTimestamp, difficulty,
Seq(createCoinbaseTx(0, genesisMiner, genesisTimestamp)))

// TODO (Chang): implement parallel version
def mineNextBlock(
nextIndex: Int,
prevHash: String,
Expand Down
17 changes: 17 additions & 0 deletions src/main/scala/com/github/fluency03/blockchain/core/Merkle.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,14 @@ import com.github.fluency03.blockchain.crypto.SHA256

import scala.annotation.tailrec

// TODO (Chang): implement a full nodes merkle tree


object Merkle {
def computeRoot(trans: Seq[Transaction]): String = computeRootOfHashes(trans.map(_.id))

// TODO (Chang): double SHA256 hash instead of single.
// TODO (Chang): hash and concatenate hash string or hash bytes?
@tailrec
def computeRootOfHashes(hashes: Seq[String]): String = hashes.length match {
case 0 => ZERO64
Expand All @@ -16,4 +21,16 @@ object Merkle {
case _ => computeRootOfHashes(hashes.grouped(2).map { a => SHA256.hashAll(a(0), a(1)) } .toList)
}

@tailrec
def hashViaMerklePath(init: String, path: Seq[String], index: Int): String =
if (path.isEmpty) init
else {
val newHash = if (index % 2 == 0) SHA256.hashAll(init, path.head) else SHA256.hashAll(path.head, init)
hashViaMerklePath(newHash, path.tail, index/2)
}

def simplifiedPaymentVerification(init: String, root: String, path: Seq[String], index: Int): Boolean =
hashViaMerklePath(init, path, index) == root


}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import org.json4s.{Extraction, JValue}
import scala.collection.mutable

case class Outpoint(id: String, index: Int)
// TODO (Chang): add public key into TxIn
case class TxIn(previousOut: Outpoint, signature: String)
case class TxOut(address: String, amount: Long)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,8 @@ object RIPEMD160 {
out
}

def doubleHash(bytes: Bytes): String = hash(SHA256.hashToDigest(bytes))

def doubleHashToDigest(bytes: Bytes): Bytes = hashToDigest(SHA256.hashToDigest(bytes))
def hash160(bytes: Bytes): String = hash(SHA256.hashToDigest(bytes))

def hash160ToDigest(bytes: Bytes): Bytes = hashToDigest(SHA256.hashToDigest(bytes))

}
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,8 @@ object SHA256 {
*/
def hashAll(strings: String*): String = hash(strings mkString "")

def hash256(bytes: Bytes): String = hash(hashToDigest(bytes))

def hash256ToDigest(bytes: Bytes): Bytes = hashToDigest(hashToDigest(bytes))

}
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ object Secp256k1 {
def publicKeyToAddress(publicKey: PublicKey, networkBytes: String = "00"): String =
Base58.checkEncode(networkBytes.hex2Bytes ++ publicKeyToBytes(publicKey).toHash160Digest)

def hash160ToAddress(hash160: String, networkBytes: String = "00"): String =
Base58.checkEncode(networkBytes.hex2Bytes ++ hash160.hex2Bytes)

def addressToHash160(address: String, networkBytes: String = "00"): (String, String) = {
val decoded: Bytes = Base58.decode(address)
val (preBytes, fourBytes) = decoded.splitAt(decoded.length - 4)
Expand Down
13 changes: 8 additions & 5 deletions src/main/scala/com/github/fluency03/blockchain/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import java.nio.charset.Charset
import java.security.{PrivateKey, PublicKey}
import java.time.Instant

import com.github.fluency03.blockchain.crypto.Secp256k1.{privateKeyToHex, publicKeyToHex}
import com.github.fluency03.blockchain.crypto.Secp256k1
import com.github.fluency03.blockchain.core.{Peer, PeerSimple, TxIn, TxOut}
import com.github.fluency03.blockchain.crypto.{RIPEMD160, SHA256, Secp256k1}
import org.bouncycastle.util.encoders.{Base64, Hex}
Expand Down Expand Up @@ -59,17 +59,20 @@ package object blockchain {
def toSha256Digest: Bytes = SHA256.hashToDigest(bytes)
def toRipemd160: String = RIPEMD160.hash(bytes)
def toRipemd160ODigest: Bytes = RIPEMD160.hashToDigest(bytes)
def toHash160: String = RIPEMD160.doubleHash(bytes)
def toHash160Digest: Bytes = RIPEMD160.doubleHashToDigest(bytes)
def toHash160: String = RIPEMD160.hash160(bytes)
def toHash160Digest: Bytes = RIPEMD160.hash160ToDigest(bytes)
}

implicit class PublicKeyImplicit(val publicKey: PublicKey) {
def toHex: String = publicKeyToHex(publicKey)
def toHex: String = Secp256k1.publicKeyToHex(publicKey)
def toBytes: Bytes = Secp256k1.publicKeyToBytes(publicKey)
def toHash160: String = Secp256k1.publicKeyToBytes(publicKey).toHash160
def address: String = Secp256k1.publicKeyToAddress(publicKey)
}

implicit class PrivateKeyImplicit(val privateKey: PrivateKey) {
def toHex: String = privateKeyToHex(privateKey)
def toHex: String = Secp256k1.privateKeyToHex(privateKey)
def toBytes: Bytes = Secp256k1.privateKeyToBytes(privateKey)
}

implicit class PeerImplicit(val peer: Peer) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ class RIPEMD160Test extends FlatSpec with Matchers {
RIPEMD160.hash("173BDED8F2A2069C193E63EA30DC8FD20E815EC3642B9C24AD7002C03D1BFB9B".hex2Bytes) shouldEqual
"88C2D2FA846282C870A76CADECBE45C4ACD72BB6".toLowerCase

RIPEMD160.doubleHashToDigest(("04b4d653fcbb4b96000c99343f23b08a44fa306031e0587f9e657ab4a25411" +
RIPEMD160.hash160ToDigest(("04b4d653fcbb4b96000c99343f23b08a44fa306031e0587f9e657ab4a25411" +
"29368d7d9bb05cd8afbdf7705a6540d98028236965553f91bf1c5b4f70073f55b55d").hex2Bytes) shouldEqual
"88C2D2FA846282C870A76CADECBE45C4ACD72BB6".hex2Bytes

RIPEMD160.doubleHash(("04b4d653fcbb4b96000c99343f23b08a44fa306031e0587f9e657ab4a25411" +
RIPEMD160.hash160(("04b4d653fcbb4b96000c99343f23b08a44fa306031e0587f9e657ab4a25411" +
"29368d7d9bb05cd8afbdf7705a6540d98028236965553f91bf1c5b4f70073f55b55d").hex2Bytes) shouldEqual
"88C2D2FA846282C870A76CADECBE45C4ACD72BB6".toLowerCase

Expand Down

0 comments on commit 019d5f3

Please sign in to comment.