mirror of
https://github.com/bitcoin-s/bitcoin-s.git
synced 2025-02-23 22:56:52 +01:00
Added Compute Contract Id test Vectors (#4385)
* Testing contract id calculation * Added implicit json reader imports
This commit is contained in:
parent
cbeae5cdbc
commit
5f82307e27
4 changed files with 103 additions and 6 deletions
|
@ -44,6 +44,8 @@ object JsonSerializers {
|
|||
implicit val doubleSha256DigestBEReads: Reads[DoubleSha256DigestBE] =
|
||||
DoubleSha256DigestBEReads
|
||||
|
||||
implicit val sha256DigestReads: Reads[Sha256Digest] = Sha256DigestReads
|
||||
|
||||
implicit val ripeMd160DigestReads: Reads[RipeMd160Digest] =
|
||||
RipeMd160DigestReads
|
||||
|
||||
|
|
|
@ -27,6 +27,24 @@ import scala.util.Try
|
|||
|
||||
object DLCUtil {
|
||||
|
||||
/** @see https://github.com/discreetlogcontracts/dlcspecs/blob/master/Protocol.md#definition-of-contract_id
|
||||
* @param fundingTxId the id of the transaction that contains the DLC funding output
|
||||
* @param outputIdx the index of the output
|
||||
* @param tempContractId the temporary contractId in the offer message
|
||||
* @return
|
||||
*/
|
||||
def computeContractId(
|
||||
fundingTxId: DoubleSha256DigestBE,
|
||||
outputIdx: Int,
|
||||
tempContractId: Sha256Digest): ByteVector = {
|
||||
val u16 = UInt16(outputIdx)
|
||||
//we need to pad the u16 due to how xor works in scodec so we don't lose precision
|
||||
val padded = ByteVector.fill(30)(0.toByte) ++ u16.bytes
|
||||
fundingTxId.bytes
|
||||
.xor(tempContractId.bytes)
|
||||
.xor(padded)
|
||||
}
|
||||
|
||||
/** @see https://github.com/discreetlogcontracts/dlcspecs/blob/master/Protocol.md#definition-of-contract_id
|
||||
* @param fundingTx the transaction that contains the DLC funding output
|
||||
* @param outputIdx the index of the output
|
||||
|
@ -37,12 +55,7 @@ object DLCUtil {
|
|||
fundingTx: Transaction,
|
||||
outputIdx: Int,
|
||||
tempContractId: Sha256Digest): ByteVector = {
|
||||
val u16 = UInt16(outputIdx)
|
||||
//we need to pad the u16 due to how xor works in scodec so we don't lose precision
|
||||
val padded = ByteVector.fill(30)(0.toByte) ++ u16.bytes
|
||||
fundingTx.txIdBE.bytes
|
||||
.xor(tempContractId.bytes)
|
||||
.xor(padded)
|
||||
computeContractId(fundingTx.txIdBE, outputIdx, tempContractId)
|
||||
}
|
||||
|
||||
/** Extracts an adaptor secret from cetSig assuming it is the completion
|
||||
|
|
26
wallet-test/src/test/resources/contract_id_test.json
Normal file
26
wallet-test/src/test/resources/contract_id_test.json
Normal file
|
@ -0,0 +1,26 @@
|
|||
[
|
||||
{
|
||||
"fundTxId": "22141d1118d666016f384cff3bf7fa124fe9ff0dcc206de88226219be5c6ee04",
|
||||
"fundOutputIndex": 2,
|
||||
"temporaryContractId": "925b5cbfdd7742d9e9ae0a6c869ce58ec56843ab539dd125a34a19661f3dabe9",
|
||||
"contractId": "b04f41aec5a124d886964693bd6b1f9c8a81bca69fbdbccd216c38fdfafb45ef"
|
||||
},
|
||||
{
|
||||
"fundTxId": "67f25e18f0aca45196836508f5b3149fc900bd1709b32cf8f4d9f390744ba0b2",
|
||||
"fundOutputIndex": 0,
|
||||
"temporaryContractId": "83b848da05afbb4aa984731742ace0217cbc1a2bed72abfcdbd3059e171e78b4",
|
||||
"contractId": "e44a16c2f5031f1b3f07161fb71ff4beb5bca73ce4c187042f0af60e6355d806"
|
||||
},
|
||||
{
|
||||
"fundTxId": "f10dc6857bb7562ef1920a5401c8332ac22adf12df695739b6afd5ed0ae2ee9b",
|
||||
"fundOutputIndex": 2,
|
||||
"temporaryContractId": "942bcce00a0a6ca1b41381e290fdcd68474ba6527131b81eeb2a143414fa4f4c",
|
||||
"contractId": "65260a6571bd3a8f45818bb69135fe4285617940ae58ef275d85c1d91e18a1d5"
|
||||
},
|
||||
{
|
||||
"fundTxId": "75511322ccf0422f723ebc359bdde79f46134b046544bbfdd945dc1848cbc5c4",
|
||||
"fundOutputIndex": 1,
|
||||
"temporaryContractId": "c690e64ac286fc379c4b1f6fb69fb17626e589f50b6d6c2efc93ce8f299142b9",
|
||||
"contractId": "b3c1f5680e76be18ee75a35a2d4256e960f6c2f16e29d7d325d61297615a877c"
|
||||
}
|
||||
]
|
|
@ -0,0 +1,56 @@
|
|||
package org.bitcoins.wallet
|
||||
|
||||
import org.bitcoins.commons.serializers.JsonReaders.byteVectorReads
|
||||
import org.bitcoins.commons.serializers.JsonSerializers._
|
||||
import org.bitcoins.core.protocol.dlc.compute.DLCUtil
|
||||
import org.bitcoins.crypto.{DoubleSha256DigestBE, Sha256Digest}
|
||||
import org.bitcoins.testkit.fixtures.EmptyFixture
|
||||
import org.bitcoins.testkit.wallet.BitcoinSWalletTest
|
||||
import play.api.libs.json._
|
||||
import scodec.bits.ByteVector
|
||||
import scala.io.Source
|
||||
|
||||
class ComputeContractIdTest extends BitcoinSWalletTest with EmptyFixture {
|
||||
|
||||
lazy val json: JsValue = {
|
||||
val stream = {
|
||||
val classLoader = getClass().getClassLoader()
|
||||
classLoader.getResourceAsStream("contract_id_test.json")
|
||||
}
|
||||
val rawText = Source
|
||||
.fromInputStream(stream)
|
||||
.getLines()
|
||||
.mkString
|
||||
Json.parse(rawText)
|
||||
}
|
||||
|
||||
case class ContractIdTestVector(
|
||||
fundTxId: DoubleSha256DigestBE,
|
||||
fundOutputIndex: Int,
|
||||
temporaryContractId: Sha256Digest,
|
||||
contractId: ByteVector)
|
||||
|
||||
object ContractIdTestVector {
|
||||
|
||||
implicit val reads: Reads[ContractIdTestVector] =
|
||||
Json.reads[ContractIdTestVector]
|
||||
}
|
||||
|
||||
lazy val vectors: Vector[ContractIdTestVector] =
|
||||
json.validate[Vector[ContractIdTestVector]] match {
|
||||
case JsError(errors) => fail(errors.head.toString)
|
||||
case JsSuccess(value, _) => value
|
||||
}
|
||||
|
||||
"DLCUtil" must "compute contract ids correctly as in the JSON file" in { _ =>
|
||||
vectors.foreach { testVector =>
|
||||
assert(
|
||||
DLCUtil.computeContractId(
|
||||
testVector.fundTxId,
|
||||
testVector.fundOutputIndex,
|
||||
testVector.temporaryContractId) == testVector.contractId)
|
||||
}
|
||||
|
||||
succeed
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue