mirror of
https://github.com/bitcoin-s/bitcoin-s.git
synced 2025-02-23 06:45:21 +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.PSBT
|
||||
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.rescan.RescanState
|
||||
import org.bitcoins.core.wallet.utxo._
|
||||
|
@ -935,7 +936,7 @@ class RoutesSpec extends AnyWordSpec with ScalatestRouteTest with MockFactory {
|
|||
val dummyOracleAttestment =
|
||||
OracleAttestmentV0TLV("eventId",
|
||||
dummyPubKey.schnorrPublicKey,
|
||||
Vector(dummyOracleSig),
|
||||
OrderedSchnorrSignatures(dummyOracleSig),
|
||||
Vector("outcome"))
|
||||
|
||||
lazy val winStr: String = "WIN"
|
||||
|
|
|
@ -522,7 +522,7 @@ object DLCParsingTestVector extends TestVectorParser[DLCParsingTestVector] {
|
|||
val fields = Vector(
|
||||
"tpe" -> Element(OracleEventV0TLV.tpe),
|
||||
"length" -> Element(tlv.length),
|
||||
"oracleNonces" -> MultiElement(nonces.vec.map(Element(_))),
|
||||
"oracleNonces" -> MultiElement(nonces.toVector.map(Element(_))),
|
||||
"eventMaturityEpoch" -> Element(eventMaturity),
|
||||
"eventDescriptor" -> Element(descriptor),
|
||||
"event_uri" -> Element(CryptoUtil.serializeForHash(uri))
|
||||
|
@ -545,7 +545,7 @@ object DLCParsingTestVector extends TestVectorParser[DLCParsingTestVector] {
|
|||
"length" -> Element(tlv.length),
|
||||
"eventId" -> Element(eventId),
|
||||
"oraclePubKey" -> Element(pubkey),
|
||||
"signatures" -> MultiElement(sigs.map(Element(_))),
|
||||
"signatures" -> MultiElement(sigs.toVector.map(Element(_))),
|
||||
"outcomes" -> MultiElement(outcomes.map(Element(_)))
|
||||
)
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ import org.bitcoins.core.protocol.tlv.{
|
|||
EnumOutcome,
|
||||
OracleAnnouncementV0TLV
|
||||
}
|
||||
import org.bitcoins.core.util.sorted.OrderedAnnouncements
|
||||
import org.bitcoins.core.util.sorted.{OrderedAnnouncements, OrderedNonces}
|
||||
import org.bitcoins.crypto.ECPrivateKey
|
||||
import org.bitcoins.testkitcore.util.BitcoinSUnitTest
|
||||
|
||||
|
@ -67,10 +67,12 @@ class ContractOraclePairTest extends BitcoinSUnitTest {
|
|||
)
|
||||
|
||||
def numericOracleInfo(numDigits: Int): NumericSingleOracleInfo = {
|
||||
val unsorted =
|
||||
Vector.fill(numDigits)(ECPrivateKey.freshPrivateKey.schnorrNonce)
|
||||
val sorted = OrderedNonces.fromUnsorted(unsorted)
|
||||
NumericSingleOracleInfo(
|
||||
OracleAnnouncementV0TLV.dummyForKeys(
|
||||
ECPrivateKey.freshPrivateKey,
|
||||
Vector.fill(numDigits)(ECPrivateKey.freshPrivateKey.schnorrNonce)))
|
||||
OracleAnnouncementV0TLV.dummyForKeys(ECPrivateKey.freshPrivateKey,
|
||||
sorted))
|
||||
}
|
||||
|
||||
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.tlv._
|
||||
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 java.time.Instant
|
||||
|
@ -60,10 +60,12 @@ sealed trait CompletedOracleEvent extends OracleEvent {
|
|||
require(attestations.size == nonces.size,
|
||||
"Must have a signature for every nonce")
|
||||
|
||||
def signatures: Vector[SchnorrDigitalSignature] =
|
||||
nonces.vec
|
||||
def signatures: OrderedSchnorrSignatures = {
|
||||
val unsorted = nonces.toVector
|
||||
.zip(attestations)
|
||||
.map(sigPieces => SchnorrDigitalSignature(sigPieces._1, sigPieces._2))
|
||||
OrderedSchnorrSignatures.fromUnsorted(unsorted)
|
||||
}
|
||||
|
||||
def oracleAttestmentV0TLV: OracleAttestmentV0TLV =
|
||||
OracleAttestmentV0TLV(eventName,
|
||||
|
@ -231,7 +233,7 @@ object OracleEvent {
|
|||
|
||||
CompletedDigitDecompositionV0OracleEvent(
|
||||
eventDb.pubkey,
|
||||
OrderedNonces(sortedEventDbs.map(_.nonce)),
|
||||
OrderedNonces.fromUnsorted(sortedEventDbs.map(_.nonce)),
|
||||
eventDb.eventName,
|
||||
eventDb.signingVersion,
|
||||
eventDb.maturationTime,
|
||||
|
@ -248,7 +250,7 @@ object OracleEvent {
|
|||
|
||||
PendingDigitDecompositionV0OracleEvent(
|
||||
eventDb.pubkey,
|
||||
OrderedNonces(sortedEventDbs.map(_.nonce)),
|
||||
OrderedNonces.fromUnsorted(sortedEventDbs.map(_.nonce)),
|
||||
eventDb.eventName,
|
||||
eventDb.signingVersion,
|
||||
eventDb.maturationTime,
|
||||
|
|
|
@ -5,10 +5,14 @@ import org.bitcoins.core.protocol.transaction.{
|
|||
TransactionOutput
|
||||
}
|
||||
import org.bitcoins.core.wallet.fee.SatoshisPerKiloByte
|
||||
import org.bitcoins.crypto.{
|
||||
CryptoOrdering,
|
||||
SchnorrDigitalSignature,
|
||||
SchnorrNonce
|
||||
}
|
||||
import scodec.bits._
|
||||
|
||||
import java.math.BigInteger
|
||||
import scala.annotation.tailrec
|
||||
import scala.math.Ordering
|
||||
|
||||
package object core {
|
||||
|
@ -54,23 +58,7 @@ package object core {
|
|||
}
|
||||
|
||||
implicit 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
CryptoOrdering.byteVectorOrdering
|
||||
|
||||
implicit val transactionInputOrder: Ordering[TransactionInput] =
|
||||
new Ordering[TransactionInput] {
|
||||
|
@ -87,4 +75,17 @@ package object core {
|
|||
x.scriptPubKey.hex.compare(y.scriptPubKey.hex)
|
||||
} 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 =>
|
||||
val announcement = info.announcement
|
||||
val pubKey = announcement.publicKey
|
||||
val nonces = announcement.eventTLV.nonces.vec.map(_.publicKey)
|
||||
val nonces = announcement.eventTLV.nonces.toVector.map(_.publicKey)
|
||||
|
||||
nonces.map { nonce =>
|
||||
possibleOutcomes.map { outcome =>
|
||||
|
|
|
@ -19,7 +19,7 @@ import org.bitcoins.core.protocol.tlv.{
|
|||
OracleAttestmentTLV
|
||||
}
|
||||
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 scodec.bits.ByteVector
|
||||
|
||||
|
@ -263,11 +263,14 @@ object DLCUtil {
|
|||
val announcementNonces: Vector[Vector[SchnorrNonce]] = {
|
||||
announcements
|
||||
.map(_.eventTLV.nonces)
|
||||
.map(_.vec)
|
||||
.map(_.toVector)
|
||||
}
|
||||
val resultOpt = oracleSignatures.find { case oracleSignature =>
|
||||
val oracleSigNonces: Vector[SchnorrNonce] = oracleSignature.sigs.map(_.rx)
|
||||
announcementNonces.contains(oracleSigNonces)
|
||||
val oracleSigNonces: Vector[SchnorrNonce] = {
|
||||
val unsorted = oracleSignature.sigs.map(_.rx).toVector
|
||||
OrderedNonces.fromUnsorted(unsorted).toVector
|
||||
}
|
||||
announcementNonces.exists(_ == oracleSigNonces)
|
||||
}
|
||||
resultOpt
|
||||
}
|
||||
|
|
|
@ -138,7 +138,9 @@ object DLCExecutor {
|
|||
): ExecutedDLCOutcome = {
|
||||
require(
|
||||
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 oracleInfoOpt = contractInfo.oracleInfos.find { oracleInfo =>
|
||||
|
|
|
@ -78,7 +78,7 @@ sealed trait SingleOracleInfo
|
|||
* This point is used for adaptor signing.
|
||||
*/
|
||||
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 */
|
||||
|
@ -214,7 +214,7 @@ object NumericSingleOracleInfo {
|
|||
|
||||
def dummyForKeys(
|
||||
privKey: ECPrivateKey,
|
||||
nonces: Vector[SchnorrNonce]): NumericSingleOracleInfo = {
|
||||
nonces: OrderedNonces): NumericSingleOracleInfo = {
|
||||
NumericSingleOracleInfo(
|
||||
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.tlv._
|
||||
import org.bitcoins.core.util.SeqWrapper
|
||||
import org.bitcoins.core.util.sorted.OrderedSchnorrSignatures
|
||||
import org.bitcoins.crypto.{CryptoUtil, ECPrivateKey, SchnorrDigitalSignature}
|
||||
|
||||
/** Corresponds to a set of SchnorrDigitalSignatures given by a single oracle. */
|
||||
sealed trait OracleSignatures extends SeqWrapper[SchnorrDigitalSignature] {
|
||||
|
||||
/** This oracle's signatures */
|
||||
def sigs: Vector[SchnorrDigitalSignature]
|
||||
def sigs: OrderedSchnorrSignatures
|
||||
|
||||
/** The SingleOracleInfo for the oracle whose signatures are stored here. */
|
||||
def oracle: SingleOracleInfo
|
||||
|
||||
override def wrapped: Vector[SchnorrDigitalSignature] = sigs
|
||||
override def wrapped: Vector[SchnorrDigitalSignature] = sigs.toVector
|
||||
|
||||
/** Verifies the signatures against a given outcome. */
|
||||
def verifySignatures(outcome: DLCOutcomeType): Boolean = {
|
||||
|
@ -38,7 +39,7 @@ object OracleSignatures {
|
|||
|
||||
def apply(
|
||||
oracle: SingleOracleInfo,
|
||||
sigs: Vector[SchnorrDigitalSignature]): OracleSignatures = {
|
||||
sigs: OrderedSchnorrSignatures): OracleSignatures = {
|
||||
oracle match {
|
||||
case info: EnumSingleOracleInfo =>
|
||||
require(sigs.length == 1, s"Expected one signature, got $sigs")
|
||||
|
@ -76,7 +77,7 @@ case class EnumOracleSignature(
|
|||
oracle: EnumSingleOracleInfo,
|
||||
sig: SchnorrDigitalSignature)
|
||||
extends OracleSignatures {
|
||||
override def sigs: Vector[SchnorrDigitalSignature] = Vector(sig)
|
||||
override def sigs: OrderedSchnorrSignatures = OrderedSchnorrSignatures(sig)
|
||||
|
||||
lazy val getOutcome: EnumOutcome = {
|
||||
// cast is safe, EnumSingleOracleInfo enforces this
|
||||
|
@ -105,7 +106,7 @@ case class EnumOracleSignature(
|
|||
/** Wraps a set of oracle signatures of numeric digits. */
|
||||
case class NumericOracleSignatures(
|
||||
oracle: NumericSingleOracleInfo,
|
||||
sigs: Vector[SchnorrDigitalSignature])
|
||||
sigs: OrderedSchnorrSignatures)
|
||||
extends OracleSignatures {
|
||||
|
||||
lazy val getOutcome: UnsignedNumericOutcome = {
|
||||
|
@ -127,7 +128,7 @@ case class NumericOracleSignatures(
|
|||
.getOrElse(throw new IllegalArgumentException(
|
||||
s"Signature $sig does not match any digit 0-${base - 1}"))
|
||||
}
|
||||
UnsignedNumericOutcome(digits)
|
||||
UnsignedNumericOutcome(digits.toVector)
|
||||
}
|
||||
|
||||
/** 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.{BigSizeUInt, BlockTimeStamp}
|
||||
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.crypto._
|
||||
import scodec.bits.ByteVector
|
||||
|
@ -775,14 +779,14 @@ case class OracleEventV0TLV(
|
|||
) extends OracleEventTLV {
|
||||
|
||||
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}"
|
||||
)
|
||||
|
||||
override def tpe: BigSizeUInt = OracleEventV0TLV.tpe
|
||||
|
||||
override val value: ByteVector = {
|
||||
u16PrefixedList(nonces.vec) ++
|
||||
u16PrefixedList(nonces.toVector) ++
|
||||
eventMaturityEpoch.bytes ++
|
||||
eventDescriptor.bytes ++
|
||||
strBytes(eventId)
|
||||
|
@ -805,7 +809,7 @@ object OracleEventV0TLV extends TLVFactory[OracleEventV0TLV] {
|
|||
val eventDescriptor = iter.take(EventDescriptorTLV)
|
||||
val eventId = iter.takeString()
|
||||
|
||||
OracleEventV0TLV(OrderedNonces(nonces),
|
||||
OracleEventV0TLV(OrderedNonces.fromUnsorted(nonces),
|
||||
eventMaturity,
|
||||
eventDescriptor,
|
||||
eventId)
|
||||
|
@ -865,7 +869,7 @@ object OracleAnnouncementV0TLV extends TLVFactory[OracleAnnouncementV0TLV] {
|
|||
val dummyPrivKey: ECPrivateKey = ECPrivateKey.fromHex(
|
||||
"f04671ab68f3fefbeaa344c49149748f722287a81b19cd956b2332d07b8f6853")
|
||||
val event = OracleEventV0TLV(
|
||||
OrderedNonces(Vector(dummyPrivKey.schnorrNonce)),
|
||||
OrderedNonces.fromUnsorted(Vector(dummyPrivKey.schnorrNonce)),
|
||||
UInt32.zero,
|
||||
EnumEventDescriptorV0TLV.dummy,
|
||||
"dummy")
|
||||
|
@ -881,7 +885,7 @@ object OracleAnnouncementV0TLV extends TLVFactory[OracleAnnouncementV0TLV] {
|
|||
nonce: SchnorrNonce,
|
||||
events: Vector[EnumOutcome]): OracleAnnouncementTLV = {
|
||||
val event = OracleEventV0TLV(
|
||||
OrderedNonces(Vector(nonce)),
|
||||
OrderedNonces.fromUnsorted(Vector(nonce)),
|
||||
UInt32.zero,
|
||||
EnumEventDescriptorV0TLV(events.map(outcome => outcome.outcome)),
|
||||
"dummy")
|
||||
|
@ -893,17 +897,14 @@ object OracleAnnouncementV0TLV extends TLVFactory[OracleAnnouncementV0TLV] {
|
|||
|
||||
def dummyForKeys(
|
||||
privKey: ECPrivateKey,
|
||||
nonces: Vector[SchnorrNonce]): OracleAnnouncementTLV = {
|
||||
nonces: OrderedNonces): OracleAnnouncementTLV = {
|
||||
val eventDescriptor = DigitDecompositionEventDescriptorV0TLV(UInt16(2),
|
||||
isSigned =
|
||||
false,
|
||||
nonces.length,
|
||||
"dummy",
|
||||
Int32.zero)
|
||||
val event = OracleEventV0TLV(OrderedNonces(nonces),
|
||||
UInt32.zero,
|
||||
eventDescriptor,
|
||||
"dummy")
|
||||
val event = OracleEventV0TLV(nonces, UInt32.zero, eventDescriptor, "dummy")
|
||||
val sig =
|
||||
privKey.schnorrSign(CryptoUtil.sha256DLCAnnouncement(event.bytes).bytes)
|
||||
|
||||
|
@ -916,7 +917,8 @@ object OracleAnnouncementV0TLV extends TLVFactory[OracleAnnouncementV0TLV] {
|
|||
sealed trait OracleAttestmentTLV extends DLCOracleTLV {
|
||||
def eventId: NormalizedString
|
||||
def publicKey: SchnorrPublicKey
|
||||
def sigs: Vector[SchnorrDigitalSignature]
|
||||
def sigs: OrderedSchnorrSignatures
|
||||
|
||||
def outcomes: Vector[NormalizedString]
|
||||
}
|
||||
|
||||
|
@ -931,7 +933,7 @@ object OracleAttestmentTLV extends TLVParentFactory[OracleAttestmentTLV] {
|
|||
case class OracleAttestmentV0TLV(
|
||||
eventId: NormalizedString,
|
||||
publicKey: SchnorrPublicKey,
|
||||
sigs: Vector[SchnorrDigitalSignature],
|
||||
sigs: OrderedSchnorrSignatures,
|
||||
outcomes: Vector[NormalizedString])
|
||||
extends OracleAttestmentTLV {
|
||||
require(sigs.nonEmpty, "Cannot have 0 signatures")
|
||||
|
@ -948,7 +950,7 @@ case class OracleAttestmentV0TLV(
|
|||
|
||||
strBytes(eventId) ++
|
||||
publicKey.bytes ++
|
||||
u16PrefixedList(sigs) ++
|
||||
u16PrefixedList(sigs.toVector) ++
|
||||
outcomesBytes
|
||||
}
|
||||
}
|
||||
|
@ -967,7 +969,10 @@ object OracleAttestmentV0TLV extends TLVFactory[OracleAttestmentV0TLV] {
|
|||
iter.takeString()
|
||||
}
|
||||
|
||||
OracleAttestmentV0TLV(eventId, pubKey, sigs, outcomes)
|
||||
OracleAttestmentV0TLV(eventId,
|
||||
pubKey,
|
||||
OrderedSchnorrSignatures.fromUnsorted(sigs),
|
||||
outcomes)
|
||||
}
|
||||
|
||||
lazy val dummy: OracleAttestmentV0TLV = {
|
||||
|
@ -978,7 +983,7 @@ object OracleAttestmentV0TLV extends TLVFactory[OracleAttestmentV0TLV] {
|
|||
|
||||
OracleAttestmentV0TLV(eventId,
|
||||
key.schnorrPublicKey,
|
||||
Vector(sig),
|
||||
OrderedSchnorrSignatures(sig),
|
||||
Vector(outcome))
|
||||
}
|
||||
|
||||
|
|
|
@ -3,13 +3,19 @@ package org.bitcoins.core.util.sorted
|
|||
import org.bitcoins.crypto.SchnorrNonce
|
||||
|
||||
/** Represents an ordered set of SchnorrNonces */
|
||||
case class OrderedNonces(vec: Vector[SchnorrNonce])
|
||||
extends SortedVec[SchnorrNonce, SchnorrNonce](vec,
|
||||
SortedVec.forOrdered(vec))
|
||||
case class OrderedNonces(private val vec: Vector[SchnorrNonce])
|
||||
extends SortedVec[SchnorrNonce, SchnorrNonce](
|
||||
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))
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
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. */
|
||||
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.
|
||||
|
|
|
@ -6,6 +6,7 @@ import org.bitcoins.core.protocol.tlv.{
|
|||
OracleAnnouncementV0TLV,
|
||||
OracleAttestmentV0TLV
|
||||
}
|
||||
import org.bitcoins.core.util.sorted.OrderedSchnorrSignatures
|
||||
import org.bitcoins.crypto.FieldElement
|
||||
import org.bitcoins.testkitcore.util.BitcoinSUnitTest
|
||||
|
||||
|
@ -22,9 +23,11 @@ class AttestationVerificationTest extends BitcoinSUnitTest {
|
|||
val validEnumAttestation: OracleAttestmentV0TLV = OracleAttestmentV0TLV(
|
||||
"fdd868690474657374545aa0024da81c3fec63e56e07ee141cbefbd2c6e7d4dede124fe856ea453a8500013168cb6d4c4e52aeb5bb75ce141cd9e1aa40e1d9123134d9aa390cffb338d51e323d991dadb52f32d0541027f973c363c0b746bb40dd1d42686f172d88ddef380161")
|
||||
|
||||
val invalidEnumAttestation: OracleAttestmentV0TLV =
|
||||
val invalidEnumAttestation: OracleAttestmentV0TLV = {
|
||||
val unsorted = validEnumAttestation.sigs.map(_.copy(sig = FieldElement.one))
|
||||
validEnumAttestation.copy(sigs =
|
||||
validEnumAttestation.sigs.map(_.copy(sig = FieldElement.one)))
|
||||
OrderedSchnorrSignatures.fromUnsorted(unsorted.toVector))
|
||||
}
|
||||
|
||||
val unsignedDigitDecompAnnouncement: OracleAnnouncementV0TLV =
|
||||
OracleAnnouncementV0TLV(
|
||||
|
@ -35,10 +38,12 @@ class AttestationVerificationTest extends BitcoinSUnitTest {
|
|||
"fdd868fd01b40564756d6d79545aa0024da81c3fec63e56e07ee141cbefbd2c6e7d4dede124fe856ea453a850006280b657b9c1cd8de3da2619194e2c71831598be3e60d39a242c232f580451c43050ce8ac95b549bb5fed9e3800cf3c040207071032a5c458485ad1817373c0b7bd61d1a6c395c99202058ddabf851e1c8220f12bd801bbb90efcf45d4a2d769cdaa4e883da6b59cac21fc8f18dae7893997d5d13ac63f33fdb7643bba4c4fc8d57ae1c605b9d36ff8477baa8c216abbfe6c3742236ecfad2415745a7cf7850c6cb6a147a2e2a8875133147055027ed130dec47c6a9f75983d532a5c5940a763546f4835c5b80ca64832a6b9e7526fd575db4913ce0a9686072c5f970f94c3a2e72d0655c541eac15e9caa5af059c1f3e433507f1782e8775c555f1c402509f0c87d4b2e93e52b2283c81185fb8ab14a757ff04b00b821d1aaac0a81e05d15da68e710b25a91bfdacf179d9da3b90dec98844d8ac1ed534922dfa362b9db86c134ca823f9aa4b18525521073096f73fd583205086c7db2b6ac243901e4f1898bc476a311fbcd5d2fb7a355a9032c67dead084fe66eed00f7e9646e6fa83902bc7013001300130013001300130")
|
||||
|
||||
// this one was generated with the same public key
|
||||
val invalidUnsignedDigitDecompAttestation: OracleAttestmentV0TLV =
|
||||
validUnsignedDigitDecompAttestation.copy(sigs =
|
||||
validUnsignedDigitDecompAttestation.sigs.map(
|
||||
_.copy(sig = FieldElement.one)))
|
||||
val invalidUnsignedDigitDecompAttestation: OracleAttestmentV0TLV = {
|
||||
val unsorted = validUnsignedDigitDecompAttestation.sigs.map(
|
||||
_.copy(sig = FieldElement.one))
|
||||
val sorted = OrderedSchnorrSignatures.fromUnsorted(unsorted.toVector)
|
||||
validUnsignedDigitDecompAttestation.copy(sigs = sorted)
|
||||
}
|
||||
|
||||
// this one was generated with a different public key
|
||||
val invalidUnsignedDigitDecompAttestation1: OracleAttestmentV0TLV =
|
||||
|
@ -47,16 +52,18 @@ class AttestationVerificationTest extends BitcoinSUnitTest {
|
|||
|
||||
val signedDigitDecompAnnouncement: OracleAnnouncementV0TLV =
|
||||
OracleAnnouncementV0TLV(
|
||||
"fdd824fd01661aabd9bbcae0207aff9510f05099295f32ff72290cf5c494d3869f582f8c4a6cf1b7d832562047f68ce607eb39dcd7ec8ce64432dc51a8853dc5a3acd96a8bc5545aa0024da81c3fec63e56e07ee141cbefbd2c6e7d4dede124fe856ea453a85fdd822fd010000070652285e89487dc8ce816a81234082394d9602263d35a7322b77299082257767b559c622def4bba15a2ad7fc336edd71ace9b4c366b9eaba22b73df00589e74b7ca5b6c7301ef7dc62aeae1823018107868d8956677421e11ffd8f125f2fedf4a527003355640ee9333cda6c37a92d4989c6ab96eddc9266f0ddce0e2a3ffb77aa9eefa1fe40eddd0fa63f501e9b368eed6ab0cc0d2e5e6da1baa570ed9e857134bbc8a15dd5949eb1203b1d15ae701fe4b04707a1ea54c10fef16308bf806f2aa0b17f8673fe785f6b9ff0718e55b621c8e9d92839759a98b88bd6590a0ff856011fe80fdd80a0f00020105756e697473000000000006067369676e6564")
|
||||
"fdd824fd010126487da78218c4fd04d85575595584c54bbec4f2ab3cb64f820bab24c14f9738f4284846c3780985f5c1189decc7680d9c0dbfa5e454b72ac6e292de0df0121ec22db0a9b26f825ccff38cd776103c952c5ede3fc5da3a69770d446011ac126ffdd8229d00049ef0f2b1e7befd3840b4ae6b9f690c6ed42ba9fcddbcde1a7ee91732d63b802ec1e88c69f414e1b47db730ccd4ec1f6e2049e5ce7d569b9dc42263503efb85ed60cbb1d5d42b28d571ef9cb37dba9927a65c819742267862d88acd50a276ad9a624b05aa3829dc181f785f31a0450299a972cc0eb44384529ef30a9a17c0f2aa63328350fdd80a0e00020004746573740000000000040474657374")
|
||||
|
||||
val validSignedDigitDecompAttestation: OracleAttestmentV0TLV =
|
||||
OracleAttestmentV0TLV(
|
||||
"fdd868fd01f7067369676e6564545aa0024da81c3fec63e56e07ee141cbefbd2c6e7d4dede124fe856ea453a8500070652285e89487dc8ce816a81234082394d9602263d35a7322b772990822577670ab288b31d99f56d18d4f34be875c0a4d73aae135c4f50349a1014b686d69841b559c622def4bba15a2ad7fc336edd71ace9b4c366b9eaba22b73df00589e74ba7b82eef2041bf6af1511016cadabe9d52e64d875caf5bfef85903dbc4fc00737ca5b6c7301ef7dc62aeae1823018107868d8956677421e11ffd8f125f2fedf469f40edbb7846274f46a973f5442ece91b5a6e450a8cdcef272058a27176dabba527003355640ee9333cda6c37a92d4989c6ab96eddc9266f0ddce0e2a3ffb7762f10e09f79273ab04d1549c1d60054738fe903575aa732760bd2668530459e9aa9eefa1fe40eddd0fa63f501e9b368eed6ab0cc0d2e5e6da1baa570ed9e857188bae5c59c9ac89bec3fa00c8e1b725789e1af15f7b256ae7f169edfe7f3ef8834bbc8a15dd5949eb1203b1d15ae701fe4b04707a1ea54c10fef16308bf806f2144d3e7aa63705924da607162f59bff757490469c2c8d4e62a1aa0bf27323bcdaa0b17f8673fe785f6b9ff0718e55b621c8e9d92839759a98b88bd6590a0ff85e072b65d258bbfdc653444b08714c2be395b7e645caa214567b22916ffb7ebeb012d013001310130013101300130")
|
||||
"fdd868fd012f0474657374c22db0a9b26f825ccff38cd776103c952c5ede3fc5da3a69770d446011ac126f00049ef0f2b1e7befd3840b4ae6b9f690c6ed42ba9fcddbcde1a7ee91732d63b802ec8230d8b4f0c926fa79dd4d24dcda5487c6e4957f4b208811baa11fde9849dddc1e88c69f414e1b47db730ccd4ec1f6e2049e5ce7d569b9dc42263503efb85ed08bfb84dab00ad7f1d1c07eb8e1559ba0c700e88f7387e936883fe77b406efb560cbb1d5d42b28d571ef9cb37dba9927a65c819742267862d88acd50a276ad9a1b25f23a7c49150f83f6b241a5b6b0f91951f285853452ae05ea5f7e8f3846a5624b05aa3829dc181f785f31a0450299a972cc0eb44384529ef30a9a17c0f2aa593b017b084ea40c7f364e5235c9a27f659dc2cfa689e0aa80f4a4cacd4d4de10131013101300130")
|
||||
|
||||
val invalidSignedDigitDecompAttestation: OracleAttestmentV0TLV =
|
||||
validSignedDigitDecompAttestation.copy(sigs =
|
||||
validSignedDigitDecompAttestation.sigs.map(
|
||||
_.copy(sig = FieldElement.one)))
|
||||
val invalidSignedDigitDecompAttestation: OracleAttestmentV0TLV = {
|
||||
val unsorted =
|
||||
validSignedDigitDecompAttestation.sigs.map(_.copy(sig = FieldElement.one))
|
||||
val sorted = OrderedSchnorrSignatures.fromUnsorted(unsorted.toVector)
|
||||
validSignedDigitDecompAttestation.copy(sigs = sorted)
|
||||
}
|
||||
|
||||
val invalidSignedDigitDecompAttestation1: OracleAttestmentV0TLV =
|
||||
OracleAttestmentV0TLV(
|
||||
|
|
|
@ -248,7 +248,7 @@ case class DLCOracle()(implicit val conf: DLCOracleAppConfig)
|
|||
|
||||
nonces = rValueDbs.map(_.nonce)
|
||||
|
||||
eventTLV = OracleEventV0TLV(OrderedNonces(nonces),
|
||||
eventTLV = OracleEventV0TLV(OrderedNonces.fromUnsorted(nonces),
|
||||
epoch,
|
||||
descriptor,
|
||||
eventName)
|
||||
|
|
|
@ -70,7 +70,7 @@ trait EventDbUtil {
|
|||
eventName: String,
|
||||
signingVersion: SigningVersion = SigningVersion.latest): Vector[
|
||||
EventDb] = {
|
||||
val nonces = oracleAnnouncementV0TLV.eventTLV.nonces.vec
|
||||
val nonces = oracleAnnouncementV0TLV.eventTLV.nonces.toVector
|
||||
nonces.zipWithIndex.map { case (nonce, index) =>
|
||||
EventDb(
|
||||
nonce = nonce,
|
||||
|
|
|
@ -437,43 +437,6 @@ class DLCExecutionTest extends BitcoinSDualWalletTest {
|
|||
} 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 {
|
||||
wallets =>
|
||||
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._
|
||||
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.testkit.wallet.BitcoinSDualWalletTest
|
||||
import org.bitcoins.testkit.wallet.DLCWalletUtil._
|
||||
|
@ -77,7 +80,7 @@ class DLCMultiOracleEnumExecutionTest extends BitcoinSDualWalletTest {
|
|||
val initiatorWinSig = priv.schnorrSignWithNonce(hash, kValue)
|
||||
OracleAttestmentV0TLV(eventId,
|
||||
priv.schnorrPublicKey,
|
||||
Vector(initiatorWinSig),
|
||||
OrderedSchnorrSignatures(initiatorWinSig),
|
||||
Vector(initiatorWinStr))
|
||||
}
|
||||
|
||||
|
@ -98,7 +101,7 @@ class DLCMultiOracleEnumExecutionTest extends BitcoinSDualWalletTest {
|
|||
val recipientWinSig = priv.schnorrSignWithNonce(hash, kValue)
|
||||
OracleAttestmentV0TLV(eventId,
|
||||
priv.schnorrPublicKey,
|
||||
Vector(recipientWinSig),
|
||||
OrderedSchnorrSignatures(recipientWinSig),
|
||||
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._
|
||||
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.testkitcore.dlc.DLCTest.genNumericOracleOutcome
|
||||
import org.bitcoins.testkit.wallet.DLCWalletUtil._
|
||||
|
@ -18,19 +22,32 @@ class DLCMultiOracleExactNumericExecutionTest extends BitcoinSDualWalletTest {
|
|||
|
||||
behavior of "DLCWallet"
|
||||
|
||||
val privateKeys: Vector[ECPrivateKey] =
|
||||
0.until(5).map(_ => ECPrivateKey.freshPrivateKey).toVector
|
||||
val privateKeys: Vector[ECPrivateKey] = {
|
||||
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]] =
|
||||
privateKeys.map(_ =>
|
||||
0.until(numDigits).map(_ => ECPrivateKey.freshPrivateKey).toVector)
|
||||
val kValues: Vector[Vector[ECPrivateKey]] = {
|
||||
privateKeys.map { _ =>
|
||||
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 =
|
||||
DLCWalletUtil.multiNonceContractDescriptor
|
||||
|
||||
val announcements: Vector[OracleAnnouncementTLV] =
|
||||
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
|
||||
|
@ -228,7 +245,7 @@ class DLCMultiOracleExactNumericExecutionTest extends BitcoinSDualWalletTest {
|
|||
s"kValues.length=${kValues.length} sigs.length=${sigs.length}")
|
||||
OracleAttestmentV0TLV(eventId,
|
||||
priv.schnorrPublicKey,
|
||||
sigs,
|
||||
OrderedSchnorrSignatures.fromUnsorted(sigs),
|
||||
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._
|
||||
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.testkitcore.dlc.DLCTest
|
||||
import org.bitcoins.testkit.wallet.DLCWalletUtil._
|
||||
|
@ -20,20 +24,34 @@ class DLCMultiOracleNumericExecutionTest
|
|||
|
||||
behavior of "DLCWallet"
|
||||
|
||||
val privateKeys: Vector[ECPrivateKey] =
|
||||
0.until(5).map(_ => ECPrivateKey.freshPrivateKey).toVector
|
||||
val privateKeys: Vector[ECPrivateKey] = {
|
||||
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]] =
|
||||
privateKeys.map(_ =>
|
||||
0.until(numDigits).map(_ => ECPrivateKey.freshPrivateKey).toVector)
|
||||
val kValues: Vector[Vector[ECPrivateKey]] = {
|
||||
privateKeys.map { _ =>
|
||||
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 =
|
||||
DLCWalletUtil.multiNonceContractDescriptor
|
||||
|
||||
val announcements: Vector[OracleAnnouncementTLV] =
|
||||
val announcements: Vector[OracleAnnouncementTLV] = {
|
||||
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
|
||||
|
||||
|
@ -237,7 +255,7 @@ class DLCMultiOracleNumericExecutionTest
|
|||
s"kValues.length=${kValues.length} sigs.length=${sigs.length}")
|
||||
OracleAttestmentV0TLV(eventId,
|
||||
priv.schnorrPublicKey,
|
||||
sigs,
|
||||
OrderedSchnorrSignatures.fromUnsorted(sigs),
|
||||
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._
|
||||
import org.bitcoins.core.protocol.tlv._
|
||||
import org.bitcoins.core.util.sorted.OrderedSchnorrSignatures
|
||||
import org.bitcoins.crypto._
|
||||
import org.bitcoins.testkit.wallet.DLCWalletUtil._
|
||||
import org.bitcoins.testkit.wallet.{BitcoinSDualWalletTest, DLCWalletUtil}
|
||||
|
@ -78,11 +79,11 @@ class DLCNumericExecutionTest extends BitcoinSDualWalletTest {
|
|||
|
||||
(OracleAttestmentV0TLV(eventId,
|
||||
publicKey,
|
||||
initiatorWinSigs,
|
||||
OrderedSchnorrSignatures(initiatorWinSigs),
|
||||
initiatorWinVec.map(_.toString)),
|
||||
OracleAttestmentV0TLV(eventId,
|
||||
publicKey,
|
||||
recipientWinSigs,
|
||||
OrderedSchnorrSignatures(recipientWinSigs),
|
||||
recipientWinVec.map(_.toString)))
|
||||
}
|
||||
|
||||
|
@ -175,7 +176,8 @@ class DLCNumericExecutionTest extends BitcoinSDualWalletTest {
|
|||
//purposefully drop these
|
||||
//we cannot drop just a sig, or just an outcome because
|
||||
//of invariants in OracleAttestmentV0TLV
|
||||
badSigs = goodAttestment.sigs.dropRight(1)
|
||||
badSigs = OrderedSchnorrSignatures.fromUnsorted(
|
||||
goodAttestment.sigs.dropRight(1).toVector)
|
||||
badOutcomes = goodAttestment.outcomes.dropRight(1)
|
||||
badAttestment = OracleAttestmentV0TLV(eventId = goodAttestment.eventId,
|
||||
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.script.P2WPKHWitnessV0
|
||||
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.utxo.TxoState
|
||||
import org.bitcoins.crypto._
|
||||
|
@ -763,7 +764,8 @@ class WalletDLCSetupTest extends BitcoinSDualWalletTest {
|
|||
val oracleSig = SchnorrDigitalSignature(
|
||||
"a6a09c7c83c50b34f9db560a2e14fef2eab5224c15b18c7114331756364bfce6c59736cdcfe1e0a89064f846d5dbde0902f82688dde34dc1833965a60240f287")
|
||||
|
||||
val sig = OracleSignatures(oracleInfo, Vector(oracleSig))
|
||||
val sig =
|
||||
OracleSignatures(oracleInfo, OrderedSchnorrSignatures(oracleSig))
|
||||
|
||||
for {
|
||||
offer <- walletA.createDLCOffer(
|
||||
|
@ -887,24 +889,8 @@ class WalletDLCSetupTest extends BitcoinSDualWalletTest {
|
|||
} yield succeed
|
||||
}
|
||||
|
||||
//https://test.oracle.suredbits.com/contract/numeric/022428196c6a60673d1f2b90e7be14ac615986dce5571246e8bcc9d2d689d57b
|
||||
private val numericContractInfo = ContractInfoV0TLV.fromHex(
|
||||
"""fdd82efd033f00000000000186a0fda720540012fda72648000501000000000000000000000001fd88b80000000000000000000001
|
||||
|fdafc8000000000000c350000001fdd6d800000000000186a0000001fe0003ffff00000000000186a00000fda724020000fda712fd
|
||||
|02d9fdd824fd02d391177fd623a72d56e7bc12e3903f8d6bce7f07a25226d54009cd7e670f5e7a7320b0704286580d8b6a7f31ab7b
|
||||
|f71356a13c28aa609a021111b2e3d2b2db26bc120bd29248895b81f76b07d85a21b86021f22352d6376d19bbf5c93f918828f1fdd8
|
||||
|22fd026d0012fad0cde50a2258efa25cbba60ef0b6677cd29654802937c112097edb64bd205beea02263d6461e60a9ca8e08209c8b
|
||||
|d5552863156014d5418cad91ac590bbf13a847f105db9899d560e5040f9565c043c9e7fdf3782ad2708c5b99646c722b4118547472
|
||||
|48fb52e6486cce3eca5ddf9d64ecbe0864501a446efd378863f9a4055fab50d2112320ff14d8747a72467589822103f197063b49e7
|
||||
|7b90d82d3a8d49b63c3ceb9bd3328398a53989d4237216a24a1d12364efa2d2aec59cdc87909b115dca5b07106b70032ff78072f82
|
||||
|ceeaf2e20db55086e9a2e5e5cac864992d747fd40f4b26bc3d7de958ee02460d1199ff81438c9b76b3934cbc4566d10f242563b95e
|
||||
|7df79c28d52c9c46b617676a4ee84a549ee1f0f53865c9ef4d0ff825e2f438384c5f6238d0734beb570a1a49d035d9f86ee31c23f1
|
||||
|e97bd34fba3f586c0fdf29997530e528b3200a0d7e34f865dc4ca7bfd722bf77c0478ddd25bfa2dc6a4ab973d0c1b7a9ff38283b7c
|
||||
|19bbe02677a9b628f3ee3d5198d66c1623c9608293093c126d4124a445bb6412f720493b6ffa411db53923895fd50c9563d50a97a8
|
||||
|6188084fe4c0f15ce50438ff0b00e1a9470185fd7c96296ae2be12056f61ceaeee7ced48314a3b6855bc9aa3b446b9dfad68553f53
|
||||
|02c60670a95fb9bdc5e72db7f1e9d42e4f4baca1bcbb22612db6417b45cc3d78b1ef33fc362a68db56df00ab1ee0700bd900200f6a
|
||||
|24882101e71de7e18a7fb0d7da27b340de52f97d96239f359cfe31afcaf69cc9ddfcbfbdb2267e673ad728a29dd22d31d1a1187162
|
||||
|037480fdd80a100002000642544355534400000000001212446572696269742d4254432d394645423232""".stripMargin)
|
||||
private val numericContractInfo =
|
||||
DLCWalletUtil.numericContractInfoV0
|
||||
|
||||
it must "fail accepting an offer twice simultaneously" in { wallets =>
|
||||
val walletA = wallets._1.wallet
|
||||
|
|
|
@ -110,10 +110,11 @@ case class DLCDataManagement(dlcWalletDAOs: DLCWalletDAOs)(implicit
|
|||
.exists(_.used)
|
||||
if (used) {
|
||||
val nonces = nonceDbs.sortBy(_.index).map(_.nonce)
|
||||
val eventTLV = OracleEventV0TLV(OrderedNonces(nonces),
|
||||
data.eventMaturity,
|
||||
data.eventDescriptor,
|
||||
data.eventId)
|
||||
val eventTLV =
|
||||
OracleEventV0TLV(OrderedNonces.fromUnsorted(nonces),
|
||||
data.eventMaturity,
|
||||
data.eventDescriptor,
|
||||
data.eventId)
|
||||
Some(
|
||||
(OracleAnnouncementV0TLV(data.announcementSignature,
|
||||
data.publicKey,
|
||||
|
@ -151,7 +152,7 @@ case class DLCDataManagement(dlcWalletDAOs: DLCWalletDAOs)(implicit
|
|||
announcementData.find(_.id.contains(id)) match {
|
||||
case Some(data) =>
|
||||
val nonces = nonceDbs.sortBy(_.index).map(_.nonce)
|
||||
val eventTLV = OracleEventV0TLV(OrderedNonces(nonces),
|
||||
val eventTLV = OracleEventV0TLV(OrderedNonces.fromUnsorted(nonces),
|
||||
data.eventMaturity,
|
||||
data.eventDescriptor,
|
||||
data.eventId)
|
||||
|
|
|
@ -17,7 +17,7 @@ object OracleNonceDbHelper {
|
|||
def fromAnnouncement(
|
||||
id: Long,
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -141,7 +141,8 @@ val descriptor = NumericContractDescriptor(curve, numDigits = 15, roundTo100)
|
|||
val announcements = 0.until(5).toVector.map { _ =>
|
||||
val oraclePrivKey = ECPrivateKey.freshPrivateKey
|
||||
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(
|
||||
threshold = 3,
|
||||
|
|
|
@ -14,7 +14,11 @@ import org.bitcoins.core.protocol.script._
|
|||
import org.bitcoins.core.protocol.tlv.{NumericDLCOutcomeType, _}
|
||||
import org.bitcoins.core.protocol.transaction._
|
||||
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.wallet.fee.SatoshisPerVirtualByte
|
||||
import org.bitcoins.core.wallet.utxo._
|
||||
|
@ -40,22 +44,27 @@ trait DLCTest {
|
|||
}
|
||||
}
|
||||
|
||||
val oraclePrivKeys: Vector[ECPrivateKey] =
|
||||
(0 until 50).toVector.map(_ => ECPrivateKey.freshPrivateKey)
|
||||
val oraclePrivKeys: Vector[ECPrivateKey] = {
|
||||
ECPrivateKey.generateNonceOrderedPrivKeys(50)
|
||||
}
|
||||
|
||||
val oraclePubKeys: Vector[SchnorrPublicKey] =
|
||||
oraclePrivKeys.map(_.schnorrPublicKey)
|
||||
val oraclePrivKey: ECPrivateKey = oraclePrivKeys.head
|
||||
val oraclePubKey: SchnorrPublicKey = oraclePubKeys.head
|
||||
|
||||
val preCommittedKsPerOracle: Vector[Vector[ECPrivateKey]] =
|
||||
oraclePrivKeys.map(_ =>
|
||||
(0 until 50).toVector.map(_ => ECPrivateKey.freshPrivateKey))
|
||||
val preCommittedKsPerOracle: Vector[Vector[ECPrivateKey]] = {
|
||||
oraclePrivKeys.map { _ =>
|
||||
ECPrivateKey.generateNonceOrderedPrivKeys(50)
|
||||
}
|
||||
}
|
||||
|
||||
val preCommittedRsPerOracle: Vector[Vector[SchnorrNonce]] =
|
||||
preCommittedKsPerOracle.map(_.map(_.schnorrNonce))
|
||||
val preCommittedRsPerOracle: Vector[OrderedNonces] =
|
||||
preCommittedKsPerOracle.map { privKeys =>
|
||||
OrderedNonces.fromUnsorted(privKeys.map(_.schnorrNonce))
|
||||
}
|
||||
val preCommittedKs: Vector[ECPrivateKey] = preCommittedKsPerOracle.head
|
||||
val preCommittedRs: Vector[SchnorrNonce] = preCommittedRsPerOracle.head
|
||||
val preCommittedRs: OrderedNonces = preCommittedRsPerOracle.head
|
||||
val preCommittedK: ECPrivateKey = preCommittedKs.head
|
||||
val preCommittedR: SchnorrNonce = preCommittedRs.head
|
||||
|
||||
|
@ -454,8 +463,9 @@ trait DLCTest {
|
|||
.zip(preCommittedRsPerOracle
|
||||
.slice(oracleShift, oracleShift + params.numOracles))
|
||||
.map { case (privKey, rVals) =>
|
||||
OracleAnnouncementV0TLV.dummyForKeys(privKey,
|
||||
rVals.take(params.numDigits))
|
||||
val nonces =
|
||||
OrderedNonces.fromUnsorted(rVals.take(params.numDigits).toVector)
|
||||
OracleAnnouncementV0TLV.dummyForKeys(privKey, nonces)
|
||||
}
|
||||
val oracleInfo = if (params.numOracles == 1) {
|
||||
NumericSingleOracleInfo(announcements.head)
|
||||
|
@ -779,14 +789,17 @@ trait DLCTest {
|
|||
def computeNumericOracleSignatures(
|
||||
digits: Vector[Int],
|
||||
privKey: ECPrivateKey = oraclePrivKey,
|
||||
kVals: Vector[ECPrivateKey] = preCommittedKs): Vector[
|
||||
SchnorrDigitalSignature] = {
|
||||
digits.zip(kVals.take(digits.length)).map { case (digit, kValue) =>
|
||||
privKey.schnorrSignWithNonce(CryptoUtil
|
||||
.sha256DLCAttestation(digit.toString)
|
||||
.bytes,
|
||||
kValue)
|
||||
}
|
||||
kVals: Vector[ECPrivateKey] =
|
||||
preCommittedKs): OrderedSchnorrSignatures = {
|
||||
val unsorted =
|
||||
digits.zip(kVals.take(digits.length)).map { case (digit, kValue) =>
|
||||
privKey.schnorrSignWithNonce(CryptoUtil
|
||||
.sha256DLCAttestation(digit.toString)
|
||||
.bytes,
|
||||
kValue)
|
||||
}
|
||||
|
||||
OrderedSchnorrSignatures.fromUnsorted(unsorted)
|
||||
}
|
||||
|
||||
/** 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) =>
|
||||
val testFs = outcomeIndices.map {
|
||||
case (contractIndex, outcomeIndex) =>
|
||||
executeForOutcome(outcomeIndex,
|
||||
dlcOffer,
|
||||
offerSetup,
|
||||
dlcAccept,
|
||||
acceptSetup,
|
||||
outcomes,
|
||||
contractIndex)
|
||||
executeForOutcome(
|
||||
outcomeIndex = outcomeIndex,
|
||||
dlcOffer = dlcOffer,
|
||||
offerSetup = offerSetup,
|
||||
dlcAccept = dlcAccept,
|
||||
acceptSetup = acceptSetup,
|
||||
outcomes = outcomes,
|
||||
contractIndex = contractIndex
|
||||
)
|
||||
}
|
||||
|
||||
Future.sequence(testFs).map(_ => succeed)
|
||||
|
|
|
@ -134,7 +134,10 @@ trait TLVGen {
|
|||
Gen
|
||||
.listOfN(desc.noncesNeeded, CryptoGenerators.schnorrNonce)
|
||||
.map(_.toVector)
|
||||
} yield OracleEventV0TLV(OrderedNonces(nonces), maturity, desc, uri)
|
||||
} yield OracleEventV0TLV(OrderedNonces.fromUnsorted(nonces),
|
||||
maturity,
|
||||
desc,
|
||||
uri)
|
||||
}
|
||||
|
||||
def oracleAnnouncementV0TLV: Gen[OracleAnnouncementV0TLV] = {
|
||||
|
@ -150,10 +153,11 @@ trait TLVGen {
|
|||
eventId <- StringGenerators.genUTF8String
|
||||
pubkey <- CryptoGenerators.schnorrPublicKey
|
||||
numSigs <- Gen.choose(1, 10)
|
||||
sigs <-
|
||||
unsorted <-
|
||||
Gen
|
||||
.listOfN(numSigs, CryptoGenerators.schnorrDigitalSignature)
|
||||
.map(_.toVector)
|
||||
sigs = OrderedSchnorrSignatures.fromUnsorted(unsorted)
|
||||
outcomes <-
|
||||
Gen
|
||||
.listOfN(numSigs, StringGenerators.genUTF8String)
|
||||
|
@ -237,10 +241,10 @@ trait TLVGen {
|
|||
def oracleInfoV0TLV(numDigits: Int): Gen[OracleInfoV0TLV] = {
|
||||
for {
|
||||
privKey <- CryptoGenerators.privateKey
|
||||
rValues <- Gen.listOfN(numDigits, CryptoGenerators.schnorrNonce)
|
||||
unsorted <- Gen.listOfN(numDigits, CryptoGenerators.schnorrNonce)
|
||||
rValues = OrderedNonces.fromUnsorted(unsorted.toVector)
|
||||
} yield {
|
||||
OracleInfoV0TLV(
|
||||
OracleAnnouncementV0TLV.dummyForKeys(privKey, rValues.toVector))
|
||||
OracleInfoV0TLV(OracleAnnouncementV0TLV.dummyForKeys(privKey, rValues))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ import org.bitcoins.core.psbt.InputPSBTRecord.PartialSignature
|
|||
import org.bitcoins.core.script.PreExecutionScriptProgram
|
||||
import org.bitcoins.core.script.interpreter.ScriptInterpreter
|
||||
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.crypto._
|
||||
import org.bitcoins.dlc.wallet.DLCWallet
|
||||
|
@ -37,9 +38,14 @@ import scala.concurrent.{ExecutionContext, Future}
|
|||
object DLCWalletUtil extends Logging {
|
||||
lazy val oraclePrivKey: ECPrivateKey = ECPrivateKey.freshPrivateKey
|
||||
|
||||
lazy val kValues: Vector[ECPrivateKey] =
|
||||
0.to(10).map(_ => ECPrivateKey.freshPrivateKey).toVector
|
||||
lazy val rValues: Vector[SchnorrNonce] = kValues.map(_.schnorrNonce)
|
||||
lazy val kValues: Vector[ECPrivateKey] = {
|
||||
ECPrivateKey.generateNonceOrderedPrivKeys(10)
|
||||
}
|
||||
|
||||
lazy val rValues: OrderedNonces = {
|
||||
val nonces = kValues.map(_.schnorrNonce)
|
||||
OrderedNonces.fromUnsorted(nonces)
|
||||
}
|
||||
|
||||
lazy val kValue: ECPrivateKey = kValues.head
|
||||
lazy val rValue: SchnorrNonce = rValues.head
|
||||
|
@ -133,10 +139,12 @@ object DLCWalletUtil extends Logging {
|
|||
lazy val multiNonceContractDescriptor: NumericContractDescriptor =
|
||||
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(
|
||||
OracleAnnouncementV0TLV.dummyForKeys(oraclePrivKey,
|
||||
rValues.take(numDigits)))
|
||||
OracleAnnouncementV0TLV.dummyForKeys(oraclePrivKey, sorted))
|
||||
}
|
||||
|
||||
lazy val multiNonceContractOraclePair: ContractOraclePair.NumericPair = {
|
||||
ContractOraclePair.NumericPair(multiNonceContractDescriptor,
|
||||
|
@ -146,6 +154,9 @@ object DLCWalletUtil extends Logging {
|
|||
lazy val multiNonceContractInfo: ContractInfo =
|
||||
SingleContractInfo(total, multiNonceContractOraclePair)
|
||||
|
||||
lazy val numericContractInfoV0 =
|
||||
multiNonceContractInfo.toTLV.asInstanceOf[ContractInfoV0TLV]
|
||||
|
||||
lazy val dummyContractMaturity: BlockTimeStamp = BlockTimeStamp(0)
|
||||
lazy val dummyContractTimeout: BlockTimeStamp = BlockTimeStamp(1)
|
||||
|
||||
|
@ -503,11 +514,11 @@ object DLCWalletUtil extends Logging {
|
|||
|
||||
(OracleAttestmentV0TLV(eventId,
|
||||
publicKey,
|
||||
Vector(initiatorWinSig),
|
||||
OrderedSchnorrSignatures(initiatorWinSig),
|
||||
Vector(initiatorWinStr)),
|
||||
OracleAttestmentV0TLV(eventId,
|
||||
publicKey,
|
||||
Vector(recipientWinSig),
|
||||
OrderedSchnorrSignatures(recipientWinSig),
|
||||
Vector(recipientWinStr)))
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue