mirror of
https://github.com/bitcoin-s/bitcoin-s.git
synced 2025-02-23 14:50:42 +01:00
Add OrderedSchnorrSignatures, use it in OracleAttestment (#4803)
* Add OrderedSchnorrSignatures, use it in OracleAttestment, propagate it threw the codebase * Small cleanups * Add SortedVecFactory * Fix test case with out of order nonces
This commit is contained in:
parent
a1fad6bcc4
commit
9c506b639f
33 changed files with 394 additions and 204 deletions
|
@ -29,6 +29,7 @@ import org.bitcoins.core.protocol.{
|
||||||
import org.bitcoins.core.psbt.InputPSBTRecord.PartialSignature
|
import org.bitcoins.core.psbt.InputPSBTRecord.PartialSignature
|
||||||
import org.bitcoins.core.psbt.PSBT
|
import org.bitcoins.core.psbt.PSBT
|
||||||
import org.bitcoins.core.util.FutureUtil
|
import org.bitcoins.core.util.FutureUtil
|
||||||
|
import org.bitcoins.core.util.sorted.OrderedSchnorrSignatures
|
||||||
import org.bitcoins.core.wallet.fee.{FeeUnit, SatoshisPerVirtualByte}
|
import org.bitcoins.core.wallet.fee.{FeeUnit, SatoshisPerVirtualByte}
|
||||||
import org.bitcoins.core.wallet.rescan.RescanState
|
import org.bitcoins.core.wallet.rescan.RescanState
|
||||||
import org.bitcoins.core.wallet.utxo._
|
import org.bitcoins.core.wallet.utxo._
|
||||||
|
@ -935,7 +936,7 @@ class RoutesSpec extends AnyWordSpec with ScalatestRouteTest with MockFactory {
|
||||||
val dummyOracleAttestment =
|
val dummyOracleAttestment =
|
||||||
OracleAttestmentV0TLV("eventId",
|
OracleAttestmentV0TLV("eventId",
|
||||||
dummyPubKey.schnorrPublicKey,
|
dummyPubKey.schnorrPublicKey,
|
||||||
Vector(dummyOracleSig),
|
OrderedSchnorrSignatures(dummyOracleSig),
|
||||||
Vector("outcome"))
|
Vector("outcome"))
|
||||||
|
|
||||||
lazy val winStr: String = "WIN"
|
lazy val winStr: String = "WIN"
|
||||||
|
|
|
@ -522,7 +522,7 @@ object DLCParsingTestVector extends TestVectorParser[DLCParsingTestVector] {
|
||||||
val fields = Vector(
|
val fields = Vector(
|
||||||
"tpe" -> Element(OracleEventV0TLV.tpe),
|
"tpe" -> Element(OracleEventV0TLV.tpe),
|
||||||
"length" -> Element(tlv.length),
|
"length" -> Element(tlv.length),
|
||||||
"oracleNonces" -> MultiElement(nonces.vec.map(Element(_))),
|
"oracleNonces" -> MultiElement(nonces.toVector.map(Element(_))),
|
||||||
"eventMaturityEpoch" -> Element(eventMaturity),
|
"eventMaturityEpoch" -> Element(eventMaturity),
|
||||||
"eventDescriptor" -> Element(descriptor),
|
"eventDescriptor" -> Element(descriptor),
|
||||||
"event_uri" -> Element(CryptoUtil.serializeForHash(uri))
|
"event_uri" -> Element(CryptoUtil.serializeForHash(uri))
|
||||||
|
@ -545,7 +545,7 @@ object DLCParsingTestVector extends TestVectorParser[DLCParsingTestVector] {
|
||||||
"length" -> Element(tlv.length),
|
"length" -> Element(tlv.length),
|
||||||
"eventId" -> Element(eventId),
|
"eventId" -> Element(eventId),
|
||||||
"oraclePubKey" -> Element(pubkey),
|
"oraclePubKey" -> Element(pubkey),
|
||||||
"signatures" -> MultiElement(sigs.map(Element(_))),
|
"signatures" -> MultiElement(sigs.toVector.map(Element(_))),
|
||||||
"outcomes" -> MultiElement(outcomes.map(Element(_)))
|
"outcomes" -> MultiElement(outcomes.map(Element(_)))
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ import org.bitcoins.core.protocol.tlv.{
|
||||||
EnumOutcome,
|
EnumOutcome,
|
||||||
OracleAnnouncementV0TLV
|
OracleAnnouncementV0TLV
|
||||||
}
|
}
|
||||||
import org.bitcoins.core.util.sorted.OrderedAnnouncements
|
import org.bitcoins.core.util.sorted.{OrderedAnnouncements, OrderedNonces}
|
||||||
import org.bitcoins.crypto.ECPrivateKey
|
import org.bitcoins.crypto.ECPrivateKey
|
||||||
import org.bitcoins.testkitcore.util.BitcoinSUnitTest
|
import org.bitcoins.testkitcore.util.BitcoinSUnitTest
|
||||||
|
|
||||||
|
@ -67,10 +67,12 @@ class ContractOraclePairTest extends BitcoinSUnitTest {
|
||||||
)
|
)
|
||||||
|
|
||||||
def numericOracleInfo(numDigits: Int): NumericSingleOracleInfo = {
|
def numericOracleInfo(numDigits: Int): NumericSingleOracleInfo = {
|
||||||
|
val unsorted =
|
||||||
|
Vector.fill(numDigits)(ECPrivateKey.freshPrivateKey.schnorrNonce)
|
||||||
|
val sorted = OrderedNonces.fromUnsorted(unsorted)
|
||||||
NumericSingleOracleInfo(
|
NumericSingleOracleInfo(
|
||||||
OracleAnnouncementV0TLV.dummyForKeys(
|
OracleAnnouncementV0TLV.dummyForKeys(ECPrivateKey.freshPrivateKey,
|
||||||
ECPrivateKey.freshPrivateKey,
|
sorted))
|
||||||
Vector.fill(numDigits)(ECPrivateKey.freshPrivateKey.schnorrNonce)))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val oracleInfo1 = numericOracleInfo(1)
|
val oracleInfo1 = numericOracleInfo(1)
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
package org.bitcoins.core.util
|
||||||
|
|
||||||
|
import org.bitcoins.core.util.sorted.OrderedNonces
|
||||||
|
import org.bitcoins.crypto.SchnorrNonce
|
||||||
|
import org.bitcoins.testkitcore.util.BitcoinSUnitTest
|
||||||
|
|
||||||
|
class OrderedNoncesTest extends BitcoinSUnitTest {
|
||||||
|
|
||||||
|
behavior of "OrderedNonces"
|
||||||
|
|
||||||
|
val unsorted = Vector(
|
||||||
|
SchnorrNonce(
|
||||||
|
"c4b89873c8753de3f0a9e94c4a6190badaa983513a6624a3469eb4577904bfea"),
|
||||||
|
SchnorrNonce(
|
||||||
|
"92efe81609c773d97da2b084eb691f48ef5e926acc6eecd629f80fb1184711bc")
|
||||||
|
)
|
||||||
|
|
||||||
|
it must "throw an exception if you create an unordered nonces" in {
|
||||||
|
|
||||||
|
intercept[IllegalArgumentException] {
|
||||||
|
OrderedNonces(unsorted)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
it must "sort nonces with OrderedNonces.fromUnsorted" in {
|
||||||
|
val sorted = OrderedNonces.fromUnsorted(unsorted)
|
||||||
|
assert(sorted.toVector != unsorted)
|
||||||
|
assert(sorted.toVector == Vector(unsorted(1), unsorted(0)))
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
package org.bitcoins.core.util
|
||||||
|
|
||||||
|
import org.bitcoins.core.util.sorted.OrderedSchnorrSignatures
|
||||||
|
import org.bitcoins.crypto.{FieldElement, SchnorrDigitalSignature, SchnorrNonce}
|
||||||
|
import org.bitcoins.testkitcore.util.BitcoinSUnitTest
|
||||||
|
|
||||||
|
class OrderedSchnorrSignaturesTest extends BitcoinSUnitTest {
|
||||||
|
|
||||||
|
behavior of "OrderedSchnorrSignatures"
|
||||||
|
|
||||||
|
val unsorted = Vector(
|
||||||
|
SchnorrDigitalSignature(
|
||||||
|
SchnorrNonce(
|
||||||
|
"c4b89873c8753de3f0a9e94c4a6190badaa983513a6624a3469eb4577904bfea"),
|
||||||
|
FieldElement.one),
|
||||||
|
SchnorrDigitalSignature(
|
||||||
|
SchnorrNonce(
|
||||||
|
"92efe81609c773d97da2b084eb691f48ef5e926acc6eecd629f80fb1184711bc"),
|
||||||
|
FieldElement.one)
|
||||||
|
)
|
||||||
|
|
||||||
|
it must "throw an exception if the signatures are out of order" in {
|
||||||
|
intercept[IllegalArgumentException] {
|
||||||
|
OrderedSchnorrSignatures(unsorted)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
it must "sort the signatures" in {
|
||||||
|
val sorted = OrderedSchnorrSignatures.fromUnsorted(unsorted)
|
||||||
|
assert(sorted.toVector != unsorted)
|
||||||
|
assert(sorted.toVector == Vector(unsorted(1), unsorted(0)))
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,7 +5,7 @@ import org.bitcoins.core.number.UInt32
|
||||||
import org.bitcoins.core.protocol.dlc.compute.SigningVersion
|
import org.bitcoins.core.protocol.dlc.compute.SigningVersion
|
||||||
import org.bitcoins.core.protocol.tlv._
|
import org.bitcoins.core.protocol.tlv._
|
||||||
import org.bitcoins.core.util.NumberUtil
|
import org.bitcoins.core.util.NumberUtil
|
||||||
import org.bitcoins.core.util.sorted.OrderedNonces
|
import org.bitcoins.core.util.sorted.{OrderedNonces, OrderedSchnorrSignatures}
|
||||||
import org.bitcoins.crypto._
|
import org.bitcoins.crypto._
|
||||||
|
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
|
@ -60,10 +60,12 @@ sealed trait CompletedOracleEvent extends OracleEvent {
|
||||||
require(attestations.size == nonces.size,
|
require(attestations.size == nonces.size,
|
||||||
"Must have a signature for every nonce")
|
"Must have a signature for every nonce")
|
||||||
|
|
||||||
def signatures: Vector[SchnorrDigitalSignature] =
|
def signatures: OrderedSchnorrSignatures = {
|
||||||
nonces.vec
|
val unsorted = nonces.toVector
|
||||||
.zip(attestations)
|
.zip(attestations)
|
||||||
.map(sigPieces => SchnorrDigitalSignature(sigPieces._1, sigPieces._2))
|
.map(sigPieces => SchnorrDigitalSignature(sigPieces._1, sigPieces._2))
|
||||||
|
OrderedSchnorrSignatures.fromUnsorted(unsorted)
|
||||||
|
}
|
||||||
|
|
||||||
def oracleAttestmentV0TLV: OracleAttestmentV0TLV =
|
def oracleAttestmentV0TLV: OracleAttestmentV0TLV =
|
||||||
OracleAttestmentV0TLV(eventName,
|
OracleAttestmentV0TLV(eventName,
|
||||||
|
@ -231,7 +233,7 @@ object OracleEvent {
|
||||||
|
|
||||||
CompletedDigitDecompositionV0OracleEvent(
|
CompletedDigitDecompositionV0OracleEvent(
|
||||||
eventDb.pubkey,
|
eventDb.pubkey,
|
||||||
OrderedNonces(sortedEventDbs.map(_.nonce)),
|
OrderedNonces.fromUnsorted(sortedEventDbs.map(_.nonce)),
|
||||||
eventDb.eventName,
|
eventDb.eventName,
|
||||||
eventDb.signingVersion,
|
eventDb.signingVersion,
|
||||||
eventDb.maturationTime,
|
eventDb.maturationTime,
|
||||||
|
@ -248,7 +250,7 @@ object OracleEvent {
|
||||||
|
|
||||||
PendingDigitDecompositionV0OracleEvent(
|
PendingDigitDecompositionV0OracleEvent(
|
||||||
eventDb.pubkey,
|
eventDb.pubkey,
|
||||||
OrderedNonces(sortedEventDbs.map(_.nonce)),
|
OrderedNonces.fromUnsorted(sortedEventDbs.map(_.nonce)),
|
||||||
eventDb.eventName,
|
eventDb.eventName,
|
||||||
eventDb.signingVersion,
|
eventDb.signingVersion,
|
||||||
eventDb.maturationTime,
|
eventDb.maturationTime,
|
||||||
|
|
|
@ -5,10 +5,14 @@ import org.bitcoins.core.protocol.transaction.{
|
||||||
TransactionOutput
|
TransactionOutput
|
||||||
}
|
}
|
||||||
import org.bitcoins.core.wallet.fee.SatoshisPerKiloByte
|
import org.bitcoins.core.wallet.fee.SatoshisPerKiloByte
|
||||||
|
import org.bitcoins.crypto.{
|
||||||
|
CryptoOrdering,
|
||||||
|
SchnorrDigitalSignature,
|
||||||
|
SchnorrNonce
|
||||||
|
}
|
||||||
import scodec.bits._
|
import scodec.bits._
|
||||||
|
|
||||||
import java.math.BigInteger
|
import java.math.BigInteger
|
||||||
import scala.annotation.tailrec
|
|
||||||
import scala.math.Ordering
|
import scala.math.Ordering
|
||||||
|
|
||||||
package object core {
|
package object core {
|
||||||
|
@ -54,23 +58,7 @@ package object core {
|
||||||
}
|
}
|
||||||
|
|
||||||
implicit val byteVectorOrdering: Ordering[ByteVector] =
|
implicit val byteVectorOrdering: Ordering[ByteVector] =
|
||||||
new Ordering[ByteVector] {
|
CryptoOrdering.byteVectorOrdering
|
||||||
|
|
||||||
@tailrec
|
|
||||||
override def compare(x: ByteVector, y: ByteVector): Int = {
|
|
||||||
if (x == y) {
|
|
||||||
0
|
|
||||||
} else if (x.isEmpty) {
|
|
||||||
-1
|
|
||||||
} else if (y.isEmpty) {
|
|
||||||
1
|
|
||||||
} else if (x.head != y.head) {
|
|
||||||
x.head.compare(y.head)
|
|
||||||
} else {
|
|
||||||
compare(x.tail, y.tail)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
implicit val transactionInputOrder: Ordering[TransactionInput] =
|
implicit val transactionInputOrder: Ordering[TransactionInput] =
|
||||||
new Ordering[TransactionInput] {
|
new Ordering[TransactionInput] {
|
||||||
|
@ -87,4 +75,17 @@ package object core {
|
||||||
x.scriptPubKey.hex.compare(y.scriptPubKey.hex)
|
x.scriptPubKey.hex.compare(y.scriptPubKey.hex)
|
||||||
} else x.value.compare(y.value)
|
} else x.value.compare(y.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
implicit val nonceOrdering: Ordering[SchnorrNonce] =
|
||||||
|
CryptoOrdering.nonceOrdering
|
||||||
|
|
||||||
|
implicit val schnorrSignatureOrdering: Ordering[SchnorrDigitalSignature] = {
|
||||||
|
new Ordering[SchnorrDigitalSignature] {
|
||||||
|
override def compare(
|
||||||
|
x: SchnorrDigitalSignature,
|
||||||
|
y: SchnorrDigitalSignature): Int = {
|
||||||
|
nonceOrdering.compare(x.rx, y.rx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -137,7 +137,7 @@ object DLCAdaptorPointComputer {
|
||||||
contractInfo.oracleInfo.singleOracleInfos.map { info =>
|
contractInfo.oracleInfo.singleOracleInfos.map { info =>
|
||||||
val announcement = info.announcement
|
val announcement = info.announcement
|
||||||
val pubKey = announcement.publicKey
|
val pubKey = announcement.publicKey
|
||||||
val nonces = announcement.eventTLV.nonces.vec.map(_.publicKey)
|
val nonces = announcement.eventTLV.nonces.toVector.map(_.publicKey)
|
||||||
|
|
||||||
nonces.map { nonce =>
|
nonces.map { nonce =>
|
||||||
possibleOutcomes.map { outcome =>
|
possibleOutcomes.map { outcome =>
|
||||||
|
|
|
@ -19,7 +19,7 @@ import org.bitcoins.core.protocol.tlv.{
|
||||||
OracleAttestmentTLV
|
OracleAttestmentTLV
|
||||||
}
|
}
|
||||||
import org.bitcoins.core.protocol.transaction.{Transaction, WitnessTransaction}
|
import org.bitcoins.core.protocol.transaction.{Transaction, WitnessTransaction}
|
||||||
import org.bitcoins.core.util.sorted.OrderedAnnouncements
|
import org.bitcoins.core.util.sorted.{OrderedAnnouncements, OrderedNonces}
|
||||||
import org.bitcoins.crypto._
|
import org.bitcoins.crypto._
|
||||||
import scodec.bits.ByteVector
|
import scodec.bits.ByteVector
|
||||||
|
|
||||||
|
@ -263,11 +263,14 @@ object DLCUtil {
|
||||||
val announcementNonces: Vector[Vector[SchnorrNonce]] = {
|
val announcementNonces: Vector[Vector[SchnorrNonce]] = {
|
||||||
announcements
|
announcements
|
||||||
.map(_.eventTLV.nonces)
|
.map(_.eventTLV.nonces)
|
||||||
.map(_.vec)
|
.map(_.toVector)
|
||||||
}
|
}
|
||||||
val resultOpt = oracleSignatures.find { case oracleSignature =>
|
val resultOpt = oracleSignatures.find { case oracleSignature =>
|
||||||
val oracleSigNonces: Vector[SchnorrNonce] = oracleSignature.sigs.map(_.rx)
|
val oracleSigNonces: Vector[SchnorrNonce] = {
|
||||||
announcementNonces.contains(oracleSigNonces)
|
val unsorted = oracleSignature.sigs.map(_.rx).toVector
|
||||||
|
OrderedNonces.fromUnsorted(unsorted).toVector
|
||||||
|
}
|
||||||
|
announcementNonces.exists(_ == oracleSigNonces)
|
||||||
}
|
}
|
||||||
resultOpt
|
resultOpt
|
||||||
}
|
}
|
||||||
|
|
|
@ -138,7 +138,9 @@ object DLCExecutor {
|
||||||
): ExecutedDLCOutcome = {
|
): ExecutedDLCOutcome = {
|
||||||
require(
|
require(
|
||||||
DLCUtil.checkOracleSignaturesAgainstContract(contractInfo, oracleSigs),
|
DLCUtil.checkOracleSignaturesAgainstContract(contractInfo, oracleSigs),
|
||||||
s"Incorrect oracle signatures and contract combination")
|
s"Incorrect oracle signatures and contract combination, got=${oracleSigs} contractInfo.announcement=${contractInfo.oracleInfos
|
||||||
|
.map(_.singleOracleInfos.map(_.announcement.eventTLV.nonces))}"
|
||||||
|
)
|
||||||
val sigOracles = oracleSigs.map(_.oracle)
|
val sigOracles = oracleSigs.map(_.oracle)
|
||||||
|
|
||||||
val oracleInfoOpt = contractInfo.oracleInfos.find { oracleInfo =>
|
val oracleInfoOpt = contractInfo.oracleInfos.find { oracleInfo =>
|
||||||
|
|
|
@ -78,7 +78,7 @@ sealed trait SingleOracleInfo
|
||||||
* This point is used for adaptor signing.
|
* This point is used for adaptor signing.
|
||||||
*/
|
*/
|
||||||
def sigPoint(outcome: DLCOutcomeType): ECPublicKey = {
|
def sigPoint(outcome: DLCOutcomeType): ECPublicKey = {
|
||||||
publicKey.computeSigPoint(outcome.serialized, nonces.vec)
|
publicKey.computeSigPoint(outcome.serialized, nonces.toVector)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Computes the sum of all nonces used in a given outcome */
|
/** Computes the sum of all nonces used in a given outcome */
|
||||||
|
@ -214,7 +214,7 @@ object NumericSingleOracleInfo {
|
||||||
|
|
||||||
def dummyForKeys(
|
def dummyForKeys(
|
||||||
privKey: ECPrivateKey,
|
privKey: ECPrivateKey,
|
||||||
nonces: Vector[SchnorrNonce]): NumericSingleOracleInfo = {
|
nonces: OrderedNonces): NumericSingleOracleInfo = {
|
||||||
NumericSingleOracleInfo(
|
NumericSingleOracleInfo(
|
||||||
OracleAnnouncementV0TLV.dummyForKeys(privKey, nonces))
|
OracleAnnouncementV0TLV.dummyForKeys(privKey, nonces))
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,18 +3,19 @@ package org.bitcoins.core.protocol.dlc.models
|
||||||
import org.bitcoins.core.protocol.dlc.compute.CETCalculator
|
import org.bitcoins.core.protocol.dlc.compute.CETCalculator
|
||||||
import org.bitcoins.core.protocol.tlv._
|
import org.bitcoins.core.protocol.tlv._
|
||||||
import org.bitcoins.core.util.SeqWrapper
|
import org.bitcoins.core.util.SeqWrapper
|
||||||
|
import org.bitcoins.core.util.sorted.OrderedSchnorrSignatures
|
||||||
import org.bitcoins.crypto.{CryptoUtil, ECPrivateKey, SchnorrDigitalSignature}
|
import org.bitcoins.crypto.{CryptoUtil, ECPrivateKey, SchnorrDigitalSignature}
|
||||||
|
|
||||||
/** Corresponds to a set of SchnorrDigitalSignatures given by a single oracle. */
|
/** Corresponds to a set of SchnorrDigitalSignatures given by a single oracle. */
|
||||||
sealed trait OracleSignatures extends SeqWrapper[SchnorrDigitalSignature] {
|
sealed trait OracleSignatures extends SeqWrapper[SchnorrDigitalSignature] {
|
||||||
|
|
||||||
/** This oracle's signatures */
|
/** This oracle's signatures */
|
||||||
def sigs: Vector[SchnorrDigitalSignature]
|
def sigs: OrderedSchnorrSignatures
|
||||||
|
|
||||||
/** The SingleOracleInfo for the oracle whose signatures are stored here. */
|
/** The SingleOracleInfo for the oracle whose signatures are stored here. */
|
||||||
def oracle: SingleOracleInfo
|
def oracle: SingleOracleInfo
|
||||||
|
|
||||||
override def wrapped: Vector[SchnorrDigitalSignature] = sigs
|
override def wrapped: Vector[SchnorrDigitalSignature] = sigs.toVector
|
||||||
|
|
||||||
/** Verifies the signatures against a given outcome. */
|
/** Verifies the signatures against a given outcome. */
|
||||||
def verifySignatures(outcome: DLCOutcomeType): Boolean = {
|
def verifySignatures(outcome: DLCOutcomeType): Boolean = {
|
||||||
|
@ -38,7 +39,7 @@ object OracleSignatures {
|
||||||
|
|
||||||
def apply(
|
def apply(
|
||||||
oracle: SingleOracleInfo,
|
oracle: SingleOracleInfo,
|
||||||
sigs: Vector[SchnorrDigitalSignature]): OracleSignatures = {
|
sigs: OrderedSchnorrSignatures): OracleSignatures = {
|
||||||
oracle match {
|
oracle match {
|
||||||
case info: EnumSingleOracleInfo =>
|
case info: EnumSingleOracleInfo =>
|
||||||
require(sigs.length == 1, s"Expected one signature, got $sigs")
|
require(sigs.length == 1, s"Expected one signature, got $sigs")
|
||||||
|
@ -76,7 +77,7 @@ case class EnumOracleSignature(
|
||||||
oracle: EnumSingleOracleInfo,
|
oracle: EnumSingleOracleInfo,
|
||||||
sig: SchnorrDigitalSignature)
|
sig: SchnorrDigitalSignature)
|
||||||
extends OracleSignatures {
|
extends OracleSignatures {
|
||||||
override def sigs: Vector[SchnorrDigitalSignature] = Vector(sig)
|
override def sigs: OrderedSchnorrSignatures = OrderedSchnorrSignatures(sig)
|
||||||
|
|
||||||
lazy val getOutcome: EnumOutcome = {
|
lazy val getOutcome: EnumOutcome = {
|
||||||
// cast is safe, EnumSingleOracleInfo enforces this
|
// cast is safe, EnumSingleOracleInfo enforces this
|
||||||
|
@ -105,7 +106,7 @@ case class EnumOracleSignature(
|
||||||
/** Wraps a set of oracle signatures of numeric digits. */
|
/** Wraps a set of oracle signatures of numeric digits. */
|
||||||
case class NumericOracleSignatures(
|
case class NumericOracleSignatures(
|
||||||
oracle: NumericSingleOracleInfo,
|
oracle: NumericSingleOracleInfo,
|
||||||
sigs: Vector[SchnorrDigitalSignature])
|
sigs: OrderedSchnorrSignatures)
|
||||||
extends OracleSignatures {
|
extends OracleSignatures {
|
||||||
|
|
||||||
lazy val getOutcome: UnsignedNumericOutcome = {
|
lazy val getOutcome: UnsignedNumericOutcome = {
|
||||||
|
@ -127,7 +128,7 @@ case class NumericOracleSignatures(
|
||||||
.getOrElse(throw new IllegalArgumentException(
|
.getOrElse(throw new IllegalArgumentException(
|
||||||
s"Signature $sig does not match any digit 0-${base - 1}"))
|
s"Signature $sig does not match any digit 0-${base - 1}"))
|
||||||
}
|
}
|
||||||
UnsignedNumericOutcome(digits)
|
UnsignedNumericOutcome(digits.toVector)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Computes the NumericOutcome to which these signatures correspond. */
|
/** Computes the NumericOutcome to which these signatures correspond. */
|
||||||
|
|
|
@ -21,7 +21,11 @@ import org.bitcoins.core.protocol.tlv.TLV.{
|
||||||
import org.bitcoins.core.protocol.transaction._
|
import org.bitcoins.core.protocol.transaction._
|
||||||
import org.bitcoins.core.protocol.{BigSizeUInt, BlockTimeStamp}
|
import org.bitcoins.core.protocol.{BigSizeUInt, BlockTimeStamp}
|
||||||
import org.bitcoins.core.psbt.InputPSBTRecord.PartialSignature
|
import org.bitcoins.core.psbt.InputPSBTRecord.PartialSignature
|
||||||
import org.bitcoins.core.util.sorted.{OrderedAnnouncements, OrderedNonces}
|
import org.bitcoins.core.util.sorted.{
|
||||||
|
OrderedAnnouncements,
|
||||||
|
OrderedNonces,
|
||||||
|
OrderedSchnorrSignatures
|
||||||
|
}
|
||||||
import org.bitcoins.core.wallet.fee.SatoshisPerVirtualByte
|
import org.bitcoins.core.wallet.fee.SatoshisPerVirtualByte
|
||||||
import org.bitcoins.crypto._
|
import org.bitcoins.crypto._
|
||||||
import scodec.bits.ByteVector
|
import scodec.bits.ByteVector
|
||||||
|
@ -775,14 +779,14 @@ case class OracleEventV0TLV(
|
||||||
) extends OracleEventTLV {
|
) extends OracleEventTLV {
|
||||||
|
|
||||||
require(
|
require(
|
||||||
eventDescriptor.noncesNeeded == nonces.vec.size,
|
eventDescriptor.noncesNeeded == nonces.toVector.size,
|
||||||
s"Not enough nonces for this event descriptor, noncesNeeded=${eventDescriptor.noncesNeeded} nonces=${nonces.toVector.size}"
|
s"Not enough nonces for this event descriptor, noncesNeeded=${eventDescriptor.noncesNeeded} nonces=${nonces.toVector.size}"
|
||||||
)
|
)
|
||||||
|
|
||||||
override def tpe: BigSizeUInt = OracleEventV0TLV.tpe
|
override def tpe: BigSizeUInt = OracleEventV0TLV.tpe
|
||||||
|
|
||||||
override val value: ByteVector = {
|
override val value: ByteVector = {
|
||||||
u16PrefixedList(nonces.vec) ++
|
u16PrefixedList(nonces.toVector) ++
|
||||||
eventMaturityEpoch.bytes ++
|
eventMaturityEpoch.bytes ++
|
||||||
eventDescriptor.bytes ++
|
eventDescriptor.bytes ++
|
||||||
strBytes(eventId)
|
strBytes(eventId)
|
||||||
|
@ -805,7 +809,7 @@ object OracleEventV0TLV extends TLVFactory[OracleEventV0TLV] {
|
||||||
val eventDescriptor = iter.take(EventDescriptorTLV)
|
val eventDescriptor = iter.take(EventDescriptorTLV)
|
||||||
val eventId = iter.takeString()
|
val eventId = iter.takeString()
|
||||||
|
|
||||||
OracleEventV0TLV(OrderedNonces(nonces),
|
OracleEventV0TLV(OrderedNonces.fromUnsorted(nonces),
|
||||||
eventMaturity,
|
eventMaturity,
|
||||||
eventDescriptor,
|
eventDescriptor,
|
||||||
eventId)
|
eventId)
|
||||||
|
@ -865,7 +869,7 @@ object OracleAnnouncementV0TLV extends TLVFactory[OracleAnnouncementV0TLV] {
|
||||||
val dummyPrivKey: ECPrivateKey = ECPrivateKey.fromHex(
|
val dummyPrivKey: ECPrivateKey = ECPrivateKey.fromHex(
|
||||||
"f04671ab68f3fefbeaa344c49149748f722287a81b19cd956b2332d07b8f6853")
|
"f04671ab68f3fefbeaa344c49149748f722287a81b19cd956b2332d07b8f6853")
|
||||||
val event = OracleEventV0TLV(
|
val event = OracleEventV0TLV(
|
||||||
OrderedNonces(Vector(dummyPrivKey.schnorrNonce)),
|
OrderedNonces.fromUnsorted(Vector(dummyPrivKey.schnorrNonce)),
|
||||||
UInt32.zero,
|
UInt32.zero,
|
||||||
EnumEventDescriptorV0TLV.dummy,
|
EnumEventDescriptorV0TLV.dummy,
|
||||||
"dummy")
|
"dummy")
|
||||||
|
@ -881,7 +885,7 @@ object OracleAnnouncementV0TLV extends TLVFactory[OracleAnnouncementV0TLV] {
|
||||||
nonce: SchnorrNonce,
|
nonce: SchnorrNonce,
|
||||||
events: Vector[EnumOutcome]): OracleAnnouncementTLV = {
|
events: Vector[EnumOutcome]): OracleAnnouncementTLV = {
|
||||||
val event = OracleEventV0TLV(
|
val event = OracleEventV0TLV(
|
||||||
OrderedNonces(Vector(nonce)),
|
OrderedNonces.fromUnsorted(Vector(nonce)),
|
||||||
UInt32.zero,
|
UInt32.zero,
|
||||||
EnumEventDescriptorV0TLV(events.map(outcome => outcome.outcome)),
|
EnumEventDescriptorV0TLV(events.map(outcome => outcome.outcome)),
|
||||||
"dummy")
|
"dummy")
|
||||||
|
@ -893,17 +897,14 @@ object OracleAnnouncementV0TLV extends TLVFactory[OracleAnnouncementV0TLV] {
|
||||||
|
|
||||||
def dummyForKeys(
|
def dummyForKeys(
|
||||||
privKey: ECPrivateKey,
|
privKey: ECPrivateKey,
|
||||||
nonces: Vector[SchnorrNonce]): OracleAnnouncementTLV = {
|
nonces: OrderedNonces): OracleAnnouncementTLV = {
|
||||||
val eventDescriptor = DigitDecompositionEventDescriptorV0TLV(UInt16(2),
|
val eventDescriptor = DigitDecompositionEventDescriptorV0TLV(UInt16(2),
|
||||||
isSigned =
|
isSigned =
|
||||||
false,
|
false,
|
||||||
nonces.length,
|
nonces.length,
|
||||||
"dummy",
|
"dummy",
|
||||||
Int32.zero)
|
Int32.zero)
|
||||||
val event = OracleEventV0TLV(OrderedNonces(nonces),
|
val event = OracleEventV0TLV(nonces, UInt32.zero, eventDescriptor, "dummy")
|
||||||
UInt32.zero,
|
|
||||||
eventDescriptor,
|
|
||||||
"dummy")
|
|
||||||
val sig =
|
val sig =
|
||||||
privKey.schnorrSign(CryptoUtil.sha256DLCAnnouncement(event.bytes).bytes)
|
privKey.schnorrSign(CryptoUtil.sha256DLCAnnouncement(event.bytes).bytes)
|
||||||
|
|
||||||
|
@ -916,7 +917,8 @@ object OracleAnnouncementV0TLV extends TLVFactory[OracleAnnouncementV0TLV] {
|
||||||
sealed trait OracleAttestmentTLV extends DLCOracleTLV {
|
sealed trait OracleAttestmentTLV extends DLCOracleTLV {
|
||||||
def eventId: NormalizedString
|
def eventId: NormalizedString
|
||||||
def publicKey: SchnorrPublicKey
|
def publicKey: SchnorrPublicKey
|
||||||
def sigs: Vector[SchnorrDigitalSignature]
|
def sigs: OrderedSchnorrSignatures
|
||||||
|
|
||||||
def outcomes: Vector[NormalizedString]
|
def outcomes: Vector[NormalizedString]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -931,7 +933,7 @@ object OracleAttestmentTLV extends TLVParentFactory[OracleAttestmentTLV] {
|
||||||
case class OracleAttestmentV0TLV(
|
case class OracleAttestmentV0TLV(
|
||||||
eventId: NormalizedString,
|
eventId: NormalizedString,
|
||||||
publicKey: SchnorrPublicKey,
|
publicKey: SchnorrPublicKey,
|
||||||
sigs: Vector[SchnorrDigitalSignature],
|
sigs: OrderedSchnorrSignatures,
|
||||||
outcomes: Vector[NormalizedString])
|
outcomes: Vector[NormalizedString])
|
||||||
extends OracleAttestmentTLV {
|
extends OracleAttestmentTLV {
|
||||||
require(sigs.nonEmpty, "Cannot have 0 signatures")
|
require(sigs.nonEmpty, "Cannot have 0 signatures")
|
||||||
|
@ -948,7 +950,7 @@ case class OracleAttestmentV0TLV(
|
||||||
|
|
||||||
strBytes(eventId) ++
|
strBytes(eventId) ++
|
||||||
publicKey.bytes ++
|
publicKey.bytes ++
|
||||||
u16PrefixedList(sigs) ++
|
u16PrefixedList(sigs.toVector) ++
|
||||||
outcomesBytes
|
outcomesBytes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -967,7 +969,10 @@ object OracleAttestmentV0TLV extends TLVFactory[OracleAttestmentV0TLV] {
|
||||||
iter.takeString()
|
iter.takeString()
|
||||||
}
|
}
|
||||||
|
|
||||||
OracleAttestmentV0TLV(eventId, pubKey, sigs, outcomes)
|
OracleAttestmentV0TLV(eventId,
|
||||||
|
pubKey,
|
||||||
|
OrderedSchnorrSignatures.fromUnsorted(sigs),
|
||||||
|
outcomes)
|
||||||
}
|
}
|
||||||
|
|
||||||
lazy val dummy: OracleAttestmentV0TLV = {
|
lazy val dummy: OracleAttestmentV0TLV = {
|
||||||
|
@ -978,7 +983,7 @@ object OracleAttestmentV0TLV extends TLVFactory[OracleAttestmentV0TLV] {
|
||||||
|
|
||||||
OracleAttestmentV0TLV(eventId,
|
OracleAttestmentV0TLV(eventId,
|
||||||
key.schnorrPublicKey,
|
key.schnorrPublicKey,
|
||||||
Vector(sig),
|
OrderedSchnorrSignatures(sig),
|
||||||
Vector(outcome))
|
Vector(outcome))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,13 +3,19 @@ package org.bitcoins.core.util.sorted
|
||||||
import org.bitcoins.crypto.SchnorrNonce
|
import org.bitcoins.crypto.SchnorrNonce
|
||||||
|
|
||||||
/** Represents an ordered set of SchnorrNonces */
|
/** Represents an ordered set of SchnorrNonces */
|
||||||
case class OrderedNonces(vec: Vector[SchnorrNonce])
|
case class OrderedNonces(private val vec: Vector[SchnorrNonce])
|
||||||
extends SortedVec[SchnorrNonce, SchnorrNonce](vec,
|
extends SortedVec[SchnorrNonce, SchnorrNonce](
|
||||||
SortedVec.forOrdered(vec))
|
vec,
|
||||||
|
org.bitcoins.core.nonceOrdering)
|
||||||
|
|
||||||
object OrderedNonces {
|
object OrderedNonces extends SortedVecFactory[SchnorrNonce, OrderedNonces] {
|
||||||
|
|
||||||
def apply(single: SchnorrNonce): OrderedNonces = {
|
override def apply(single: SchnorrNonce): OrderedNonces = {
|
||||||
OrderedNonces(Vector(single))
|
OrderedNonces(Vector(single))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override def fromUnsorted(vec: Vector[SchnorrNonce]): OrderedNonces = {
|
||||||
|
val sorted = vec.sorted(org.bitcoins.core.nonceOrdering)
|
||||||
|
OrderedNonces(sorted)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
package org.bitcoins.core.util.sorted
|
||||||
|
|
||||||
|
import org.bitcoins.crypto.SchnorrDigitalSignature
|
||||||
|
|
||||||
|
case class OrderedSchnorrSignatures(
|
||||||
|
private val vec: Vector[SchnorrDigitalSignature])
|
||||||
|
extends SortedVec[SchnorrDigitalSignature, SchnorrDigitalSignature](
|
||||||
|
vec,
|
||||||
|
org.bitcoins.core.schnorrSignatureOrdering)
|
||||||
|
|
||||||
|
object OrderedSchnorrSignatures
|
||||||
|
extends SortedVecFactory[
|
||||||
|
SchnorrDigitalSignature,
|
||||||
|
OrderedSchnorrSignatures] {
|
||||||
|
|
||||||
|
override def apply(sig: SchnorrDigitalSignature): OrderedSchnorrSignatures = {
|
||||||
|
OrderedSchnorrSignatures(Vector(sig))
|
||||||
|
}
|
||||||
|
|
||||||
|
def fromUnsorted(
|
||||||
|
vec: Vector[SchnorrDigitalSignature]): OrderedSchnorrSignatures = {
|
||||||
|
val sorted = vec.sorted(org.bitcoins.core.schnorrSignatureOrdering)
|
||||||
|
OrderedSchnorrSignatures(sorted)
|
||||||
|
}
|
||||||
|
}
|
|
@ -38,3 +38,9 @@ object SortedVec {
|
||||||
SortedVecImpl(vec)
|
SortedVecImpl(vec)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trait SortedVecFactory[U, T <: SortedVec[U, U]] {
|
||||||
|
|
||||||
|
def apply(t: U): T
|
||||||
|
def fromUnsorted(vec: Vector[U]): T
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
package org.bitcoins.crypto
|
||||||
|
|
||||||
|
import scodec.bits.ByteVector
|
||||||
|
|
||||||
|
import scala.annotation.tailrec
|
||||||
|
|
||||||
|
object CryptoOrdering {
|
||||||
|
|
||||||
|
val nonceOrdering: Ordering[SchnorrNonce] = {
|
||||||
|
new Ordering[SchnorrNonce] {
|
||||||
|
override def compare(x: SchnorrNonce, y: SchnorrNonce): Int = {
|
||||||
|
byteVectorOrdering.compare(x.bytes, y.bytes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val byteVectorOrdering: Ordering[ByteVector] =
|
||||||
|
new Ordering[ByteVector] {
|
||||||
|
|
||||||
|
@tailrec
|
||||||
|
override def compare(x: ByteVector, y: ByteVector): Int = {
|
||||||
|
if (x == y) {
|
||||||
|
0
|
||||||
|
} else if (x.isEmpty) {
|
||||||
|
-1
|
||||||
|
} else if (y.isEmpty) {
|
||||||
|
1
|
||||||
|
} else if (x.head != y.head) {
|
||||||
|
x.head.compare(y.head)
|
||||||
|
} else {
|
||||||
|
compare(x.tail, y.tail)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -277,6 +277,16 @@ object ECPrivateKey extends Factory[ECPrivateKey] {
|
||||||
|
|
||||||
/** Generates a fresh [[org.bitcoins.crypto.ECPrivateKey ECPrivateKey]] that has not been used before. */
|
/** Generates a fresh [[org.bitcoins.crypto.ECPrivateKey ECPrivateKey]] that has not been used before. */
|
||||||
def freshPrivateKey: ECPrivateKey = CryptoUtil.freshPrivateKey
|
def freshPrivateKey: ECPrivateKey = CryptoUtil.freshPrivateKey
|
||||||
|
|
||||||
|
/** Generates [[num]] private keys that are ordered by [[ECPrivateKey.schnorrNonce]] */
|
||||||
|
def generateNonceOrderedPrivKeys(num: Int): Vector[ECPrivateKey] = {
|
||||||
|
val privKeys = 0.to(num).map(_ => ECPrivateKey.freshPrivateKey).toVector
|
||||||
|
val sortByNonce = privKeys
|
||||||
|
.map(p => (p, p.schnorrNonce))
|
||||||
|
.sortBy(_._2)(CryptoOrdering.nonceOrdering)
|
||||||
|
|
||||||
|
sortByNonce.map(_._1)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Created by chris on 2/16/16.
|
/** Created by chris on 2/16/16.
|
||||||
|
|
|
@ -6,6 +6,7 @@ import org.bitcoins.core.protocol.tlv.{
|
||||||
OracleAnnouncementV0TLV,
|
OracleAnnouncementV0TLV,
|
||||||
OracleAttestmentV0TLV
|
OracleAttestmentV0TLV
|
||||||
}
|
}
|
||||||
|
import org.bitcoins.core.util.sorted.OrderedSchnorrSignatures
|
||||||
import org.bitcoins.crypto.FieldElement
|
import org.bitcoins.crypto.FieldElement
|
||||||
import org.bitcoins.testkitcore.util.BitcoinSUnitTest
|
import org.bitcoins.testkitcore.util.BitcoinSUnitTest
|
||||||
|
|
||||||
|
@ -22,9 +23,11 @@ class AttestationVerificationTest extends BitcoinSUnitTest {
|
||||||
val validEnumAttestation: OracleAttestmentV0TLV = OracleAttestmentV0TLV(
|
val validEnumAttestation: OracleAttestmentV0TLV = OracleAttestmentV0TLV(
|
||||||
"fdd868690474657374545aa0024da81c3fec63e56e07ee141cbefbd2c6e7d4dede124fe856ea453a8500013168cb6d4c4e52aeb5bb75ce141cd9e1aa40e1d9123134d9aa390cffb338d51e323d991dadb52f32d0541027f973c363c0b746bb40dd1d42686f172d88ddef380161")
|
"fdd868690474657374545aa0024da81c3fec63e56e07ee141cbefbd2c6e7d4dede124fe856ea453a8500013168cb6d4c4e52aeb5bb75ce141cd9e1aa40e1d9123134d9aa390cffb338d51e323d991dadb52f32d0541027f973c363c0b746bb40dd1d42686f172d88ddef380161")
|
||||||
|
|
||||||
val invalidEnumAttestation: OracleAttestmentV0TLV =
|
val invalidEnumAttestation: OracleAttestmentV0TLV = {
|
||||||
|
val unsorted = validEnumAttestation.sigs.map(_.copy(sig = FieldElement.one))
|
||||||
validEnumAttestation.copy(sigs =
|
validEnumAttestation.copy(sigs =
|
||||||
validEnumAttestation.sigs.map(_.copy(sig = FieldElement.one)))
|
OrderedSchnorrSignatures.fromUnsorted(unsorted.toVector))
|
||||||
|
}
|
||||||
|
|
||||||
val unsignedDigitDecompAnnouncement: OracleAnnouncementV0TLV =
|
val unsignedDigitDecompAnnouncement: OracleAnnouncementV0TLV =
|
||||||
OracleAnnouncementV0TLV(
|
OracleAnnouncementV0TLV(
|
||||||
|
@ -35,10 +38,12 @@ class AttestationVerificationTest extends BitcoinSUnitTest {
|
||||||
"fdd868fd01b40564756d6d79545aa0024da81c3fec63e56e07ee141cbefbd2c6e7d4dede124fe856ea453a850006280b657b9c1cd8de3da2619194e2c71831598be3e60d39a242c232f580451c43050ce8ac95b549bb5fed9e3800cf3c040207071032a5c458485ad1817373c0b7bd61d1a6c395c99202058ddabf851e1c8220f12bd801bbb90efcf45d4a2d769cdaa4e883da6b59cac21fc8f18dae7893997d5d13ac63f33fdb7643bba4c4fc8d57ae1c605b9d36ff8477baa8c216abbfe6c3742236ecfad2415745a7cf7850c6cb6a147a2e2a8875133147055027ed130dec47c6a9f75983d532a5c5940a763546f4835c5b80ca64832a6b9e7526fd575db4913ce0a9686072c5f970f94c3a2e72d0655c541eac15e9caa5af059c1f3e433507f1782e8775c555f1c402509f0c87d4b2e93e52b2283c81185fb8ab14a757ff04b00b821d1aaac0a81e05d15da68e710b25a91bfdacf179d9da3b90dec98844d8ac1ed534922dfa362b9db86c134ca823f9aa4b18525521073096f73fd583205086c7db2b6ac243901e4f1898bc476a311fbcd5d2fb7a355a9032c67dead084fe66eed00f7e9646e6fa83902bc7013001300130013001300130")
|
"fdd868fd01b40564756d6d79545aa0024da81c3fec63e56e07ee141cbefbd2c6e7d4dede124fe856ea453a850006280b657b9c1cd8de3da2619194e2c71831598be3e60d39a242c232f580451c43050ce8ac95b549bb5fed9e3800cf3c040207071032a5c458485ad1817373c0b7bd61d1a6c395c99202058ddabf851e1c8220f12bd801bbb90efcf45d4a2d769cdaa4e883da6b59cac21fc8f18dae7893997d5d13ac63f33fdb7643bba4c4fc8d57ae1c605b9d36ff8477baa8c216abbfe6c3742236ecfad2415745a7cf7850c6cb6a147a2e2a8875133147055027ed130dec47c6a9f75983d532a5c5940a763546f4835c5b80ca64832a6b9e7526fd575db4913ce0a9686072c5f970f94c3a2e72d0655c541eac15e9caa5af059c1f3e433507f1782e8775c555f1c402509f0c87d4b2e93e52b2283c81185fb8ab14a757ff04b00b821d1aaac0a81e05d15da68e710b25a91bfdacf179d9da3b90dec98844d8ac1ed534922dfa362b9db86c134ca823f9aa4b18525521073096f73fd583205086c7db2b6ac243901e4f1898bc476a311fbcd5d2fb7a355a9032c67dead084fe66eed00f7e9646e6fa83902bc7013001300130013001300130")
|
||||||
|
|
||||||
// this one was generated with the same public key
|
// this one was generated with the same public key
|
||||||
val invalidUnsignedDigitDecompAttestation: OracleAttestmentV0TLV =
|
val invalidUnsignedDigitDecompAttestation: OracleAttestmentV0TLV = {
|
||||||
validUnsignedDigitDecompAttestation.copy(sigs =
|
val unsorted = validUnsignedDigitDecompAttestation.sigs.map(
|
||||||
validUnsignedDigitDecompAttestation.sigs.map(
|
_.copy(sig = FieldElement.one))
|
||||||
_.copy(sig = FieldElement.one)))
|
val sorted = OrderedSchnorrSignatures.fromUnsorted(unsorted.toVector)
|
||||||
|
validUnsignedDigitDecompAttestation.copy(sigs = sorted)
|
||||||
|
}
|
||||||
|
|
||||||
// this one was generated with a different public key
|
// this one was generated with a different public key
|
||||||
val invalidUnsignedDigitDecompAttestation1: OracleAttestmentV0TLV =
|
val invalidUnsignedDigitDecompAttestation1: OracleAttestmentV0TLV =
|
||||||
|
@ -47,16 +52,18 @@ class AttestationVerificationTest extends BitcoinSUnitTest {
|
||||||
|
|
||||||
val signedDigitDecompAnnouncement: OracleAnnouncementV0TLV =
|
val signedDigitDecompAnnouncement: OracleAnnouncementV0TLV =
|
||||||
OracleAnnouncementV0TLV(
|
OracleAnnouncementV0TLV(
|
||||||
"fdd824fd01661aabd9bbcae0207aff9510f05099295f32ff72290cf5c494d3869f582f8c4a6cf1b7d832562047f68ce607eb39dcd7ec8ce64432dc51a8853dc5a3acd96a8bc5545aa0024da81c3fec63e56e07ee141cbefbd2c6e7d4dede124fe856ea453a85fdd822fd010000070652285e89487dc8ce816a81234082394d9602263d35a7322b77299082257767b559c622def4bba15a2ad7fc336edd71ace9b4c366b9eaba22b73df00589e74b7ca5b6c7301ef7dc62aeae1823018107868d8956677421e11ffd8f125f2fedf4a527003355640ee9333cda6c37a92d4989c6ab96eddc9266f0ddce0e2a3ffb77aa9eefa1fe40eddd0fa63f501e9b368eed6ab0cc0d2e5e6da1baa570ed9e857134bbc8a15dd5949eb1203b1d15ae701fe4b04707a1ea54c10fef16308bf806f2aa0b17f8673fe785f6b9ff0718e55b621c8e9d92839759a98b88bd6590a0ff856011fe80fdd80a0f00020105756e697473000000000006067369676e6564")
|
"fdd824fd010126487da78218c4fd04d85575595584c54bbec4f2ab3cb64f820bab24c14f9738f4284846c3780985f5c1189decc7680d9c0dbfa5e454b72ac6e292de0df0121ec22db0a9b26f825ccff38cd776103c952c5ede3fc5da3a69770d446011ac126ffdd8229d00049ef0f2b1e7befd3840b4ae6b9f690c6ed42ba9fcddbcde1a7ee91732d63b802ec1e88c69f414e1b47db730ccd4ec1f6e2049e5ce7d569b9dc42263503efb85ed60cbb1d5d42b28d571ef9cb37dba9927a65c819742267862d88acd50a276ad9a624b05aa3829dc181f785f31a0450299a972cc0eb44384529ef30a9a17c0f2aa63328350fdd80a0e00020004746573740000000000040474657374")
|
||||||
|
|
||||||
val validSignedDigitDecompAttestation: OracleAttestmentV0TLV =
|
val validSignedDigitDecompAttestation: OracleAttestmentV0TLV =
|
||||||
OracleAttestmentV0TLV(
|
OracleAttestmentV0TLV(
|
||||||
"fdd868fd01f7067369676e6564545aa0024da81c3fec63e56e07ee141cbefbd2c6e7d4dede124fe856ea453a8500070652285e89487dc8ce816a81234082394d9602263d35a7322b772990822577670ab288b31d99f56d18d4f34be875c0a4d73aae135c4f50349a1014b686d69841b559c622def4bba15a2ad7fc336edd71ace9b4c366b9eaba22b73df00589e74ba7b82eef2041bf6af1511016cadabe9d52e64d875caf5bfef85903dbc4fc00737ca5b6c7301ef7dc62aeae1823018107868d8956677421e11ffd8f125f2fedf469f40edbb7846274f46a973f5442ece91b5a6e450a8cdcef272058a27176dabba527003355640ee9333cda6c37a92d4989c6ab96eddc9266f0ddce0e2a3ffb7762f10e09f79273ab04d1549c1d60054738fe903575aa732760bd2668530459e9aa9eefa1fe40eddd0fa63f501e9b368eed6ab0cc0d2e5e6da1baa570ed9e857188bae5c59c9ac89bec3fa00c8e1b725789e1af15f7b256ae7f169edfe7f3ef8834bbc8a15dd5949eb1203b1d15ae701fe4b04707a1ea54c10fef16308bf806f2144d3e7aa63705924da607162f59bff757490469c2c8d4e62a1aa0bf27323bcdaa0b17f8673fe785f6b9ff0718e55b621c8e9d92839759a98b88bd6590a0ff85e072b65d258bbfdc653444b08714c2be395b7e645caa214567b22916ffb7ebeb012d013001310130013101300130")
|
"fdd868fd012f0474657374c22db0a9b26f825ccff38cd776103c952c5ede3fc5da3a69770d446011ac126f00049ef0f2b1e7befd3840b4ae6b9f690c6ed42ba9fcddbcde1a7ee91732d63b802ec8230d8b4f0c926fa79dd4d24dcda5487c6e4957f4b208811baa11fde9849dddc1e88c69f414e1b47db730ccd4ec1f6e2049e5ce7d569b9dc42263503efb85ed08bfb84dab00ad7f1d1c07eb8e1559ba0c700e88f7387e936883fe77b406efb560cbb1d5d42b28d571ef9cb37dba9927a65c819742267862d88acd50a276ad9a1b25f23a7c49150f83f6b241a5b6b0f91951f285853452ae05ea5f7e8f3846a5624b05aa3829dc181f785f31a0450299a972cc0eb44384529ef30a9a17c0f2aa593b017b084ea40c7f364e5235c9a27f659dc2cfa689e0aa80f4a4cacd4d4de10131013101300130")
|
||||||
|
|
||||||
val invalidSignedDigitDecompAttestation: OracleAttestmentV0TLV =
|
val invalidSignedDigitDecompAttestation: OracleAttestmentV0TLV = {
|
||||||
validSignedDigitDecompAttestation.copy(sigs =
|
val unsorted =
|
||||||
validSignedDigitDecompAttestation.sigs.map(
|
validSignedDigitDecompAttestation.sigs.map(_.copy(sig = FieldElement.one))
|
||||||
_.copy(sig = FieldElement.one)))
|
val sorted = OrderedSchnorrSignatures.fromUnsorted(unsorted.toVector)
|
||||||
|
validSignedDigitDecompAttestation.copy(sigs = sorted)
|
||||||
|
}
|
||||||
|
|
||||||
val invalidSignedDigitDecompAttestation1: OracleAttestmentV0TLV =
|
val invalidSignedDigitDecompAttestation1: OracleAttestmentV0TLV =
|
||||||
OracleAttestmentV0TLV(
|
OracleAttestmentV0TLV(
|
||||||
|
|
|
@ -248,7 +248,7 @@ case class DLCOracle()(implicit val conf: DLCOracleAppConfig)
|
||||||
|
|
||||||
nonces = rValueDbs.map(_.nonce)
|
nonces = rValueDbs.map(_.nonce)
|
||||||
|
|
||||||
eventTLV = OracleEventV0TLV(OrderedNonces(nonces),
|
eventTLV = OracleEventV0TLV(OrderedNonces.fromUnsorted(nonces),
|
||||||
epoch,
|
epoch,
|
||||||
descriptor,
|
descriptor,
|
||||||
eventName)
|
eventName)
|
||||||
|
|
|
@ -70,7 +70,7 @@ trait EventDbUtil {
|
||||||
eventName: String,
|
eventName: String,
|
||||||
signingVersion: SigningVersion = SigningVersion.latest): Vector[
|
signingVersion: SigningVersion = SigningVersion.latest): Vector[
|
||||||
EventDb] = {
|
EventDb] = {
|
||||||
val nonces = oracleAnnouncementV0TLV.eventTLV.nonces.vec
|
val nonces = oracleAnnouncementV0TLV.eventTLV.nonces.toVector
|
||||||
nonces.zipWithIndex.map { case (nonce, index) =>
|
nonces.zipWithIndex.map { case (nonce, index) =>
|
||||||
EventDb(
|
EventDb(
|
||||||
nonce = nonce,
|
nonce = nonce,
|
||||||
|
|
|
@ -437,43 +437,6 @@ class DLCExecutionTest extends BitcoinSDualWalletTest {
|
||||||
} yield succeed
|
} yield succeed
|
||||||
}
|
}
|
||||||
|
|
||||||
it must "throw an exception for a enum contract when do not have all the oracle signatures/outcomes" in {
|
|
||||||
wallets =>
|
|
||||||
val walletA = wallets._1.wallet
|
|
||||||
val resultF = for {
|
|
||||||
contractId <- getContractId(walletA)
|
|
||||||
status <- getDLCStatus(walletA)
|
|
||||||
(goodAttestment, _) = {
|
|
||||||
status.contractInfo match {
|
|
||||||
case single: SingleContractInfo =>
|
|
||||||
DLCWalletUtil.getSigs(single)
|
|
||||||
case disjoint: DisjointUnionContractInfo =>
|
|
||||||
sys.error(
|
|
||||||
s"Cannot retrieve sigs for disjoint union contract, got=$disjoint")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//purposefully drop these
|
|
||||||
//we cannot drop just a sig, or just an outcome because
|
|
||||||
//of invariants in OracleAttestmentV0TLV
|
|
||||||
badSigs = goodAttestment.sigs.dropRight(1)
|
|
||||||
badOutcomes = goodAttestment.outcomes.dropRight(1)
|
|
||||||
badAttestment = OracleAttestmentV0TLV(eventId = goodAttestment.eventId,
|
|
||||||
publicKey =
|
|
||||||
goodAttestment.publicKey,
|
|
||||||
sigs = badSigs,
|
|
||||||
outcomes = badOutcomes)
|
|
||||||
func = (wallet: DLCWallet) =>
|
|
||||||
wallet.executeDLC(contractId, badAttestment).map(_.get)
|
|
||||||
|
|
||||||
result <- dlcExecutionTest(wallets = wallets,
|
|
||||||
asInitiator = true,
|
|
||||||
func = func,
|
|
||||||
expectedOutputs = 1)
|
|
||||||
} yield assert(result)
|
|
||||||
|
|
||||||
recoverToSucceededIf[IllegalArgumentException](resultF)
|
|
||||||
}
|
|
||||||
|
|
||||||
it must "throw an exception when you try to execute a DLC in the SIGNED state" in {
|
it must "throw an exception when you try to execute a DLC in the SIGNED state" in {
|
||||||
wallets =>
|
wallets =>
|
||||||
val walletA = wallets._1.wallet
|
val walletA = wallets._1.wallet
|
||||||
|
|
|
@ -4,7 +4,10 @@ import org.bitcoins.core.currency.Satoshis
|
||||||
import org.bitcoins.core.protocol.dlc.models.DLCStatus.{Claimed, RemoteClaimed}
|
import org.bitcoins.core.protocol.dlc.models.DLCStatus.{Claimed, RemoteClaimed}
|
||||||
import org.bitcoins.core.protocol.dlc.models._
|
import org.bitcoins.core.protocol.dlc.models._
|
||||||
import org.bitcoins.core.protocol.tlv._
|
import org.bitcoins.core.protocol.tlv._
|
||||||
import org.bitcoins.core.util.sorted.OrderedAnnouncements
|
import org.bitcoins.core.util.sorted.{
|
||||||
|
OrderedAnnouncements,
|
||||||
|
OrderedSchnorrSignatures
|
||||||
|
}
|
||||||
import org.bitcoins.crypto.{CryptoUtil, ECPrivateKey, SchnorrDigitalSignature}
|
import org.bitcoins.crypto.{CryptoUtil, ECPrivateKey, SchnorrDigitalSignature}
|
||||||
import org.bitcoins.testkit.wallet.BitcoinSDualWalletTest
|
import org.bitcoins.testkit.wallet.BitcoinSDualWalletTest
|
||||||
import org.bitcoins.testkit.wallet.DLCWalletUtil._
|
import org.bitcoins.testkit.wallet.DLCWalletUtil._
|
||||||
|
@ -77,7 +80,7 @@ class DLCMultiOracleEnumExecutionTest extends BitcoinSDualWalletTest {
|
||||||
val initiatorWinSig = priv.schnorrSignWithNonce(hash, kValue)
|
val initiatorWinSig = priv.schnorrSignWithNonce(hash, kValue)
|
||||||
OracleAttestmentV0TLV(eventId,
|
OracleAttestmentV0TLV(eventId,
|
||||||
priv.schnorrPublicKey,
|
priv.schnorrPublicKey,
|
||||||
Vector(initiatorWinSig),
|
OrderedSchnorrSignatures(initiatorWinSig),
|
||||||
Vector(initiatorWinStr))
|
Vector(initiatorWinStr))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,7 +101,7 @@ class DLCMultiOracleEnumExecutionTest extends BitcoinSDualWalletTest {
|
||||||
val recipientWinSig = priv.schnorrSignWithNonce(hash, kValue)
|
val recipientWinSig = priv.schnorrSignWithNonce(hash, kValue)
|
||||||
OracleAttestmentV0TLV(eventId,
|
OracleAttestmentV0TLV(eventId,
|
||||||
priv.schnorrPublicKey,
|
priv.schnorrPublicKey,
|
||||||
Vector(recipientWinSig),
|
OrderedSchnorrSignatures(recipientWinSig),
|
||||||
Vector(recipientWinStr))
|
Vector(recipientWinStr))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,11 @@ import org.bitcoins.core.currency.Satoshis
|
||||||
import org.bitcoins.core.protocol.dlc.models.DLCStatus.{Claimed, RemoteClaimed}
|
import org.bitcoins.core.protocol.dlc.models.DLCStatus.{Claimed, RemoteClaimed}
|
||||||
import org.bitcoins.core.protocol.dlc.models._
|
import org.bitcoins.core.protocol.dlc.models._
|
||||||
import org.bitcoins.core.protocol.tlv._
|
import org.bitcoins.core.protocol.tlv._
|
||||||
import org.bitcoins.core.util.sorted.OrderedAnnouncements
|
import org.bitcoins.core.util.sorted.{
|
||||||
|
OrderedAnnouncements,
|
||||||
|
OrderedNonces,
|
||||||
|
OrderedSchnorrSignatures
|
||||||
|
}
|
||||||
import org.bitcoins.crypto._
|
import org.bitcoins.crypto._
|
||||||
import org.bitcoins.testkitcore.dlc.DLCTest.genNumericOracleOutcome
|
import org.bitcoins.testkitcore.dlc.DLCTest.genNumericOracleOutcome
|
||||||
import org.bitcoins.testkit.wallet.DLCWalletUtil._
|
import org.bitcoins.testkit.wallet.DLCWalletUtil._
|
||||||
|
@ -18,19 +22,32 @@ class DLCMultiOracleExactNumericExecutionTest extends BitcoinSDualWalletTest {
|
||||||
|
|
||||||
behavior of "DLCWallet"
|
behavior of "DLCWallet"
|
||||||
|
|
||||||
val privateKeys: Vector[ECPrivateKey] =
|
val privateKeys: Vector[ECPrivateKey] = {
|
||||||
0.until(5).map(_ => ECPrivateKey.freshPrivateKey).toVector
|
val unsorted = 0.until(5).map(_ => ECPrivateKey.freshPrivateKey).toVector
|
||||||
|
val nonces = unsorted
|
||||||
|
.map(u => (u, u.schnorrNonce))
|
||||||
|
.sortBy(_._2)(org.bitcoins.core.nonceOrdering)
|
||||||
|
nonces.map(_._1)
|
||||||
|
}
|
||||||
|
|
||||||
val kValues: Vector[Vector[ECPrivateKey]] =
|
val kValues: Vector[Vector[ECPrivateKey]] = {
|
||||||
privateKeys.map(_ =>
|
privateKeys.map { _ =>
|
||||||
0.until(numDigits).map(_ => ECPrivateKey.freshPrivateKey).toVector)
|
val unsorted =
|
||||||
|
0.until(numDigits).map(_ => ECPrivateKey.freshPrivateKey).toVector
|
||||||
|
val sorted = unsorted
|
||||||
|
.map(u => (u, u.schnorrNonce))
|
||||||
|
.sortBy(_._2)(org.bitcoins.core.nonceOrdering)
|
||||||
|
sorted.map(_._1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val contractDescriptor: NumericContractDescriptor =
|
val contractDescriptor: NumericContractDescriptor =
|
||||||
DLCWalletUtil.multiNonceContractDescriptor
|
DLCWalletUtil.multiNonceContractDescriptor
|
||||||
|
|
||||||
val announcements: Vector[OracleAnnouncementTLV] =
|
val announcements: Vector[OracleAnnouncementTLV] =
|
||||||
privateKeys.zip(kValues).map { case (priv, ks) =>
|
privateKeys.zip(kValues).map { case (priv, ks) =>
|
||||||
OracleAnnouncementV0TLV.dummyForKeys(priv, ks.map(_.schnorrNonce))
|
val ordered = OrderedNonces.fromUnsorted(ks.map(_.schnorrNonce))
|
||||||
|
OracleAnnouncementV0TLV.dummyForKeys(priv, ordered)
|
||||||
}
|
}
|
||||||
|
|
||||||
val threshold = 3
|
val threshold = 3
|
||||||
|
@ -228,7 +245,7 @@ class DLCMultiOracleExactNumericExecutionTest extends BitcoinSDualWalletTest {
|
||||||
s"kValues.length=${kValues.length} sigs.length=${sigs.length}")
|
s"kValues.length=${kValues.length} sigs.length=${sigs.length}")
|
||||||
OracleAttestmentV0TLV(eventId,
|
OracleAttestmentV0TLV(eventId,
|
||||||
priv.schnorrPublicKey,
|
priv.schnorrPublicKey,
|
||||||
sigs,
|
OrderedSchnorrSignatures.fromUnsorted(sigs),
|
||||||
digitsPadded.map(_.toString))
|
digitsPadded.map(_.toString))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,11 @@ import org.bitcoins.core.currency.Satoshis
|
||||||
import org.bitcoins.core.protocol.dlc.models.DLCStatus.{Claimed, RemoteClaimed}
|
import org.bitcoins.core.protocol.dlc.models.DLCStatus.{Claimed, RemoteClaimed}
|
||||||
import org.bitcoins.core.protocol.dlc.models._
|
import org.bitcoins.core.protocol.dlc.models._
|
||||||
import org.bitcoins.core.protocol.tlv._
|
import org.bitcoins.core.protocol.tlv._
|
||||||
import org.bitcoins.core.util.sorted.OrderedAnnouncements
|
import org.bitcoins.core.util.sorted.{
|
||||||
|
OrderedAnnouncements,
|
||||||
|
OrderedNonces,
|
||||||
|
OrderedSchnorrSignatures
|
||||||
|
}
|
||||||
import org.bitcoins.crypto._
|
import org.bitcoins.crypto._
|
||||||
import org.bitcoins.testkitcore.dlc.DLCTest
|
import org.bitcoins.testkitcore.dlc.DLCTest
|
||||||
import org.bitcoins.testkit.wallet.DLCWalletUtil._
|
import org.bitcoins.testkit.wallet.DLCWalletUtil._
|
||||||
|
@ -20,19 +24,33 @@ class DLCMultiOracleNumericExecutionTest
|
||||||
|
|
||||||
behavior of "DLCWallet"
|
behavior of "DLCWallet"
|
||||||
|
|
||||||
val privateKeys: Vector[ECPrivateKey] =
|
val privateKeys: Vector[ECPrivateKey] = {
|
||||||
0.until(5).map(_ => ECPrivateKey.freshPrivateKey).toVector
|
val unsorted = 0.until(5).map(_ => ECPrivateKey.freshPrivateKey).toVector
|
||||||
|
val nonces = unsorted
|
||||||
|
.map(u => (u, u.schnorrNonce))
|
||||||
|
.sortBy(_._2)(org.bitcoins.core.nonceOrdering)
|
||||||
|
nonces.map(_._1)
|
||||||
|
}
|
||||||
|
|
||||||
val kValues: Vector[Vector[ECPrivateKey]] =
|
val kValues: Vector[Vector[ECPrivateKey]] = {
|
||||||
privateKeys.map(_ =>
|
privateKeys.map { _ =>
|
||||||
0.until(numDigits).map(_ => ECPrivateKey.freshPrivateKey).toVector)
|
val unsorted =
|
||||||
|
0.until(numDigits).map(_ => ECPrivateKey.freshPrivateKey).toVector
|
||||||
|
val sorted = unsorted
|
||||||
|
.map(u => (u, u.schnorrNonce))
|
||||||
|
.sortBy(_._2)(org.bitcoins.core.nonceOrdering)
|
||||||
|
sorted.map(_._1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val contractDescriptor: NumericContractDescriptor =
|
val contractDescriptor: NumericContractDescriptor =
|
||||||
DLCWalletUtil.multiNonceContractDescriptor
|
DLCWalletUtil.multiNonceContractDescriptor
|
||||||
|
|
||||||
val announcements: Vector[OracleAnnouncementTLV] =
|
val announcements: Vector[OracleAnnouncementTLV] = {
|
||||||
privateKeys.zip(kValues).map { case (priv, ks) =>
|
privateKeys.zip(kValues).map { case (priv, ks) =>
|
||||||
OracleAnnouncementV0TLV.dummyForKeys(priv, ks.map(_.schnorrNonce))
|
val ordered = OrderedNonces.fromUnsorted(ks.map(_.schnorrNonce))
|
||||||
|
OracleAnnouncementV0TLV.dummyForKeys(priv, ordered)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val threshold = 3
|
val threshold = 3
|
||||||
|
@ -237,7 +255,7 @@ class DLCMultiOracleNumericExecutionTest
|
||||||
s"kValues.length=${kValues.length} sigs.length=${sigs.length}")
|
s"kValues.length=${kValues.length} sigs.length=${sigs.length}")
|
||||||
OracleAttestmentV0TLV(eventId,
|
OracleAttestmentV0TLV(eventId,
|
||||||
priv.schnorrPublicKey,
|
priv.schnorrPublicKey,
|
||||||
sigs,
|
OrderedSchnorrSignatures.fromUnsorted(sigs),
|
||||||
digitsPadded.map(_.toString))
|
digitsPadded.map(_.toString))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import org.bitcoins.core.currency.Satoshis
|
||||||
import org.bitcoins.core.protocol.dlc.models.DLCStatus.{Claimed, RemoteClaimed}
|
import org.bitcoins.core.protocol.dlc.models.DLCStatus.{Claimed, RemoteClaimed}
|
||||||
import org.bitcoins.core.protocol.dlc.models._
|
import org.bitcoins.core.protocol.dlc.models._
|
||||||
import org.bitcoins.core.protocol.tlv._
|
import org.bitcoins.core.protocol.tlv._
|
||||||
|
import org.bitcoins.core.util.sorted.OrderedSchnorrSignatures
|
||||||
import org.bitcoins.crypto._
|
import org.bitcoins.crypto._
|
||||||
import org.bitcoins.testkit.wallet.DLCWalletUtil._
|
import org.bitcoins.testkit.wallet.DLCWalletUtil._
|
||||||
import org.bitcoins.testkit.wallet.{BitcoinSDualWalletTest, DLCWalletUtil}
|
import org.bitcoins.testkit.wallet.{BitcoinSDualWalletTest, DLCWalletUtil}
|
||||||
|
@ -78,11 +79,11 @@ class DLCNumericExecutionTest extends BitcoinSDualWalletTest {
|
||||||
|
|
||||||
(OracleAttestmentV0TLV(eventId,
|
(OracleAttestmentV0TLV(eventId,
|
||||||
publicKey,
|
publicKey,
|
||||||
initiatorWinSigs,
|
OrderedSchnorrSignatures(initiatorWinSigs),
|
||||||
initiatorWinVec.map(_.toString)),
|
initiatorWinVec.map(_.toString)),
|
||||||
OracleAttestmentV0TLV(eventId,
|
OracleAttestmentV0TLV(eventId,
|
||||||
publicKey,
|
publicKey,
|
||||||
recipientWinSigs,
|
OrderedSchnorrSignatures(recipientWinSigs),
|
||||||
recipientWinVec.map(_.toString)))
|
recipientWinVec.map(_.toString)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,7 +176,8 @@ class DLCNumericExecutionTest extends BitcoinSDualWalletTest {
|
||||||
//purposefully drop these
|
//purposefully drop these
|
||||||
//we cannot drop just a sig, or just an outcome because
|
//we cannot drop just a sig, or just an outcome because
|
||||||
//of invariants in OracleAttestmentV0TLV
|
//of invariants in OracleAttestmentV0TLV
|
||||||
badSigs = goodAttestment.sigs.dropRight(1)
|
badSigs = OrderedSchnorrSignatures.fromUnsorted(
|
||||||
|
goodAttestment.sigs.dropRight(1).toVector)
|
||||||
badOutcomes = goodAttestment.outcomes.dropRight(1)
|
badOutcomes = goodAttestment.outcomes.dropRight(1)
|
||||||
badAttestment = OracleAttestmentV0TLV(eventId = goodAttestment.eventId,
|
badAttestment = OracleAttestmentV0TLV(eventId = goodAttestment.eventId,
|
||||||
publicKey =
|
publicKey =
|
||||||
|
|
|
@ -7,6 +7,7 @@ import org.bitcoins.core.protocol.dlc.models.DLCMessage._
|
||||||
import org.bitcoins.core.protocol.dlc.models._
|
import org.bitcoins.core.protocol.dlc.models._
|
||||||
import org.bitcoins.core.protocol.script.P2WPKHWitnessV0
|
import org.bitcoins.core.protocol.script.P2WPKHWitnessV0
|
||||||
import org.bitcoins.core.protocol.tlv._
|
import org.bitcoins.core.protocol.tlv._
|
||||||
|
import org.bitcoins.core.util.sorted.OrderedSchnorrSignatures
|
||||||
import org.bitcoins.core.wallet.fee.SatoshisPerVirtualByte
|
import org.bitcoins.core.wallet.fee.SatoshisPerVirtualByte
|
||||||
import org.bitcoins.core.wallet.utxo.TxoState
|
import org.bitcoins.core.wallet.utxo.TxoState
|
||||||
import org.bitcoins.crypto._
|
import org.bitcoins.crypto._
|
||||||
|
@ -763,7 +764,8 @@ class WalletDLCSetupTest extends BitcoinSDualWalletTest {
|
||||||
val oracleSig = SchnorrDigitalSignature(
|
val oracleSig = SchnorrDigitalSignature(
|
||||||
"a6a09c7c83c50b34f9db560a2e14fef2eab5224c15b18c7114331756364bfce6c59736cdcfe1e0a89064f846d5dbde0902f82688dde34dc1833965a60240f287")
|
"a6a09c7c83c50b34f9db560a2e14fef2eab5224c15b18c7114331756364bfce6c59736cdcfe1e0a89064f846d5dbde0902f82688dde34dc1833965a60240f287")
|
||||||
|
|
||||||
val sig = OracleSignatures(oracleInfo, Vector(oracleSig))
|
val sig =
|
||||||
|
OracleSignatures(oracleInfo, OrderedSchnorrSignatures(oracleSig))
|
||||||
|
|
||||||
for {
|
for {
|
||||||
offer <- walletA.createDLCOffer(
|
offer <- walletA.createDLCOffer(
|
||||||
|
@ -887,24 +889,8 @@ class WalletDLCSetupTest extends BitcoinSDualWalletTest {
|
||||||
} yield succeed
|
} yield succeed
|
||||||
}
|
}
|
||||||
|
|
||||||
//https://test.oracle.suredbits.com/contract/numeric/022428196c6a60673d1f2b90e7be14ac615986dce5571246e8bcc9d2d689d57b
|
private val numericContractInfo =
|
||||||
private val numericContractInfo = ContractInfoV0TLV.fromHex(
|
DLCWalletUtil.numericContractInfoV0
|
||||||
"""fdd82efd033f00000000000186a0fda720540012fda72648000501000000000000000000000001fd88b80000000000000000000001
|
|
||||||
|fdafc8000000000000c350000001fdd6d800000000000186a0000001fe0003ffff00000000000186a00000fda724020000fda712fd
|
|
||||||
|02d9fdd824fd02d391177fd623a72d56e7bc12e3903f8d6bce7f07a25226d54009cd7e670f5e7a7320b0704286580d8b6a7f31ab7b
|
|
||||||
|f71356a13c28aa609a021111b2e3d2b2db26bc120bd29248895b81f76b07d85a21b86021f22352d6376d19bbf5c93f918828f1fdd8
|
|
||||||
|22fd026d0012fad0cde50a2258efa25cbba60ef0b6677cd29654802937c112097edb64bd205beea02263d6461e60a9ca8e08209c8b
|
|
||||||
|d5552863156014d5418cad91ac590bbf13a847f105db9899d560e5040f9565c043c9e7fdf3782ad2708c5b99646c722b4118547472
|
|
||||||
|48fb52e6486cce3eca5ddf9d64ecbe0864501a446efd378863f9a4055fab50d2112320ff14d8747a72467589822103f197063b49e7
|
|
||||||
|7b90d82d3a8d49b63c3ceb9bd3328398a53989d4237216a24a1d12364efa2d2aec59cdc87909b115dca5b07106b70032ff78072f82
|
|
||||||
|ceeaf2e20db55086e9a2e5e5cac864992d747fd40f4b26bc3d7de958ee02460d1199ff81438c9b76b3934cbc4566d10f242563b95e
|
|
||||||
|7df79c28d52c9c46b617676a4ee84a549ee1f0f53865c9ef4d0ff825e2f438384c5f6238d0734beb570a1a49d035d9f86ee31c23f1
|
|
||||||
|e97bd34fba3f586c0fdf29997530e528b3200a0d7e34f865dc4ca7bfd722bf77c0478ddd25bfa2dc6a4ab973d0c1b7a9ff38283b7c
|
|
||||||
|19bbe02677a9b628f3ee3d5198d66c1623c9608293093c126d4124a445bb6412f720493b6ffa411db53923895fd50c9563d50a97a8
|
|
||||||
|6188084fe4c0f15ce50438ff0b00e1a9470185fd7c96296ae2be12056f61ceaeee7ced48314a3b6855bc9aa3b446b9dfad68553f53
|
|
||||||
|02c60670a95fb9bdc5e72db7f1e9d42e4f4baca1bcbb22612db6417b45cc3d78b1ef33fc362a68db56df00ab1ee0700bd900200f6a
|
|
||||||
|24882101e71de7e18a7fb0d7da27b340de52f97d96239f359cfe31afcaf69cc9ddfcbfbdb2267e673ad728a29dd22d31d1a1187162
|
|
||||||
|037480fdd80a100002000642544355534400000000001212446572696269742d4254432d394645423232""".stripMargin)
|
|
||||||
|
|
||||||
it must "fail accepting an offer twice simultaneously" in { wallets =>
|
it must "fail accepting an offer twice simultaneously" in { wallets =>
|
||||||
val walletA = wallets._1.wallet
|
val walletA = wallets._1.wallet
|
||||||
|
|
|
@ -110,7 +110,8 @@ case class DLCDataManagement(dlcWalletDAOs: DLCWalletDAOs)(implicit
|
||||||
.exists(_.used)
|
.exists(_.used)
|
||||||
if (used) {
|
if (used) {
|
||||||
val nonces = nonceDbs.sortBy(_.index).map(_.nonce)
|
val nonces = nonceDbs.sortBy(_.index).map(_.nonce)
|
||||||
val eventTLV = OracleEventV0TLV(OrderedNonces(nonces),
|
val eventTLV =
|
||||||
|
OracleEventV0TLV(OrderedNonces.fromUnsorted(nonces),
|
||||||
data.eventMaturity,
|
data.eventMaturity,
|
||||||
data.eventDescriptor,
|
data.eventDescriptor,
|
||||||
data.eventId)
|
data.eventId)
|
||||||
|
@ -151,7 +152,7 @@ case class DLCDataManagement(dlcWalletDAOs: DLCWalletDAOs)(implicit
|
||||||
announcementData.find(_.id.contains(id)) match {
|
announcementData.find(_.id.contains(id)) match {
|
||||||
case Some(data) =>
|
case Some(data) =>
|
||||||
val nonces = nonceDbs.sortBy(_.index).map(_.nonce)
|
val nonces = nonceDbs.sortBy(_.index).map(_.nonce)
|
||||||
val eventTLV = OracleEventV0TLV(OrderedNonces(nonces),
|
val eventTLV = OracleEventV0TLV(OrderedNonces.fromUnsorted(nonces),
|
||||||
data.eventMaturity,
|
data.eventMaturity,
|
||||||
data.eventDescriptor,
|
data.eventDescriptor,
|
||||||
data.eventId)
|
data.eventId)
|
||||||
|
|
|
@ -17,7 +17,7 @@ object OracleNonceDbHelper {
|
||||||
def fromAnnouncement(
|
def fromAnnouncement(
|
||||||
id: Long,
|
id: Long,
|
||||||
tlv: OracleAnnouncementTLV): Vector[OracleNonceDb] = {
|
tlv: OracleAnnouncementTLV): Vector[OracleNonceDb] = {
|
||||||
tlv.eventTLV.nonces.vec.zipWithIndex.map { case (nonce, index) =>
|
tlv.eventTLV.nonces.toVector.zipWithIndex.map { case (nonce, index) =>
|
||||||
OracleNonceDb(id, index, SchnorrDigitalSignature.dummy, nonce, None, None)
|
OracleNonceDb(id, index, SchnorrDigitalSignature.dummy, nonce, None, None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -141,7 +141,8 @@ val descriptor = NumericContractDescriptor(curve, numDigits = 15, roundTo100)
|
||||||
val announcements = 0.until(5).toVector.map { _ =>
|
val announcements = 0.until(5).toVector.map { _ =>
|
||||||
val oraclePrivKey = ECPrivateKey.freshPrivateKey
|
val oraclePrivKey = ECPrivateKey.freshPrivateKey
|
||||||
val nonces = 0.until(15).toVector.map(_ => ECPrivateKey.freshPrivateKey.schnorrNonce)
|
val nonces = 0.until(15).toVector.map(_ => ECPrivateKey.freshPrivateKey.schnorrNonce)
|
||||||
OracleAnnouncementV0TLV.dummyForKeys(oraclePrivKey, nonces)
|
val orderedNonces = OrderedNonces.fromUnsorted(nonces)
|
||||||
|
OracleAnnouncementV0TLV.dummyForKeys(oraclePrivKey, orderedNonces)
|
||||||
}
|
}
|
||||||
val oracleInfo = NumericMultiOracleInfo(
|
val oracleInfo = NumericMultiOracleInfo(
|
||||||
threshold = 3,
|
threshold = 3,
|
||||||
|
|
|
@ -14,7 +14,11 @@ import org.bitcoins.core.protocol.script._
|
||||||
import org.bitcoins.core.protocol.tlv.{NumericDLCOutcomeType, _}
|
import org.bitcoins.core.protocol.tlv.{NumericDLCOutcomeType, _}
|
||||||
import org.bitcoins.core.protocol.transaction._
|
import org.bitcoins.core.protocol.transaction._
|
||||||
import org.bitcoins.core.psbt.InputPSBTRecord.PartialSignature
|
import org.bitcoins.core.psbt.InputPSBTRecord.PartialSignature
|
||||||
import org.bitcoins.core.util.sorted.OrderedAnnouncements
|
import org.bitcoins.core.util.sorted.{
|
||||||
|
OrderedAnnouncements,
|
||||||
|
OrderedNonces,
|
||||||
|
OrderedSchnorrSignatures
|
||||||
|
}
|
||||||
import org.bitcoins.core.util.{BitcoinScriptUtil, FutureUtil, NumberUtil}
|
import org.bitcoins.core.util.{BitcoinScriptUtil, FutureUtil, NumberUtil}
|
||||||
import org.bitcoins.core.wallet.fee.SatoshisPerVirtualByte
|
import org.bitcoins.core.wallet.fee.SatoshisPerVirtualByte
|
||||||
import org.bitcoins.core.wallet.utxo._
|
import org.bitcoins.core.wallet.utxo._
|
||||||
|
@ -40,22 +44,27 @@ trait DLCTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val oraclePrivKeys: Vector[ECPrivateKey] =
|
val oraclePrivKeys: Vector[ECPrivateKey] = {
|
||||||
(0 until 50).toVector.map(_ => ECPrivateKey.freshPrivateKey)
|
ECPrivateKey.generateNonceOrderedPrivKeys(50)
|
||||||
|
}
|
||||||
|
|
||||||
val oraclePubKeys: Vector[SchnorrPublicKey] =
|
val oraclePubKeys: Vector[SchnorrPublicKey] =
|
||||||
oraclePrivKeys.map(_.schnorrPublicKey)
|
oraclePrivKeys.map(_.schnorrPublicKey)
|
||||||
val oraclePrivKey: ECPrivateKey = oraclePrivKeys.head
|
val oraclePrivKey: ECPrivateKey = oraclePrivKeys.head
|
||||||
val oraclePubKey: SchnorrPublicKey = oraclePubKeys.head
|
val oraclePubKey: SchnorrPublicKey = oraclePubKeys.head
|
||||||
|
|
||||||
val preCommittedKsPerOracle: Vector[Vector[ECPrivateKey]] =
|
val preCommittedKsPerOracle: Vector[Vector[ECPrivateKey]] = {
|
||||||
oraclePrivKeys.map(_ =>
|
oraclePrivKeys.map { _ =>
|
||||||
(0 until 50).toVector.map(_ => ECPrivateKey.freshPrivateKey))
|
ECPrivateKey.generateNonceOrderedPrivKeys(50)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val preCommittedRsPerOracle: Vector[Vector[SchnorrNonce]] =
|
val preCommittedRsPerOracle: Vector[OrderedNonces] =
|
||||||
preCommittedKsPerOracle.map(_.map(_.schnorrNonce))
|
preCommittedKsPerOracle.map { privKeys =>
|
||||||
|
OrderedNonces.fromUnsorted(privKeys.map(_.schnorrNonce))
|
||||||
|
}
|
||||||
val preCommittedKs: Vector[ECPrivateKey] = preCommittedKsPerOracle.head
|
val preCommittedKs: Vector[ECPrivateKey] = preCommittedKsPerOracle.head
|
||||||
val preCommittedRs: Vector[SchnorrNonce] = preCommittedRsPerOracle.head
|
val preCommittedRs: OrderedNonces = preCommittedRsPerOracle.head
|
||||||
val preCommittedK: ECPrivateKey = preCommittedKs.head
|
val preCommittedK: ECPrivateKey = preCommittedKs.head
|
||||||
val preCommittedR: SchnorrNonce = preCommittedRs.head
|
val preCommittedR: SchnorrNonce = preCommittedRs.head
|
||||||
|
|
||||||
|
@ -454,8 +463,9 @@ trait DLCTest {
|
||||||
.zip(preCommittedRsPerOracle
|
.zip(preCommittedRsPerOracle
|
||||||
.slice(oracleShift, oracleShift + params.numOracles))
|
.slice(oracleShift, oracleShift + params.numOracles))
|
||||||
.map { case (privKey, rVals) =>
|
.map { case (privKey, rVals) =>
|
||||||
OracleAnnouncementV0TLV.dummyForKeys(privKey,
|
val nonces =
|
||||||
rVals.take(params.numDigits))
|
OrderedNonces.fromUnsorted(rVals.take(params.numDigits).toVector)
|
||||||
|
OracleAnnouncementV0TLV.dummyForKeys(privKey, nonces)
|
||||||
}
|
}
|
||||||
val oracleInfo = if (params.numOracles == 1) {
|
val oracleInfo = if (params.numOracles == 1) {
|
||||||
NumericSingleOracleInfo(announcements.head)
|
NumericSingleOracleInfo(announcements.head)
|
||||||
|
@ -779,14 +789,17 @@ trait DLCTest {
|
||||||
def computeNumericOracleSignatures(
|
def computeNumericOracleSignatures(
|
||||||
digits: Vector[Int],
|
digits: Vector[Int],
|
||||||
privKey: ECPrivateKey = oraclePrivKey,
|
privKey: ECPrivateKey = oraclePrivKey,
|
||||||
kVals: Vector[ECPrivateKey] = preCommittedKs): Vector[
|
kVals: Vector[ECPrivateKey] =
|
||||||
SchnorrDigitalSignature] = {
|
preCommittedKs): OrderedSchnorrSignatures = {
|
||||||
|
val unsorted =
|
||||||
digits.zip(kVals.take(digits.length)).map { case (digit, kValue) =>
|
digits.zip(kVals.take(digits.length)).map { case (digit, kValue) =>
|
||||||
privKey.schnorrSignWithNonce(CryptoUtil
|
privKey.schnorrSignWithNonce(CryptoUtil
|
||||||
.sha256DLCAttestation(digit.toString)
|
.sha256DLCAttestation(digit.toString)
|
||||||
.bytes,
|
.bytes,
|
||||||
kValue)
|
kValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OrderedSchnorrSignatures.fromUnsorted(unsorted)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Deterministically chooses an outcome from the middle third of the interesting possible outcomes. */
|
/** Deterministically chooses an outcome from the middle third of the interesting possible outcomes. */
|
||||||
|
@ -1059,13 +1072,15 @@ trait DLCTest {
|
||||||
case (dlcOffer, offerSetup, dlcAccept, acceptSetup, outcomes) =>
|
case (dlcOffer, offerSetup, dlcAccept, acceptSetup, outcomes) =>
|
||||||
val testFs = outcomeIndices.map {
|
val testFs = outcomeIndices.map {
|
||||||
case (contractIndex, outcomeIndex) =>
|
case (contractIndex, outcomeIndex) =>
|
||||||
executeForOutcome(outcomeIndex,
|
executeForOutcome(
|
||||||
dlcOffer,
|
outcomeIndex = outcomeIndex,
|
||||||
offerSetup,
|
dlcOffer = dlcOffer,
|
||||||
dlcAccept,
|
offerSetup = offerSetup,
|
||||||
acceptSetup,
|
dlcAccept = dlcAccept,
|
||||||
outcomes,
|
acceptSetup = acceptSetup,
|
||||||
contractIndex)
|
outcomes = outcomes,
|
||||||
|
contractIndex = contractIndex
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
Future.sequence(testFs).map(_ => succeed)
|
Future.sequence(testFs).map(_ => succeed)
|
||||||
|
|
|
@ -134,7 +134,10 @@ trait TLVGen {
|
||||||
Gen
|
Gen
|
||||||
.listOfN(desc.noncesNeeded, CryptoGenerators.schnorrNonce)
|
.listOfN(desc.noncesNeeded, CryptoGenerators.schnorrNonce)
|
||||||
.map(_.toVector)
|
.map(_.toVector)
|
||||||
} yield OracleEventV0TLV(OrderedNonces(nonces), maturity, desc, uri)
|
} yield OracleEventV0TLV(OrderedNonces.fromUnsorted(nonces),
|
||||||
|
maturity,
|
||||||
|
desc,
|
||||||
|
uri)
|
||||||
}
|
}
|
||||||
|
|
||||||
def oracleAnnouncementV0TLV: Gen[OracleAnnouncementV0TLV] = {
|
def oracleAnnouncementV0TLV: Gen[OracleAnnouncementV0TLV] = {
|
||||||
|
@ -150,10 +153,11 @@ trait TLVGen {
|
||||||
eventId <- StringGenerators.genUTF8String
|
eventId <- StringGenerators.genUTF8String
|
||||||
pubkey <- CryptoGenerators.schnorrPublicKey
|
pubkey <- CryptoGenerators.schnorrPublicKey
|
||||||
numSigs <- Gen.choose(1, 10)
|
numSigs <- Gen.choose(1, 10)
|
||||||
sigs <-
|
unsorted <-
|
||||||
Gen
|
Gen
|
||||||
.listOfN(numSigs, CryptoGenerators.schnorrDigitalSignature)
|
.listOfN(numSigs, CryptoGenerators.schnorrDigitalSignature)
|
||||||
.map(_.toVector)
|
.map(_.toVector)
|
||||||
|
sigs = OrderedSchnorrSignatures.fromUnsorted(unsorted)
|
||||||
outcomes <-
|
outcomes <-
|
||||||
Gen
|
Gen
|
||||||
.listOfN(numSigs, StringGenerators.genUTF8String)
|
.listOfN(numSigs, StringGenerators.genUTF8String)
|
||||||
|
@ -237,10 +241,10 @@ trait TLVGen {
|
||||||
def oracleInfoV0TLV(numDigits: Int): Gen[OracleInfoV0TLV] = {
|
def oracleInfoV0TLV(numDigits: Int): Gen[OracleInfoV0TLV] = {
|
||||||
for {
|
for {
|
||||||
privKey <- CryptoGenerators.privateKey
|
privKey <- CryptoGenerators.privateKey
|
||||||
rValues <- Gen.listOfN(numDigits, CryptoGenerators.schnorrNonce)
|
unsorted <- Gen.listOfN(numDigits, CryptoGenerators.schnorrNonce)
|
||||||
|
rValues = OrderedNonces.fromUnsorted(unsorted.toVector)
|
||||||
} yield {
|
} yield {
|
||||||
OracleInfoV0TLV(
|
OracleInfoV0TLV(OracleAnnouncementV0TLV.dummyForKeys(privKey, rValues))
|
||||||
OracleAnnouncementV0TLV.dummyForKeys(privKey, rValues.toVector))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ import org.bitcoins.core.psbt.InputPSBTRecord.PartialSignature
|
||||||
import org.bitcoins.core.script.PreExecutionScriptProgram
|
import org.bitcoins.core.script.PreExecutionScriptProgram
|
||||||
import org.bitcoins.core.script.interpreter.ScriptInterpreter
|
import org.bitcoins.core.script.interpreter.ScriptInterpreter
|
||||||
import org.bitcoins.core.script.util.PreviousOutputMap
|
import org.bitcoins.core.script.util.PreviousOutputMap
|
||||||
|
import org.bitcoins.core.util.sorted.{OrderedNonces, OrderedSchnorrSignatures}
|
||||||
import org.bitcoins.core.wallet.fee.SatoshisPerVirtualByte
|
import org.bitcoins.core.wallet.fee.SatoshisPerVirtualByte
|
||||||
import org.bitcoins.crypto._
|
import org.bitcoins.crypto._
|
||||||
import org.bitcoins.dlc.wallet.DLCWallet
|
import org.bitcoins.dlc.wallet.DLCWallet
|
||||||
|
@ -37,9 +38,14 @@ import scala.concurrent.{ExecutionContext, Future}
|
||||||
object DLCWalletUtil extends Logging {
|
object DLCWalletUtil extends Logging {
|
||||||
lazy val oraclePrivKey: ECPrivateKey = ECPrivateKey.freshPrivateKey
|
lazy val oraclePrivKey: ECPrivateKey = ECPrivateKey.freshPrivateKey
|
||||||
|
|
||||||
lazy val kValues: Vector[ECPrivateKey] =
|
lazy val kValues: Vector[ECPrivateKey] = {
|
||||||
0.to(10).map(_ => ECPrivateKey.freshPrivateKey).toVector
|
ECPrivateKey.generateNonceOrderedPrivKeys(10)
|
||||||
lazy val rValues: Vector[SchnorrNonce] = kValues.map(_.schnorrNonce)
|
}
|
||||||
|
|
||||||
|
lazy val rValues: OrderedNonces = {
|
||||||
|
val nonces = kValues.map(_.schnorrNonce)
|
||||||
|
OrderedNonces.fromUnsorted(nonces)
|
||||||
|
}
|
||||||
|
|
||||||
lazy val kValue: ECPrivateKey = kValues.head
|
lazy val kValue: ECPrivateKey = kValues.head
|
||||||
lazy val rValue: SchnorrNonce = rValues.head
|
lazy val rValue: SchnorrNonce = rValues.head
|
||||||
|
@ -133,10 +139,12 @@ object DLCWalletUtil extends Logging {
|
||||||
lazy val multiNonceContractDescriptor: NumericContractDescriptor =
|
lazy val multiNonceContractDescriptor: NumericContractDescriptor =
|
||||||
DLCTestUtil.genMultiDigitContractInfo(numDigits, total)._1
|
DLCTestUtil.genMultiDigitContractInfo(numDigits, total)._1
|
||||||
|
|
||||||
lazy val multiNonceOracleInfo: NumericSingleOracleInfo =
|
lazy val multiNonceOracleInfo: NumericSingleOracleInfo = {
|
||||||
|
val unsorted = rValues.take(numDigits).toVector
|
||||||
|
val sorted = OrderedNonces.fromUnsorted(unsorted)
|
||||||
NumericSingleOracleInfo(
|
NumericSingleOracleInfo(
|
||||||
OracleAnnouncementV0TLV.dummyForKeys(oraclePrivKey,
|
OracleAnnouncementV0TLV.dummyForKeys(oraclePrivKey, sorted))
|
||||||
rValues.take(numDigits)))
|
}
|
||||||
|
|
||||||
lazy val multiNonceContractOraclePair: ContractOraclePair.NumericPair = {
|
lazy val multiNonceContractOraclePair: ContractOraclePair.NumericPair = {
|
||||||
ContractOraclePair.NumericPair(multiNonceContractDescriptor,
|
ContractOraclePair.NumericPair(multiNonceContractDescriptor,
|
||||||
|
@ -146,6 +154,9 @@ object DLCWalletUtil extends Logging {
|
||||||
lazy val multiNonceContractInfo: ContractInfo =
|
lazy val multiNonceContractInfo: ContractInfo =
|
||||||
SingleContractInfo(total, multiNonceContractOraclePair)
|
SingleContractInfo(total, multiNonceContractOraclePair)
|
||||||
|
|
||||||
|
lazy val numericContractInfoV0 =
|
||||||
|
multiNonceContractInfo.toTLV.asInstanceOf[ContractInfoV0TLV]
|
||||||
|
|
||||||
lazy val dummyContractMaturity: BlockTimeStamp = BlockTimeStamp(0)
|
lazy val dummyContractMaturity: BlockTimeStamp = BlockTimeStamp(0)
|
||||||
lazy val dummyContractTimeout: BlockTimeStamp = BlockTimeStamp(1)
|
lazy val dummyContractTimeout: BlockTimeStamp = BlockTimeStamp(1)
|
||||||
|
|
||||||
|
@ -503,11 +514,11 @@ object DLCWalletUtil extends Logging {
|
||||||
|
|
||||||
(OracleAttestmentV0TLV(eventId,
|
(OracleAttestmentV0TLV(eventId,
|
||||||
publicKey,
|
publicKey,
|
||||||
Vector(initiatorWinSig),
|
OrderedSchnorrSignatures(initiatorWinSig),
|
||||||
Vector(initiatorWinStr)),
|
Vector(initiatorWinStr)),
|
||||||
OracleAttestmentV0TLV(eventId,
|
OracleAttestmentV0TLV(eventId,
|
||||||
publicKey,
|
publicKey,
|
||||||
Vector(recipientWinSig),
|
OrderedSchnorrSignatures(recipientWinSig),
|
||||||
Vector(recipientWinStr)))
|
Vector(recipientWinStr)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue