Merge pull request #110 from Christewart/address_refactor

Address refactor
This commit is contained in:
Chris Stewart 2018-02-08 07:03:21 -06:00 committed by GitHub
commit 368826ccbf
6 changed files with 91 additions and 68 deletions

View file

@ -1,16 +1,22 @@
package org.bitcoins.core.config package org.bitcoins.core.config
import org.bitcoins.core.protocol.blockchain._
/** /**
* Created by chris on 7/27/15. * Created by chris on 7/27/15.
*/ */
sealed abstract class NetworkParameters { sealed abstract class NetworkParameters {
def p2pkhNetworkByte : Byte /** The parameters of the blockchain we are connecting to */
def p2shNetworkByte : Byte def chainParams: ChainParams
def privateKey : Byte
def p2pkhNetworkByte: Byte = chainParams.base58Prefix(Base58Type.PubKeyAddress).head
def p2shNetworkByte: Byte = chainParams.base58Prefix(Base58Type.ScriptAddress).head
def privateKey: Byte = chainParams.base58Prefix(Base58Type.SecretKey).head
def port : Int def port : Int
def rpcPort: Int def rpcPort: Int
def name: String def name: String = chainParams.networkId
/** The seeds used to bootstrap the network */ /** The seeds used to bootstrap the network */
def dnsSeeds : Seq[String] def dnsSeeds : Seq[String]
@ -23,13 +29,17 @@ sealed abstract class NetworkParameters {
def magicBytes : Seq[Byte] def magicBytes : Seq[Byte]
/** In bitcoin, the network recaculates the difficulty for the network every 2016 blocks */ /** In bitcoin, the network recaculates the difficulty for the network every 2016 blocks */
def difficultyChangeThreshold = 2016 def difficultyChangeThreshold: Int
} }
trait MainNet extends NetworkParameters { sealed abstract class BitcoinNetwork extends NetworkParameters {
override def p2pkhNetworkByte = 0x00 override def difficultyChangeThreshold: Int = 2016
override def p2shNetworkByte = 0x05
override def privateKey = 0x80.toByte override def chainParams: BitcoinChainParams
}
sealed abstract class MainNet extends BitcoinNetwork {
override def chainParams = MainNetChainParams
override def port = 8333 override def port = 8333
override def rpcPort = 8332 override def rpcPort = 8332
//mainnet doesn't need to be specified like testnet or regtest //mainnet doesn't need to be specified like testnet or regtest
@ -38,34 +48,52 @@ trait MainNet extends NetworkParameters {
"seed.bitcoinstats.com","bitseed.xf2.org","seed.bitcoin.jonasschnelli.ch") "seed.bitcoinstats.com","bitseed.xf2.org","seed.bitcoin.jonasschnelli.ch")
override def magicBytes = Seq(0xf9.toByte, 0xbe.toByte, 0xb4.toByte, 0xd9.toByte) override def magicBytes = Seq(0xf9.toByte, 0xbe.toByte, 0xb4.toByte, 0xd9.toByte)
override def difficultyChangeThreshold: Int = 2016
} }
object MainNet extends MainNet object MainNet extends MainNet
trait TestNet3 extends NetworkParameters { sealed abstract class TestNet3 extends NetworkParameters {
override def p2pkhNetworkByte = 0x6F override def chainParams = TestNetChainParams
override def p2shNetworkByte = 0xC4.toByte
override def privateKey = 0xEF.toByte
override def port = 18333 override def port = 18333
override def rpcPort = 18332 override def rpcPort = 18332
override def name = "testnet"
override def dnsSeeds = Seq("testnet-seed.bitcoin.petertodd.org", override def dnsSeeds = Seq("testnet-seed.bitcoin.petertodd.org",
"testnet-seed.bluematt.me","testnet-seed.bitcoin.schildbach.de") "testnet-seed.bluematt.me","testnet-seed.bitcoin.schildbach.de")
override def magicBytes = Seq(0x0b.toByte, 0x11.toByte, 0x09.toByte, 0x07.toByte) override def magicBytes = Seq(0x0b.toByte, 0x11.toByte, 0x09.toByte, 0x07.toByte)
override def difficultyChangeThreshold: Int = 2016
} }
object TestNet3 extends TestNet3 object TestNet3 extends TestNet3
trait RegTest extends NetworkParameters { sealed abstract class RegTest extends NetworkParameters {
override def p2pkhNetworkByte = TestNet3.p2pkhNetworkByte override def chainParams: ChainParams = RegTestNetChainParams
override def p2shNetworkByte = TestNet3.p2shNetworkByte
override def privateKey = TestNet3.privateKey
override def port = 18444 override def port = 18444
override def rpcPort = TestNet3.rpcPort override def rpcPort = TestNet3.rpcPort
override def name = "regtest"
override def dnsSeeds = Nil override def dnsSeeds = Nil
override def magicBytes = Seq(0xfa.toByte, 0xbf.toByte, 0xb5.toByte, 0xda.toByte) override def magicBytes = Seq(0xfa.toByte, 0xbf.toByte, 0xb5.toByte, 0xda.toByte)
override def difficultyChangeThreshold: Int = 2016
} }
object RegTest extends RegTest object RegTest extends RegTest
object Networks {
val knownNetworks: Seq[NetworkParameters] = Seq(MainNet, TestNet3, RegTest)
val secretKeyBytes = knownNetworks.map(_.privateKey)
val p2pkhNetworkBytes = knownNetworks.map(_.p2pkhNetworkByte)
val p2shNetworkBytes = knownNetworks.map(_.p2shNetworkByte)
def byteToNetwork: Map[Byte, NetworkParameters] = Map(
MainNet.p2shNetworkByte -> MainNet,
MainNet.p2pkhNetworkByte -> MainNet,
MainNet.privateKey -> MainNet,
TestNet3.p2pkhNetworkByte -> TestNet3,
TestNet3.p2shNetworkByte -> TestNet3,
TestNet3.privateKey -> TestNet3
//ommitting regtest as it has the same network bytes as testnet3
)
}

View file

@ -4,9 +4,8 @@ import java.math.BigInteger
import java.security.SecureRandom import java.security.SecureRandom
import org.bitcoin.NativeSecp256k1 import org.bitcoin.NativeSecp256k1
import org.bitcoins.core.config.{MainNet, NetworkParameters, TestNet3} import org.bitcoins.core.config.{NetworkParameters, Networks}
import org.bitcoins.core.protocol.NetworkElement import org.bitcoins.core.protocol.NetworkElement
import org.bitcoins.core.protocol.blockchain.{MainNetChainParams, SecretKey, TestNetChainParams}
import org.bitcoins.core.util.{BitcoinSUtil, _} import org.bitcoins.core.util.{BitcoinSUtil, _}
import org.spongycastle.crypto.AsymmetricCipherKeyPair import org.spongycastle.crypto.AsymmetricCipherKeyPair
import org.spongycastle.crypto.digests.SHA256Digest import org.spongycastle.crypto.digests.SHA256Digest
@ -155,8 +154,7 @@ object ECPrivateKey extends Factory[ECPrivateKey] {
* @return * @return
*/ */
def isCompressed(bytes : Seq[Byte]): Boolean = { def isCompressed(bytes : Seq[Byte]): Boolean = {
val validCompressedBytes: Seq[Byte] = val validCompressedBytes: Seq[Byte] = Networks.secretKeyBytes
MainNetChainParams.base58Prefix(SecretKey) ++ TestNetChainParams.base58Prefixes(SecretKey)
val validCompressedBytesInHex: Seq[String] = validCompressedBytes.map(byte => BitcoinSUtil.encodeHex(byte)) val validCompressedBytesInHex: Seq[String] = validCompressedBytes.map(byte => BitcoinSUtil.encodeHex(byte))
val firstByteHex = BitcoinSUtil.encodeHex(bytes.head) val firstByteHex = BitcoinSUtil.encodeHex(bytes.head)
if (validCompressedBytesInHex.contains(firstByteHex)) bytes(bytes.length - 5) == 0x01.toByte if (validCompressedBytesInHex.contains(firstByteHex)) bytes(bytes.length - 5) == 0x01.toByte
@ -199,11 +197,7 @@ object ECPrivateKey extends Factory[ECPrivateKey] {
val decoded = Base58.decodeCheck(wif) val decoded = Base58.decodeCheck(wif)
decoded.map { bytes => decoded.map { bytes =>
val b = bytes.head val b = bytes.head
if (b == TestNetChainParams.base58Prefixes(SecretKey).head) { Networks.byteToNetwork(b)
TestNet3
} else if (b == MainNetChainParams.base58Prefixes(SecretKey).head) {
MainNet
} else throw new IllegalArgumentException("Cannot match wif private key with a network, prefix was: " + BitcoinSUtil.encodeHex(b))
} }
} }
} }

