mirror of
https://github.com/bitcoin-s/bitcoin-s.git
synced 2025-02-22 14:33:06 +01:00
Compile and publish locally before tests (#282)
* Adds CONTRIBUTING.MD * Compile and publish locally before tests
This commit is contained in:
parent
c12bc0dd59
commit
4dd45847fc
2 changed files with 96 additions and 58 deletions
96
CONTRIBUTING.md
Normal file
96
CONTRIBUTING.md
Normal file
|
@ -0,0 +1,96 @@
|
|||
# Contributing to Bitcoin-S
|
||||
|
||||
Bitcoin-S is an open source project where anyone is welcome to contribute. All contributions are encouraged and appreciated, whether that is code, testing, documentation or something else entirely.
|
||||
|
||||
## Communication Channels
|
||||
|
||||
It's possible to communicate with other developers through a variety of communication channels:
|
||||
|
||||
- [Suredbits Slack](https://join.slack.com/t/suredbits/shared_invite/enQtNDEyMjY3MTg1MTg3LTYyYjkwOGUzMDQ4NDAwZjE1M2I3MmQyNWNlZjNlYjg4OGRjYTRjNWUwNjRjNjg4Y2NjZjAxYjU1N2JjMTU1YWM) - Suredbits is a company monetizing APIs through the Lightning Network. Suredbits doesn't own Bitcoin-S, but the Suredbits CEO Chris Stewart is the maintainer of this library. There's a separate Bitcoin-S channel on their Slack, this is probably the easiest way of getting in touch with someone working on this project.
|
||||
- [Bitcoin-S Gitter](https://gitter.im/bitcoin-s-core/)
|
||||
- [#bitcoin-scala](https://webchat.freenode.net/?channels=bitcoin-scala) on IRC Freenode
|
||||
|
||||
## Development
|
||||
|
||||
### `testkit` and circular dependencies
|
||||
|
||||
One issue you might run into when making local changes and compiling/testing is a circular depedency conundrum. Bitcoin-S has multiple submodules, such as `rpc` (interfacing with a Bitcoin Core RPC server), `eclair-rpc` (interfacing with an Eclair RPC server) and `testkit` (utilities for spinning up Bitcoin and Lightning nodes, etc.). `testkit` depends on `rpc` and `eclair-rpc`, and both `rpc` and `eclair-rpc` tests depend on `testkit`. This causes the compiler and build system to have a hard time. We solve this problem by publishing `testkit` as a standalone project in [Bintray](https://bintray.com/beta/#/bitcoin-s/bitcoin-s-core/bitcoin-s-testkit?tab=overview).
|
||||
|
||||
Now, what happens when you need to make changes in `testkit`, and have either `rpc` or `eclair-rpc` utilize these changes?
|
||||
|
||||
1. Change the value of `version in ThisBuild` in [`version.sbt`](version.sbt) by adding `-SNAPSHOT` to it. If the file previously was `version in ThisBuild := "0.0.1"`, change it to `version in ThisBuild := "0.0.1-SNAPSHOT"`
|
||||
2. If you have an active sbt shell/session, do `sbt reload`
|
||||
3. Compile the project: `sbt compile`
|
||||
4. Publish the freshly compiled project locally: `sbt publishLocal`. This places the newly compiled files into `~/.ivy2/local/org.bitcoins`, where sbt will find them.
|
||||
5. Change the value of `Deps.V.bitcoinsV` in [`project/Deps.scala`](project/Deps.scala) to the version number you previously changed in `version.sbt`. In our case, `"0.0.1-SNAPSHOT"`.
|
||||
6. If you have an active sbt shell/session, do `sbt reload` again
|
||||
7. You should now be good to go, and both `sbt test:compile` and `sbt test` should work without issues.
|
||||
|
||||
## Testing
|
||||
|
||||
### 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`](testkit/src/main/scala/org/bitcoins/core/gen/TransactionGenerators.scala) 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 (see [`TransactionSignatureCreatorSpec`](core-test/src/test/scala/org/bitcoins/core/crypto/TransactionSignatureCreatorSpec.scala) line 29-34). First we generate a _supposedly_ validly signed multisig transaction with [`TransactionGenerators.signedMultiSigTransaction`](testkit/src/main/scala/org/bitcoins/core/gen/TransactionGenerators.scala) (line 102-108). 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`](core/src/main/scala/org/bitcoins/core/script/interpreter/ScriptInterpreter.scala). If we have built our functionality correctly the ScriptInterpreter should always return [`ScriptOk`](core/src/main/scala/org/bitcoins/core/script/result/ScriptResult.scala) 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
|
||||
}
|
||||
```
|
||||
|
||||
### Running tests
|
||||
|
||||
To run the entire test suite all you need to do is run the following command
|
||||
|
||||
```scala
|
||||
$ sbt test
|
||||
[info] Elapsed time: 4 min 36.760 sec
|
||||
[info] ScalaCheck
|
||||
[info] Passed: Total 149, Failed 0, Errors 0, Passed 149
|
||||
[info] ScalaTest
|
||||
[info] Run completed in 4 minutes, 55 seconds.
|
||||
[info] Total number of tests run: 744
|
||||
[info] Suites: completed 97, aborted 0
|
||||
[info] Tests: succeeded 744, failed 0, canceled 0, ignored 0, pending 0
|
||||
[info] All tests passed.
|
||||
[info] Passed: Total 909, Failed 0, Errors 0, Passed 909
|
||||
[success] Total time: 297 s, completed Jul 20, 2017 10:34:16 AM
|
||||
```
|
||||
|
||||
To run a specific suite of tests you can specify the suite name in the following way
|
||||
|
||||
```scala
|
||||
$ sbt testOnly *ScriptInterpreterTest*
|
||||
[info] ScriptInterpreterTest:
|
||||
[info] ScriptInterpreter
|
||||
[info] - must evaluate all the scripts from the bitcoin core script_tests.json
|
||||
[info] Run completed in 8 seconds, 208 milliseconds.
|
||||
[info] Total number of tests run: 1
|
||||
[info] Suites: completed 1, aborted 0
|
||||
[info] Tests: succeeded 1, failed 0, canceled 0, ignored 0, pending 0
|
||||
[info] All tests passed.
|
||||
```
|
||||
|
||||
The command `sbt testQuick` can also be handy. It runs tests that either:
|
||||
|
||||
1. Failed previously
|
||||
2. Has not been run previously
|
||||
3. Either the test or one of its dependencies has been recompiled
|
||||
|
||||
For more information on `testQuick`, see the offical [sbt docs](https://www.scala-sbt.org/1.x/docs/Testing.html#testQuick).
|
58
README.md
58
README.md
|
@ -51,30 +51,6 @@ $ sbt -Djava.library.path=/your/class/path
|
|||
|
||||
You can also copy `libsecp256k1.so` to your system library path.
|
||||
|
||||
# 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
|
||||
- Simple [`TransactionBuilder`](https://github.com/MetacoSA/NBitcoin/blob/56bfd1cbca535424b160d8a40688a79de4800630/NBitcoin/TransactionBuilder.cs#L172) similar nbitcoin
|
||||
- Hardware wallet support (trezor, ledger etc)
|
||||
|
@ -190,40 +166,6 @@ program: org.bitcoins.core.script.PreExecutionScriptProgram = PreExecutionScript
|
|||
scala> ScriptInterpreter.run(program)
|
||||
res0: org.bitcoins.core.script.result.ScriptResult = ScriptOk
|
||||
```
|
||||
# Running tests
|
||||
|
||||
To run the entire test suite all you need to do is run the following command
|
||||
```scala
|
||||
|
||||
chris@chris:~/dev/bitcoins-core$ sbt test
|
||||
[info] Elapsed time: 4 min 36.760 sec
|
||||
[info] ScalaCheck
|
||||
[info] Passed: Total 149, Failed 0, Errors 0, Passed 149
|
||||
[info] ScalaTest
|
||||
[info] Run completed in 4 minutes, 55 seconds.
|
||||
[info] Total number of tests run: 744
|
||||
[info] Suites: completed 97, aborted 0
|
||||
[info] Tests: succeeded 744, failed 0, canceled 0, ignored 0, pending 0
|
||||
[info] All tests passed.
|
||||
[info] Passed: Total 909, Failed 0, Errors 0, Passed 909
|
||||
[success] Total time: 297 s, completed Jul 20, 2017 10:34:16 AM
|
||||
chris@chris:~/dev/bitcoin-s-core$
|
||||
```
|
||||
|
||||
To run a specific suite of tests you can specify the suite name in the following way
|
||||
```scala
|
||||
chris@chris:~/dev/bitcoins-core$ sbt
|
||||
> test-only *ScriptInterpreterTest*
|
||||
[info] ScriptInterpreterTest:
|
||||
[info] ScriptInterpreter
|
||||
[info] - must evaluate all the scripts from the bitcoin core script_tests.json
|
||||
[info] Run completed in 8 seconds, 208 milliseconds.
|
||||
[info] Total number of tests run: 1
|
||||
[info] Suites: completed 1, aborted 0
|
||||
[info] Tests: succeeded 1, failed 0, canceled 0, ignored 0, pending 0
|
||||
[info] All tests passed.
|
||||
>
|
||||
```
|
||||
|
||||
# Interacting with bitcoind
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue