Added Compute Contract Id test Vectors (#4385)

* Testing contract id calculation

* Added implicit json reader imports
This commit is contained in:
GreyMcCarthy 2022-06-13 15:13:48 -04:00 committed by GitHub
parent cbeae5cdbc
commit 5f82307e27
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 103 additions and 6 deletions

View file

@ -44,6 +44,8 @@ object JsonSerializers {
implicit val doubleSha256DigestBEReads: Reads[DoubleSha256DigestBE] =
DoubleSha256DigestBEReads
implicit val sha256DigestReads: Reads[Sha256Digest] = Sha256DigestReads
implicit val ripeMd160DigestReads: Reads[RipeMd160Digest] =
RipeMd160DigestReads

View file

@ -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

View 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"
}
]

View file

@ -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
}
}