View file

@ -321,8 +321,7 @@ object P2PKHAddress {
decodeCheckP2PKH match { decodeCheckP2PKH match {
case Success(bytes) => case Success(bytes) =>
val firstByte = bytes.head val firstByte = bytes.head
(firstByte == MainNet.p2pkhNetworkByte || firstByte == TestNet3.p2pkhNetworkByte || Networks.p2pkhNetworkBytes.contains(firstByte) && bytes.size == 21
firstByte == RegTest.p2pkhNetworkByte) && bytes.size == 21
case Failure(exception) => false case Failure(exception) => false
} }
} }
@ -357,9 +356,7 @@ object P2SHAddress {
decodeCheckP2SH match { decodeCheckP2SH match {
case Success(bytes) => case Success(bytes) =>
val firstByte = bytes.head val firstByte = bytes.head
((firstByte == MainNet.p2shNetworkByte || firstByte == TestNet3.p2shNetworkByte || Networks.p2shNetworkBytes.contains(firstByte) && bytes.size == 21
RegTest.p2shNetworkByte == firstByte)
&& bytes.size == 21)
case Failure(_) => false case Failure(_) => false
} }
} }

View file

@ -1,15 +1,16 @@
package org.bitcoins.core.protocol.blockchain package org.bitcoins.core.protocol.blockchain
import java.nio.charset.StandardCharsets
import org.bitcoins.core.consensus.Merkle import org.bitcoins.core.consensus.Merkle
import org.bitcoins.core.crypto.DoubleSha256Digest import org.bitcoins.core.crypto.DoubleSha256Digest
import org.bitcoins.core.currency.{CurrencyUnit, Satoshis} import org.bitcoins.core.currency.{CurrencyUnit, Satoshis}
import org.bitcoins.core.number.{Int64, UInt32, UInt64} import org.bitcoins.core.number.{Int64, UInt32}
import org.bitcoins.core.protocol.CompactSizeUInt
import org.bitcoins.core.protocol.script.{ScriptPubKey, ScriptSignature} import org.bitcoins.core.protocol.script.{ScriptPubKey, ScriptSignature}
import org.bitcoins.core.protocol.transaction.{Transaction, TransactionConstants, TransactionInput, TransactionOutput} import org.bitcoins.core.protocol.transaction.{Transaction, TransactionConstants, TransactionInput, TransactionOutput}
import org.bitcoins.core.script.constant.{BytesToPushOntoStack, ScriptConstant, ScriptNumber} import org.bitcoins.core.script.constant.{BytesToPushOntoStack, ScriptConstant, ScriptNumber}
import org.bitcoins.core.script.crypto.OP_CHECKSIG import org.bitcoins.core.script.crypto.OP_CHECKSIG
import org.bitcoins.core.util.BitcoinSUtil import org.bitcoins.core.util.{BitcoinSUtil, BitcoinScriptUtil}
/** /**
* Created by chris on 5/22/16. * Created by chris on 5/22/16.
@ -21,7 +22,7 @@ import org.bitcoins.core.util.BitcoinSUtil
* Mimics this C++ interface * Mimics this C++ interface
* https://github.com/bitcoin/bitcoin/blob/master/src/chainparams.h#L42 * https://github.com/bitcoin/bitcoin/blob/master/src/chainparams.h#L42
*/ */
sealed trait ChainParams { sealed abstract class ChainParams {
/** Return the BIP70 network string ([[MainNetChainParams]], [[TestNetChainParams]] or [[RegTestNetChainParams]].) */ /** Return the BIP70 network string ([[MainNetChainParams]], [[TestNetChainParams]] or [[RegTestNetChainParams]].) */
def networkId : String def networkId : String
@ -31,7 +32,7 @@ sealed trait ChainParams {
/** Filter transactions that do not match well-defined patterns /** Filter transactions that do not match well-defined patterns
* inside of [[org.bitcoins.core.policy.Policy]]. */ * inside of [[org.bitcoins.core.policy.Policy]]. */
def requireStandardTransaction : Boolean def requireStandardTransaction : Boolean = true
/** Takes in a [[Base58Type]] and returns its base58 prefix. */ /** Takes in a [[Base58Type]] and returns its base58 prefix. */
def base58Prefix(base58 : Base58Type) : Seq[Byte] = base58Prefixes(base58) def base58Prefix(base58 : Base58Type) : Seq[Byte] = base58Prefixes(base58)
@ -70,72 +71,72 @@ sealed trait ChainParams {
*/ */
def createGenesisBlock(timestamp : String, scriptPubKey : ScriptPubKey, time : UInt32, nonce : UInt32, nBits : UInt32, def createGenesisBlock(timestamp : String, scriptPubKey : ScriptPubKey, time : UInt32, nonce : UInt32, nBits : UInt32,
version : UInt32, amount : CurrencyUnit) : Block = { version : UInt32, amount : CurrencyUnit) : Block = {
val timestampHex = timestamp.toCharArray.map(_.toByte) val timestampBytes = timestamp.getBytes(StandardCharsets.UTF_8)
//see https://bitcoin.stackexchange.com/questions/13122/scriptsig-coinbase-structure-of-the-genesis-block //see https://bitcoin.stackexchange.com/questions/13122/scriptsig-coinbase-structure-of-the-genesis-block
//for a full breakdown of the genesis block & its script signature //for a full breakdown of the genesis block & its script signature
val const = ScriptConstant(timestampBytes)
val scriptSignature = ScriptSignature.fromAsm(Seq(BytesToPushOntoStack(4), ScriptNumber(486604799), val scriptSignature = ScriptSignature.fromAsm(Seq(BytesToPushOntoStack(4), ScriptNumber(486604799),
BytesToPushOntoStack(1), ScriptNumber(4), BytesToPushOntoStack(69), ScriptConstant(timestampHex))) BytesToPushOntoStack(1), ScriptNumber(4)) ++ BitcoinScriptUtil.calculatePushOp(const) ++ Seq(const))
val input = TransactionInput(scriptSignature) val input = TransactionInput(scriptSignature)
val output = TransactionOutput(amount,scriptPubKey) val output = TransactionOutput(amount,scriptPubKey)
val tx = Transaction(TransactionConstants.version,Seq(input), Seq(output), TransactionConstants.lockTime) val tx = Transaction(TransactionConstants.version,Seq(input), Seq(output), TransactionConstants.lockTime)
val prevBlockHash = DoubleSha256Digest("0000000000000000000000000000000000000000000000000000000000000000") val prevBlockHash = DoubleSha256Digest("0000000000000000000000000000000000000000000000000000000000000000")
val merkleRootHash = Merkle.computeMerkleRoot(Seq(tx)) val merkleRootHash = Merkle.computeMerkleRoot(Seq(tx))
val genesisBlockHeader = BlockHeader(version,prevBlockHash,merkleRootHash,time,nBits,nonce) val genesisBlockHeader = BlockHeader(version,prevBlockHash,merkleRootHash,time,nBits,nonce)
val genesisBlock = Block(genesisBlockHeader,CompactSizeUInt(UInt64.one,1),Seq(tx)) val genesisBlock = Block(genesisBlockHeader,Seq(tx))
genesisBlock genesisBlock
} }
} }
sealed abstract class BitcoinChainParams extends ChainParams
/** The Main Network parameters. */ /** The Main Network parameters. */
object MainNetChainParams extends ChainParams { object MainNetChainParams extends BitcoinChainParams {
override def networkId = "main" override def networkId = "main"
override def genesisBlock : Block = createGenesisBlock(UInt32(1231006505), UInt32(2083236893), UInt32(0x1d00ffff), UInt32.one, Satoshis(Int64(5000000000L))) override def genesisBlock : Block = createGenesisBlock(UInt32(1231006505), UInt32(2083236893), UInt32(0x1d00ffff), UInt32.one, Satoshis(Int64(5000000000L)))
override def requireStandardTransaction : Boolean = true
override def base58Prefixes : Map[Base58Type,Seq[Byte]] = Map( override def base58Prefixes : Map[Base58Type,Seq[Byte]] = Map(
PubKeyAddress -> BitcoinSUtil.decodeHex("00"), Base58Type.PubKeyAddress -> BitcoinSUtil.decodeHex("00"),
ScriptAddress -> BitcoinSUtil.decodeHex("05"), Base58Type.ScriptAddress -> BitcoinSUtil.decodeHex("05"),
SecretKey -> BitcoinSUtil.decodeHex("80"), Base58Type.SecretKey -> BitcoinSUtil.decodeHex("80"),
ExtPublicKey -> Seq(BitcoinSUtil.hexToByte("04"), BitcoinSUtil.hexToByte("88"), Base58Type.ExtPublicKey -> Seq(BitcoinSUtil.hexToByte("04"), BitcoinSUtil.hexToByte("88"),
BitcoinSUtil.hexToByte("b2"), BitcoinSUtil.hexToByte("1e")), BitcoinSUtil.hexToByte("b2"), BitcoinSUtil.hexToByte("1e")),
ExtSecretKey -> Seq(BitcoinSUtil.hexToByte("04"), BitcoinSUtil.hexToByte("88"), Base58Type.ExtSecretKey -> Seq(BitcoinSUtil.hexToByte("04"), BitcoinSUtil.hexToByte("88"),
BitcoinSUtil.hexToByte("ad"), BitcoinSUtil.hexToByte("e4"))) BitcoinSUtil.hexToByte("ad"), BitcoinSUtil.hexToByte("e4")))
} }
object TestNetChainParams extends ChainParams { object TestNetChainParams extends BitcoinChainParams {
override def networkId = "test" override def networkId = "test"
override def genesisBlock : Block = createGenesisBlock(UInt32(1296688602), UInt32(414098458), UInt32(0x1d00ffff), UInt32.one, Satoshis(Int64(5000000000L))) override def genesisBlock : Block = createGenesisBlock(UInt32(1296688602), UInt32(414098458), UInt32(0x1d00ffff), UInt32.one, Satoshis(Int64(5000000000L)))
override def requireStandardTransaction : Boolean = true
override def base58Prefixes : Map[Base58Type,Seq[Byte]] = Map( override def base58Prefixes : Map[Base58Type,Seq[Byte]] = Map(
PubKeyAddress -> BitcoinSUtil.decodeHex("6f"), Base58Type.PubKeyAddress -> BitcoinSUtil.decodeHex("6f"),
ScriptAddress -> BitcoinSUtil.decodeHex("c4"), Base58Type.ScriptAddress -> BitcoinSUtil.decodeHex("c4"),
SecretKey -> BitcoinSUtil.decodeHex("ef"), Base58Type.SecretKey -> BitcoinSUtil.decodeHex("ef"),
ExtPublicKey -> Seq(BitcoinSUtil.hexToByte("04"), BitcoinSUtil.hexToByte("35"), Base58Type.ExtPublicKey -> Seq(BitcoinSUtil.hexToByte("04"), BitcoinSUtil.hexToByte("35"),
BitcoinSUtil.hexToByte("87"), BitcoinSUtil.hexToByte("cf")), BitcoinSUtil.hexToByte("87"), BitcoinSUtil.hexToByte("cf")),
ExtSecretKey -> Seq(BitcoinSUtil.hexToByte("04"), BitcoinSUtil.hexToByte("35"), Base58Type.ExtSecretKey -> Seq(BitcoinSUtil.hexToByte("04"), BitcoinSUtil.hexToByte("35"),
BitcoinSUtil.hexToByte("83"), BitcoinSUtil.hexToByte("94"))) BitcoinSUtil.hexToByte("83"), BitcoinSUtil.hexToByte("94")))
} }
object RegTestNetChainParams extends ChainParams { object RegTestNetChainParams extends BitcoinChainParams {
override def networkId = "regtest" override def networkId = "regtest"
override def genesisBlock : Block = createGenesisBlock(UInt32(1296688602), UInt32(2), UInt32(0x207fffff), UInt32.one, Satoshis(Int64(5000000000L))) override def genesisBlock : Block = createGenesisBlock(UInt32(1296688602), UInt32(2), UInt32(0x207fffff), UInt32.one, Satoshis(Int64(5000000000L)))
override def requireStandardTransaction : Boolean = TestNetChainParams.requireStandardTransaction
override def base58Prefixes : Map[Base58Type, Seq[Byte]] = TestNetChainParams.base58Prefixes override def base58Prefixes : Map[Base58Type, Seq[Byte]] = TestNetChainParams.base58Prefixes
} }
sealed trait Base58Type
case object PubKeyAddress extends Base58Type sealed abstract class Base58Type
case object ScriptAddress extends Base58Type object Base58Type {
case object SecretKey extends Base58Type case object PubKeyAddress extends Base58Type
case object ExtPublicKey extends Base58Type case object ScriptAddress extends Base58Type
case object ExtSecretKey extends Base58Type case object SecretKey extends Base58Type
case object ExtPublicKey extends Base58Type
case object ExtSecretKey extends Base58Type
}

View file

@ -10,11 +10,11 @@ import scala.util.{Failure, Success, Try}
* Created by chris on 5/16/16. * Created by chris on 5/16/16.
* source of values: https://en.bitcoin.it/wiki/Base58Check_encoding * source of values: https://en.bitcoin.it/wiki/Base58Check_encoding
*/ */
trait Base58 extends BitcoinSLogger { sealed abstract class Base58 {
import Base58Type._
val base58Characters = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz" val base58Characters = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
val base58Pairs = base58Characters.zipWithIndex.toMap val base58Pairs = base58Characters.zipWithIndex.toMap
private val logger = BitcoinSLogger.logger
/** Verifies a given [[Base58Type]] string against its checksum (last 4 decoded bytes). */ /** Verifies a given [[Base58Type]] string against its checksum (last 4 decoded bytes). */
def decodeCheck(input: String) : Try[Seq[Byte]] = { def decodeCheck(input: String) : Try[Seq[Byte]] = {
val decoded : Seq[Byte] = decode(input) val decoded : Seq[Byte] = decode(input)

View file

@ -95,6 +95,7 @@ class ChainParamsTest extends FlatSpec with MustMatchers {
} }
it must "have the correct base58 prefix for MainNet" in { it must "have the correct base58 prefix for MainNet" in {
import Base58Type._
//correct answers taken from https://en.bitcoin.it/wiki/List_of_address_prefixes //correct answers taken from https://en.bitcoin.it/wiki/List_of_address_prefixes
BitcoinSUtil.encodeHex(MainNetChainParams.base58Prefixes(PubKeyAddress)) must be ("00") BitcoinSUtil.encodeHex(MainNetChainParams.base58Prefixes(PubKeyAddress)) must be ("00")
BitcoinSUtil.encodeHex(MainNetChainParams.base58Prefixes(ScriptAddress)) must be ("05") BitcoinSUtil.encodeHex(MainNetChainParams.base58Prefixes(ScriptAddress)) must be ("05")
@ -104,6 +105,7 @@ class ChainParamsTest extends FlatSpec with MustMatchers {
} }
it must "have the correct base58 prefix for TestNet" in { it must "have the correct base58 prefix for TestNet" in {
import Base58Type._
BitcoinSUtil.encodeHex(TestNetChainParams.base58Prefixes(PubKeyAddress)) must be ("6f") BitcoinSUtil.encodeHex(TestNetChainParams.base58Prefixes(PubKeyAddress)) must be ("6f")
BitcoinSUtil.encodeHex(TestNetChainParams.base58Prefixes(ScriptAddress)) must be ("c4") BitcoinSUtil.encodeHex(TestNetChainParams.base58Prefixes(ScriptAddress)) must be ("c4")
BitcoinSUtil.encodeHex(TestNetChainParams.base58Prefixes(SecretKey)) must be ("ef") BitcoinSUtil.encodeHex(TestNetChainParams.base58Prefixes(SecretKey)) must be ("ef")
@ -112,6 +114,7 @@ class ChainParamsTest extends FlatSpec with MustMatchers {
} }
it must "have the correct base58 prefix for RegTest" in { it must "have the correct base58 prefix for RegTest" in {
import Base58Type._
BitcoinSUtil.encodeHex(RegTestNetChainParams.base58Prefixes(PubKeyAddress)) must be ("6f") BitcoinSUtil.encodeHex(RegTestNetChainParams.base58Prefixes(PubKeyAddress)) must be ("6f")
BitcoinSUtil.encodeHex(RegTestNetChainParams.base58Prefixes(ScriptAddress)) must be ("c4") BitcoinSUtil.encodeHex(RegTestNetChainParams.base58Prefixes(ScriptAddress)) must be ("c4")
BitcoinSUtil.encodeHex(RegTestNetChainParams.base58Prefixes(SecretKey)) must be ("ef") BitcoinSUtil.encodeHex(RegTestNetChainParams.base58Prefixes(SecretKey)) must be ("ef")