mirror of
https://github.com/bitcoin-s/bitcoin-s.git
synced 2025-02-24 23:08:31 +01:00
fixing various bugs, increasing test coverage
This commit is contained in:
parent
d7f236d2db
commit
a71b62808f
10 changed files with 97 additions and 29 deletions
|
@ -3,6 +3,8 @@ package org.scalacoin.protocol
|
|||
import org.bitcoinj.core.{VersionedChecksummedBytes, Base58, Utils}
|
||||
import org.scalacoin.config.{RegTest, TestNet3, MainNet}
|
||||
|
||||
import scala.util.{Failure, Success, Try}
|
||||
|
||||
case class AddressInfo(bitcoinAddress: BitcoinAddress, n_tx: Long, total_received: Long, total_sent: Long,
|
||||
final_balance: Long)
|
||||
|
||||
|
@ -89,12 +91,16 @@ object BitcoinAddress {
|
|||
}
|
||||
|
||||
object AssetAddress {
|
||||
def validate(assetAddress : String) = {
|
||||
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 : Array[Byte] = Base58.decodeChecked(assetAddress)
|
||||
require(base58decodechecked != null)
|
||||
base58decodechecked.size == 22 && base58decodechecked(0) == 0x13
|
||||
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
|
||||
case Failure(_) => false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -23,22 +23,6 @@ sealed trait ScriptPubKey extends TransactionElement with BitcoinSLogger {
|
|||
*/
|
||||
def asm : Seq[ScriptToken]
|
||||
|
||||
/* /**
|
||||
* Returns the script type of this scriptPubKey
|
||||
* @return
|
||||
*/
|
||||
def scriptType : ScriptType = {
|
||||
asm match {
|
||||
case List(OP_DUP, OP_HASH160, BytesToPushOntoStackImpl(x), ScriptConstantImpl(pubKeyHash), OP_EQUALVERIFY, OP_CHECKSIG) => P2PKH
|
||||
case List(OP_HASH160, BytesToPushOntoStackImpl(x), ScriptConstantImpl(scriptHash), OP_EQUAL) => P2SH
|
||||
//TODO: make this more robust, this isn't the pattern that multsignature scriptPubKeys follow
|
||||
case _ if (asm.last == OP_CHECKMULTISIG) => MultiSignature
|
||||
case _ => NonStandard
|
||||
}
|
||||
}*/
|
||||
|
||||
//the addresses that the bitcoins correlated to the output
|
||||
def addresses : Seq[BitcoinAddress] = ???
|
||||
|
||||
}
|
||||
|
||||
|
@ -61,15 +45,19 @@ trait MultiSignatureScriptPubKey extends ScriptPubKey {
|
|||
* Returns the amount of required signatures for this multisignature script pubkey output
|
||||
* @return
|
||||
*/
|
||||
def requiredSigs = {
|
||||
def requiredSigs : Long = {
|
||||
val asmWithoutPushOps = asm.filterNot(_.isInstanceOf[BytesToPushOntoStack])
|
||||
val opCheckMultiSigIndex = if (asm.indexOf(OP_CHECKMULTISIG) != -1) asmWithoutPushOps.indexOf(OP_CHECKMULTISIG) else asmWithoutPushOps.indexOf(OP_CHECKMULTISIGVERIFY)
|
||||
logger.debug("opCheckMultiSigIndex: " + opCheckMultiSigIndex)
|
||||
logger.debug("maxSigs: " + maxSigs)
|
||||
logger.debug("asmWithoutPushOps: " + asmWithoutPushOps)
|
||||
//magic number 2 represents the maxSig operation and the OP_CHECKMULTISIG operation at the end of the asm
|
||||
val numSigsRequired = asmWithoutPushOps(opCheckMultiSigIndex - maxSigs.toInt - 2)
|
||||
numSigsRequired match {
|
||||
case x : ScriptNumber => x.num
|
||||
case _ => throw new RuntimeException("The first element of the multisignature pubkey must be a script number operation\n" +
|
||||
"scriptPubKey: " + this)
|
||||
"operation: " + numSigsRequired +
|
||||
"\nscriptPubKey: " + this)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -77,8 +65,7 @@ trait MultiSignatureScriptPubKey extends ScriptPubKey {
|
|||
* The maximum amount of signatures for this multisignature script pubkey output
|
||||
* @return
|
||||
*/
|
||||
def maxSigs = {
|
||||
val checkMultiSigIndex = asm.indexOf(OP_CHECKMULTISIG)
|
||||
def maxSigs : Long = {
|
||||
if (checkMultiSigIndex == -1 || checkMultiSigIndex == 0) {
|
||||
//means that we do not have a max signature requirement
|
||||
0.toLong
|
||||
|
@ -90,6 +77,15 @@ trait MultiSignatureScriptPubKey extends ScriptPubKey {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gives the OP_CHECKMULTISIG or OP_CHECKMULTISIGVERIFY index inside of asm
|
||||
* @return the index of OP_CHECKMULTISIG or OP_CHECKMULTISIGVERIFY
|
||||
*/
|
||||
private def checkMultiSigIndex : Int = {
|
||||
if (asm.indexOf(OP_CHECKMULTISIG) != -1) asm.indexOf(OP_CHECKMULTISIG) else asm.indexOf(OP_CHECKMULTISIGVERIFY)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the public keys encoded into the scriptPubKey
|
||||
* @return
|
||||
|
|
|
@ -28,9 +28,6 @@ trait BitwiseInterpreter extends ControlOperationsInterpreter {
|
|||
|
||||
val result = (h,h1) match {
|
||||
case (ScriptConstantImpl(x),ScriptConstantImpl(y)) => x == y
|
||||
case (BytesToPushOntoStackImpl(x), BytesToPushOntoStackImpl(y)) => x == y
|
||||
case (BytesToPushOntoStackImpl(x), ScriptConstantImpl(y)) => BytesToPushOntoStackImpl(x).hex == y
|
||||
case (ScriptConstantImpl(x), BytesToPushOntoStackImpl(y)) => x == BytesToPushOntoStackImpl(y).hex
|
||||
case (ScriptConstantImpl(x), ScriptNumberImpl(y)) => BitcoinSUtil.hexToLong(x) == y
|
||||
case (ScriptNumberImpl(x), ScriptConstantImpl(y)) => x == BitcoinSUtil.hexToLong(y)
|
||||
case (OP_0, x) => OP_0.hex == x.hex
|
||||
|
|
|
@ -65,7 +65,8 @@ trait BitcoinSUtil extends NumberUtil {
|
|||
|
||||
def decodeBase58(base58 : String) : Seq[Byte] = Base58.decode(base58).toList
|
||||
|
||||
def encodeBase58(bytes : List[Byte]) : String = Base58.encode(bytes.toArray)
|
||||
def encodeBase58(bytes : Seq[Byte]) : String = Base58.encode(bytes.toArray)
|
||||
|
||||
|
||||
/**
|
||||
* Converts a little endian encoded hex string to a big endian encoded hex string
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
package org.scalacoin.protocol
|
||||
|
||||
import org.scalacoin.util.{BitcoinSUtil, TestUtil}
|
||||
import org.scalatest.{FlatSpec, MustMatchers}
|
||||
|
||||
/**
|
||||
* Created by chris on 3/30/16.
|
||||
*/
|
||||
class AddressFactoryTest extends FlatSpec with MustMatchers {
|
||||
|
||||
"AddressFactory" must "create an address from a base58 encoded string" in {
|
||||
AddressFactory.factory(TestUtil.bitcoinAddress.value) must be (TestUtil.bitcoinAddress)
|
||||
}
|
||||
|
||||
it must "create an address from a sequence of bytes" in {
|
||||
AddressFactory.fromBytes(BitcoinSUtil.decodeBase58(TestUtil.bitcoinAddress.value)) must be (TestUtil.bitcoinAddress)
|
||||
}
|
||||
|
||||
|
||||
it must "create an asset address from a base58 encoded string" in {
|
||||
AddressFactory.fromBytes(BitcoinSUtil.decodeBase58(TestUtil.assetAddress.value)) must be (TestUtil.assetAddress)
|
||||
}
|
||||
|
||||
it must "throw an exception if the given string" in {
|
||||
intercept[RuntimeException] {
|
||||
AddressFactory.factory("01234567890abcdef")
|
||||
}
|
||||
}
|
||||
|
||||
it must "throw an exception if we give a hex string to create a bitcoin address from" in {
|
||||
intercept[RuntimeException] {
|
||||
AddressFactory.fromHex("01234567890abcdef")
|
||||
}
|
||||
}
|
||||
}
|
|
@ -48,7 +48,7 @@ class BitcoinAddressTest extends FlatSpec with MustMatchers {
|
|||
|
||||
"An asset address with the first character replaced" must "not be a valid asset address" in {
|
||||
//3J98t1WpEZ73CNmQviecrnyiWrnqRhWNLyy
|
||||
intercept[org.bitcoinj.core.AddressFormatException] {
|
||||
intercept[IllegalArgumentException] {
|
||||
val assetAddress = AssetAddress("aJ98t1WpEZ73CNmQviecrnyiWrnqRhWNLyy")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,4 +60,21 @@ class MultiSignatureScriptPubKeyTest extends FlatSpec with MustMatchers {
|
|||
}
|
||||
|
||||
|
||||
it must "find the required signatures from a multisignature scriptPubKey using an OP_CHECKMULTISIGVERFIY" in {
|
||||
val multiSigRawScriptPubKeyHex = "5221025878e270211662a27181cf" +
|
||||
"4d6ad4d2cf0e69a98a3815c086f587c7e9388d87182103fc85980e3fac1f3d" +
|
||||
"8a5c3223c3ef5bffc1bd42d2cc42add8c3899cc66e7f1906210215b5bd0508" +
|
||||
"69166a70a7341b4f216e268b7c6c7504576dcea2cce7d11cc9a35f53af"
|
||||
val scriptPubKey = ScriptPubKeyFactory.fromHex(multiSigRawScriptPubKeyHex)
|
||||
val multiSigScriptPubKey : MultiSignatureScriptPubKey = scriptPubKey match {
|
||||
case s : MultiSignatureScriptPubKey => s
|
||||
case _ => throw new RuntimeException("Should be a multisig script pub key")
|
||||
}
|
||||
|
||||
multiSigScriptPubKey.maxSigs must be (3)
|
||||
multiSigScriptPubKey.requiredSigs must be (2)
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -45,5 +45,19 @@ class ScriptPubKeyFactoryTest extends FlatSpec with MustMatchers {
|
|||
|
||||
}
|
||||
|
||||
it must "create a multisignature scriptPubKey from a script using OP_CHECKMULTISIGVERIFY" in {
|
||||
val multiSigRawScriptPubKeyHex = "5221025878e270211662a27181cf" +
|
||||
"4d6ad4d2cf0e69a98a3815c086f587c7e9388d87182103fc85980e3fac1f3d" +
|
||||
"8a5c3223c3ef5bffc1bd42d2cc42add8c3899cc66e7f1906210215b5bd0508" +
|
||||
"69166a70a7341b4f216e268b7c6c7504576dcea2cce7d11cc9a35f53af"
|
||||
val scriptPubKey = ScriptPubKeyFactory.fromHex(multiSigRawScriptPubKeyHex)
|
||||
val isMultiSigScriptPubKey : Boolean = scriptPubKey match {
|
||||
case s : MultiSignatureScriptPubKey => true
|
||||
case _ => false
|
||||
}
|
||||
|
||||
isMultiSigScriptPubKey must be (true)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -78,6 +78,8 @@ class BitwiseInterpreterTest extends FlatSpec with MustMatchers with BitwiseInte
|
|||
opEqual(program).stack.head must be (ScriptTrue)
|
||||
}
|
||||
|
||||
it must "evaluate two "
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue