diff --git a/build.sbt b/build.sbt index 7c2bdc3d2a..2de010cce3 100644 --- a/build.sbt +++ b/build.sbt @@ -1 +1 @@ -import AssemblyKeys._ \ No newline at end of file +import AssemblyKeys._ test in assembly := {} \ No newline at end of file diff --git a/src/main/scala/org/bitcoins/core/config/NetworkParameters.scala b/src/main/scala/org/bitcoins/core/config/NetworkParameters.scala index 06988f2210..74850c3daa 100644 --- a/src/main/scala/org/bitcoins/core/config/NetworkParameters.scala +++ b/src/main/scala/org/bitcoins/core/config/NetworkParameters.scala @@ -1,41 +1,41 @@ package org.bitcoins.core.config -import org.bitcoinj.params.{MainNetParams, RegTestParams, TestNet3Params} /** * Created by chris on 7/27/15. - */ + */ trait NetworkParameters { - def network : org.bitcoinj.core.NetworkParameters def p2pkhNetworkByte : Byte def p2shNetworkByte : Byte + def privateKey : Byte def port : Int } trait MainNet extends NetworkParameters { - override def network = MainNetParams.get override def p2pkhNetworkByte = 0x00 override def p2shNetworkByte = 0x05 + override def privateKey = 0x80.toByte override def port = 8333 } object MainNet extends MainNet trait TestNet3 extends NetworkParameters { - override def network = TestNet3Params.get override def p2pkhNetworkByte = 0x6F - override def p2shNetworkByte = 196.toByte + override def p2shNetworkByte = 0xC4.toByte + override def privateKey = 0xEF.toByte override def port = 18333 } object TestNet3 extends TestNet3 trait RegTest extends NetworkParameters { - override def network = RegTestParams.get override def p2pkhNetworkByte = TestNet3.p2pkhNetworkByte override def p2shNetworkByte = TestNet3.p2shNetworkByte + override def privateKey = TestNet3.privateKey override def port = 18444 } object RegTest extends RegTest + diff --git a/src/main/scala/org/bitcoins/core/crypto/DERSignatureUtil.scala b/src/main/scala/org/bitcoins/core/crypto/DERSignatureUtil.scala index ab8c431a40..f6cec0a2cb 100644 --- a/src/main/scala/org/bitcoins/core/crypto/DERSignatureUtil.scala +++ b/src/main/scala/org/bitcoins/core/crypto/DERSignatureUtil.scala @@ -13,7 +13,6 @@ trait DERSignatureUtil extends BitcoinSLogger { /** * Checks if this signature is encoded to DER correctly * https://crypto.stackexchange.com/questions/1795/how-can-i-convert-a-der-ecdsa-signature-to-asn-1 - * * @return boolean representing if the signature is a valid */ def isDEREncoded(signature : ECDigitalSignature) : Boolean = isDEREncoded(signature.bytes) @@ -21,7 +20,6 @@ trait DERSignatureUtil extends BitcoinSLogger { /** * Checks if the bytes are encoded to DER correctly * https://crypto.stackexchange.com/questions/1795/how-can-i-convert-a-der-ecdsa-signature-to-asn-1 - * * @return boolean representing if the signature is a valid */ def isDEREncoded(bytes : Seq[Byte]) : Boolean = { @@ -65,7 +63,6 @@ trait DERSignatureUtil extends BitcoinSLogger { /** * Decodes the given digital signature into it's r and s points - * * @param signature * @return */ @@ -74,7 +71,6 @@ trait DERSignatureUtil extends BitcoinSLogger { /** * Decodes the given sequence of bytes into it's r and s points * throws an exception if the given sequence of bytes is not a DER encoded signature - * * @param bytes * @return */ @@ -119,7 +115,6 @@ trait DERSignatureUtil extends BitcoinSLogger { /** * This functions implements the strict der encoding rules that were created in BIP66 * https://github.com/bitcoin/bips/blob/master/bip-0066.mediawiki - * * @param signature the signature to check if they are strictly der encoded * @return boolean indicating whether the signature was der encoded or not */ @@ -134,7 +129,6 @@ trait DERSignatureUtil extends BitcoinSLogger { /** * This functions implements the strict der encoding rules that were created in BIP66 * https://github.com/bitcoin/bips/blob/master/bip-0066.mediawiki - * * @param bytes the bytes to check if they are strictly der encoded * @return boolean indicating whether the bytes were der encoded or not */ diff --git a/src/main/scala/org/bitcoins/core/crypto/ECDigitalSignature.scala b/src/main/scala/org/bitcoins/core/crypto/ECDigitalSignature.scala index 8e80642d2d..6ff0d0d823 100644 --- a/src/main/scala/org/bitcoins/core/crypto/ECDigitalSignature.scala +++ b/src/main/scala/org/bitcoins/core/crypto/ECDigitalSignature.scala @@ -1,17 +1,18 @@ package org.bitcoins.core.crypto -import org.bitcoins.core.util.{BitcoinSLogger, BitcoinSUtil} - +import org.bitcoins.core.util.{BitcoinSLogger, BitcoinSUtil, Factory} /** * Created by chris on 2/26/16. */ sealed trait ECDigitalSignature extends BitcoinSLogger { def hex : String = BitcoinSUtil.encodeHex(bytes) - def bytes : Seq[Byte] - def isEmpty = bytes.isEmpty - override def toString = hex + def bytes : Seq[Byte] + + def isEmpty = bytes.isEmpty + + override def toString = "ECDigitalSignature(" + hex + ")" /** * Checks if this signature is encoded to DER correctly @@ -50,6 +51,33 @@ case object EmptyDigitalSignature extends ECDigitalSignature { def bytes = Seq() override def r = java.math.BigInteger.valueOf(0) override def s = r - } -sealed case class ECDigitalSignatureImpl(bytes : Seq[Byte]) extends ECDigitalSignature + + +object ECDigitalSignature extends Factory[ECDigitalSignature] { + private case class ECDigitalSignatureImpl(bytes : Seq[Byte]) extends ECDigitalSignature + + override def fromBytes(bytes : Seq[Byte]) : ECDigitalSignature = { + //this represents the empty signature + if (bytes.size == 1 && bytes.head == 0x0) EmptyDigitalSignature + else if (bytes.size == 0) EmptyDigitalSignature + else ECDigitalSignatureImpl(bytes) + } + + def apply(r : BigInt, s : BigInt) = fromRS(r,s) + /** + * Takes in the r and s component of a digital signature and gives back a ECDigitalSignature object + * The ECDigitalSignature object complies with strict der encoding as per BIP62 + * note: That the hash type for the signature CANNOT be added to the digital signature + * @param r the r component of the digital signature + * @param s the s component of the digital signature + * @return + */ + def fromRS(r : BigInt, s : BigInt) : ECDigitalSignature = { + val rsSize = r.toByteArray.size + s.toByteArray.size + val totalSize = 4 + rsSize + val bytes : Seq[Byte] = Seq(0x30.toByte, totalSize.toByte, 0x2.toByte, r.toByteArray.size.toByte) ++ + r.toByteArray.toSeq ++ Seq(0x2.toByte, s.toByteArray.size.toByte) ++ s.toByteArray.toSeq + fromBytes(bytes) + } +} diff --git a/src/main/scala/org/bitcoins/core/crypto/HashDigest.scala b/src/main/scala/org/bitcoins/core/crypto/HashDigest.scala index 671669b6a8..3e6699e3df 100644 --- a/src/main/scala/org/bitcoins/core/crypto/HashDigest.scala +++ b/src/main/scala/org/bitcoins/core/crypto/HashDigest.scala @@ -1,6 +1,6 @@ package org.bitcoins.core.crypto -import org.bitcoins.core.util.BitcoinSUtil +import org.bitcoins.core.util.{Factory, BitcoinSUtil} /** * Created by chris on 5/24/16. @@ -34,9 +34,16 @@ case class Sha256Digest(bytes : Seq[Byte]) extends HashDigest /** * Represents the result of SHA256(SHA256()) - * @param bytes */ -case class DoubleSha256Digest(bytes : Seq[Byte]) extends HashDigest +sealed trait DoubleSha256Digest extends HashDigest + +object DoubleSha256Digest extends Factory[DoubleSha256Digest] { + private case class DoubleSha256DigestImpl(bytes: Seq[Byte]) extends DoubleSha256Digest { + override def toString = "DoubleSha256DigestImpl(" + hex + ")" + } + override def fromBytes(bytes : Seq[Byte]) : DoubleSha256Digest = DoubleSha256DigestImpl(bytes) + +} /** * Represents the result of RIPEMD160() diff --git a/src/main/scala/org/bitcoins/core/protocol/Address.scala b/src/main/scala/org/bitcoins/core/protocol/Address.scala index 6161a4cc7a..115c1d6622 100644 --- a/src/main/scala/org/bitcoins/core/protocol/Address.scala +++ b/src/main/scala/org/bitcoins/core/protocol/Address.scala @@ -1,22 +1,18 @@ package org.bitcoins.core.protocol - -import org.bitcoinj.core.{VersionedChecksummedBytes, Base58, Utils} import org.bitcoins.core.config.{RegTest, TestNet3, MainNet} import org.bitcoins.core.util.{Factory, BitcoinSUtil} - +import org.bitcoins.core.config.{RegTest, TestNet3, MainNet} +import org.bitcoins.core.util.{CryptoUtil, Base58, Factory} import scala.util.{Failure, Success, Try} -case class AddressInfo(bitcoinAddress: BitcoinAddress, n_tx: Long, total_received: Long, total_sent: Long, - final_balance: Long) - -sealed abstract class Address( val value : String) +sealed abstract class Address(val value : String) sealed case class BitcoinAddress(override val value: String) extends Address(value ) { require(BitcoinAddress.validate(value), "Bitcoin address was invalid " + value) } sealed case class AssetAddress(override val value : String) extends Address(value) { - require(AssetAddress.validate(value), "The provided asset was was invalid: " + value) + require(AssetAddress.validate(value), "The provided asset was invalid: " + value) } object BitcoinAddress { @@ -35,11 +31,17 @@ object BitcoinAddress { */ def convertToAssetAddress(address : BitcoinAddress) : AssetAddress = { val underlying : String = address.value - val base58decodeChecked : Array[Byte] = Base58.decodeChecked(underlying) + val decodedBase58 : Seq[Byte] = Base58.decode(underlying) require ( - base58decodeChecked.size == 21 + decodedBase58.size == 25 ) - AssetAddress(new VersionedChecksummedBytes(0x13, base58decodeChecked){}.toString()) + val decodedWithNameSpaceByte = Seq(0x13.toByte) ++ decodedBase58 + val split = decodedWithNameSpaceByte.splitAt(decodedWithNameSpaceByte.length - 4) + val data = split._1 + val newCheckSum = CryptoUtil.doubleSHA256(data).bytes.slice(0,4) + val constructedAssetAddress = data ++ newCheckSum + val encodedAssetAddress = Base58.encode(constructedAssetAddress) + AssetAddress(encodedAssetAddress) } /** @@ -49,15 +51,15 @@ object BitcoinAddress { * @return */ def p2shAddress(address : String) : Boolean = { - try { - val base58decodeChecked : Array[Byte] = Base58.decodeChecked(address) - val firstByte = base58decodeChecked(0) - ((firstByte == MainNet.p2shNetworkByte || firstByte == TestNet3.p2shNetworkByte || RegTest.p2shNetworkByte == firstByte) - && base58decodeChecked.size == 21) - } catch { - case _ : Throwable => false + val decodeCheckP2SH : Try[Seq[Byte]] = Base58.decodeCheck(address) + decodeCheckP2SH match { + case Success(bytes) => + val firstByte = bytes.head + ((firstByte == MainNet.p2shNetworkByte || firstByte == TestNet3.p2shNetworkByte || + RegTest.p2shNetworkByte == firstByte) + && bytes.size == 21) + case Failure(exception) => false } - } /** @@ -75,16 +77,14 @@ object BitcoinAddress { * @return */ def p2pkh(address : String) : Boolean = { - try { - val base58decodeChecked : Array[Byte] = Base58.decodeChecked(address) - val firstByte = base58decodeChecked(0) - - ((firstByte == MainNet.p2pkhNetworkByte || firstByte == TestNet3.p2pkhNetworkByte || - firstByte == RegTest.p2pkhNetworkByte) && base58decodeChecked.size == 21) - } catch { - case _ : Throwable => false + val decodeCheckP2PKH : Try[Seq[Byte]] = Base58.decodeCheck(address) + decodeCheckP2PKH match { + case Success(bytes) => + val firstByte = bytes.head + (firstByte == MainNet.p2pkhNetworkByte || firstByte == TestNet3.p2pkhNetworkByte || + firstByte == RegTest.p2pkhNetworkByte) && bytes.size == 21 + case Failure(exception) => false } - } /** @@ -99,12 +99,11 @@ object BitcoinAddress { object AssetAddress { def validate(assetAddress : String) : Boolean = { //asset addresses must have the one byte namespace equivalent to 19 - //which ends up being 'a' in the ascii character set - val base58DecodeChecked : Try[Array[Byte]] = Try(Base58.decodeChecked(assetAddress)) - base58DecodeChecked match { - case Success(bytes) => - if (bytes == null) false - else bytes.size == 22 && bytes(0) == 0x13 + //which ends up being 'a' in the ascii character set. + //bytes size becomes 22 + val decodeCheckAssetAddress : Try[Seq[Byte]] = Base58.decodeCheck(assetAddress) + decodeCheckAssetAddress match { + case Success(bytes) => bytes.size == 22 && bytes.head == 0x13 case Failure(_) => false } } @@ -115,14 +114,17 @@ object AssetAddress { * @param assetAddress * @return */ - def convertToBitcoinAddress(assetAddress : AssetAddress) = { + def convertToBitcoinAddress(assetAddress : AssetAddress) : BitcoinAddress = { val underlying : String = assetAddress.value - val base58decodeChecked : Array[Byte] = Base58.decodeChecked(underlying) - - require(base58decodeChecked.size == 22) - - val slice = base58decodeChecked.slice(2, base58decodeChecked.length) - BitcoinAddress(new VersionedChecksummedBytes(base58decodeChecked(1), slice){}.toString()) + val decodedAsset = Base58.decode(underlying) + require { + decodedAsset.size == 26 + } + val data = decodedAsset.slice(0, decodedAsset.length - 4) + val dataDroppedNameSpace = data.drop(1) + val checkSum = CryptoUtil.doubleSHA256(dataDroppedNameSpace).bytes.slice(0,4) + val value = Base58.encode(dataDroppedNameSpace ++ checkSum) + BitcoinAddress(value) } } @@ -143,10 +145,9 @@ object Address extends Factory[Address] { } - def fromBytes(bytes : Seq[Byte]) : Address = factory(BitcoinSUtil.encodeBase58(bytes)) + def fromBytes(bytes : Seq[Byte]) : Address = factory(Base58.encode(bytes)) override def fromHex(hex : String) : Address = throw new RuntimeException("We cannot create a bitcoin address from hex - bitcoin addresses are base 58 encoded") - def apply(bytes : Seq[Byte]) : Address = fromBytes(bytes) - def apply(str : String) : Address = factory(str) + override def apply(str : String) : Address = factory(str) } \ No newline at end of file diff --git a/src/main/scala/org/bitcoins/core/protocol/blockchain/Block.scala b/src/main/scala/org/bitcoins/core/protocol/blockchain/Block.scala index 9633fb3a4f..2e4aef7397 100644 --- a/src/main/scala/org/bitcoins/core/protocol/blockchain/Block.scala +++ b/src/main/scala/org/bitcoins/core/protocol/blockchain/Block.scala @@ -59,6 +59,4 @@ object Block extends Factory[Block] { } def fromBytes(bytes : Seq[Byte]) : Block = RawBlockSerializer.read(bytes) - - def apply(bytes : Seq[Byte]) : Block = fromBytes(bytes) } \ No newline at end of file diff --git a/src/main/scala/org/bitcoins/core/protocol/blockchain/BlockHeader.scala b/src/main/scala/org/bitcoins/core/protocol/blockchain/BlockHeader.scala index 162ba3936f..f94d943520 100644 --- a/src/main/scala/org/bitcoins/core/protocol/blockchain/BlockHeader.scala +++ b/src/main/scala/org/bitcoins/core/protocol/blockchain/BlockHeader.scala @@ -99,6 +99,4 @@ object BlockHeader extends Factory[BlockHeader] { def fromBytes(bytes : Seq[Byte]) : BlockHeader = RawBlockHeaderSerializer.read(bytes) - def apply(bytes : Seq[Byte]) : BlockHeader = fromBytes(bytes) - } \ No newline at end of file diff --git a/src/main/scala/org/bitcoins/core/protocol/script/ScriptPubKey.scala b/src/main/scala/org/bitcoins/core/protocol/script/ScriptPubKey.scala index b8b28fa2e0..4124f21c5d 100644 --- a/src/main/scala/org/bitcoins/core/protocol/script/ScriptPubKey.scala +++ b/src/main/scala/org/bitcoins/core/protocol/script/ScriptPubKey.scala @@ -1,6 +1,6 @@ package org.bitcoins.core.protocol.script -import org.bitcoins.core.crypto.{ECFactory, ECPublicKey} +import org.bitcoins.core.crypto.{ECPublicKey} import org.bitcoins.core.serializers.script.{RawScriptPubKeyParser, ScriptParser} import org.bitcoins.core.protocol._ import org.bitcoins.core.script.bitwise.{OP_EQUAL, OP_EQUALVERIFY} @@ -88,7 +88,7 @@ trait MultiSignatureScriptPubKey extends ScriptPubKey { * @return */ def publicKeys : Seq[ECPublicKey] = { - asm.filter(_.isInstanceOf[ScriptConstant]).slice(1, maxSigs.toInt + 1).map(key => ECFactory.publicKey(key.hex)) + asm.filter(_.isInstanceOf[ScriptConstant]).slice(1, maxSigs.toInt + 1).map(key => ECPublicKey(key.hex)) } } @@ -105,7 +105,7 @@ trait P2SHScriptPubKey extends ScriptPubKey * Format: OP_CHECKSIG */ trait P2PKScriptPubKey extends ScriptPubKey { - def publicKey = ECFactory.publicKey(BitcoinScriptUtil.filterPushOps(asm).head.bytes) + def publicKey = ECPublicKey(BitcoinScriptUtil.filterPushOps(asm).head.bytes) } trait NonStandardScriptPubKey extends ScriptPubKey @@ -169,8 +169,4 @@ object ScriptPubKey extends Factory[ScriptPubKey] { def fromBytes(bytes : Seq[Byte]) : ScriptPubKey = RawScriptPubKeyParser.read(bytes) - def apply(bytes: Seq[Byte]) : ScriptPubKey = fromBytes(bytes) - - def apply(hex : String) : ScriptPubKey = fromHex(hex) - } \ No newline at end of file diff --git a/src/main/scala/org/bitcoins/core/protocol/script/ScriptSignature.scala b/src/main/scala/org/bitcoins/core/protocol/script/ScriptSignature.scala index 75367dc8ba..467f86985d 100644 --- a/src/main/scala/org/bitcoins/core/protocol/script/ScriptSignature.scala +++ b/src/main/scala/org/bitcoins/core/protocol/script/ScriptSignature.scala @@ -1,6 +1,6 @@ package org.bitcoins.core.protocol.script -import org.bitcoins.core.crypto.{ECDigitalSignature, ECFactory, ECPublicKey, EmptyDigitalSignature} +import org.bitcoins.core.crypto.{ECDigitalSignature, ECPublicKey, EmptyDigitalSignature} import org.bitcoins.core.protocol.NetworkElement import org.bitcoins.core.serializers.script.{RawScriptPubKeyParser, RawScriptSignatureParser, ScriptParser} import org.bitcoins.core.script.constant._ @@ -75,7 +75,7 @@ trait P2PKHScriptSignature extends ScriptSignature { * Gives us the public key inside of a p2pkh script signature * @return */ - def publicKey : ECPublicKey = ECFactory.publicKey(asm.last.bytes) + def publicKey : ECPublicKey = ECPublicKey(asm.last.bytes) /** * Returns the hash type for the p2pkh script signature @@ -84,7 +84,7 @@ trait P2PKHScriptSignature extends ScriptSignature { def hashType : HashType = HashTypeFactory.fromByte(signature.bytes.last) override def signatures : Seq[ECDigitalSignature] = { - Seq(ECFactory.digitalSignature(asm(1).hex)) + Seq(ECDigitalSignature(asm(1).hex)) } } @@ -118,7 +118,7 @@ trait P2SHScriptSignature extends ScriptSignature { def publicKeys : Seq[ECPublicKey] = { val pubKeys : Seq[ScriptToken] = redeemScript.asm.filter(_.isInstanceOf[ScriptConstant]) .filterNot(_.isInstanceOf[ScriptNumberOperation]) - pubKeys.map(k => ECFactory.publicKey(k.hex)) + pubKeys.map(k => ECPublicKey(k.hex)) } @@ -129,7 +129,7 @@ trait P2SHScriptSignature extends ScriptSignature { def signatures : Seq[ECDigitalSignature] = { val nonRedeemScript = splitAtRedeemScript(asm)._1 val sigs = nonRedeemScript.filter(_.isInstanceOf[ScriptConstant]).filterNot(_.isInstanceOf[ScriptNumberOperation]) - sigs.map(s => ECFactory.digitalSignature(s.hex)) + sigs.map(s => ECDigitalSignature(s.hex)) } @@ -161,7 +161,7 @@ trait MultiSignatureScriptSignature extends ScriptSignature { */ def signatures : Seq[ECDigitalSignature] = { asm.tail.filter(_.isInstanceOf[ScriptConstant]) - .map(sig => ECFactory.digitalSignature(sig.hex)) + .map(sig => ECDigitalSignature(sig.hex)) } } @@ -189,7 +189,7 @@ trait P2PKScriptSignature extends ScriptSignature { * @return */ def signatures : Seq[ECDigitalSignature] = { - Seq(ECFactory.digitalSignature(BitcoinScriptUtil.filterPushOps(asm).head.hex)) + Seq(ECDigitalSignature(BitcoinScriptUtil.filterPushOps(asm).head.hex)) } } @@ -346,9 +346,8 @@ object ScriptSignature extends Factory[ScriptSignature] with BitcoinSLogger { } } - def apply(bytes: Seq[Byte]) : ScriptSignature = fromBytes(bytes) - def apply(hex : String) : ScriptSignature = fromHex(hex) def apply(signature : ECDigitalSignature, pubKey : ECPublicKey) : ScriptSignature = factory(signature,pubKey) + def apply(tokens : Seq[ScriptToken], scriptPubKey : ScriptPubKey) : ScriptSignature = fromScriptPubKey(tokens, scriptPubKey) } diff --git a/src/main/scala/org/bitcoins/core/protocol/transaction/Transaction.scala b/src/main/scala/org/bitcoins/core/protocol/transaction/Transaction.scala index b87bbd967f..ee09ca15f4 100644 --- a/src/main/scala/org/bitcoins/core/protocol/transaction/Transaction.scala +++ b/src/main/scala/org/bitcoins/core/protocol/transaction/Transaction.scala @@ -3,7 +3,7 @@ package org.bitcoins.core.protocol.transaction import org.bitcoins.core.crypto.DoubleSha256Digest import org.bitcoins.core.protocol.NetworkElement import org.bitcoins.core.serializers.transaction.RawTransactionParser -import org.bitcoins.core.util.{BitcoinSUtil, CryptoUtil, Factory} +import org.bitcoins.core.util.{Factory, BitcoinSUtil, CryptoUtil} /** * Created by chris on 7/14/15. @@ -126,8 +126,6 @@ object Transaction extends Factory[Transaction] { def fromBytes(bytes : Seq[Byte]) : Transaction = RawTransactionParser.read(bytes) - def apply(bytes : Seq[Byte]) : Transaction = fromBytes(bytes) - def apply(hex: String) : Transaction = fromHex(hex) def apply(bytes : Array[Byte]) : Transaction = factory(bytes) def apply(oldTx : Transaction, lockTime : Long) : Transaction = factory(oldTx,lockTime) def apply(oldTx : Transaction, updatedInputs : UpdateTransactionInputs) : Transaction = factory(oldTx, updatedInputs) diff --git a/src/main/scala/org/bitcoins/core/protocol/transaction/TransactionInput.scala b/src/main/scala/org/bitcoins/core/protocol/transaction/TransactionInput.scala index dc43dae2e5..dedbfad27b 100644 --- a/src/main/scala/org/bitcoins/core/protocol/transaction/TransactionInput.scala +++ b/src/main/scala/org/bitcoins/core/protocol/transaction/TransactionInput.scala @@ -112,8 +112,6 @@ object TransactionInput extends Factory[TransactionInput] { def apply(outPoint : TransactionOutPoint, scriptSignature : ScriptSignature, sequenceNumber : Long) : TransactionInput = factory(outPoint,scriptSignature,sequenceNumber) - def apply(bytes : Seq[Byte]) : TransactionInput = fromBytes(bytes) - /** * Creates a coinbase input - coinbase inputs always have an empty outpoint * @param scriptSignature this can contain anything, miners use this to signify support for various protocol BIPs diff --git a/src/main/scala/org/bitcoins/core/protocol/transaction/TransactionOutPoint.scala b/src/main/scala/org/bitcoins/core/protocol/transaction/TransactionOutPoint.scala index 389f3e3ce9..7041feac94 100644 --- a/src/main/scala/org/bitcoins/core/protocol/transaction/TransactionOutPoint.scala +++ b/src/main/scala/org/bitcoins/core/protocol/transaction/TransactionOutPoint.scala @@ -2,9 +2,8 @@ package org.bitcoins.core.protocol.transaction import org.bitcoins.core.crypto.DoubleSha256Digest import org.bitcoins.core.protocol.NetworkElement -import org.bitcoins.core.serializers.transaction.RawTransactionOutPointParser import org.bitcoins.core.util.{BitcoinSUtil, Factory} - +import org.bitcoins.core.serializers.transaction.RawTransactionOutPointParser /** * Created by chris on 12/26/15. * @@ -59,9 +58,8 @@ object TransactionOutPoint extends Factory[TransactionOutPoint] { def fromBytes(bytes : Seq[Byte]) : TransactionOutPoint = RawTransactionOutPointParser.read(bytes) - def apply(bytes : Seq[Byte]) : TransactionOutPoint = fromBytes(bytes) - def apply(hex : String) : TransactionOutPoint = fromHex(hex) def apply(output : TransactionOutput,parentTransaction : Transaction) : TransactionOutPoint = factory(output,parentTransaction) + def apply(txId : DoubleSha256Digest, index: Int) : TransactionOutPoint = factory(txId,index) } diff --git a/src/main/scala/org/bitcoins/core/protocol/transaction/TransactionOutput.scala b/src/main/scala/org/bitcoins/core/protocol/transaction/TransactionOutput.scala index 93c76e245e..d8fd1c4c7f 100644 --- a/src/main/scala/org/bitcoins/core/protocol/transaction/TransactionOutput.scala +++ b/src/main/scala/org/bitcoins/core/protocol/transaction/TransactionOutput.scala @@ -1,11 +1,11 @@ package org.bitcoins.core.protocol.transaction -import org.bitcoins.core.currency.{CurrencyUnit, CurrencyUnits, Satoshis} -import org.bitcoins.core.serializers.transaction.RawTransactionOutputParser import org.bitcoins.core.protocol.{CompactSizeUInt, NetworkElement} -import org.bitcoins.core.protocol.script.ScriptPubKey -import org.bitcoins.core.util.{BitcoinSUtil, Factory} +import org.bitcoins.core.currency.{CurrencyUnits, CurrencyUnit, Satoshis} +import org.bitcoins.core.serializers.transaction.RawTransactionOutputParser +import org.bitcoins.core.protocol.script.{ScriptPubKey} +import org.bitcoins.core.util.{Factory, BitcoinSUtil} /** * Created by chris on 12/26/15. @@ -43,7 +43,9 @@ object TransactionOutput extends Factory[TransactionOutput] { def fromBytes(bytes : Seq[Byte]) : TransactionOutput = RawTransactionOutputParser.read(bytes).head def apply(oldOutput : TransactionOutput, newCurrencyUnit: CurrencyUnit) : TransactionOutput = factory(oldOutput,newCurrencyUnit) + def apply(oldOutput : TransactionOutput, newScriptPubKey : ScriptPubKey) : TransactionOutput = factory(oldOutput, newScriptPubKey) + def apply(currencyUnit: CurrencyUnit, scriptPubKey: ScriptPubKey) : TransactionOutput = factory(currencyUnit, scriptPubKey) - def apply(bytes : Seq[Byte]) : TransactionOutput = fromBytes(bytes) + } \ No newline at end of file diff --git a/src/main/scala/org/bitcoins/core/script/constant/Constants.scala b/src/main/scala/org/bitcoins/core/script/constant/Constants.scala index 70b71e380b..0069ab1a6d 100644 --- a/src/main/scala/org/bitcoins/core/script/constant/Constants.scala +++ b/src/main/scala/org/bitcoins/core/script/constant/Constants.scala @@ -23,10 +23,9 @@ sealed trait ScriptToken { /** * The byte representation of this script token - * * @return */ - def bytes = BitcoinSUtil.decodeHex(hex) + def bytes : Seq[Byte] = BitcoinSUtil.decodeHex(hex) /** * The conversion from the byte representation of a token to a number @@ -134,10 +133,6 @@ object ScriptNumber extends Factory[ScriptNumber] { if (num == 0) zero else apply(BitcoinSUtil.longToHex(num)) } - def apply(hex : String) : ScriptNumber = fromHex(hex) - - def apply(bytes : Seq[Byte]) : ScriptNumber = fromBytes(bytes) - def apply(hex : String, requireMinimal : Boolean) : Try[ScriptNumber] = { if (requireMinimal && !BitcoinScriptUtil.isShortestEncoding(hex)) { Failure(new IllegalArgumentException("The given hex was not the shortest encoding for the script number: " + hex)) @@ -405,7 +400,4 @@ object ScriptConstant extends Factory[ScriptConstant] { */ def fromBytes(bytes : Seq[Byte]) : ScriptConstant = ScriptConstantImpl(BitcoinSUtil.encodeHex(bytes)) - def apply(hex : String) : ScriptConstant = fromHex(hex) - - def apply(bytes : Seq[Byte]) : ScriptConstant = fromBytes(bytes) } diff --git a/src/main/scala/org/bitcoins/core/script/crypto/CryptoInterpreter.scala b/src/main/scala/org/bitcoins/core/script/crypto/CryptoInterpreter.scala index 79246b90f9..8929126c73 100644 --- a/src/main/scala/org/bitcoins/core/script/crypto/CryptoInterpreter.scala +++ b/src/main/scala/org/bitcoins/core/script/crypto/CryptoInterpreter.scala @@ -24,7 +24,7 @@ trait CryptoInterpreter extends ControlOperationsInterpreter with BitcoinSLogger */ def opHash160(program : ScriptProgram) : ScriptProgram = { require(program.script.headOption.isDefined && program.script.head == OP_HASH160, "Script operation must be OP_HASH160") - executeHashFunction(program, CryptoUtil.sha256Hash160(_ : List[Byte])) + executeHashFunction(program, CryptoUtil.sha256Hash160(_ : Seq[Byte])) } @@ -35,7 +35,7 @@ trait CryptoInterpreter extends ControlOperationsInterpreter with BitcoinSLogger */ def opRipeMd160(program : ScriptProgram) : ScriptProgram = { require(program.script.headOption.isDefined && program.script.head == OP_RIPEMD160, "Script operation must be OP_RIPEMD160") - executeHashFunction(program, CryptoUtil.ripeMd160(_ : List[Byte])) + executeHashFunction(program, CryptoUtil.ripeMd160(_ : Seq[Byte])) } /** @@ -45,7 +45,7 @@ trait CryptoInterpreter extends ControlOperationsInterpreter with BitcoinSLogger */ def opSha256(program : ScriptProgram) : ScriptProgram = { require(program.script.headOption.isDefined && program.script.head == OP_SHA256, "Script operation must be OP_SHA256") - executeHashFunction(program, CryptoUtil.sha256(_ : List[Byte])) + executeHashFunction(program, CryptoUtil.sha256(_ : Seq[Byte])) } /** @@ -55,7 +55,7 @@ trait CryptoInterpreter extends ControlOperationsInterpreter with BitcoinSLogger */ def opHash256(program : ScriptProgram) : ScriptProgram = { require(program.script.headOption.isDefined && program.script.head == OP_HASH256, "Script operation must be OP_HASH256") - executeHashFunction(program, CryptoUtil.doubleSHA256(_ : List[Byte])) + executeHashFunction(program, CryptoUtil.doubleSHA256(_ : Seq[Byte])) } /** @@ -65,7 +65,7 @@ trait CryptoInterpreter extends ControlOperationsInterpreter with BitcoinSLogger */ def opSha1(program : ScriptProgram) : ScriptProgram = { require(program.script.headOption.isDefined && program.script.head == OP_SHA1, "Script top must be OP_SHA1") - executeHashFunction(program, CryptoUtil.sha1(_ : List[Byte])) + executeHashFunction(program, CryptoUtil.sha1(_ : Seq[Byte])) } /** @@ -79,7 +79,6 @@ trait CryptoInterpreter extends ControlOperationsInterpreter with BitcoinSLogger */ def opCheckSig(program : ScriptProgram) : ScriptProgram = { require(program.script.headOption.isDefined && program.script.head == OP_CHECKSIG, "Script top must be OP_CHECKSIG") - program match { case preExecutionScriptProgram : PreExecutionScriptProgram => opCheckSig(ScriptProgram.toExecutionInProgress(preExecutionScriptProgram)) @@ -90,8 +89,8 @@ trait CryptoInterpreter extends ControlOperationsInterpreter with BitcoinSLogger logger.error("OP_CHECKSIG requires at lest two stack elements") ScriptProgram(program,ScriptErrorInvalidStackOperation) } else { - val pubKey = ECFactory.publicKey(executionInProgressScriptProgram.stack.head.bytes) - val signature = ECFactory.digitalSignature(executionInProgressScriptProgram.stack.tail.head.bytes) + val pubKey = ECPublicKey(executionInProgressScriptProgram.stack.head.bytes) + val signature = ECDigitalSignature(executionInProgressScriptProgram.stack.tail.head.bytes) if (ScriptFlagUtil.requiresStrictDerEncoding(executionInProgressScriptProgram.flags) && !DERSignatureUtil.isStrictDEREncoding(signature)) { @@ -230,7 +229,7 @@ trait CryptoInterpreter extends ControlOperationsInterpreter with BitcoinSLogger (program.stack.tail.slice(0, nPossibleSignatures.num.toInt), program.stack.tail.slice(nPossibleSignatures.num.toInt, program.stack.tail.size)) - val pubKeys = pubKeysScriptTokens.map(key => ECFactory.publicKey(key.bytes)) + val pubKeys = pubKeysScriptTokens.map(key => ECPublicKey(key.bytes)) logger.debug("Public keys on the stack: " + pubKeys) logger.debug("Stack without pubkeys: " + stackWithoutPubKeys) logger.debug("mRequiredSignatures: " + mRequiredSignatures) @@ -238,7 +237,7 @@ trait CryptoInterpreter extends ControlOperationsInterpreter with BitcoinSLogger //+1 is for the fact that we have the # of sigs + the script token indicating the # of sigs val signaturesScriptTokens = program.stack.tail.slice(nPossibleSignatures.num.toInt + 1, nPossibleSignatures.num.toInt + mRequiredSignatures.num.toInt + 1) - val signatures = signaturesScriptTokens.map(token => ECFactory.digitalSignature(token.bytes)) + val signatures = signaturesScriptTokens.map(token => ECDigitalSignature(token.bytes)) logger.debug("Signatures on the stack: " + signatures) //this contains the extra Script OP that is required for OP_CHECKMULTISIG @@ -336,7 +335,7 @@ trait CryptoInterpreter extends ControlOperationsInterpreter with BitcoinSLogger * @param hashFunction the hash function which needs to be used on the stack top (sha256,ripemd160,etc..) * @return */ - private def executeHashFunction(program : ScriptProgram, hashFunction : List[Byte] => HashDigest) : ScriptProgram = { + private def executeHashFunction(program : ScriptProgram, hashFunction : Seq[Byte] => HashDigest) : ScriptProgram = { if (program.stack.headOption.isDefined) { val stackTop = program.stack.head val hash = ScriptConstant(hashFunction(stackTop.bytes).bytes) diff --git a/src/main/scala/org/bitcoins/core/script/interpreter/ScriptInterpreter.scala b/src/main/scala/org/bitcoins/core/script/interpreter/ScriptInterpreter.scala index acfd64feff..debe342648 100644 --- a/src/main/scala/org/bitcoins/core/script/interpreter/ScriptInterpreter.scala +++ b/src/main/scala/org/bitcoins/core/script/interpreter/ScriptInterpreter.scala @@ -146,6 +146,7 @@ trait ScriptInterpreter extends CryptoInterpreter with StackInterpreter with Con } /** * The execution loop for a script + * * @param program the program whose script needs to be evaluated * @return program the final state of the program after being evaluated by the interpreter */ @@ -375,6 +376,7 @@ trait ScriptInterpreter extends CryptoInterpreter with StackInterpreter with Con /** * Checks the validity of a transaction in accordance to bitcoin core's CheckTransaction function * https://github.com/bitcoin/bitcoin/blob/f7a21dae5dbf71d5bc00485215e84e6f2b309d0a/src/main.cpp#L939 + * * @param transaction * @return */ @@ -405,6 +407,7 @@ trait ScriptInterpreter extends CryptoInterpreter with StackInterpreter with Con /** * Determines if the given currency unit is within the valid range for the system + * * @param currencyUnit * @return */ diff --git a/src/main/scala/org/bitcoins/core/serializers/blockchain/RawBlockHeaderSerializer.scala b/src/main/scala/org/bitcoins/core/serializers/blockchain/RawBlockHeaderSerializer.scala index 517559074e..5593c19695 100644 --- a/src/main/scala/org/bitcoins/core/serializers/blockchain/RawBlockHeaderSerializer.scala +++ b/src/main/scala/org/bitcoins/core/serializers/blockchain/RawBlockHeaderSerializer.scala @@ -1,7 +1,9 @@ package org.bitcoins.core.serializers.blockchain +import org.bitcoins.core.crypto.DoubleSha256Digest import org.bitcoins.core.protocol.blockchain.BlockHeader import org.bitcoins.core.serializers.RawBitcoinSerializer +import org.bitcoins.core.util.{CryptoUtil, BitcoinSUtil} /** * Created by chris on 5/19/16. @@ -12,17 +14,56 @@ trait RawBlockHeaderSerializer extends RawBitcoinSerializer[BlockHeader] { /** * Converts a list of bytes into a block header + * * @param bytes the bytes to parsed into a block header * @return the block header */ - def read(bytes : List[Byte]) : BlockHeader = ??? + def read(bytes : List[Byte]) : BlockHeader = { + //version first 4 bytes + val versionBytes = bytes.slice(0,4) + val versionHex = BitcoinSUtil.encodeHex(versionBytes) + val version = BitcoinSUtil.hexToLong(versionHex) + //previous header hash next 32 bytes + val prevBlockHashBytes = bytes.slice(4, 36) + val prevBlockHash : DoubleSha256Digest = DoubleSha256Digest(prevBlockHashBytes) + //merkle hash next 32 bytes + val merkleRootBytes = bytes.slice(36, 68) + val merkleRoot : DoubleSha256Digest = DoubleSha256Digest(merkleRootBytes) + //time 4 bytes + val timeBytes = bytes.slice(68,72) + val timeHex = BitcoinSUtil.encodeHex(timeBytes) + val time = BitcoinSUtil.hexToLong(timeHex) + //nbits 4 bytes + val nBitsBytes = bytes.slice(72,76) + val nBitsHex = BitcoinSUtil.encodeHex(nBitsBytes) + val nBits = BitcoinSUtil.hexToLong(nBitsHex) + //nonce 4 bytes + val nonceBytes = bytes.slice(76,80) + val nonceHex = BitcoinSUtil.encodeHex(nonceBytes) + val nonce = BitcoinSUtil.hexToLong(nonceHex) + BlockHeader(version,prevBlockHash, merkleRoot, time, nBits, nonce) + } /** * Serializes the BlockHeader to a hexadecimal string + * * @param blockHeader the block header to be serialized * @return the hexadecimal string representing the block header */ - def write(blockHeader: BlockHeader) : String = ??? + def write(blockHeader: BlockHeader) : String = { + val headerVersion = blockHeader.version.toHexString + val versionSubPadding = addPrecedingZero(headerVersion) + val version = addPadding(8,versionSubPadding) + + val prevHash = blockHeader.previousBlockHash.hex + val merkleRoot = blockHeader.merkleRootHash.hex + + val time = BitcoinSUtil.flipEndianess(blockHeader.time.toHexString) + val nBits = BitcoinSUtil.flipEndianess(blockHeader.nBits.toHexString) + val nonce = BitcoinSUtil.flipEndianess(blockHeader.nonce.toHexString) + + version + prevHash + merkleRoot + time + nBits + nonce + } } diff --git a/src/main/scala/org/bitcoins/core/serializers/script/ScriptParser.scala b/src/main/scala/org/bitcoins/core/serializers/script/ScriptParser.scala index 99651b6c17..4437f80cb3 100644 --- a/src/main/scala/org/bitcoins/core/serializers/script/ScriptParser.scala +++ b/src/main/scala/org/bitcoins/core/serializers/script/ScriptParser.scala @@ -75,7 +75,7 @@ trait ScriptParser extends Factory[List[ScriptToken]] with BitcoinSLogger { logger.debug("Found a string constant") val strippedQuotes = h.replace("'","") if (strippedQuotes.size == 0) { - loop(t, OP_0.bytes ++ accum) + loop(t, OP_0.bytes.toList ++ accum) } else { val bytes : Seq[Byte] = BitcoinSUtil.decodeHex(BitcoinSUtil.flipEndianess(strippedQuotes.getBytes.toList)) @@ -93,43 +93,46 @@ trait ScriptParser extends Factory[List[ScriptToken]] with BitcoinSLogger { case false => List(BytesToPushOntoStack(bytes.size)) } - loop(t, bytes.toList ++ bytesToPushOntoStack.flatMap(_.bytes) ++ accum) + loop(t, bytes.toList ++ bytesToPushOntoStack.flatMap(_.bytes) ++ accum) } //if we see a byte constant in the form of "0x09adb" case h :: t if (h.size > 1 && h.substring(0,2) == "0x") => - loop(t,BitcoinSUtil.decodeHex(h.substring(2,h.size).toLowerCase).reverse ++ accum) + logger.debug("Found byte constant in the form 0x..") + loop(t,BitcoinSUtil.decodeHex(h.substring(2,h.size).toLowerCase).toList.reverse ++ accum) //skip the empty string case h :: t if (h == "") => loop(t,accum) - case h :: t if (h == "0") => loop(t, OP_0.bytes ++ accum) + case h :: t if (h == "0") => loop(t, OP_0.bytes.toList ++ accum) case h :: t if (ScriptOperation.fromString(h).isDefined) => logger.debug("Founding a script operation in string form i.e. NOP or ADD") val op = ScriptOperation.fromString(h).get - loop(t,op.bytes ++ accum) + loop(t,op.bytes.toList ++ accum) case h :: t if (tryParsingLong(h)) => logger.debug("Found a decimal number") val hexLong = BitcoinSUtil.flipEndianess(BitcoinSUtil.longToHex(h.toLong)) val bytesToPushOntoStack = BytesToPushOntoStack(hexLong.size / 2) //convert the string to int, then convert to hex - loop(t, BitcoinSUtil.decodeHex(hexLong) ++ bytesToPushOntoStack.bytes ++ accum) + loop(t, BitcoinSUtil.decodeHex(hexLong).toList ++ bytesToPushOntoStack.bytes.toList ++ accum) //means that it must be a BytesToPushOntoStack followed by a script constant case h :: t => logger.debug("Generic h :: t") //find the size of the string in bytes val bytesToPushOntoStack = BytesToPushOntoStack(h.size / 2) - loop(t, BitcoinSUtil.decodeHex(BitcoinSUtil.flipEndianess(h)) ++ bytesToPushOntoStack.bytes ++ accum) + loop(t, BitcoinSUtil.decodeHex(BitcoinSUtil.flipEndianess(h)).toList ++ bytesToPushOntoStack.bytes.toList ++ accum) case Nil => accum } } if (tryParsingLong(str) && str.size > 1 && str.substring(0,2) != "0x") { + logger.debug("Parsing a single decimal constant") //for the case when there is just a single decimal constant //i.e. "8388607" val scriptNumber = ScriptNumber(parseLong(str)) val bytesToPushOntoStack = BytesToPushOntoStack(scriptNumber.bytes.size) List(bytesToPushOntoStack,scriptNumber) } - else if (BitcoinSUtil.isHex(str)) { + else if (BitcoinSUtil.isHex(str) && str.toLowerCase == str) { + logger.debug("Parsing hex string") //if the given string is hex, it is pretty straight forward to parse it //convert the hex string to a byte array and parse it val bytes = BitcoinSUtil.decodeHex(str) diff --git a/src/main/scala/org/bitcoins/core/util/Base58.scala b/src/main/scala/org/bitcoins/core/util/Base58.scala new file mode 100644 index 0000000000..82e875be75 --- /dev/null +++ b/src/main/scala/org/bitcoins/core/util/Base58.scala @@ -0,0 +1,80 @@ +package org.bitcoins.core.util + +import scala.annotation.tailrec +import scala.util.{Try, Failure, Success} + +/** + * Created by chris on 5/16/16. + * source of values: https://en.bitcoin.it/wiki/Base58Check_encoding + */ +trait Base58 extends BitcoinSLogger { + + val base58Characters = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz" + val base58Pairs = base58Characters.zipWithIndex.toMap + + /** + * Verifies a given base58 string against its checksum (last 4 decoded bytes) + * @param input base58 string + * @return decoded bytes excluding the checksum + */ + def decodeCheck(input: String) : Try[Seq[Byte]] = { + + val decoded : Seq[Byte] = decode(input) + if (decoded.length < 4) Failure(new IllegalArgumentException("Invalid input")) + else { + val splitSeqs = decoded.splitAt(decoded.length - 4) + val data : Seq[Byte] = splitSeqs._1 + val checksum : Seq[Byte] = splitSeqs._2 + val actualChecksum : Seq[Byte] = CryptoUtil.doubleSHA256(data).bytes.slice(0, 4) + if (checksum == actualChecksum) + Success(data) + else Failure(new IllegalArgumentException("checksums don't validate")) + } + } + + + /** + * Takes in sequence of bytes and returns base58 bitcoin string + * @param bytes sequence of bytes to be encoded into base58 + * @return base58 String + */ + + def encode(bytes : Seq[Byte]) : String = { + @tailrec + def loop(current : BigInt, str : String) : String = current match { + case a if current == BigInt(0) => + if (bytes.head == 0.toByte) '1' + str.reverse else str.reverse + case _ : BigInt => + val quotient : BigInt = current / BigInt(58L) + val remainder : BigInt = current.mod(58L) + val char = base58Characters.charAt(remainder.toInt).toString + val accum = str + char + loop(quotient, accum) + } + if (bytes.isEmpty) "" + else { + val big : BigInt = BigInt(1, bytes.toArray) + loop(big, "") + } + } + + + /** + * Takes in base58 string and returns sequence of bytes + * https://github.com/ACINQ/bitcoin-lib/blob/master/src/main/scala/fr/acinq/bitcoin/Base58.scala + * @param input base58 string to be decoded into a sequence of bytes + * @return decoded sequence of bytes + */ + def decode(input: String) : Seq[Byte] = { + val zeroes = input.takeWhile(_ == '1').map(_ => 0:Byte).toArray + val trim = input.dropWhile(_ == '1').toList + val decoded = trim.foldLeft(BigInt(0))((a,b) =>a.*(BigInt(58L)).+(BigInt(base58Pairs(b)))) + if (trim.isEmpty) zeroes else zeroes ++ decoded.toByteArray.dropWhile(_ == 0) + } + +} + +object Base58 extends Base58 + + + diff --git a/src/main/scala/org/bitcoins/core/util/BitcoinSUtil.scala b/src/main/scala/org/bitcoins/core/util/BitcoinSUtil.scala index 2cb2f5a764..8bae35f495 100644 --- a/src/main/scala/org/bitcoins/core/util/BitcoinSUtil.scala +++ b/src/main/scala/org/bitcoins/core/util/BitcoinSUtil.scala @@ -1,9 +1,6 @@ package org.bitcoins.core.util -import org.bitcoinj.core.{Base58, Utils} import org.bitcoins.core.currency.{CurrencyUnits, CurrencyUnit} - -import scala.collection.mutable.ArrayBuffer import scala.math.BigInt /** @@ -13,13 +10,11 @@ trait BitcoinSUtil extends NumberUtil { def hexToBigInt(hex : String) : BigInt = BigInt(hex, 16) - def decodeHex(hex : String) : List[Byte] = Utils.HEX.decode(hex.trim).toList + def decodeHex(hex : String) : Seq[Byte] = { + hex.replaceAll("[^0-9A-Fa-f]", "").sliding(2, 2).toArray.map(Integer.parseInt(_, 16).toByte).toList + } - def encodeHex(bytes : Array[Byte]) : String = Utils.HEX.encode(bytes) - - def encodeHex(bytes : List[Byte]) : String = encodeHex(bytes.toSeq) - - def encodeHex(bytes : Seq[Byte]) : String = encodeHex(bytes.toArray) + def encodeHex(bytes : Seq[Byte]) : String = bytes.map("%02x".format(_)).mkString def encodeHex(unit : CurrencyUnit) : String = { val satoshis = CurrencyUnits.toSatoshis(unit) @@ -29,24 +24,18 @@ trait BitcoinSUtil extends NumberUtil { //TODO: this is ugly, clean this up. Shouldn't have to use .toLong flipHalfByte(encodeHex(BigInt(satoshis.value.toLong).toByteArray).reverse) } - } def encodeHex(byte : Byte) : String = encodeHex(Seq(byte)) /** * Tests if a given string is a hexadecimal string - * * @param str * @return */ def isHex(str : String) = { - try { - decodeHex(str.trim) - true - } catch { - case _ : Throwable => false - } + //check valid characters & hex strings have to have an even number of chars + str.matches("^[0-9a-f]+$") && (str.size % 2 == 0) } def hexToLong(hex : String) : Long = toLong(hex) @@ -63,13 +52,8 @@ trait BitcoinSUtil extends NumberUtil { BitcoinSUtil.decodeHex(hex).head } - def decodeBase58(base58 : String) : Seq[Byte] = Base58.decode(base58).toList - - def encodeBase58(bytes : Seq[Byte]) : String = Base58.encode(bytes.toArray) - /** * Flips the endianess of the give hex string - * * @param hex * @return */ @@ -77,7 +61,6 @@ trait BitcoinSUtil extends NumberUtil { /** * Flips the endianess of the given sequence of bytes - * * @param bytes * @return */ @@ -86,7 +69,6 @@ trait BitcoinSUtil extends NumberUtil { * Flips the hex chars in a hex strings * Example: abcd would become badc * https://stackoverflow.com/questions/34799611/easiest-way-to-flip-the-endianness-of-a-byte-in-scala/34802270#34802270 - * * @param hex * @return */ diff --git a/src/main/scala/org/bitcoins/core/util/CryptoUtil.scala b/src/main/scala/org/bitcoins/core/util/CryptoUtil.scala index 85b84bde51..bbbf26799c 100644 --- a/src/main/scala/org/bitcoins/core/util/CryptoUtil.scala +++ b/src/main/scala/org/bitcoins/core/util/CryptoUtil.scala @@ -2,7 +2,6 @@ package org.bitcoins.core.util import java.security.MessageDigest -import org.bitcoinj.core.Sha256Hash import org.bitcoins.core.crypto._ import org.spongycastle.crypto.digests.RIPEMD160Digest @@ -15,45 +14,37 @@ trait CryptoUtil { /** * Does the following computation * RIPEMD160(SHA256(hex)) - * * @param hex * @return */ def sha256Hash160(hex : String) : Sha256Hash160Digest = sha256Hash160(BitcoinSUtil.decodeHex(hex)) - def sha256Hash160(bytes : List[Byte]) : Sha256Hash160Digest = { - val hash = org.bitcoinj.core.Utils.sha256hash160(bytes.toArray) - Sha256Hash160Digest(hash.toList) + + def sha256Hash160(bytes : Seq[Byte]) : Sha256Hash160Digest = { + val hash = ripeMd160(sha256(bytes.toArray).bytes).bytes + Sha256Hash160Digest(hash) } + /** * Performs sha256(sha256(hex)) - * * @param hex * @return */ def doubleSHA256(hex : String) : DoubleSha256Digest = doubleSHA256(BitcoinSUtil.decodeHex(hex)) - /** - * Performs sha256(sha256(hex)) - * - * @param bytes - * @return - */ - def doubleSHA256(bytes : List[Byte]) : DoubleSha256Digest = doubleSHA256(bytes.toSeq) + /** * Performs sha256(sha256(bytes)) - * * @param bytes * @return */ def doubleSHA256(bytes : Seq[Byte]) : DoubleSha256Digest = { - val hash : List[Byte] = Sha256Hash.hashTwice(bytes.toArray).toList + val hash : Seq[Byte] = sha256(sha256(bytes).bytes).bytes DoubleSha256Digest(hash) } /** * Takes sha256(hex) - * * @param hex * @return */ @@ -61,31 +52,29 @@ trait CryptoUtil { /** * Takes sha256(bytes) - * * @param bytes * @return */ - def sha256(bytes : List[Byte]) : Sha256Digest = { - val hash : List[Byte] = Sha256Hash.hash(bytes.toArray).toList + def sha256(bytes : Seq[Byte]) : Sha256Digest = { + val hash = MessageDigest.getInstance("SHA-256").digest(bytes.toArray).toList Sha256Digest(hash) } + /** * Performs SHA1(bytes) - * * @param bytes * @return */ - def sha1(bytes : List[Byte]) : Sha1Digest = { - val digest = MessageDigest.getInstance("SHA-1").digest(bytes.toArray).toList - Sha1Digest(digest) + def sha1(bytes : Seq[Byte]) : Sha1Digest = { + val hash = MessageDigest.getInstance("SHA-1").digest(bytes.toArray).toList + Sha1Digest(hash) } /** * Performs SHA1(hex) - * * @param hex * @return */ @@ -94,7 +83,6 @@ trait CryptoUtil { /** * Performs RIPEMD160(hex) - * * @param hex * @return */ @@ -103,11 +91,10 @@ trait CryptoUtil { /** * Performs RIPEMD160(bytes) - * * @param bytes * @return */ - def ripeMd160(bytes : List[Byte]) : RipeMd160Digest = { + def ripeMd160(bytes : Seq[Byte]) : RipeMd160Digest = { //from this tutorial http://rosettacode.org/wiki/RIPEMD-160#Scala val messageDigest = new RIPEMD160Digest val raw = bytes.toArray diff --git a/src/main/scala/org/bitcoins/core/util/Factory.scala b/src/main/scala/org/bitcoins/core/util/Factory.scala index 52350cd3c7..3a907bbfe0 100644 --- a/src/main/scala/org/bitcoins/core/util/Factory.scala +++ b/src/main/scala/org/bitcoins/core/util/Factory.scala @@ -20,4 +20,17 @@ trait Factory[T] { */ def fromBytes(bytes : Seq[Byte]) : T + /** + * Creates a T out of a sequence of bytes + * @param bytes + * @return + */ + def apply(bytes : Seq[Byte]) : T = fromBytes(bytes) + + /** + * Creates a T from a hex string + * @param hex + * @return + */ + def apply(hex : String) : T = fromHex(hex) } diff --git a/src/main/scala/org/bitcoins/core/util/NumberUtil.scala b/src/main/scala/org/bitcoins/core/util/NumberUtil.scala index 6901a7e8d2..a9597e110f 100644 --- a/src/main/scala/org/bitcoins/core/util/NumberUtil.scala +++ b/src/main/scala/org/bitcoins/core/util/NumberUtil.scala @@ -12,7 +12,6 @@ trait NumberUtil extends BitcoinSLogger { /** * Takes a hex number and converts it into a signed number * used in the bitcoin numbering system - * * @param hex * @return */ @@ -21,7 +20,6 @@ trait NumberUtil extends BitcoinSLogger { /** * Takes a list of bytes and converts it in to signed number inside of bitcoins * numbering system - * * @param bytes * @return */ @@ -36,7 +34,7 @@ trait NumberUtil extends BitcoinSLogger { } else parseLong(reversedBytes) } else { //remove the sign bit - val removedSignBit : List[Byte] = changeSignBitToPositive(reversedBytes.toList) + val removedSignBit = changeSignBitToPositive(reversedBytes.toList) if (firstByteAllZeros(removedSignBit)) -parseLong(removedSignBit.slice(1,removedSignBit.size)) else -parseLong(removedSignBit) } @@ -45,7 +43,6 @@ trait NumberUtil extends BitcoinSLogger { /** * Converts a long number to the representation of number inside of Bitcoin's number system - * * @param long * @return */ @@ -56,7 +53,7 @@ trait NumberUtil extends BitcoinSLogger { } else { val bytes = toByteSeq(long.abs) //add sign bit - val negativeNumberBytes : List[Byte] = changeSignBitToNegative(bytes.toList) + val negativeNumberBytes = changeSignBitToNegative(bytes) val hex = BitcoinSUtil.encodeHex(negativeNumberBytes.reverse) hex } @@ -64,7 +61,6 @@ trait NumberUtil extends BitcoinSLogger { /** * Determines if a given hex string is a positive number - * * @param hex * @return */ @@ -72,7 +68,6 @@ trait NumberUtil extends BitcoinSLogger { /** * Determines if a byte array is a positive or negative number - * * @param bytes * @return */ @@ -87,34 +82,34 @@ trait NumberUtil extends BitcoinSLogger { def isNegative(hex : String) : Boolean = isNegative(BitcoinSUtil.decodeHex(hex)) - def isNegative(bytes : List[Byte]) : Boolean = { + def isNegative(bytes : Seq[Byte]) : Boolean = { if (bytes.isEmpty) false else !isPositive(bytes) } /** * Change sign bit to positive - * * @param bytes * @return */ - def changeSignBitToPositive(bytes : List[Byte]) : List[Byte] = { + def changeSignBitToPositive(bytes : Seq[Byte]) : Seq[Byte] = { val newByte : Byte = (bytes.head & 0x7F).toByte - newByte :: bytes.tail + (newByte :: bytes.tail.toList) } - def changeSignBitToPositive(hex : String) : List[Byte] = changeSignBitToPositive(BitcoinSUtil.decodeHex(hex)) + def changeSignBitToPositive(hex : String) : Seq[Byte] = changeSignBitToPositive(BitcoinSUtil.decodeHex(hex)) - def changeSignBitToNegative(bytes : List[Byte]) : List[Byte] = { + + def changeSignBitToNegative(bytes : Seq[Byte]) : Seq[Byte] = { val newByte = (bytes.head | 0x80).toByte - (newByte :: bytes.tail) + (newByte :: bytes.tail.toList) } - def changeSignBitToNegative(hex : String) : List[Byte] = changeSignBitToNegative(BitcoinSUtil.decodeHex(hex)) + def changeSignBitToNegative(hex : String) : Seq[Byte] = changeSignBitToNegative(BitcoinSUtil.decodeHex(hex)) def firstByteAllZeros(hex : String) : Boolean = firstByteAllZeros(BitcoinSUtil.decodeHex(hex)) - def firstByteAllZeros(bytes : List[Byte]) : Boolean = { + def firstByteAllZeros(bytes : Seq[Byte]) : Boolean = { val lastByte = bytes.head (lastByte & 0xFF) == 0 } @@ -126,7 +121,6 @@ trait NumberUtil extends BitcoinSLogger { /** * Parses a VarInt from a string of hex characters * https://bitcoin.org/en/developer-reference#compactsize-unsigned-integers - * * @param hex * @return */ @@ -135,7 +129,6 @@ trait NumberUtil extends BitcoinSLogger { /** * Parses a CompactSizeUInt from a sequence of bytes * https://bitcoin.org/en/developer-reference#compactsize-unsigned-integers - * * @param bytes * @return */ @@ -154,7 +147,6 @@ trait NumberUtil extends BitcoinSLogger { /** * Returns the size of a VarInt in the number of bytes * https://en.bitcoin.it/wiki/Protocol_documentation#Variable_length_integer - * * @param byte * @return */ @@ -173,7 +165,6 @@ trait NumberUtil extends BitcoinSLogger { /** * Parses the compact size uint from a script signature * https://bitcoin.org/en/developer-reference#compactsize-unsigned-integers - * * @param script * @return */ @@ -191,7 +182,6 @@ trait NumberUtil extends BitcoinSLogger { /** * Parses a compact size uint from a script pubkey * https://bitcoin.org/en/developer-reference#compactsize-unsigned-integers - * * @param scriptPubKey * @return */ diff --git a/src/test/scala/org/bitcoins/core/crypto/DERSignatureUtilTest.scala b/src/test/scala/org/bitcoins/core/crypto/DERSignatureUtilTest.scala index da06df4cd3..bff38e20b0 100644 --- a/src/test/scala/org/bitcoins/core/crypto/DERSignatureUtilTest.scala +++ b/src/test/scala/org/bitcoins/core/crypto/DERSignatureUtilTest.scala @@ -8,9 +8,9 @@ import org.scalatest.{FlatSpec, MustMatchers} */ class DERSignatureUtilTest extends FlatSpec with MustMatchers { - val p2shSignature = ECFactory.digitalSignature("304402205b7d2c2f177ae76cfbbf14d589c113b0b35db753d305d5562dd0b61cbf366cfb02202e56f93c4f08a27f986cd424ffc48a462c3202c4902104d4d0ff98ed28f4bf8001") - val p2pkhSignature = ECFactory.digitalSignature("3044022016ffdbb7c57634903c5e018fcfc48d59f4e37dc4bc3bbc9ba4e6ee39150bca030220119c2241a931819bc1a75d3596e4029d803d1cd6de123bf8a1a1a2c3665e1fac01") - val p2pkSignature = ECFactory.digitalSignature("304402200a5c6163f07b8d3b013c4d1d6dba25e780b39658d79ba37af7057a3b7f15ffa102201fd9b4eaa9943f734928b99a83592c2e7bf342ea2680f6a2bb705167966b742001") + val p2shSignature = ECDigitalSignature("304402205b7d2c2f177ae76cfbbf14d589c113b0b35db753d305d5562dd0b61cbf366cfb02202e56f93c4f08a27f986cd424ffc48a462c3202c4902104d4d0ff98ed28f4bf8001") + val p2pkhSignature = ECDigitalSignature("3044022016ffdbb7c57634903c5e018fcfc48d59f4e37dc4bc3bbc9ba4e6ee39150bca030220119c2241a931819bc1a75d3596e4029d803d1cd6de123bf8a1a1a2c3665e1fac01") + val p2pkSignature = ECDigitalSignature("304402200a5c6163f07b8d3b013c4d1d6dba25e780b39658d79ba37af7057a3b7f15ffa102201fd9b4eaa9943f734928b99a83592c2e7bf342ea2680f6a2bb705167966b742001") "DERSignatureUtil" must "say that a signature taken from a p2sh transaction is a valid DER encoded signature" in { DERSignatureUtil.isDEREncoded(p2shSignature) must be (true) } @@ -56,18 +56,18 @@ class DERSignatureUtilTest extends FlatSpec with MustMatchers { } it must "say that the empty signature is a valid strictly encoded DER signature" in { - DERSignatureUtil.isStrictDEREncoding(ECFactory.digitalSignature("")) must be (true) + DERSignatureUtil.isStrictDEREncoding(ECDigitalSignature("")) must be (true) DERSignatureUtil.isStrictDEREncoding(EmptyDigitalSignature) must be (true) } it must "say that an overly long signature is NOT strict der encoded" in { - val sig = ECFactory.digitalSignature("0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") + val sig = ECDigitalSignature("0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") DERSignatureUtil.isStrictDEREncoding(sig) must be (false) } it must "determine if a signature is encoded with a low s value" in { - val highS = ECFactory.digitalSignature("304502203e4516da7253cf068effec6b95c41221c0cf3a8e6ccb8cbf1725b562e9afde2c022100ab1e3da73d67e32045a20e0b999e049978ea8d6ee5480d485fcf2ce0d03b2ef001".toLowerCase) + val highS = ECDigitalSignature("304502203e4516da7253cf068effec6b95c41221c0cf3a8e6ccb8cbf1725b562e9afde2c022100ab1e3da73d67e32045a20e0b999e049978ea8d6ee5480d485fcf2ce0d03b2ef001".toLowerCase) DERSignatureUtil.isLowDerSignature(highS) must be (false) } } diff --git a/src/test/scala/org/bitcoins/core/crypto/ECDigitalSignatureTest.scala b/src/test/scala/org/bitcoins/core/crypto/ECDigitalSignatureTest.scala index 0dd8f609dd..18a6867754 100644 --- a/src/test/scala/org/bitcoins/core/crypto/ECDigitalSignatureTest.scala +++ b/src/test/scala/org/bitcoins/core/crypto/ECDigitalSignatureTest.scala @@ -9,23 +9,23 @@ class ECDigitalSignatureTest extends FlatSpec with MustMatchers { "ECDigitalSignature" must "say that empty signature is a valid DER encoded signature" in { - val emptySiganture = ECFactory.digitalSignature(Seq()) + val emptySiganture = ECDigitalSignature(Seq()) emptySiganture.isDEREncoded must be (true) } it must "say that a signature taken from a p2sh transaction is a valid DER encoded signature" in { - val signature = ECFactory.digitalSignature("304402205b7d2c2f177ae76cfbbf14d589c113b0b35db753d305d5562dd0b61cbf366cfb02202e56f93c4f08a27f986cd424ffc48a462c3202c4902104d4d0ff98ed28f4bf8001") + val signature = ECDigitalSignature("304402205b7d2c2f177ae76cfbbf14d589c113b0b35db753d305d5562dd0b61cbf366cfb02202e56f93c4f08a27f986cd424ffc48a462c3202c4902104d4d0ff98ed28f4bf8001") signature.isDEREncoded must be (true) } it must "say that signature taken from a p2pkh transaction is a valid DER encoded signature" in { - val signature = ECFactory.digitalSignature("3044022016ffdbb7c57634903c5e018fcfc48d59f4e37dc4bc3bbc9ba4e6ee39150bca030220119c2241a931819bc1a75d3596e4029d803d1cd6de123bf8a1a1a2c3665e1fac01") + val signature = ECDigitalSignature("3044022016ffdbb7c57634903c5e018fcfc48d59f4e37dc4bc3bbc9ba4e6ee39150bca030220119c2241a931819bc1a75d3596e4029d803d1cd6de123bf8a1a1a2c3665e1fac01") signature.isDEREncoded must be (true) } it must "say that a signature taken from a p2pk transaction is a valid DER encoded signature" in { - val signature = ECFactory.digitalSignature("304402200a5c6163f07b8d3b013c4d1d6dba25e780b39658d79ba37af7057a3b7f15ffa102201fd9b4eaa9943f734928b99a83592c2e7bf342ea2680f6a2bb705167966b742001") + val signature = ECDigitalSignature("304402200a5c6163f07b8d3b013c4d1d6dba25e780b39658d79ba37af7057a3b7f15ffa102201fd9b4eaa9943f734928b99a83592c2e7bf342ea2680f6a2bb705167966b742001") signature.isDEREncoded must be (true) } @@ -33,4 +33,23 @@ class ECDigitalSignatureTest extends FlatSpec with MustMatchers { EmptyDigitalSignature.r must be (0) EmptyDigitalSignature.s must be (0) } + + + it must "create a digital signature from it's r,s components" in { + //from the tx 44e504f5b7649d215be05ad9f09026dee95201244a3b218013c504a6a49a26ff + val rawDigitalSignature = "3044022040f91c48f4011bf2e2edb6621bfa8fb802241de939cb86f1872c99c580ef0fe402204fc27388bc525e1b655b5f5b35f9d601d28602432dd5672f29e0a47f5b8bbb26" + val digitalSignature = ECDigitalSignature(rawDigitalSignature) + val (r,s) = (digitalSignature.r, digitalSignature.s) + val digitalSignatureFromRS = ECDigitalSignature(r,s) + digitalSignatureFromRS must be (digitalSignature) + } + + + it must "create an empty digital signature when given 0 in hex or byte format" in { + val hex = ECDigitalSignature("00") + val byte = ECDigitalSignature(Seq(0.toByte)) + val emptySignature = ECDigitalSignature("") + byte must be (emptySignature) + hex must be (emptySignature) + } } diff --git a/src/test/scala/org/bitcoins/core/crypto/ECPrivateKeyTest.scala b/src/test/scala/org/bitcoins/core/crypto/ECPrivateKeyTest.scala index a9eb79cfd0..09b45880de 100644 --- a/src/test/scala/org/bitcoins/core/crypto/ECPrivateKeyTest.scala +++ b/src/test/scala/org/bitcoins/core/crypto/ECPrivateKeyTest.scala @@ -1,7 +1,7 @@ package org.bitcoins.core.crypto -import org.bitcoins.core.util.{BitcoinSUtil, CryptoTestUtil} -import org.scalatest.{MustMatchers, FlatSpec} +import org.bitcoins.core.util.{BitcoinJTestUtil, BitcoinSUtil, CryptoTestUtil} +import org.scalatest.{FlatSpec, MustMatchers} /** * Created by chris on 3/7/16. @@ -11,15 +11,57 @@ class ECPrivateKeyTest extends FlatSpec with MustMatchers { "ECPrivateKey" must "have the same byte representation as a bitcoinj private key" in { val bitcoinjPrivateKey = CryptoTestUtil.bitcoinjPrivateKey.getPrivateKeyAsHex CryptoTestUtil.privateKey.hex must be (bitcoinjPrivateKey) - } - - it must "derive the same public from a private key as bitcoinj" in { val bitcoinjPublicKeyBytes = CryptoTestUtil.bitcoinjPrivateKey.getPubKey CryptoTestUtil.privateKey.publicKey.hex must be (BitcoinSUtil.encodeHex(bitcoinjPublicKeyBytes)) + } + + it must "create a bitcoin-s private key from a bitcoinj private key, then convert to the same public key" in { + val bitcoinjKey = new org.bitcoinj.core.ECKey() + val bitcoinsPrivKey = ECPrivateKey(bitcoinjKey.getSecretBytes) + val bitcoinsPublicKey = bitcoinsPrivKey.publicKey + val bitcoinjPublicKey = bitcoinjKey.getPubKey + + bitcoinsPublicKey.bytes must be (bitcoinjPublicKey) + } + + it must "create a bitcionj private key from a bitcoins private key and get the same public key" in { + val bitcoinsPrivKey = ECPrivateKey.freshPrivateKey + val bitcoinjPrivKey = org.bitcoinj.core.ECKey.fromPrivate(bitcoinsPrivKey.bytes.toArray) + val bitcoinjPublicKey = bitcoinjPrivKey.getPubKey + val bitcoinsPublicKey = bitcoinsPrivKey.publicKey + + bitcoinsPublicKey.bytes must be (bitcoinjPublicKey) + } + + it must "create a private key from the dumped base58 in bitcoin-cli" in { + val privateKeyBase58 = CryptoTestUtil.privateKeyBase58 + val bitcoinjDumpedPrivateKey = new org.bitcoinj.core.DumpedPrivateKey(BitcoinJTestUtil.params,privateKeyBase58) + val bitcoinjPrivateKey = bitcoinjDumpedPrivateKey.getKey + val privateKey = ECPrivateKey.fromBase58ToPrivateKey(privateKeyBase58) + + privateKey.hex must be (bitcoinjPrivateKey.getPrivateKeyAsHex) } + it must "create a private key from a sequence of bytes that has the same byte representation of bitcoinj ECKeys" in { + val bytes = CryptoTestUtil.bitcoinjPrivateKey.getPrivKeyBytes.toList + val bitcoinJKey = org.bitcoinj.core.ECKey.fromPrivate(bytes.toArray) + val privateKey : ECPrivateKey = ECPrivateKey(bytes) + privateKey.hex must be (bitcoinJKey.getPrivateKeyAsHex) + } + + it must "create a private key from bytes" in { + val privKeyBytes = Seq(0.toByte) + ECPrivateKey(privKeyBytes).bytes must be (privKeyBytes) + } + + it must "create a private key from its hex representation" in { + val privateKeyHex = "180cb41c7c600be951b5d3d0a7334acc7506173875834f7a6c4c786a28fcbb19" + val key: ECPrivateKey = ECPrivateKey(privateKeyHex) + key.hex must be (privateKeyHex) + } + } diff --git a/src/test/scala/org/bitcoins/core/crypto/ECPublicKeyTest.scala b/src/test/scala/org/bitcoins/core/crypto/ECPublicKeyTest.scala index 0eba779d86..3ac3b4d23e 100644 --- a/src/test/scala/org/bitcoins/core/crypto/ECPublicKeyTest.scala +++ b/src/test/scala/org/bitcoins/core/crypto/ECPublicKeyTest.scala @@ -1,5 +1,7 @@ package org.bitcoins.core.crypto +import java.math.BigInteger + import org.bitcoinj.core.Sha256Hash import org.bitcoins.core.util.BitcoinSUtil import org.scalatest.{FlatSpec, MustMatchers} @@ -12,23 +14,41 @@ class ECPublicKeyTest extends FlatSpec with MustMatchers { "ECPublicKey" must "verify that a arbitrary piece of data was signed by the private key corresponding to a public key" in { val privateKeyHex = "180cb41c7c600be951b5d3d0a7334acc7506173875834f7a6c4c786a28fcbb19" - val key: ECPrivateKey = ECFactory.privateKey(privateKeyHex) + val key: ECPrivateKey = ECPrivateKey(privateKeyHex) + val signature: ECDigitalSignature = key.sign(Sha256Hash.ZERO_HASH.getBytes.toSeq) - val isValid : Boolean = key.publicKey.verify(Sha256Hash.ZERO_HASH.getBytes.toSeq,signature) - isValid must be (true) + val isValid : Boolean = key.publicKey.verify(Sha256Hash.ZERO_HASH.getBytes.toSeq,signature) + isValid must be (true) } it must "fail to verify a piece of data if the wrong public key is given" in { val privateKeyHex = "180cb41c7c600be951b5d3d0a7334acc7506173875834f7a6c4c786a28fcbb19" - val key: ECPrivateKey = ECFactory.privateKey(privateKeyHex) + val key: ECPrivateKey = ECPrivateKey(privateKeyHex) val signature: ECDigitalSignature = key.sign(Sha256Hash.ZERO_HASH.getBytes.toSeq) - val wrongPublicKey = ECFactory.publicKey + val wrongPublicKey = ECPublicKey.freshPublicKey val isValid : Boolean = wrongPublicKey.verify(Sha256Hash.ZERO_HASH.getBytes.toSeq,signature) isValid must be (false) } + it must "verify a piece of data signed with a bitcoinj private key" in { + val bitcoinjPrivKey = new org.bitcoinj.core.ECKey + val bitcoinjSignature = bitcoinjPrivKey.sign(Sha256Hash.ZERO_HASH) + val bitcoinsSignature = ECDigitalSignature(bitcoinjSignature.encodeToDER()) + val bitcoinsPublicKey = ECPublicKey(bitcoinjPrivKey.getPubKey) + bitcoinsPublicKey.verify(Sha256Hash.ZERO_HASH.getBytes, bitcoinsSignature) must be (true) + + } + + + it must "verify a piece of data was signed with a bitcoins private key inside of bitcoinj" in { + val bitcoinsPrivKey = ECPrivateKey.freshPrivateKey + val bitcoinsSignature = bitcoinsPrivKey.sign(Sha256Hash.ZERO_HASH.getBytes) + val bitcoinjPublicKey = org.bitcoinj.core.ECKey.fromPublicOnly(bitcoinsPrivKey.publicKey.bytes.toArray) + bitcoinjPublicKey.verify(Sha256Hash.ZERO_HASH.getBytes, bitcoinsSignature.bytes.toArray) must be (true) + } + } diff --git a/src/test/scala/org/bitcoins/core/protocol/AddressFactoryTest.scala b/src/test/scala/org/bitcoins/core/protocol/AddressFactoryTest.scala index c2df6f3040..fca8b4382b 100644 --- a/src/test/scala/org/bitcoins/core/protocol/AddressFactoryTest.scala +++ b/src/test/scala/org/bitcoins/core/protocol/AddressFactoryTest.scala @@ -1,6 +1,6 @@ package org.bitcoins.core.protocol -import org.bitcoins.core.util.{BitcoinSUtil, TestUtil} +import org.bitcoins.core.util.{Base58, BitcoinSUtil, TestUtil} import org.scalatest.{FlatSpec, MustMatchers} /** @@ -13,12 +13,12 @@ class AddressFactoryTest extends FlatSpec with MustMatchers { } it must "create an address from a sequence of bytes" in { - Address(BitcoinSUtil.decodeBase58(TestUtil.bitcoinAddress.value)) must be (TestUtil.bitcoinAddress) + Address(Base58.decode(TestUtil.bitcoinAddress.value)) must be (TestUtil.bitcoinAddress) } it must "create an asset address from a base58 encoded string" in { - Address(BitcoinSUtil.decodeBase58(TestUtil.assetAddress.value)) must be (TestUtil.assetAddress) + Address(Base58.decode(TestUtil.assetAddress.value)) must be (TestUtil.assetAddress) } it must "throw an exception if the given string" in { diff --git a/src/test/scala/org/bitcoins/core/protocol/AddressTest.scala b/src/test/scala/org/bitcoins/core/protocol/AddressTest.scala index 28f8b0c848..817af39134 100644 --- a/src/test/scala/org/bitcoins/core/protocol/AddressTest.scala +++ b/src/test/scala/org/bitcoins/core/protocol/AddressTest.scala @@ -1,12 +1,12 @@ package org.bitcoins.core.protocol -import org.bitcoins.core.util.TestUtil +import org.bitcoins.core.util.{BitcoinSLogger, TestUtil} import org.scalatest.{FlatSpec, MustMatchers} /** * Created by chris on 3/23/15. */ -class AddressTest extends FlatSpec with MustMatchers { +class AddressTest extends FlatSpec with MustMatchers with BitcoinSLogger { val assetAddress = TestUtil.assetAddress "Addresses" must "be able to convert back and forth between a Bitcoin Address & an asset address" in { val convertedOnce = BitcoinAddress.convertToAssetAddress(TestUtil.bitcoinAddress) diff --git a/src/test/scala/org/bitcoins/core/protocol/script/MultiSignatureScriptPubKeyTest.scala b/src/test/scala/org/bitcoins/core/protocol/script/MultiSignatureScriptPubKeyTest.scala index 22bc3d6e48..b425dd2c0f 100644 --- a/src/test/scala/org/bitcoins/core/protocol/script/MultiSignatureScriptPubKeyTest.scala +++ b/src/test/scala/org/bitcoins/core/protocol/script/MultiSignatureScriptPubKeyTest.scala @@ -1,7 +1,7 @@ package org.bitcoins.core.protocol.script -import org.bitcoins.core.crypto.ECFactory -import org.scalatest.{MustMatchers, FlatSpec} +import org.bitcoins.core.crypto.ECPublicKey +import org.scalatest.{FlatSpec, MustMatchers} /** * Created by chris on 3/8/16. @@ -36,9 +36,9 @@ class MultiSignatureScriptPubKeyTest extends FlatSpec with MustMatchers { } multiSigScriptPubKey.publicKeys must be (Seq( - ECFactory.publicKey("025878e270211662a27181cf4d6ad4d2cf0e69a98a3815c086f587c7e9388d8718"), - ECFactory.publicKey("03fc85980e3fac1f3d8a5c3223c3ef5bffc1bd42d2cc42add8c3899cc66e7f1906"), - ECFactory.publicKey("0215b5bd050869166a70a7341b4f216e268b7c6c7504576dcea2cce7d11cc9a35f") + ECPublicKey("025878e270211662a27181cf4d6ad4d2cf0e69a98a3815c086f587c7e9388d8718"), + ECPublicKey("03fc85980e3fac1f3d8a5c3223c3ef5bffc1bd42d2cc42add8c3899cc66e7f1906"), + ECPublicKey("0215b5bd050869166a70a7341b4f216e268b7c6c7504576dcea2cce7d11cc9a35f") )) } @@ -53,8 +53,8 @@ class MultiSignatureScriptPubKeyTest extends FlatSpec with MustMatchers { } multiSigScriptPubKey.publicKeys must be (Seq( - ECFactory.publicKey("02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0"), - ECFactory.publicKey("02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0") + ECPublicKey("02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0"), + ECPublicKey("02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0") )) } diff --git a/src/test/scala/org/bitcoins/core/protocol/script/MultiSignatureScriptSignatureTest.scala b/src/test/scala/org/bitcoins/core/protocol/script/MultiSignatureScriptSignatureTest.scala index 00ac9d7666..affbbbb7f8 100644 --- a/src/test/scala/org/bitcoins/core/protocol/script/MultiSignatureScriptSignatureTest.scala +++ b/src/test/scala/org/bitcoins/core/protocol/script/MultiSignatureScriptSignatureTest.scala @@ -1,7 +1,7 @@ package org.bitcoins.core.protocol.script -import org.bitcoins.core.crypto.{ECFactory, EmptyDigitalSignature} +import org.bitcoins.core.crypto.{ECDigitalSignature, EmptyDigitalSignature} import org.bitcoins.core.script.constant.{BytesToPushOntoStack, OP_0, ScriptConstant} import org.bitcoins.core.util.TransactionTestUtil import org.scalatest.{FlatSpec, MustMatchers} @@ -21,7 +21,7 @@ class MultiSignatureScriptSignatureTest extends FlatSpec with MustMatchers { val multiSigScriptSignature = ScriptSignature.fromAsm(List(OP_0, BytesToPushOntoStack(71), ScriptConstant("30440220b119d67d389315308d1745f734a51ff3ec72e06081e84e236fdf9dc2f5d2a64802204b04e3bc38674c4422ea317231d642b56dc09d214a1ecbbf16ecca01ed996e2201"), OP_0)) multiSigScriptSignature.signatures must be (Seq( - ECFactory.digitalSignature("30440220b119d67d389315308d1745f734a51ff3ec72e06081e84e236fdf9dc2f5d2a64802204b04e3bc38674c4422ea317231d642b56dc09d214a1ecbbf16ecca01ed996e2201"), + ECDigitalSignature("30440220b119d67d389315308d1745f734a51ff3ec72e06081e84e236fdf9dc2f5d2a64802204b04e3bc38674c4422ea317231d642b56dc09d214a1ecbbf16ecca01ed996e2201"), EmptyDigitalSignature)) } } diff --git a/src/test/scala/org/bitcoins/core/protocol/script/P2PKHScriptSignatureTest.scala b/src/test/scala/org/bitcoins/core/protocol/script/P2PKHScriptSignatureTest.scala index 8c6afe1676..538ee6deb9 100644 --- a/src/test/scala/org/bitcoins/core/protocol/script/P2PKHScriptSignatureTest.scala +++ b/src/test/scala/org/bitcoins/core/protocol/script/P2PKHScriptSignatureTest.scala @@ -1,6 +1,6 @@ package org.bitcoins.core.protocol.script -import org.bitcoins.core.crypto.ECFactory +import org.bitcoins.core.crypto.{ECDigitalSignature} import org.bitcoins.core.script.crypto.SIGHASH_ALL import org.bitcoins.core.util.TestUtil import org.scalatest.{FlatSpec, MustMatchers} @@ -23,7 +23,7 @@ class P2PKHScriptSignatureTest extends FlatSpec with MustMatchers { case s : P2PKHScriptSignature => s case _ => throw new RuntimeException("Must be p2pkh scriptSig") } - p2pkhScriptSig.signature must be (ECFactory.digitalSignature("3044022016ffdbb7c57634903c5e018fcfc48d59f4e37dc4bc3bbc9ba4e6ee39150bca030220119c2241a931819bc1a75d3596e4029d803d1cd6de123bf8a1a1a2c3665e1fac01")) + p2pkhScriptSig.signature must be (ECDigitalSignature("3044022016ffdbb7c57634903c5e018fcfc48d59f4e37dc4bc3bbc9ba4e6ee39150bca030220119c2241a931819bc1a75d3596e4029d803d1cd6de123bf8a1a1a2c3665e1fac01")) } } diff --git a/src/test/scala/org/bitcoins/core/protocol/script/P2PKScriptPubKeyTest.scala b/src/test/scala/org/bitcoins/core/protocol/script/P2PKScriptPubKeyTest.scala index b29af14517..c059069207 100644 --- a/src/test/scala/org/bitcoins/core/protocol/script/P2PKScriptPubKeyTest.scala +++ b/src/test/scala/org/bitcoins/core/protocol/script/P2PKScriptPubKeyTest.scala @@ -1,6 +1,6 @@ package org.bitcoins.core.protocol.script -import org.bitcoins.core.crypto.ECFactory +import org.bitcoins.core.crypto.{ECPublicKey} import org.bitcoins.core.util.TestUtil import org.scalatest.{FlatSpec, MustMatchers} @@ -15,6 +15,6 @@ class P2PKScriptPubKeyTest extends FlatSpec with MustMatchers { case _ => throw new RuntimeException("should have been p2pk script pub key") } - p2pkScriptPubKey.publicKey must be (ECFactory.publicKey("0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8")) + p2pkScriptPubKey.publicKey must be (ECPublicKey("0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8")) } } diff --git a/src/test/scala/org/bitcoins/core/protocol/script/P2PKScriptSignatureTest.scala b/src/test/scala/org/bitcoins/core/protocol/script/P2PKScriptSignatureTest.scala index 8a8b0b2a38..2e14d116ff 100644 --- a/src/test/scala/org/bitcoins/core/protocol/script/P2PKScriptSignatureTest.scala +++ b/src/test/scala/org/bitcoins/core/protocol/script/P2PKScriptSignatureTest.scala @@ -1,8 +1,8 @@ package org.bitcoins.core.protocol.script -import org.bitcoins.core.crypto.ECFactory +import org.bitcoins.core.crypto.{ECDigitalSignature} import org.bitcoins.core.util.TestUtil -import org.scalatest.{MustMatchers, FlatSpec} +import org.scalatest.{FlatSpec, MustMatchers} /** * Created by chris on 3/16/16. @@ -14,6 +14,6 @@ class P2PKScriptSignatureTest extends FlatSpec with MustMatchers { case s : P2PKScriptSignature => s case _ => throw new RuntimeException("SHould have been a p2pk scriptSig") } - p2pkScriptSig.signature must be (ECFactory.digitalSignature("304402200a5c6163f07b8d3b013c4d1d6dba25e780b39658d79ba37af7057a3b7f15ffa102201fd9b4eaa9943f734928b99a83592c2e7bf342ea2680f6a2bb705167966b742001")) + p2pkScriptSig.signature must be (ECDigitalSignature("304402200a5c6163f07b8d3b013c4d1d6dba25e780b39658d79ba37af7057a3b7f15ffa102201fd9b4eaa9943f734928b99a83592c2e7bf342ea2680f6a2bb705167966b742001")) } } diff --git a/src/test/scala/org/bitcoins/core/protocol/script/P2SHScriptSignatureTest.scala b/src/test/scala/org/bitcoins/core/protocol/script/P2SHScriptSignatureTest.scala index 050a9e1441..15ff45a8a7 100644 --- a/src/test/scala/org/bitcoins/core/protocol/script/P2SHScriptSignatureTest.scala +++ b/src/test/scala/org/bitcoins/core/protocol/script/P2SHScriptSignatureTest.scala @@ -1,7 +1,7 @@ package org.bitcoins.core.protocol.script -import org.bitcoins.core.crypto.ECFactory +import org.bitcoins.core.crypto.{ECPublicKey} import org.bitcoins.core.script.constant.{BytesToPushOntoStack, OP_0, ScriptConstant} import org.bitcoins.core.util.TestUtil import org.scalatest.{FlatSpec, MustMatchers} @@ -18,8 +18,8 @@ class P2SHScriptSignatureTest extends FlatSpec with MustMatchers { case y => throw new RuntimeException("Must be p2sh script sig: " + y) } p2shScriptSig.publicKeys must be (Seq( - ECFactory.publicKey("0369d26ebd086523384a0f89f293d4c327a65fa73332d8efd1097cb35231295b83"), - ECFactory.publicKey("02480863e5c4a4e9763f5380c44fcfe6a3b7787397076cf9ea1049303a9d34f721") + ECPublicKey("0369d26ebd086523384a0f89f293d4c327a65fa73332d8efd1097cb35231295b83"), + ECPublicKey("02480863e5c4a4e9763f5380c44fcfe6a3b7787397076cf9ea1049303a9d34f721") )) } diff --git a/src/test/scala/org/bitcoins/core/protocol/script/ScriptPubKeyTest.scala b/src/test/scala/org/bitcoins/core/protocol/script/ScriptPubKeyTest.scala index 31d318c613..53242b63dc 100644 --- a/src/test/scala/org/bitcoins/core/protocol/script/ScriptPubKeyTest.scala +++ b/src/test/scala/org/bitcoins/core/protocol/script/ScriptPubKeyTest.scala @@ -1,6 +1,5 @@ package org.bitcoins.core.protocol.script -import org.bitcoins.core.crypto.ECFactory import org.bitcoins.core.script.bitwise.OP_EQUALVERIFY import org.bitcoins.core.script.constant.{BytesToPushOntoStack, ScriptConstant, ScriptToken} import org.bitcoins.core.script.crypto.{OP_CHECKSIG, OP_CODESEPARATOR, OP_HASH160} diff --git a/src/test/scala/org/bitcoins/core/protocol/script/ScriptSignatureFactoryTest.scala b/src/test/scala/org/bitcoins/core/protocol/script/ScriptSignatureFactoryTest.scala index aa135704b4..81a881e953 100644 --- a/src/test/scala/org/bitcoins/core/protocol/script/ScriptSignatureFactoryTest.scala +++ b/src/test/scala/org/bitcoins/core/protocol/script/ScriptSignatureFactoryTest.scala @@ -33,9 +33,9 @@ class ScriptSignatureFactoryTest extends FlatSpec with MustMatchers { } it must "build a script signature from a digital signature and a public key" in { val digitalSignatureBytes = TestUtil.p2pkhInputScriptAsm(1).bytes - val digitalSignature : ECDigitalSignature = ECFactory.digitalSignature(digitalSignatureBytes) + val digitalSignature : ECDigitalSignature = ECDigitalSignature(digitalSignatureBytes) val publicKeyBytes = TestUtil.p2pkhInputScriptAsm(3).bytes - val publicKey : ECPublicKey = ECFactory.publicKey(publicKeyBytes) + val publicKey : ECPublicKey = ECPublicKey(publicKeyBytes) val actualScriptSig : ScriptSignature = ScriptSignature(digitalSignature,publicKey) actualScriptSig.asm must be (TestUtil.p2pkhInputScriptAsm) } diff --git a/src/test/scala/org/bitcoins/core/protocol/script/ScriptSignatureTest.scala b/src/test/scala/org/bitcoins/core/protocol/script/ScriptSignatureTest.scala index f6235b6dbb..7bcc1be931 100644 --- a/src/test/scala/org/bitcoins/core/protocol/script/ScriptSignatureTest.scala +++ b/src/test/scala/org/bitcoins/core/protocol/script/ScriptSignatureTest.scala @@ -1,11 +1,11 @@ package org.bitcoins.core.protocol.script -import org.bitcoins.core.crypto.ECFactory +import org.bitcoins.core.crypto.{ECDigitalSignature} import org.bitcoins.core.serializers.script.RawScriptSignatureParser import org.bitcoins.core.script.constant._ -import org.bitcoins.core.script.crypto.{SIGHASH_SINGLE, SIGHASH_ALL} -import org.bitcoins.core.util.{BitcoinScriptUtil, TransactionTestUtil, TestUtil} +import org.bitcoins.core.script.crypto.{SIGHASH_ALL, SIGHASH_SINGLE} +import org.bitcoins.core.util.{BitcoinScriptUtil, TestUtil, TransactionTestUtil} import org.scalatest.{FlatSpec, MustMatchers} /** @@ -32,8 +32,8 @@ class ScriptSignatureTest extends FlatSpec with MustMatchers { it must "find the digital signatures for a p2sh script signature for a 2/3 p2sh address" in { val scriptSig = TestUtil.p2shInputScript2Of2 scriptSig.signatures must be (Seq( - ECFactory.digitalSignature("304402207d764cb90c9fd84b74d33a47cf3a0ffead9ded98333776becd6acd32c4426dac02203905a0d064e7f53d07793e86136571b6e4f700c1cfb888174e84d78638335b8101"), - ECFactory.digitalSignature("3045022100906aaca39f022acd8b7a38fd2f92aca9e9f35cfeaee69a6f13e1d083ae18222602204c9ed96fc6c4de56fd85c679fc59c16ee1ccc80c42563b86174e1a506fc007c801") + ECDigitalSignature("304402207d764cb90c9fd84b74d33a47cf3a0ffead9ded98333776becd6acd32c4426dac02203905a0d064e7f53d07793e86136571b6e4f700c1cfb888174e84d78638335b8101"), + ECDigitalSignature("3045022100906aaca39f022acd8b7a38fd2f92aca9e9f35cfeaee69a6f13e1d083ae18222602204c9ed96fc6c4de56fd85c679fc59c16ee1ccc80c42563b86174e1a506fc007c801") )) } @@ -41,11 +41,11 @@ class ScriptSignatureTest extends FlatSpec with MustMatchers { val scriptSig = TestUtil.p2shInputScriptLargeSignature scriptSig.signatures must be (Seq( - ECFactory.digitalSignature("3045022100a077d4fe9a81411ecb796c254d8b4e0bc73ff86a42288bc3b3ecfa1ef26c00dd02202389bf96cf38c14c3a6ccb8c688339f3fd880b724322862547a8ee3b547a9df901"), - ECFactory.digitalSignature("304402207c0692464998e7f3869f8501cdd25bbcd9d32b6fd34ae8aeae643b422a8dfd42022057eb16f8ca1f34e88babc9f8beb4c2521eb5c4dea41f8902a70d045f1c132a4401"), - ECFactory.digitalSignature("3044022024233923253c73569f4b34723a5495698bc124b099c5542a5997d13fba7d18a802203c317bddc070276c6f6c79cb3415413e608af30e4759e31b0d53eab3ca0acd4e01"), - ECFactory.digitalSignature("30450221009b9f0d8b945717d2fca3685093d547a3928d122b8894903ed51e2248303213bc022008b376422c9f2cd713b9d10b5b106d1c56c5893dcc01ae300253ed2234bdb63f01"), - ECFactory.digitalSignature("30440220257b57cb09386d82c4328461f8fe200c2f381d6b635e2a2f4ea40c8d945e9ec102201ec67d58d51a309af4d8896e9147a42944e9f9833a456f733ea5fa6954ed2fed01") + ECDigitalSignature("3045022100a077d4fe9a81411ecb796c254d8b4e0bc73ff86a42288bc3b3ecfa1ef26c00dd02202389bf96cf38c14c3a6ccb8c688339f3fd880b724322862547a8ee3b547a9df901"), + ECDigitalSignature("304402207c0692464998e7f3869f8501cdd25bbcd9d32b6fd34ae8aeae643b422a8dfd42022057eb16f8ca1f34e88babc9f8beb4c2521eb5c4dea41f8902a70d045f1c132a4401"), + ECDigitalSignature("3044022024233923253c73569f4b34723a5495698bc124b099c5542a5997d13fba7d18a802203c317bddc070276c6f6c79cb3415413e608af30e4759e31b0d53eab3ca0acd4e01"), + ECDigitalSignature("30450221009b9f0d8b945717d2fca3685093d547a3928d122b8894903ed51e2248303213bc022008b376422c9f2cd713b9d10b5b106d1c56c5893dcc01ae300253ed2234bdb63f01"), + ECDigitalSignature("30440220257b57cb09386d82c4328461f8fe200c2f381d6b635e2a2f4ea40c8d945e9ec102201ec67d58d51a309af4d8896e9147a42944e9f9833a456f733ea5fa6954ed2fed01") )) } it must "find the hash type for a p2sh script signature" in { @@ -88,5 +88,4 @@ class ScriptSignatureTest extends FlatSpec with MustMatchers { scriptSig.isInstanceOf[P2PKScriptSignature] must be (true) scriptSig.hex must be (TestUtil.p2pkScriptSig.hex) } - } diff --git a/src/test/scala/org/bitcoins/core/script/constant/ConstantInterpreterTest.scala b/src/test/scala/org/bitcoins/core/script/constant/ConstantInterpreterTest.scala index 8cdfd71f6c..2a854229b3 100644 --- a/src/test/scala/org/bitcoins/core/script/constant/ConstantInterpreterTest.scala +++ b/src/test/scala/org/bitcoins/core/script/constant/ConstantInterpreterTest.scala @@ -22,7 +22,6 @@ class ConstantInterpreterTest extends FlatSpec with MustMatchers with ConstantIn val script = List(OP_PUSHDATA1,ScriptNumber(byteConstantSize), scriptConstant,OP_7,OP_EQUAL) val program = ScriptProgram(TestUtil.testProgramExecutionInProgress, stack,script) val newProgram = opPushData1(program) - println(newProgram) newProgram.stack must be (List(scriptConstant)) newProgram.script must be (List(OP_7,OP_EQUAL)) } diff --git a/src/test/scala/org/bitcoins/core/script/interpreter/ScriptInterpreterTest.scala b/src/test/scala/org/bitcoins/core/script/interpreter/ScriptInterpreterTest.scala index 9a7bb86258..cb3e99570d 100644 --- a/src/test/scala/org/bitcoins/core/script/interpreter/ScriptInterpreterTest.scala +++ b/src/test/scala/org/bitcoins/core/script/interpreter/ScriptInterpreterTest.scala @@ -17,7 +17,7 @@ import org.bitcoins.core.util._ import org.scalatest.{FlatSpec, MustMatchers} import org.slf4j.LoggerFactory import CoreTestCaseProtocol._ -import org.bitcoins.core.crypto.{ECFactory, TransactionSignatureSerializer} +import org.bitcoins.core.crypto.{TransactionSignatureSerializer} import org.bitcoins.core.policy.Policy import org.bitcoins.core.protocol.transaction.Transaction import org.bitcoins.core.protocol.transaction.testprotocol.CoreTransactionTestCase diff --git a/src/test/scala/org/bitcoins/core/script/interpreter/testprotocol/ScriptPubKeyCoreTestCase.scala b/src/test/scala/org/bitcoins/core/script/interpreter/testprotocol/ScriptPubKeyCoreTestCase.scala new file mode 100644 index 0000000000..44c7514ded --- /dev/null +++ b/src/test/scala/org/bitcoins/core/script/interpreter/testprotocol/ScriptPubKeyCoreTestCase.scala @@ -0,0 +1,32 @@ +package org.bitcoins.core.script.interpreter.testprotocol + +import org.bitcoins.core.protocol.script.ScriptPubKey +import org.bitcoins.core.script.constant.ScriptToken + +/** + * Created by chris on 3/14/16. + */ +trait ScriptPubKeyCoreTestCase { + /** + * The parsed asm representation for the core test case + * this will be different than the asm representation + * inside of scriptPubKey + * + * @return + */ + def asm : Seq[ScriptToken] + + /** + * This is the underlying scriptPubKey that is parsed from the core test case + * this is needed because there is no ubiquitous formats for scriptPubKeys + * inside of script_valid.json. Normal scriptPubKeys have their asm representation + * parsed from the underlying hex/byte representation every time which won't work + * for core test cases. + * + * @return + */ + def scriptPubKey : ScriptPubKey +} + + +case class ScriptPubKeyCoreTestCaseImpl(asm : Seq[ScriptToken], scriptPubKey : ScriptPubKey) extends ScriptPubKeyCoreTestCase \ No newline at end of file diff --git a/src/test/scala/org/bitcoins/core/script/interpreter/testprotocol/ScriptSignatureCoreTestCase.scala b/src/test/scala/org/bitcoins/core/script/interpreter/testprotocol/ScriptSignatureCoreTestCase.scala new file mode 100644 index 0000000000..a78d6dadbd --- /dev/null +++ b/src/test/scala/org/bitcoins/core/script/interpreter/testprotocol/ScriptSignatureCoreTestCase.scala @@ -0,0 +1,32 @@ +package org.bitcoins.core.script.interpreter.testprotocol + +import org.bitcoins.core.protocol.script.{ScriptSignature, ScriptPubKey} +import org.bitcoins.core.script.constant.ScriptToken + +/** + * Created by chris on 3/14/16. + */ +trait ScriptSignatureCoreTestCase { + /** + * The parsed asm representation for the core test case + * this will be different than the asm representation + * inside of scriptSignature + * + * @return + */ + def asm : Seq[ScriptToken] + + /** + * This is the underlying scriptSignature that is parsed from the core test case + * this is needed because there is no ubiquitous formats for scriptSignatures + * inside of script_valid.json. Normal scriptSignatures have their asm representation + * parsed from the underlying hex/byte representation every time which won't work + * for core test cases. + * + * @return + */ + def scriptSignature : ScriptSignature + +} + +case class ScriptSignatureCoreTestCaseImpl(asm : Seq[ScriptToken], scriptSignature : ScriptSignature) extends ScriptSignatureCoreTestCase diff --git a/src/test/scala/org/bitcoins/core/serializers/script/ScriptParserTest.scala b/src/test/scala/org/bitcoins/core/serializers/script/ScriptParserTest.scala index 6047d7dcf0..b68f9e4cc0 100644 --- a/src/test/scala/org/bitcoins/core/serializers/script/ScriptParserTest.scala +++ b/src/test/scala/org/bitcoins/core/serializers/script/ScriptParserTest.scala @@ -50,7 +50,7 @@ class ScriptParserTest extends FlatSpec with MustMatchers with ScriptParser with } it must "parse a p2pkh output script from a byte array to script tokens" in { - val bytes : List[Byte] = decodeHex(TestUtil.p2pkhOutputScript) + val bytes : Seq[Byte] = decodeHex(TestUtil.p2pkhOutputScript) fromBytes(bytes) must be (TestUtil.p2pkhOutputScriptAsm) } @@ -133,79 +133,83 @@ class ScriptParserTest extends FlatSpec with MustMatchers with ScriptParser with } - it must "parse bytes from a string" in { - val str = "0xFF00" - parseBytesFromString(str) must be (List(ScriptNumber(255))) - } - - it must "parse an OP_PUSHDATA2 correctly" in { - val str = "0x4d 0xFF00 " + - "0x111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 " + - "0x4c 0xFF 0x111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 " + - "EQUAL" - val expectedScript = List(OP_PUSHDATA2, ScriptConstant("ff00"), - ScriptConstant("111111111111111111111111111111111111111111111111111111111111111111111111111111111111111" + - "11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111" + - "11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111" + - "11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111" + - "11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111" + - "1111111"), OP_PUSHDATA1, ScriptConstant("ff"), - ScriptConstant("111111111111111111111111111111111111111111111111111111111111111111111111111111111111111" + - "11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111" + - "11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111" + - "11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111" + - "11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111" + - "1111111"), OP_EQUAL) - - fromString(str) must be (expectedScript) - } - - it must "parse a hex string to a list of script tokens, and then back again" in { - //from this question - //https://bitcoin.stackexchange.com/questions/37125/how-are-sighash-flags-encoded-into-a-signature - val hex = "304402206e3729f021476102a06ea453cea0a26cb9c096cca641efc4229c1111ed3a96fd022037dce1456a93f53d3e868c789b1b750a48a4c1110cd5b7049779b5f4f3c8b6200103ff1104b46b2141df1948dd0df2223720a3a471ec57404cace47063843a699a0f" - - val scriptTokens : Seq[ScriptToken] = fromHex(hex) - scriptTokens.map(_.hex).mkString must be (hex) - } + it must "parse bytes from a string" in { + val str = "0xFF00" + parseBytesFromString(str) must be (List(ScriptNumber(255))) + } - it must "parse a p2pkh scriptSig properly" in { - //from b30d3148927f620f5b1228ba941c211fdabdae75d0ba0b688a58accbf018f3cc - val rawScriptSig = "4730440220048e15422cf62349dc586ffb8c749d40280781edd5064ff27a5910ff5cf225a802206a82685dbc2cf195d158c29309939d5a3cd41a889db6f766f3809fff35722305012103dcfc9882c1b3ae4e03fb6cac08bdb39e284e81d70c7aa8b27612457b2774509b" + it must "parse an OP_PUSHDATA2 correctly" in { + val str = "0x4d 0xFF00 " + + "0x111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 " + + "0x4c 0xFF 0x111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 " + + "EQUAL" + val expectedScript = List(OP_PUSHDATA2, ScriptConstant("ff00"), + ScriptConstant("111111111111111111111111111111111111111111111111111111111111111111111111111111111111111" + + "11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111" + + "11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111" + + "11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111" + + "11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111" + + "1111111"), OP_PUSHDATA1, ScriptConstant("ff"), + ScriptConstant("111111111111111111111111111111111111111111111111111111111111111111111111111111111111111" + + "11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111" + + "11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111" + + "11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111" + + "11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111" + + "1111111"), OP_EQUAL) - val expectedAsm = List(BytesToPushOntoStack(71), - ScriptConstant("30440220048e15422cf62349dc586ffb8c749d40280781edd5064ff27a5910ff5cf" + - "225a802206a82685dbc2cf195d158c29309939d5a3cd41a889db6f766f3809fff3572230501"), - BytesToPushOntoStack(33), - ScriptConstant("03dcfc9882c1b3ae4e03fb6cac08bdb39e284e81d70c7aa8b27612457b2774509b")) + fromString(str) must be (expectedScript) + } - val scriptTokens : List[ScriptToken] = ScriptParser.fromHex(rawScriptSig) + it must "parse a hex string to a list of script tokens, and then back again" in { + //from this question + //https://bitcoin.stackexchange.com/questions/37125/how-are-sighash-flags-encoded-into-a-signature + val hex = "304402206e3729f021476102a06ea453cea0a26cb9c096cca641efc4229c1111ed3a96fd022037dce1456a93f53d3e868c789b1b750a48a4c1110cd5b7049779b5f4f3c8b6200103ff1104b46b2141df1948dd0df2223720a3a471ec57404cace47063843a699a0f" - scriptTokens must be (expectedAsm) - } + val scriptTokens : Seq[ScriptToken] = fromHex(hex) + scriptTokens.map(_.hex).mkString must be (hex) + } - it must "parse 1ADD to an OP_1ADD" in { - ScriptParser.fromString("1ADD") must be (Seq(OP_1ADD)) - } - it must "parse a OP_PUSHDATA operation that pushes zero bytes correctly" in { - val str = "0x4c 0x00" - ScriptParser.fromString(str) must be (List(OP_PUSHDATA1, ScriptConstant("00"))) + it must "parse a p2pkh scriptSig properly" in { + //from b30d3148927f620f5b1228ba941c211fdabdae75d0ba0b688a58accbf018f3cc + val rawScriptSig = "4730440220048e15422cf62349dc586ffb8c749d40280781edd5064ff27a5910ff5cf225a802206a82685dbc2cf195d158c29309939d5a3cd41a889db6f766f3809fff35722305012103dcfc9882c1b3ae4e03fb6cac08bdb39e284e81d70c7aa8b27612457b2774509b" - val str1 = "0x4d 0x00" - ScriptParser.fromString(str1) must be (List(OP_PUSHDATA2, ScriptConstant("00"))) + val expectedAsm = List(BytesToPushOntoStack(71), + ScriptConstant("30440220048e15422cf62349dc586ffb8c749d40280781edd5064ff27a5910ff5cf" + + "225a802206a82685dbc2cf195d158c29309939d5a3cd41a889db6f766f3809fff3572230501"), + BytesToPushOntoStack(33), + ScriptConstant("03dcfc9882c1b3ae4e03fb6cac08bdb39e284e81d70c7aa8b27612457b2774509b")) - val str2 = "0x4e 0x00" - ScriptParser.fromString(str2) must be (List(OP_PUSHDATA4, ScriptConstant("00"))) - } + val scriptTokens : List[ScriptToken] = ScriptParser.fromHex(rawScriptSig) - it must "parse a large string constant found inside of script_valid.json" in { - val str = "'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'" - val parsed = fromString(str) - parsed must be (List(OP_PUSHDATA2, ScriptConstant("0802"), ScriptConstant( - "62626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262" - ))) - } + scriptTokens must be (expectedAsm) + } + + it must "parse 1 as an OP_1" in { + ScriptParser.fromString("1") must be (Seq(OP_1)) + } + it must "parse 1ADD to an OP_1ADD" in { + ScriptParser.fromString("1ADD") must be (Seq(OP_1ADD)) + } + + it must "parse a OP_PUSHDATA operation that pushes zero bytes correctly" in { + val str = "0x4c 0x00" + ScriptParser.fromString(str) must be (List(OP_PUSHDATA1, ScriptConstant("00"))) + + val str1 = "0x4d 0x00" + ScriptParser.fromString(str1) must be (List(OP_PUSHDATA2, ScriptConstant("00"))) + + val str2 = "0x4e 0x00" + ScriptParser.fromString(str2) must be (List(OP_PUSHDATA4, ScriptConstant("00"))) + } + + it must "parse a large string constant found inside of script_valid.json" in { + val str = "'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'" + val parsed = fromString(str) + parsed must be (List(OP_PUSHDATA2, ScriptConstant("0802"), ScriptConstant( + "62626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262" + ))) + } } diff --git a/src/test/scala/org/bitcoins/core/util/Base58Test.scala b/src/test/scala/org/bitcoins/core/util/Base58Test.scala new file mode 100644 index 0000000000..157ec86687 --- /dev/null +++ b/src/test/scala/org/bitcoins/core/util/Base58Test.scala @@ -0,0 +1,57 @@ +package org.bitcoins.core.util + +import org.bitcoins.core.protocol.BitcoinAddress +import org.bitcoins.core.util +import org.scalatest.{FlatSpec, MustMatchers} + +/** + * Created by tom on 5/17/16. + */ +class Base58Test extends FlatSpec with MustMatchers { + "Base58" must "encode byte value of 0 to character of 1" in { + Base58.base58Characters(0) must be ('1') + } + + it must "encode byte value of 22 to character P" in { + Base58.base58Characters(22) must be ('P') + } + + it must "decode character 1 to byte value of 0" in { + Base58.base58Pairs('1') must be (0.toByte) + } + + it must "decode character Z to byte value of 32" in { + Base58.base58Pairs('Z') must be (32.toByte) + } + + it must "decode and return same result as bitcoinj" in { + val address = "1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i" + val bitcoinj = org.bitcoinj.core.Base58.decode(address) + Base58.decode(address) must be (bitcoinj) + } + + it must "decode address into bytes, then encode bytes back to address the same as bitcoinj" in { + //1C4kYhyLftmkn48YarSoLupxHfYFo8kp64 + val address = TestUtil.bitcoinAddress.value + val bitcoinj = org.bitcoinj.core.Base58.encode(org.bitcoinj.core.Base58.decode(address)) + Base58.encode(Base58.decode(address)) must be (bitcoinj) + Base58.encode(Base58.decode(address)) must be ("1C4kYhyLftmkn48YarSoLupxHfYFo8kp64") + } + + it must "decode asset address into bytes then encode back to asset address" in { + //akJsoCcyh34FGPotxfEoSXGwFPCNAkyCgTA + val asset = TestUtil.assetAddress.value + val bitcoinj = org.bitcoinj.core.Base58.encode(org.bitcoinj.core.Base58.decode(asset)) + Base58.encode(Base58.decode(asset)) must be ("akJsoCcyh34FGPotxfEoSXGwFPCNAkyCgTA") + Base58.encode(Base58.decode(asset)) must be (bitcoinj) + } + + it must "decode multisig address into bytes then encode back to multisig" in { + val multi = TestUtil.multiSigAddress.value + val bitcoinj = org.bitcoinj.core.Base58.encode(org.bitcoinj.core.Base58.decode(multi)) + Base58.encode(Base58.decode(multi)) must be (TestUtil.multiSigAddress.value) + Base58.encode(Base58.decode(multi)) must be (bitcoinj) + } + + +} diff --git a/src/test/scala/org/bitcoins/core/util/BitcoinSUtilTest.scala b/src/test/scala/org/bitcoins/core/util/BitcoinSUtilTest.scala index 74b1d44e8f..56370b1ae8 100644 --- a/src/test/scala/org/bitcoins/core/util/BitcoinSUtilTest.scala +++ b/src/test/scala/org/bitcoins/core/util/BitcoinSUtilTest.scala @@ -7,4 +7,18 @@ import org.scalatest.{FlatSpec, MustMatchers} */ class BitcoinSUtilTest extends FlatSpec with MustMatchers { + + "BitcoinSUtil" must "determine if a string is a hex string" in { + BitcoinSUtil.isHex("abcdef0123456789") must be (true) + + BitcoinSUtil.isHex("") must be (false) + + //don't allow upper case hex chars + BitcoinSUtil.isHex("ABCDEF0123456789") must be (false) + + BitcoinSUtil.isHex("g") must be (false) + + //fail to parse a hex string that is uneven + BitcoinSUtil.isHex("123") must be (false) + } } diff --git a/src/test/scala/org/bitcoins/core/util/BitcoinScriptUtilTest.scala b/src/test/scala/org/bitcoins/core/util/BitcoinScriptUtilTest.scala index a982cba38b..39863d229d 100644 --- a/src/test/scala/org/bitcoins/core/util/BitcoinScriptUtilTest.scala +++ b/src/test/scala/org/bitcoins/core/util/BitcoinScriptUtilTest.scala @@ -1,6 +1,6 @@ package org.bitcoins.core.util -import org.bitcoins.core.crypto.ECFactory +import org.bitcoins.core.crypto.ECPublicKey import org.bitcoins.core.script.bitwise.OP_EQUALVERIFY import org.bitcoins.core.script.constant._ import org.bitcoins.core.script.crypto._ @@ -178,7 +178,7 @@ class BitcoinScriptUtilTest extends FlatSpec with MustMatchers { it must "check a public key's encoding" in { //pubkeys must be compressed or uncompressed or else that are not validly encoded - val key = ECFactory.publicKey("00") + val key = ECPublicKey("00") val program = TestUtil.testProgram BitcoinScriptUtil.checkPubKeyEncoding(key,program) must be (false) } diff --git a/src/test/scala/org/bitcoins/core/util/CryptoTestUtil.scala b/src/test/scala/org/bitcoins/core/util/CryptoTestUtil.scala index fdf11ab3c0..fdadfb0728 100644 --- a/src/test/scala/org/bitcoins/core/util/CryptoTestUtil.scala +++ b/src/test/scala/org/bitcoins/core/util/CryptoTestUtil.scala @@ -2,18 +2,18 @@ package org.bitcoins.core.util import org.bitcoinj.core.DumpedPrivateKey import org.bitcoins.core.config.TestNet3 -import org.bitcoins.core.crypto.ECFactory +import org.bitcoins.core.crypto.{ECPrivateKey} /** * Created by chris on 3/7/16. */ trait CryptoTestUtil { def privateKeyBase58 = "cVLwRLTvz3BxDAWkvS3yzT9pUcTCup7kQnfT2smRjvmmm1wAP6QT" - def privateKeyBytes = BitcoinSUtil.decodeBase58(privateKeyBase58) + def privateKeyBytes = Base58.decode(privateKeyBase58) def privateKeyHex = BitcoinSUtil.encodeHex(privateKeyBytes) def bitcoinjDumpedPrivateKey = new DumpedPrivateKey(BitcoinJTestUtil.params,privateKeyBase58) def bitcoinjPrivateKey = bitcoinjDumpedPrivateKey.getKey - def privateKey = ECFactory.fromBase58ToPrivateKey(privateKeyBase58,TestNet3) + def privateKey = ECPrivateKey.fromBase58ToPrivateKey(privateKeyBase58) } diff --git a/src/test/scala/org/bitcoins/core/util/CryptoUtilTest.scala b/src/test/scala/org/bitcoins/core/util/CryptoUtilTest.scala index df46c48547..b3593de708 100644 --- a/src/test/scala/org/bitcoins/core/util/CryptoUtilTest.scala +++ b/src/test/scala/org/bitcoins/core/util/CryptoUtilTest.scala @@ -13,7 +13,6 @@ class CryptoUtilTest extends FlatSpec with MustMatchers { hash.hex must be ("da39a3ee5e6b4b0d3255bfef95601890afd80709") } - it must "perform the correct RIPEMD160 on a string" in { val str = "" val expectedDigest = "9c1185a5c5e9fc54612808977ee8f548b2258d31" @@ -33,8 +32,5 @@ class CryptoUtilTest extends FlatSpec with MustMatchers { val expected = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" CryptoUtil.sha256(strBytes).hex must be (expected) CryptoUtil.sha256(hex).hex must be (expected) - - - } } diff --git a/src/test/scala/org/bitcoins/core/util/TestUtil.scala b/src/test/scala/org/bitcoins/core/util/TestUtil.scala index 08834b43af..499dd43749 100644 --- a/src/test/scala/org/bitcoins/core/util/TestUtil.scala +++ b/src/test/scala/org/bitcoins/core/util/TestUtil.scala @@ -17,11 +17,11 @@ import org.bitcoins.core.script.stack.OP_DUP */ object TestUtil { - val testBitcoinAddress = BitcoinAddress("n3p1ct69ao3qxWvEvzLhLtWG2zJGTjN3EV") - val testP2SHAddress = BitcoinAddress("2MzYbQdkSVp5wVyMRp6A5PHPuQNHpiaTbCj") - val bitcoinAddress = BitcoinAddress("1C4kYhyLftmkn48YarSoLupxHfYFo8kp64") - val multiSigAddress = BitcoinAddress("342ftSRCvFHfCeFFBuz4xwbeqnDw6BGUey") - val assetAddress = AssetAddress("akJsoCcyh34FGPotxfEoSXGwFPCNAkyCgTA") + def testBitcoinAddress = BitcoinAddress("n3p1ct69ao3qxWvEvzLhLtWG2zJGTjN3EV") + def testP2SHAddress = BitcoinAddress("2MzYbQdkSVp5wVyMRp6A5PHPuQNHpiaTbCj") + def bitcoinAddress = BitcoinAddress("1C4kYhyLftmkn48YarSoLupxHfYFo8kp64") + def multiSigAddress = BitcoinAddress("342ftSRCvFHfCeFFBuz4xwbeqnDw6BGUey") + def assetAddress = AssetAddress("akJsoCcyh34FGPotxfEoSXGwFPCNAkyCgTA") val p2pkhInputScript = "473044022016ffdbb7c57634903c5e018fcfc48d59f4e37dc4bc3bbc9ba4e6ee39150bca030220119c2241a931819bc1a75d3596e4029d803d1cd6de123bf8a1a1a2c3665e1fac012102af7dad03e682fcd0427b5c24140c220ac9d8abe286c15f8cf5bf77eed19c3652" def p2pkhScriptSig = ScriptSignature(p2pkhInputScript) @@ -141,7 +141,7 @@ object TestUtil { def p2shScriptPubKey = ScriptPubKey(rawP2SHScriptPubKey) //https://tbtc.blockr.io/api/v1/tx/raw/bdc221db675c06dbee2ae75d33e31cad4e2555efea10c337ff32c8cdf97f8e74 val rawScriptSig = "483045022100ad8e961fe3c22b2647d92b078f4c0cf81b3106ea5bf8b900ab8646aa4430216f022071d4edc2b5588be20ac4c2d07edd8ed069e10b2402d3dce2d3b835ccd075f283014104fa79182bbc26c708b5d9f36b8635947d4a834ea356cf612ede08395c295f962e0b1dc2557aba34188640e51a58ed547f2c89c8265cd0c04ff890d8435648746e" - val scriptSig = ScriptSignature(rawScriptSig) + def scriptSig = ScriptSignature(rawScriptSig) def testProgram : ScriptProgram = ScriptProgram(TransactionTestUtil.testTransaction, EmptyScriptPubKey,0,List(),Policy.standardScriptVerifyFlags) @@ -165,10 +165,10 @@ object TestUtil { * This is a script sig that doesn't have a signature strictly der encoded * Zero-length R is correctly encoded */ - val rawScriptSigNotStrictDerEncoded = "173014020002107777777777777777777777777777777701" + def rawScriptSigNotStrictDerEncoded = "173014020002107777777777777777777777777777777701" def scriptSigNotStrictDerEncoded = ScriptSignature(rawScriptSigNotStrictDerEncoded) - val p2pkhScriptSigNotStrictDerEncoded = ScriptSignature.fromAsm(List(BytesToPushOntoStack(71), + def p2pkhScriptSigNotStrictDerEncoded = ScriptSignature.fromAsm(List(BytesToPushOntoStack(71), ScriptConstant("173014020002107777777777777777777777777777777701"), BytesToPushOntoStack(33), ScriptConstant("02af7dad03e682fcd0427b5c24140c220ac9d8abe286c15f8cf5bf77eed19c3652"))) diff --git a/src/test/scala/org/bitcoins/core/util/TransactionTestUtil.scala b/src/test/scala/org/bitcoins/core/util/TransactionTestUtil.scala index 216e098511..fbdf22c8a1 100644 --- a/src/test/scala/org/bitcoins/core/util/TransactionTestUtil.scala +++ b/src/test/scala/org/bitcoins/core/util/TransactionTestUtil.scala @@ -1,13 +1,9 @@ package org.bitcoins.core.util -import org.bitcoinj.core.DumpedPrivateKey - -import org.bitcoins.core.config.TestNet3 -import org.bitcoins.core.crypto.{ECFactory, ECPublicKey} +import org.bitcoins.core.crypto.{ECPrivateKey, ECPublicKey} import org.bitcoins.core.currency.CurrencyUnits import org.bitcoins.core.protocol.script._ import org.bitcoins.core.protocol.transaction._ -import org.slf4j.LoggerFactory /** * Created by chris on 2/12/16. @@ -16,7 +12,6 @@ trait TransactionTestUtil extends BitcoinSLogger { /** * Raw multisignature script pub key output - * * @return */ def rawMultiSignatureScriptPubKey = "5221025878e270211662a27181cf4d6ad4d2cf0e69a98a3815c086f587c7e9388d87182103fc85980e3fac1f3d8a5c3223c3ef5bffc1bd42d2cc42add8c3899cc66e7f1906210215b5bd050869166a70a7341b4f216e268b7c6c7504576dcea2cce7d11cc9a35f53ae" @@ -24,14 +19,12 @@ trait TransactionTestUtil extends BitcoinSLogger { /** * First input of this raw tx is a spending a multisignature output * the first input is signed for this tx - * * @return */ def rawSignedMultiSignatureTx = "0100000001d324b34c80c2e611b23c92ed1be31729b2856ae439d54b237a296d618425e912010000009300483045022100f5d203c0b36027ce61cd72ecd09b9629de029cd5cb34155c459f55999d7a08df02206db673c84556c202e5a5a354eca2bb6effeffff2fa040d34ecdbe642dc2219c001483045022100f0e0c53f1ebddb97407e801d90e5131f40dcab071168322454237b49f3bf74ca022069e2545cf9e2e7dc2c708be403f356c3d436fd498b68ef5f0c9138299547f14701ffffffff0140420f00000000001976a914edc96705498831b16782d439fa93164bc5c8db6f88ac00000000" /** * First input of this raw tx is a spending a multisignature output * the first input is signed for this tx - * * @return */ def signedMultiSignatureTx = Transaction(rawSignedMultiSignatureTx) @@ -39,7 +32,6 @@ trait TransactionTestUtil extends BitcoinSLogger { /** * Mimics this test utility found in bitcoin core * https://github.com/bitcoin/bitcoin/blob/605c17844ea32b6d237db6d83871164dc7d59dab/src/test/script_tests.cpp#L57 - * * @param scriptPubKey * @return the transaction and the output index of the scriptPubKey */ @@ -61,7 +53,6 @@ trait TransactionTestUtil extends BitcoinSLogger { /** * Builds a spending transaction according to bitcoin core - * * @param creditingTx * @param scriptSignature * @param outputIndex @@ -96,7 +87,6 @@ trait TransactionTestUtil extends BitcoinSLogger { /** * Returns a transaction, the input that is spending the output, and the inputIndex inside of the tx - * * @return */ def transactionWithSpendingInputAndCreditingOutput : (Transaction, TransactionInput, Int, TransactionOutput) = { @@ -112,16 +102,15 @@ trait TransactionTestUtil extends BitcoinSLogger { } def signedMultiSignatureTransaction : (Transaction, Int, ScriptPubKey, Seq[ECPublicKey]) = { - val key1 = ECFactory.fromBase58ToPrivateKey("cVLwRLTvz3BxDAWkvS3yzT9pUcTCup7kQnfT2smRjvmmm1wAP6QT", TestNet3) - val key2 = ECFactory.fromBase58ToPrivateKey("cTine92s8GLpVqvebi8rYce3FrUYq78ZGQffBYCS1HmDPJdSTxUo",TestNet3) - def key3 = ECFactory.fromBase58ToPrivateKey("cVHwXSPRZmL9adctwBwmn4oTZdZMbaCsR5XF6VznqMgcvt1FDDxg",TestNet3) + val key1 = ECPrivateKey.fromBase58ToPrivateKey("cVLwRLTvz3BxDAWkvS3yzT9pUcTCup7kQnfT2smRjvmmm1wAP6QT") + val key2 = ECPrivateKey.fromBase58ToPrivateKey("cTine92s8GLpVqvebi8rYce3FrUYq78ZGQffBYCS1HmDPJdSTxUo") + def key3 = ECPrivateKey.fromBase58ToPrivateKey("cVHwXSPRZmL9adctwBwmn4oTZdZMbaCsR5XF6VznqMgcvt1FDDxg") (signedMultiSignatureTx,0,multiSignatureScriptPubKey, Seq(key1.publicKey,key2.publicKey,key3.publicKey)) } /** * Returns a p2sh transaction with its corresponding crediting output - * * @return */ def p2shTransactionWithSpendingInputAndCreditingOutput : (Transaction, TransactionInput, Int, TransactionOutput) = { @@ -129,25 +118,20 @@ trait TransactionTestUtil extends BitcoinSLogger { val spendingTx = TestUtil.p2sh2Of2Tx val inputIndex = 0 val input = spendingTx.inputs(inputIndex) - (spendingTx, input, inputIndex, creditingTx.outputs(input.previousOutput.vout)) - } - - - - //https://tbtc.blockr.io/api/v1/tx/raw/d77d905fc29f86bc3db39fdb68cfcab4e35f677d4f2ec33ed749912e0fa5f385 def rawP2sh2Of3Transaction = "010000000197e355df4b040cdca3b5623864dfcd9b94cce06417a620e2826e81d6335186c300000000fc004730440220724714702c6c172dfb72dbc1536e3a7604b9fb5f9dcdf05d76c284010f97f75602200c0c749f2efc71234a752dddee42f38967a2c5eb725be3752c4d8c3a2e2403d60147304402200173f0628f05258829a71d62bfe3baaf48d9fa9f1b4c39355be74acc2db0cee6022067357b735da08fdc63546c81437b182e84ee505d7748cbcd32f8cb9098fb0df6014c69522102ab07ab88e8211f8d48820b78ca1276960e1d09ecdc5382afc59f17c660e01d7d210346d594bfc39dc5bc4a2afb62a8717bb049d1543289d78ceec533359e77d845092103c1d5b135b3b082dc20eab6ae7d39d80bb26b5fb33b8f1b4da72f995bca9fe05353aeffffffff02bbda02000000000017a91432f3a016b96be26f9cd088675012c26fca675cfc87a08601000000000017a9149fe9d38bb4054f1827285097f3ce7293030365ee8700000000" + def p2sh2Of3Transaction = Transaction(rawP2sh2Of3Transaction) //https://tbtc.blockr.io/api/v1/tx/raw/c3865133d6816e82e220a61764e0cc949bcddf643862b5a3dc0c044bdf55e397 def rawP2sh2Of3CreditingTransaction = "01000000016f817a337d3b7c09a7d3484eaad5467730cb48404492968047a0877232a081d000000000fdfd0000473044022053b21ad6a9c63c36792fa9ccabcecaca90015ef5cf93515010fb2f55597b4498022045889d57c7eb01113b50a403287baa1202f7e6cf65ff74c04d1b2bac18f6622201483045022100cdbe4cf74116ef080b0251dc79c65fc94cb601466dcca46852aaf648af7c701302206330a9f97c952cf033faca3dd623aa8150e4f325e228244c737950d38abd7bde014c69522103ed9accffc87e17042feb7dcffb8af8231739aa6ee87a4fc09b5523b5997a295f210310d24963b6777568731efe17a4d06cfeb207b55d869ab641636468ec5e551889210393d6f0fad0c89c190b5a6ce77241e4ff416bc562003c9308394021707f0fd9bd53aeffffffff022e8204000000000017a914aa75a01abb09b58eedd4a97612056c94a3ceafcf87a0860100000000001976a914c810ad20630f02790741f5458f666798b86470c688ac00000000" + def p2sh2Of3CreditingTransaction = Transaction(rawP2sh2Of3CreditingTransaction) /** * Returns a p2sh transaction that has 2 of 3 signatures with the creiditing output - * * @return */ def p2sh2Of3TransactionWithSpendingInputAndCreditingOutput : (Transaction, TransactionInput, Int, TransactionOutput) = { @@ -160,7 +144,6 @@ trait TransactionTestUtil extends BitcoinSLogger { /** * Builds a transaction with a non strict der encoded signature - * * @return the transaction and the inputIndex of the non strict der encoded signature */ def transactionWithNonStrictDerSignature : (Transaction, Int) = { @@ -172,7 +155,6 @@ trait TransactionTestUtil extends BitcoinSLogger { /** * Returns a valid transaction that spends a p2pkh output at the inputIndex - * * @return */ def p2pkhTransactionWithCreditingScriptPubKey : (Transaction, Int, ScriptPubKey) = { @@ -185,7 +167,6 @@ trait TransactionTestUtil extends BitcoinSLogger { * This transaction has one input which is set to EmptyTransactionInput * The purpose of this transaction is a base transaction that can be used to manipulate * the scriptSignature to be whatever we need it to be - * * @return */ def testTransaction : Transaction = {