diff --git a/src/main/resources/address b/src/main/resources/address new file mode 100644 index 0000000..a931102 --- /dev/null +++ b/src/main/resources/address @@ -0,0 +1 @@ +1DU8Hi1sbHTpEP9vViBEkEw6noeUrgKkJH \ No newline at end of file diff --git a/src/main/scala/com/github/fluency03/blockchain/crypto/Secp256k1.scala b/src/main/scala/com/github/fluency03/blockchain/crypto/Secp256k1.scala index 140169f..72f6bb6 100644 --- a/src/main/scala/com/github/fluency03/blockchain/crypto/Secp256k1.scala +++ b/src/main/scala/com/github/fluency03/blockchain/crypto/Secp256k1.scala @@ -90,5 +90,10 @@ object Secp256k1 { def publicKeyToAddress(publicKey: PublicKey, networkBytes: String = "00"): String = Base58.checkEncode(networkBytes.hex2Bytes ++ publicKeyToBytes(publicKey).toHash160Digest) + def addressToHash160(address: String, networkBytes: String = "00"): (String, String) = { + val decoded: Bytes = Base58.decode(address) + val (preBytes, fourBytes) = decoded.splitAt(decoded.length - 4) + preBytes.toHex.splitAt(2) + } } diff --git a/src/main/scala/com/github/fluency03/blockchain/package.scala b/src/main/scala/com/github/fluency03/blockchain/package.scala index e42fd1a..55eb5ed 100644 --- a/src/main/scala/com/github/fluency03/blockchain/package.scala +++ b/src/main/scala/com/github/fluency03/blockchain/package.scala @@ -6,7 +6,7 @@ import java.time.Instant import com.github.fluency03.blockchain.crypto.Secp256k1.{privateKeyToHex, publicKeyToHex} import com.github.fluency03.blockchain.core.{Peer, PeerSimple, TxIn, TxOut} -import com.github.fluency03.blockchain.crypto.{RIPEMD160, SHA256} +import com.github.fluency03.blockchain.crypto.{RIPEMD160, SHA256, Secp256k1} import org.bouncycastle.util.encoders.{Base64, Hex} import org.json4s.native.Serialization import org.json4s.{Formats, NoTypeHints} @@ -22,13 +22,18 @@ package object blockchain { implicit val defaultCharset: Charset = Charset.forName("UTF-8") + val GENESIS_MINER_PUBLIC_KEY_RESOURCE: String = "public-key" + val GENESIS_MINER_PRIVATE_KEY_RESOURCE: String = "private-key" + val GENESIS_MINER_ADDRESS_RESOURCE: String = "address" + + def getResource(re: String): String = Source.fromResource(re).getLines.mkString + val ZERO64: String = "0000000000000000000000000000000000000000000000000000000000000000" - lazy val genesisTimestamp: Long = Instant.parse(genesisTime).getEpochSecond + val genesisTimestamp: Long = Instant.parse(genesisTime).getEpochSecond val genesisTime: String = "2018-04-11T18:52:01Z" - - val genesisMiner: String = Source.fromResource("public-key").getLines.mkString + val genesisMiner: String = getResource(GENESIS_MINER_PUBLIC_KEY_RESOURCE) val SLOGAN: String = "Welcome to Blockchain in Scala!" @@ -56,6 +61,7 @@ package object blockchain { implicit class PublicKeyImplicit(val publicKey: PublicKey) { def toHex: String = publicKeyToHex(publicKey) + def address: String = Secp256k1.publicKeyToAddress(publicKey) } implicit class PrivateKeyImplicit(val privateKey: PrivateKey) { diff --git a/src/test/resources/address b/src/test/resources/address new file mode 100644 index 0000000..a931102 --- /dev/null +++ b/src/test/resources/address @@ -0,0 +1 @@ +1DU8Hi1sbHTpEP9vViBEkEw6noeUrgKkJH \ No newline at end of file diff --git a/src/test/scala/com/github/fluency03/blockchain/crypto/Secp256k1Test.scala b/src/test/scala/com/github/fluency03/blockchain/crypto/Secp256k1Test.scala index 6c7657b..d699afc 100644 --- a/src/test/scala/com/github/fluency03/blockchain/crypto/Secp256k1Test.scala +++ b/src/test/scala/com/github/fluency03/blockchain/crypto/Secp256k1Test.scala @@ -28,6 +28,13 @@ class Secp256k1Test extends FlatSpec with Matchers { "4A2541129368D7D9BB05CD8AFBDF7705A6540D98028236965553F91BF1C5B4F70073F55B55D")) shouldEqual "1DU8Hi1sbHTpEP9vViBEkEw6noeUrgKkJH" + recoverPublicKey("04B4D653FCBB4B96000C99343F23B08A44FA306031E0587F9E657AB" + + "4A2541129368D7D9BB05CD8AFBDF7705A6540D98028236965553F91BF1C5B4F70073F55B55D").address shouldEqual + "1DU8Hi1sbHTpEP9vViBEkEw6noeUrgKkJH" + + Secp256k1.addressToHash160("1DU8Hi1sbHTpEP9vViBEkEw6noeUrgKkJH") shouldEqual + ("00", "88C2D2FA846282C870A76CADECBE45C4ACD72BB6".toLowerCase) + Secp256k1.privateKeyToBytes(pair.getPrivate).toBigInt shouldEqual Secp256k1.privateKeyToHex(pair.getPrivate).hex2BigInt }