updating README.md

Fixing typos
This commit is contained in:
Chris Stewart 2017-12-05 12:47:24 -06:00
parent 7fd06b573c
commit bde25028cb
5 changed files with 89 additions and 59 deletions

View file

@ -1,8 +1,8 @@
[![Build Status](https://travis-ci.org/bitcoin-s/bitcoin-s-core.svg?branch=master)](https://travis-ci.org/bitcoin-s/bitcoin-s-core) [![Coverage Status](https://coveralls.io/repos/github/bitcoin-s/bitcoin-s-core/badge.svg?branch=master)](https://coveralls.io/github/bitcoin-s/bitcoin-s-core?branch=master)
[![Build Status](https://travis-ci.org/bitcoin-s/bitcoin-s-core.svg?branch=master)](https://travis-ci.org/bitcoin-s/bitcoin-s-core) [![Coverage Status](https://coveralls.io/repos/github/bitcoin-s/bitcoin-s-core/badge.svg?branch=master)](https://coveralls.io/github/bitcoin-s/bitcoin-s-core?branch=master) [![IRC Network](https://img.shields.io/badge/irc-%23bitcoin--scala-blue.svg "IRC Freenode")](https://webchat.freenode.net/?channels=bitcoin-scala)
# Bitcoin-S-Core
This is the core functionality of bitcoin-s. Please join us in #bitcoin-scala on freenode for help/collaboration.
This is the core functionality of bitcoin-s.
[Quick Build Guide](BUILD_README.md)
@ -19,6 +19,7 @@ This repostitory includes the following functionality:
- A robust set of [generators](https://github.com/bitcoin-s/bitcoin-s-core/tree/master/src/main/scala/org/bitcoins/core/gen), which are used in property based testing
- These are extremely useful for testing bitcoin applications
- Here is an example of a specification for our [ECPrivateKey](https://github.com/bitcoin-s/bitcoin-s-core/blob/master/src/test/scala/org/bitcoins/core/crypto/ECPrivateKeySpec.scala)
- [Number types](https://github.com/bitcoin-s/bitcoin-s-core/blob/master/src/main/scala/org/bitcoins/core/number/NumberType.scala#L16) to represent C's unsigned numbers ([`UInt8`](https://github.com/bitcoin-s/bitcoin-s-core/blob/1c7a7b9f46679a753248d9f55246c272bb3d63b9/src/main/scala/org/bitcoins/core/number/NumberType.scala#L91), [`UInt32`](https://github.com/bitcoin-s/bitcoin-s-core/blob/1c7a7b9f46679a753248d9f55246c272bb3d63b9/src/main/scala/org/bitcoins/core/number/NumberType.scala#L102) etc) which are used in the bitcoin protocol
- 90% test coverage throughout the codebase to ensure high quality code.
- Functions documented with Scaladocs for user friendliness
@ -27,8 +28,35 @@ This repostitory includes the following functionality:
- Algebraic Data Types to allow the compiler to check for exhaustiveness on match statements
- Using [property based testing](http://www.scalatest.org/user_guide/property_based_testing) to test robustness of code
# Property based testing
This library aims to achieve high level of correctness via property based testing. At the simplest level, you can think of property based testing as specifying a invariant that must always hold true. [Here](https://github.com/bitcoin-s/bitcoin-s-core/blob/89fbf35d78046b7ed21fd93fec05bb57cba023bb/src/test/scala/org/bitcoins/core/protocol/transaction/TransactionSpec.scala#L13-L17) is an example of a property in the bitcoin-s-core test suite
```scala
property("Serialization symmetry") =
Prop.forAll(TransactionGenerators.transactions) { tx =>
Transaction(tx.hex) == tx
}
```
What this property says is that for every transaction we can generate with [`TransactionGenerators.transactions`](https://github.com/bitcoin-s/bitcoin-s-core/blob/1c7a7b9f46679a753248d9f55246c272bb3d63b9/src/main/scala/org/bitcoins/core/gen/TransactionGenerators.scala#L50) we *must* be able to serialize it to hex format, then deserialize it back to a transaction and get the original `tx` back.
A more complex example of property based testing is checking that a [multi signature transaction was signed correctly](https://github.com/bitcoin-s/bitcoin-s-core/blob/89fbf35d78046b7ed21fd93fec05bb57cba023bb/src/test/scala/org/bitcoins/core/crypto/TransactionSignatureCreatorSpec.scala#L33-L40). First we generate a *supposedly* validly signed multisig transaction with [`TransactionGenerators.signedMultiSigTransaction`](https://github.com/bitcoin-s/bitcoin-s-core/blob/1c7a7b9f46679a753248d9f55246c272bb3d63b9/src/main/scala/org/bitcoins/core/gen/TransactionGenerators.scala#L102-L108). These transactions have varying m of n requirements. An interesting corner case if when you have 0 of n signatures. Which means no signature is required. Property based testing is really good at fleshing out these corner cases. We check to see if this transaction is valid by running it through our [`ScriptInterpreter`](https://github.com/bitcoin-s/bitcoin-s-core/blob/89fbf35d78046b7ed21fd93fec05bb57cba023bb/src/main/scala/org/bitcoins/core/script/interpreter/ScriptInterpreter.scala#L29). If we have built our functionality correctly the ScriptInterpreter should always return [`ScriptOk`](https://github.com/bitcoin-s/bitcoin-s-core/blob/89fbf35d78046b7ed21fd93fec05bb57cba023bb/src/main/scala/org/bitcoins/core/script/result/ScriptResult.scala#L15) indicating the script was valid.
```scala
property("generate valid signatures for a multisignature transaction") =
Prop.forAllNoShrink(TransactionGenerators.signedMultiSigTransaction) {
case (txSignatureComponent: TxSigComponent, _) =>
//run it through the interpreter
val program = ScriptProgram(txSignatureComponent)
val result = ScriptInterpreter.run(program)
result == ScriptOk
}
```
# TODO
- [BIP32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki) HD keys
- Simple [`TransactionBuilder`](https://github.com/MetacoSA/NBitcoin/blob/56bfd1cbca535424b160d8a40688a79de4800630/NBitcoin/TransactionBuilder.cs#L172) similar nbitcoin
- Hardware wallet support (trezor, ledger etc)
- Lightning network scriptpubkey types (some work done [here](https://github.com/Christewart/bitcoin-s-core/commits/lightning_contracts))
- sbt respository
- Java support
- Android support
@ -59,25 +87,39 @@ $ sbt assembly
# Examples
Every bitcoin protocol data structure (and some other data structures) extends [`NetworkElement`](https://github.com/bitcoin-s/bitcoin-s-core/blob/master/src/main/scala/org/bitcoins/core/protocol/NetworkElement.scala). NetworkElement provides easier methods to convert the data structure to hex or a byte representation. When paired with our [`Factory`](https://github.com/bitcoin-s/bitcoin-s-core/blob/master/src/main/scala/org/bitcoins/core/util/Factory.scala) we can easily serialize and deserialize data structures. Most data structures have companion objects that extends `Factory` to be able to easily create protocol data structures. An example of this is the [`ScriptPubKey`](https://github.com/bitcoin-s/bitcoin-s-core/blob/1c7a7b9f46679a753248d9f55246c272bb3d63b9/src/main/scala/org/bitcoins/core/protocol/script/ScriptPubKey.scala#L462) companion object. You can use this companion object to create a SPK from hex or a byte array.
Here is an example scala console session with bitcoins-core
```scala
chris@chris:~/dev/bitcoins-core-chris$ sbt console
$ sbt console
[info] Loading global plugins from /home/chris/.sbt/0.13/plugins
[info] Loading project definition from /home/chris/dev/bitcoin-s-core/project
[info] Set current project to bitcoin-s-core (in build file:/home/chris/dev/bitcoin-s-core/)
[info] Starting scala interpreter...
[info]
Welcome to Scala version 2.11.7 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_151).
Type in expressions to have them evaluated.
Type :help for more information.
scala> import org.bitcoins.core.protocol.transaction._
import org.bitcoins.protocol.transaction._
import org.bitcoins.core.protocol.transaction._
scala> import org.bitcoins.core.protocol.script._
import org.bitcoins.protocol.script._
scala> val hexTx = "0100000001ccf318f0cbac588a680bbad075aebdda1f211c94ba28125b0f627f9248310db3000000006b4830450221008337ce3ce0c6ac0ab72509f8$9c1d52701817a2362d6357457b63e3bdedc0c0602202908963b9cf1a095ab3b34b95ce2bc0d67fb0f19be1cc5f7b3de0b3a325629bf01210241d746ca08da0a668735c3e01c1$a02045f2f399c5937079b6434b5a31dfe353ffffffff0210335d05000000001976a914b1d7591b69e9def0feb13254bace942923c7922d88ac48030000000000001976a9145e$90c865c2f6f7a9710a474154ab1423abb5b9288ac00000000"
hexTx: String = 0100000001ccf318f0cbac588a680bbad075aebdda1f211c94ba28125b0f627f9248310db3000000006b4830450221008337ce3ce0c6ac0ab72509f889c1$52701817a2362d6357457b63e3bdedc0c0602202908963b9cf1a095ab3b34b95ce2bc0d67fb0f19be1cc5f7b3de0b3a325629bf01210241d746ca08da0a668735c3e01c1fa02$45f2f399c5937079b6434b5a31dfe353ffffffff0210335d05000000001976a914b1d7591b69e9def0feb13254bace942923c7922d88ac48030000000000001976a9145e690c$65c2f6f7a9710a474154ab1423abb5b9288ac00000000
scala> val simpleRawTransaction = "0100000001ccf318f0cbac588a680bbad075aebdda1f211c94ba28125b0f627f9248310db3000000006b4830450221008337ce3ce0c6ac0ab72509f889c1d52701817a2362d6357457b63e3bdedc0c0602202908963b9cf1a095ab3b34b95ce2bc0d67fb0f19be1cc5f7b3de0b3a325629bf01210241d746ca08da0a668735c3e01c1fa02045f2f399c5937079b6434b5a31dfe353ffffffff0210335d05000000001976a914b1d7591b69e9def0feb13254bace942923c7922d88ac48030000000000001976a9145e690c865c2f6f7a9710a474154ab1423abb5b9288ac00000000"
simpleRawTransaction: String = 0100000001ccf318f0cbac588a680bbad075aebdda1f211c94ba28125b0f627f9248310db3000000006b4830450221008337ce3ce0c6ac0ab72509f889c1d52701817a2362d6357457b63e3bdedc0c0602202908963b9cf1a095ab3b34b95ce2bc0d67fb0f19be1cc5f7b3de0b3a325629bf01210241d746ca08da0a668735c3e01c1fa02045f2f399c5937079b6434b5a31dfe353ffffffff0210335d05000000001976a914b1d7591b69e9def0feb13254bace942923c7922d88ac48030000000000001976a9145e690c865c2f6f7a9710a474154ab1423abb5b9288ac00000000
scala> val tx = Transaction(hexTx)
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
tx: org.bitcoins.core.protocol.transaction.Transaction = BaseTransactionImpl(UInt32Impl(1),List(TransactionInputImpl(TransactionOutPointImpl$DoubleSha256DigestImpl(ccf318f0cbac588a680bbad075aebdda1f211c94ba28125b0f627f9248310db3),UInt32Impl(0)),P2PKHScriptSignatureImpl(6b483045022$008337ce3ce0c6ac0ab72509f889c1d52701817a2362d6357457b63e3bdedc0c0602202908963b9cf1a095ab3b34b95ce2bc0d67fb0f19be1cc5f7b3de0b3a325629bf012102$1d746ca08da0a668735c3e01c1fa02045f2f399c5937079b6434b5a31dfe353),UInt32Impl(4294967295))),List(TransactionOutputImpl(SatoshisImpl(Int64Impl($9994000)),P2PKHScriptPubKeyImpl(1976a914b1d7591b69e9def0feb13254bace942923c7922d88ac)), TransactionOutputImpl(SatoshisImpl(Int64Impl(840)),P$PKHScriptPubKeyImpl(1976a9145e690c865c2f6f7a9710a474154ab1423abb5b9288ac))),UInt32Impl(0))
scala> val hexAgain = tx.hex
hexAgain: String = 0100000001ccf318f0cbac588a680bbad075aebdda1f211c94ba28125b0f627f9248310db3000000006b4830450221008337ce3ce0c6ac0ab72509f88$c1d52701817a2362d6357457b63e3bdedc0c0602202908963b9cf1a095ab3b34b95ce2bc0d67fb0f19be1cc5f7b3de0b3a325629bf01210241d746ca08da0a668735c3e01c1f$02045f2f399c5937079b6434b5a31dfe353ffffffff0210335d05000000001976a914b1d7591b69e9def0feb13254bace942923c7922d88ac48030000000000001976a9145e6$0c865c2f6f7a9710a474154ab1423abb5b9288ac00000000
scala> val tx = Transaction(simpleRawTransaction)
tx: org.bitcoins.core.protocol.transaction.Transaction = TransactionImpl(1,List(TransactionInputImpl(TransactionOutPointImpl(b30d3148927f620f5b1228ba941c211fdabdae75d0ba0b688a58accbf018f3cc,0),P2PKHScriptSignatureImpl(4830450221008337ce3ce0c6ac0ab72509f889c1d52701817a2362d6357457b63e3bdedc0c0602202908963b9cf1a095ab3b34b95ce2bc0d67fb0f19be1cc5f7b3de0b3a325629bf01210241d746ca08da0a668735c3e01c1fa02045f2f399c5937079b6434b5a31dfe353,List(BytesToPushOntoStackImpl(72), ScriptConstantImpl(30450221008337ce3ce0c6ac0ab72509f889c1d52701817a2362d6357457b63e3bdedc0c0602202908963b9cf1a095ab3b34b95ce2bc0d67fb0f19be1cc5f7b3de0b3a325629bf01), BytesToPushOntoStackImpl(33), ScriptConstantImpl(0241d746ca08da0a668735c3e01c1fa02045f2f399c5937079b6434b5a31dfe353))),4294967295)),List(TransactionOutputImpl(89994000 ...
```
This gives us an example of a bitcoin transaction that is encoded in hex format that is deserialized to a native Scala object called a Transaction.
This gives us an example of a bitcoin transaction that is encoded in hex format that is deserialized to a native Scala object called a [`Transaction`](https://github.com/bitcoin-s/bitcoin-s-core/blob/6358eb83067909771f989d615b422759222d060a/src/main/scala/org/bitcoins/core/protocol/transaction/Transaction.scala#L14-L42). You could also serialize the transaction to bytes using `tx.bytes` instead of `tx.hex`. These methods are available on every data structure that extends NetworkElement, like [`ECPrivateKey`](https://github.com/bitcoin-s/bitcoin-s-core/blob/6358eb83067909771f989d615b422759222d060a/src/main/scala/org/bitcoins/core/crypto/ECKey.scala#L23-L67), [`ScriptPubKey`](https://github.com/bitcoin-s/bitcoin-s-core/blob/6358eb83067909771f989d615b422759222d060a/src/main/scala/org/bitcoins/core/protocol/script/ScriptPubKey.scala#L23), [`ScriptWitness`](https://github.com/bitcoin-s/bitcoin-s-core/blob/6358eb83067909771f989d615b422759222d060a/src/main/scala/org/bitcoins/core/protocol/script/ScriptWitness.scala#L13), and [`Block`](https://github.com/bitcoin-s/bitcoin-s-core/blob/6358eb83067909771f989d615b422759222d060a/src/main/scala/org/bitcoins/core/protocol/blockchain/Block.scala#L17).
Transactions are run through the interpreter to check the validity of the Transaction. These are packaged up into an object called ScriptProgram, which contains the following:
- The transaction that is being checked
@ -160,4 +202,10 @@ chris@chris:~/dev/bitcoins-core$ sbt
>
```
# Interacting with bitcoind
Please see our other project [`bitcoin-s-rpc-client`](https://github.com/bitcoin-s/bitcoin-s-rpc-client)
# Stand alone SPV Node
Please see our other project [`bitcoin-s-spv-node`](https://github.com/bitcoin-s/bitcoin-s-spv-node)

View file

@ -11,7 +11,7 @@ import scala.util.Try
/**
* Created by chris on 1/7/16.
*/
trait ScriptParser extends Factory[List[ScriptToken]] {
sealed abstract class ScriptParser extends Factory[List[ScriptToken]] {
/** Parses a list of bytes into a list of script tokens */
@ -123,7 +123,6 @@ trait ScriptParser extends Factory[List[ScriptToken]] {
//for the offical parsing algorithm, for examples of weird formats look inside of
//[[https://github.com/bitcoin/bitcoin/blob/master/src/test/data/script_valid.json]]
val parsedBytesFromString = loop(str.split(" ").toList, List()).reverse
logger.info("Parsed bytes from the given string: " + BitcoinSUtil.encodeHex(parsedBytesFromString))
parse(parsedBytesFromString)
}
}

View file

@ -116,12 +116,7 @@ class ScriptSignatureTest extends FlatSpec with MustMatchers {
testCase <- testCases
} yield {
Transaction(testCase.transaction.hex) must be (testCase.transaction)
logger.info("Test case: " + testCase)
logger.info("Hash type num: " + testCase.hashTypeNum)
logger.info("Hash type: " + testCase.hashType)
val hashForSig = TransactionSignatureSerializer.hashForSignature(testCase.transaction, testCase.inputIndex, testCase.script.asm, testCase.hashType)
//the hash is returned with opposite endianness
logger.info("Expected hash: " + testCase.hash.hex)
val flipHash = BitcoinSUtil.flipEndianness(testCase.hash.hex)
hashForSig must be (DoubleSha256Digest(flipHash))
}

View file

@ -1,12 +1,11 @@
package org.bitcoins.core.serializers.script
import org.bitcoins.core.protocol.script.ScriptSignature
import org.bitcoins.core.script.arithmetic.{OP_1ADD, OP_ADD}
import org.bitcoins.core.script.arithmetic.OP_1ADD
import org.bitcoins.core.script.bitwise.OP_EQUAL
import org.bitcoins.core.script.constant._
import org.bitcoins.core.script.control.{OP_ENDIF, OP_IF}
import org.bitcoins.core.script.crypto.{OP_CHECKMULTISIG, OP_HASH160}
import org.bitcoins.core.script.reserved.{OP_NOP10, OP_NOP}
import org.bitcoins.core.script.crypto.OP_HASH160
import org.bitcoins.core.script.reserved.OP_NOP
import org.bitcoins.core.script.stack.OP_PICK
import org.bitcoins.core.util.{BitcoinSUtil, TestUtil}
import org.scalatest.{FlatSpec, MustMatchers}
@ -14,29 +13,29 @@ import org.scalatest.{FlatSpec, MustMatchers}
/**
* Created by chris on 1/7/16.
*/
class ScriptParserTest extends FlatSpec with MustMatchers with ScriptParser with BitcoinSUtil {
class ScriptParserTest extends FlatSpec with MustMatchers with BitcoinSUtil {
"ScriptParser" must "parse 0x00 to a OP_0" in {
fromBytes(List(0.toByte)) must be (List(OP_0))
ScriptParser.fromBytes(List(0.toByte)) must be (List(OP_0))
}
it must "parse the number 0 as an OP_0" in {
fromString("0") must be (List(OP_0))
ScriptParser.fromString("0") must be (List(OP_0))
}
it must "parse a number larger than an integer into a ScriptNumberImpl" in {
fromString("2147483648") must be (List(BytesToPushOntoStack(5),ScriptNumber(2147483648L)))
ScriptParser.fromString("2147483648") must be (List(BytesToPushOntoStack(5),ScriptNumber(2147483648L)))
}
it must "parse a decimal number and correctly add its corresponding BytesToPushOntoStack" in {
fromString("127") must be (List(BytesToPushOntoStack(1), ScriptNumber(127)))
ScriptParser.fromString("127") must be (List(BytesToPushOntoStack(1), ScriptNumber(127)))
}
it must "parse a decimal number that is pushed onto the stack" in {
val str = "NOP 0x01 1"
fromString(str) must be (List(OP_NOP, BytesToPushOntoStack(1), ScriptConstant("51")))
ScriptParser.fromString(str) must be (List(OP_NOP, BytesToPushOntoStack(1), ScriptConstant("51")))
}
it must "parse a pay-to-pubkey-hash output script" in {
@ -45,66 +44,66 @@ class ScriptParserTest extends FlatSpec with MustMatchers with ScriptParser with
}
it must "parse a pay-to-script-hash output script" in {
val parsedOutput = fromString(TestUtil.p2shOutputScriptNotParsedAsm)
val parsedOutput = ScriptParser.fromString(TestUtil.p2shOutputScriptNotParsedAsm)
parsedOutput must be (TestUtil.p2shOutputScriptAsm)
}
it must "parse a p2pkh output script from a byte array to script tokens" in {
val bytes : Seq[Byte] = decodeHex(TestUtil.p2pkhOutputScript).tail
fromBytes(bytes) must be (TestUtil.p2pkhOutputScriptAsm)
ScriptParser.fromBytes(bytes) must be (TestUtil.p2pkhOutputScriptAsm)
}
it must "parse a p2pkh input script from a byte array to script tokens" in {
val bytes = decodeHex(TestUtil.p2pkhInputScript).tail
fromBytes(bytes) must be (TestUtil.p2pkhInputScriptAsm)
ScriptParser.fromBytes(bytes) must be (TestUtil.p2pkhInputScriptAsm)
}
it must "parse a p2sh input script from a byte array into script tokens" in {
val bytes = decodeHex(TestUtil.rawP2shInputScript).tail
fromBytes(bytes) must be (TestUtil.p2shInputScriptAsm)
ScriptParser.fromBytes(bytes) must be (TestUtil.p2shInputScriptAsm)
}
it must "parse a p2sh outputscript from a byte array into script tokens" in {
val bytes = decodeHex(TestUtil.p2shOutputScript).tail
fromBytes(bytes) must be (TestUtil.p2shOutputScriptAsm)
ScriptParser.fromBytes(bytes) must be (TestUtil.p2shOutputScriptAsm)
}
it must "parse a script constant from 'Az' EQUAL" in {
val str = "'Az' EQUAL"
fromString(str) must equal (List(BytesToPushOntoStack(2), ScriptConstant("417a"), OP_EQUAL))
ScriptParser.fromString(str) must equal (List(BytesToPushOntoStack(2), ScriptConstant("417a"), OP_EQUAL))
}
it must "parse a script number that has a leading zero" in {
val str = "0x02 0x0100"
fromString(str) must equal (List(BytesToPushOntoStack(2), ScriptConstant("0100")))
ScriptParser.fromString(str) must equal (List(BytesToPushOntoStack(2), ScriptConstant("0100")))
}
it must "parse an OP_PICK" in {
val str = "PICK"
fromString(str) must equal (List(OP_PICK))
ScriptParser.fromString(str) must equal (List(OP_PICK))
}
it must "parse an OP_NOP" in {
val str = "NOP"
fromString(str) must equal (List(OP_NOP))
ScriptParser.fromString(str) must equal (List(OP_NOP))
}
it must "parse a script that has a decimal and a hexadecimal number in it " in {
val str = "32767 0x02 0xff7f EQUAL"
fromString(str) must equal (List(BytesToPushOntoStack(2), ScriptConstant("ff7f"),
ScriptParser.fromString(str) must equal (List(BytesToPushOntoStack(2), ScriptConstant("ff7f"),
BytesToPushOntoStack(2), ScriptConstant("ff7f"), OP_EQUAL))
}
it must "parse an OP_1" in {
val str = "0x51"
fromString(str) must equal (List(OP_1))
ScriptParser.fromString(str) must equal (List(OP_1))
}
it must "parse an extremely long hex constant" in {
val str = "0x4b 0x417a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a " +
"'Azzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz' EQUAL"
fromString(str) must equal (List(BytesToPushOntoStack(75),
ScriptParser.fromString(str) must equal (List(BytesToPushOntoStack(75),
ScriptConstant("417a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a"),
BytesToPushOntoStack(75),
ScriptConstant("417a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a"), OP_EQUAL))
@ -112,7 +111,7 @@ class ScriptParserTest extends FlatSpec with MustMatchers with ScriptParser with
it must "parse an OP_IF OP_ENDIF block" in {
val str = "1 0x01 0x80 IF 0 ENDIF"
fromString(str) must be (List(OP_1, BytesToPushOntoStack(1), ScriptConstant("80"), OP_IF, OP_0, OP_ENDIF))
ScriptParser.fromString(str) must be (List(OP_1, BytesToPushOntoStack(1), ScriptConstant("80"), OP_IF, OP_0, OP_ENDIF))
}
@ -120,14 +119,14 @@ class ScriptParserTest extends FlatSpec with MustMatchers with ScriptParser with
val str = "'abcdefghijklmnopqrstuvwxyz' HASH160 0x4c 0x14 0xc286a1af0947f58d1ad787385b1c2c4a976f9e71 EQUAL"
val expectedScript = List(BytesToPushOntoStack(26), ScriptConstant("6162636465666768696a6b6c6d6e6f707172737475767778797a"),OP_HASH160,
OP_PUSHDATA1, ScriptConstant("14"), ScriptConstant("c286a1af0947f58d1ad787385b1c2c4a976f9e71"), OP_EQUAL)
fromString(str) must be (expectedScript)
ScriptParser.fromString(str) must be (expectedScript)
}
it must "parse a OP_PUSHDATA1 correct from a scriptSig" in {
//https://tbtc.blockr.io/api/v1/tx/raw/5d254a872c9197c683ea9111fb5c0e2e0f49280a89961c45b9fea76834d335fe
val str = "4cf1" +
"55210269992fb441ae56968e5b77d46a3e53b69f136444ae65a94041fc937bdb28d93321021df31471281d4478df85bfce08a10aab82601dca949a79950f8ddf7002bd915a2102174c82021492c2c6dfcbfa4187d10d38bed06afb7fdcd72c880179fddd641ea121033f96e43d72c33327b6a4631ccaa6ea07f0b106c88b9dc71c9000bb6044d5e88a210313d8748790f2a86fb524579b46ce3c68fedd58d2a738716249a9f7d5458a15c221030b632eeb079eb83648886122a04c7bf6d98ab5dfb94cf353ee3e9382a4c2fab02102fb54a7fcaa73c307cfd70f3fa66a2e4247a71858ca731396343ad30c7c4009ce57ae"
fromString(str) must be (List(OP_PUSHDATA1, ScriptConstant("f1"),
ScriptParser.fromString(str) must be (List(OP_PUSHDATA1, ScriptConstant("f1"),
ScriptConstant("55210269992fb441ae56968e5b77d46a3e53b69f136444ae65a94041fc937bdb28d93321021df31471281d4478df85bfce08a10aab82601dca949a79950f8ddf7002bd915a2102174c82021492c2c6dfcbfa4187d10d38bed06afb7fdcd72c880179fddd641ea121033f96e43d72c33327b6a4631ccaa6ea07f0b106c88b9dc71c9000bb6044d5e88a210313d8748790f2a86fb524579b46ce3c68fedd58d2a738716249a9f7d5458a15c221030b632eeb079eb83648886122a04c7bf6d98ab5dfb94cf353ee3e9382a4c2fab02102fb54a7fcaa73c307cfd70f3fa66a2e4247a71858ca731396343ad30c7c4009ce57ae"))
)
}
@ -135,7 +134,7 @@ 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)))
ScriptParser.parseBytesFromString(str) must be (List(ScriptNumber(255)))
}
@ -158,7 +157,7 @@ class ScriptParserTest extends FlatSpec with MustMatchers with ScriptParser with
"11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111" +
"1111111"), OP_EQUAL)
fromString(str) must be (expectedScript)
ScriptParser.fromString(str) must be (expectedScript)
}
it must "parse a hex string to a list of script tokens, and then back again" in {
@ -166,7 +165,7 @@ class ScriptParserTest extends FlatSpec with MustMatchers with ScriptParser with
//https://bitcoin.stackexchange.com/questions/37125/how-are-sighash-flags-encoded-into-a-signature
val hex = "304402206e3729f021476102a06ea453cea0a26cb9c096cca641efc4229c1111ed3a96fd022037dce1456a93f53d3e868c789b1b750a48a4c1110cd5b7049779b5f4f3c8b6200103ff1104b46b2141df1948dd0df2223720a3a471ec57404cace47063843a699a0f"
val scriptTokens : Seq[ScriptToken] = fromHex(hex)
val scriptTokens : Seq[ScriptToken] = ScriptParser.fromHex(hex)
scriptTokens.map(_.hex).mkString must be (hex)
}
@ -206,7 +205,7 @@ class ScriptParserTest extends FlatSpec with MustMatchers with ScriptParser with
it must "parse a large string constant found inside of script_valid.json" in {
val str = "'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'"
val parsed = fromString(str)
val parsed = ScriptParser.fromString(str)
parsed must be (List(OP_PUSHDATA2, ScriptConstant("0802"), ScriptConstant(
"62626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262"
)))

View file

@ -1,11 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/scala" isTestSource="true" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>