2022 09 29 handle unordered sigs (#4807)

* Get unit tests passing for unordered nonces/signatures

* Get v0 oracle announcements working again on listannouncements

* Add unit test to make sure we can still validate signatures for attestments with nonces out of order
This commit is contained in:
Chris Stewart 2022-09-29 11:43:50 -05:00 committed by GitHub
parent 2c85f92b18
commit 34e023e93f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 226 additions and 108 deletions

View File

@ -936,7 +936,7 @@ class RoutesSpec extends AnyWordSpec with ScalatestRouteTest with MockFactory {
val dummyOracleAttestment =
OracleAttestmentV0TLV("eventId",
dummyPubKey.schnorrPublicKey,
OrderedSchnorrSignatures(dummyOracleSig),
OrderedSchnorrSignatures(dummyOracleSig).toVector,
Vector("outcome"))
lazy val winStr: String = "WIN"

View File

@ -36,11 +36,15 @@ sealed trait OracleEvent {
def eventDescriptorTLV: EventDescriptorTLV
def eventTLV: OracleEventTLV =
OracleEventV0TLV(nonces,
def eventTLV: OracleEventTLV = {
require(eventDbsOpt.isDefined,
s"Event dbs must be defined to figure out ordering of nonces")
val v0NonceOrder = eventDbsOpt.get.sortBy(_.nonceIndex).map(_.nonce)
OracleEventV0TLV(v0NonceOrder,
UInt32(maturationTime.getEpochSecond),
eventDescriptorTLV,
eventName)
}
def announcementTLV: OracleAnnouncementTLV = {
eventTLV match {
@ -48,6 +52,11 @@ sealed trait OracleEvent {
OracleAnnouncementV0TLV(announcementSignature, pubkey, v0TLV)
}
}
/** These are needed for old announcements/attesatations that do not follow the requirement
* to order nonces
*/
protected def eventDbsOpt: Option[Vector[EventDb]]
}
/** An oracle event that has not been signed yet */
@ -67,11 +76,22 @@ sealed trait CompletedOracleEvent extends OracleEvent {
OrderedSchnorrSignatures.fromUnsorted(unsorted)
}
def oracleAttestmentV0TLV: OracleAttestmentV0TLV =
OracleAttestmentV0TLV(eventName,
pubkey,
signatures,
outcomes.map(_.outcomeString))
def oracleAttestmentV0TLV: OracleAttestmentV0TLV = {
announcementTLV match {
case ann: OracleAnnouncementV0TLV =>
//v0 announcements do not have a invariant stating that nonces neeed to be sorted
//a specific way, so we need to use the unsorted variant to make sure
//announcementSignatures evaluate to true
val unsorted = ann.eventTLV.nonces
.zip(attestations)
.map(sigPieces => SchnorrDigitalSignature(sigPieces._1, sigPieces._2))
OracleAttestmentV0TLV(eventName,
pubkey,
unsorted,
outcomes.map(_.outcomeString))
}
}
def outcomes: Vector[DLCAttestationType]
@ -92,7 +112,8 @@ case class PendingEnumV0OracleEvent(
signingVersion: SigningVersion,
maturationTime: Instant,
announcementSignature: SchnorrDigitalSignature,
eventDescriptorTLV: EnumEventDescriptorV0TLV)
eventDescriptorTLV: EnumEventDescriptorV0TLV,
eventDbsOpt: Option[Vector[EventDb]])
extends PendingOracleEvent
with EnumV0OracleEvent
@ -105,13 +126,16 @@ case class CompletedEnumV0OracleEvent(
announcementSignature: SchnorrDigitalSignature,
eventDescriptorTLV: EnumEventDescriptorV0TLV,
outcome: EnumAttestation,
attestation: FieldElement)
attestation: FieldElement,
eventDbsOpt: Option[Vector[EventDb]])
extends CompletedOracleEvent
with EnumV0OracleEvent {
require(OracleEvent.verifyAttestations(announcementTLV,
oracleAttestmentV0TLV,
signingVersion),
"Signatures given are invalid")
require(
OracleEvent.verifyAttestations(announcementTLV,
oracleAttestmentV0TLV,
signingVersion),
s"Signatures given are invalid, eventId=${announcementTLV.eventTLV.eventId}"
)
override def attestations: Vector[FieldElement] = Vector(attestation)
@ -131,7 +155,8 @@ case class PendingDigitDecompositionV0OracleEvent(
signingVersion: SigningVersion,
maturationTime: Instant,
announcementSignature: SchnorrDigitalSignature,
eventDescriptorTLV: DigitDecompositionEventDescriptorV0TLV)
eventDescriptorTLV: DigitDecompositionEventDescriptorV0TLV,
eventDbsOpt: Option[Vector[EventDb]])
extends PendingOracleEvent
with DigitDecompositionV0OracleEvent
@ -144,14 +169,17 @@ case class CompletedDigitDecompositionV0OracleEvent(
announcementSignature: SchnorrDigitalSignature,
eventDescriptorTLV: DigitDecompositionEventDescriptorV0TLV,
dlcOutcome: NumericDLCOutcomeType,
attestations: Vector[FieldElement])
attestations: Vector[FieldElement],
eventDbsOpt: Option[Vector[EventDb]])
extends CompletedOracleEvent
with DigitDecompositionV0OracleEvent {
require(OracleEvent.verifyAttestations(announcementTLV,
oracleAttestmentV0TLV,
signingVersion),
"Signatures given are invalid")
require(
OracleEvent.verifyAttestations(announcementTLV,
oracleAttestmentV0TLV,
signingVersion),
s"Signatures given are invalid for eventId=${announcementTLV.eventTLV.eventId}"
)
val outcomeBase10: Long = {
val (digits, positive) = dlcOutcome match {
@ -199,7 +227,8 @@ object OracleEvent {
eventDb.announcementSignature,
enum,
EnumAttestation(eventDb.outcomeOpt.get),
sig
sig,
Some(eventDbs)
)
case (enum: EnumEventDescriptorV0TLV, None) =>
require(eventDbs.size == 1, "Enum events may only have one eventDb")
@ -209,7 +238,8 @@ object OracleEvent {
eventDb.signingVersion,
eventDb.maturationTime,
eventDb.announcementSignature,
enum)
enum,
Some(eventDbs))
case (decomp: DigitDecompositionEventDescriptorV0TLV, Some(_)) =>
require(eventDbs.forall(_.attestationOpt.isDefined),
"Cannot have a partially signed event")
@ -230,7 +260,6 @@ object OracleEvent {
}
UnsignedNumericOutcome(digits)
}
CompletedDigitDecompositionV0OracleEvent(
eventDb.pubkey,
OrderedNonces.fromUnsorted(sortedEventDbs.map(_.nonce)),
@ -240,7 +269,8 @@ object OracleEvent {
eventDb.announcementSignature,
decomp,
dlcOutcome,
attestations
attestations,
Some(eventDbs)
)
case (decomp: DigitDecompositionEventDescriptorV0TLV, None) =>
require(eventDbs.forall(_.attestationOpt.isEmpty),
@ -255,7 +285,8 @@ object OracleEvent {
eventDb.signingVersion,
eventDb.maturationTime,
eventDb.announcementSignature,
decomp
decomp,
Some(eventDbs)
)
}
}
@ -267,8 +298,14 @@ object OracleEvent {
attestationTLV: OracleAttestmentTLV,
signingVersion: SigningVersion): Boolean = {
val tlvOutcomes = attestationTLV.outcomes
val attestations = attestationTLV.sigs
val nonces = announcement.eventTLV.nonces
val attestations = attestationTLV match {
case v0: OracleAttestmentV0TLV =>
v0.unsortedSignatures
}
val nonces = announcement.eventTLV match {
case v0: OracleEventV0TLV =>
v0.nonces
}
if (
announcement.publicKey != attestationTLV.publicKey ||
nonces.size != attestations.size ||

View File

@ -7,6 +7,7 @@ import org.bitcoins.core.protocol.dlc.models.{
}
import org.bitcoins.core.protocol.tlv.{
EnumOutcome,
OracleEventV0TLV,
SignedNumericOutcome,
UnsignedNumericOutcome
}
@ -137,7 +138,10 @@ object DLCAdaptorPointComputer {
contractInfo.oracleInfo.singleOracleInfos.map { info =>
val announcement = info.announcement
val pubKey = announcement.publicKey
val nonces = announcement.eventTLV.nonces.toVector.map(_.publicKey)
val nonces = announcement.eventTLV match {
case v0: OracleEventV0TLV =>
v0.nonces.map(_.publicKey)
}
nonces.map { nonce =>
possibleOutcomes.map { outcome =>

View File

@ -16,7 +16,8 @@ import org.bitcoins.core.protocol.dlc.models._
import org.bitcoins.core.protocol.script.P2WSHWitnessV0
import org.bitcoins.core.protocol.tlv.{
OracleAnnouncementTLV,
OracleAttestmentTLV
OracleAttestmentTLV,
OracleEventV0TLV
}
import org.bitcoins.core.protocol.transaction.{Transaction, WitnessTransaction}
import org.bitcoins.core.util.sorted.{OrderedAnnouncements, OrderedNonces}
@ -262,7 +263,12 @@ object DLCUtil {
oracleSignatures: Vector[OracleSignatures]): Option[OracleSignatures] = {
val announcementNonces: Vector[Vector[SchnorrNonce]] = {
announcements
.map(_.eventTLV.nonces)
.map { ann =>
ann.eventTLV match {
case v0: OracleEventV0TLV =>
v0.nonces
}
}
.map(_.toVector)
}
val resultOpt = oracleSignatures.find { case oracleSignature =>
@ -324,9 +330,13 @@ object DLCUtil {
// Nonces should be unique so searching for the first nonce should be safe
val firstNonce = sig.sigs.head.rx
announcements
.find(
_.eventTLV.nonces.headOption
.contains(firstNonce)) match {
.find { ann =>
ann.eventTLV match {
case v0: OracleEventV0TLV =>
v0.nonces.headOption
.contains(firstNonce)
}
} match {
case Some(announcement) =>
acc :+ OracleSignatures(SingleOracleInfo(announcement), sig.sigs)
case None =>

View File

@ -138,8 +138,7 @@ object DLCExecutor {
): ExecutedDLCOutcome = {
require(
DLCUtil.checkOracleSignaturesAgainstContract(contractInfo, oracleSigs),
s"Incorrect oracle signatures and contract combination, got=${oracleSigs} contractInfo.announcement=${contractInfo.oracleInfos
.map(_.singleOracleInfos.map(_.announcement.eventTLV.nonces))}"
s"Incorrect oracle signatures and contract combination, got=${oracleSigs}"
)
val sigOracles = oracleSigs.map(_.oracle)

View File

@ -69,7 +69,12 @@ sealed trait SingleOracleInfo
def publicKey: SchnorrPublicKey = announcement.publicKey
/** The oracle's pre-committed nonces, in the correct order */
def nonces: OrderedNonces = announcement.eventTLV.nonces
def nonces: OrderedNonces = {
announcement.eventTLV match {
case v0: OracleEventV0TLV =>
OrderedNonces(v0.nonces)
}
}
/** The order of the given sigs should correspond to the given outcome. */
def verifySigs(outcome: DLCOutcomeType, sigs: OracleSignatures): Boolean
@ -125,7 +130,12 @@ case class EnumSingleOracleInfo(announcement: OracleAnnouncementTLV)
.isInstanceOf[EnumEventDescriptorV0TLV],
s"Enum OracleInfo requires EnumEventDescriptor, $announcement")
val nonce: SchnorrNonce = announcement.eventTLV.nonces.head
val nonce: SchnorrNonce = {
announcement.eventTLV match {
case v0: OracleEventV0TLV =>
v0.nonces.head
}
}
/** @inheritdoc */
override def verifySigs(

View File

@ -766,13 +766,12 @@ object DigitDecompositionEventDescriptorV0TLV
sealed trait OracleEventTLV extends DLCOracleTLV {
def eventDescriptor: EventDescriptorTLV
def nonces: OrderedNonces
def eventId: NormalizedString
def eventMaturityEpoch: UInt32
}
case class OracleEventV0TLV(
nonces: OrderedNonces,
nonces: Vector[SchnorrNonce],
eventMaturityEpoch: UInt32,
eventDescriptor: EventDescriptorTLV,
eventId: NormalizedString
@ -786,7 +785,7 @@ case class OracleEventV0TLV(
override def tpe: BigSizeUInt = OracleEventV0TLV.tpe
override val value: ByteVector = {
u16PrefixedList(nonces.toVector) ++
u16PrefixedList(nonces) ++
eventMaturityEpoch.bytes ++
eventDescriptor.bytes ++
strBytes(eventId)
@ -809,10 +808,7 @@ object OracleEventV0TLV extends TLVFactory[OracleEventV0TLV] {
val eventDescriptor = iter.take(EventDescriptorTLV)
val eventId = iter.takeString()
OracleEventV0TLV(OrderedNonces.fromUnsorted(nonces),
eventMaturity,
eventDescriptor,
eventId)
OracleEventV0TLV(nonces, eventMaturity, eventDescriptor, eventId)
}
override val typeName: String = "OracleEventV0TLV"
@ -868,11 +864,10 @@ object OracleAnnouncementV0TLV extends TLVFactory[OracleAnnouncementV0TLV] {
lazy val dummy: OracleAnnouncementV0TLV = {
val dummyPrivKey: ECPrivateKey = ECPrivateKey.fromHex(
"f04671ab68f3fefbeaa344c49149748f722287a81b19cd956b2332d07b8f6853")
val event = OracleEventV0TLV(
OrderedNonces.fromUnsorted(Vector(dummyPrivKey.schnorrNonce)),
UInt32.zero,
EnumEventDescriptorV0TLV.dummy,
"dummy")
val event = OracleEventV0TLV(Vector(dummyPrivKey.schnorrNonce),
UInt32.zero,
EnumEventDescriptorV0TLV.dummy,
"dummy")
val sig =
dummyPrivKey.schnorrSign(
CryptoUtil.sha256DLCAnnouncement(event.bytes).bytes)
@ -885,7 +880,7 @@ object OracleAnnouncementV0TLV extends TLVFactory[OracleAnnouncementV0TLV] {
nonce: SchnorrNonce,
events: Vector[EnumOutcome]): OracleAnnouncementTLV = {
val event = OracleEventV0TLV(
OrderedNonces.fromUnsorted(Vector(nonce)),
Vector(nonce),
UInt32.zero,
EnumEventDescriptorV0TLV(events.map(outcome => outcome.outcome)),
"dummy")
@ -904,7 +899,8 @@ object OracleAnnouncementV0TLV extends TLVFactory[OracleAnnouncementV0TLV] {
nonces.length,
"dummy",
Int32.zero)
val event = OracleEventV0TLV(nonces, UInt32.zero, eventDescriptor, "dummy")
val event =
OracleEventV0TLV(nonces.toVector, UInt32.zero, eventDescriptor, "dummy")
val sig =
privKey.schnorrSign(CryptoUtil.sha256DLCAnnouncement(event.bytes).bytes)
@ -933,15 +929,22 @@ object OracleAttestmentTLV extends TLVParentFactory[OracleAttestmentTLV] {
case class OracleAttestmentV0TLV(
eventId: NormalizedString,
publicKey: SchnorrPublicKey,
sigs: OrderedSchnorrSignatures,
unsortedSignatures: Vector[SchnorrDigitalSignature],
outcomes: Vector[NormalizedString])
extends OracleAttestmentTLV {
require(sigs.nonEmpty, "Cannot have 0 signatures")
require(unsortedSignatures.nonEmpty, "Cannot have 0 signatures")
require(
outcomes.size == sigs.size,
outcomes.size == unsortedSignatures.size,
s"Number of outcomes must match number of signatures, ${outcomes.size} != ${sigs.size}")
override val tpe: BigSizeUInt = OracleAttestmentV0TLV.tpe
/** This should be used very carefully with v0 attestments. We do not have a requirement in the
* in the original protocol that signatures are sorted. If you are seeing signature verification
* failing you probably need to be using [[unsortedSignatures]] rather than [[sigs]]
*/
override val sigs: OrderedSchnorrSignatures =
OrderedSchnorrSignatures.fromUnsorted(unsortedSignatures)
override val value: ByteVector = {
val outcomesBytes = outcomes.foldLeft(ByteVector.empty) {
case (accum, elem) =>
@ -963,16 +966,13 @@ object OracleAttestmentV0TLV extends TLVFactory[OracleAttestmentV0TLV] {
val eventId = iter.takeString()
val pubKey = iter.take(SchnorrPublicKey, 32)
val sigs =
val unsortedSigs =
iter.takeU16PrefixedList(() => iter.take(SchnorrDigitalSignature, 64))
val outcomes = sigs.indices.toVector.map { _ =>
val outcomes = unsortedSigs.indices.toVector.map { _ =>
iter.takeString()
}
OracleAttestmentV0TLV(eventId,
pubKey,
OrderedSchnorrSignatures.fromUnsorted(sigs),
outcomes)
OracleAttestmentV0TLV(eventId, pubKey, unsortedSigs, outcomes)
}
lazy val dummy: OracleAttestmentV0TLV = {
@ -983,7 +983,7 @@ object OracleAttestmentV0TLV extends TLVFactory[OracleAttestmentV0TLV] {
OracleAttestmentV0TLV(eventId,
key.schnorrPublicKey,
OrderedSchnorrSignatures(sig),
Vector(sig),
Vector(outcome))
}

View File

@ -25,8 +25,7 @@ class AttestationVerificationTest extends BitcoinSUnitTest {
val invalidEnumAttestation: OracleAttestmentV0TLV = {
val unsorted = validEnumAttestation.sigs.map(_.copy(sig = FieldElement.one))
validEnumAttestation.copy(sigs =
OrderedSchnorrSignatures.fromUnsorted(unsorted.toVector))
validEnumAttestation.copy(unsortedSignatures = unsorted.toVector)
}
val unsignedDigitDecompAnnouncement: OracleAnnouncementV0TLV =
@ -42,7 +41,8 @@ class AttestationVerificationTest extends BitcoinSUnitTest {
val unsorted = validUnsignedDigitDecompAttestation.sigs.map(
_.copy(sig = FieldElement.one))
val sorted = OrderedSchnorrSignatures.fromUnsorted(unsorted.toVector)
validUnsignedDigitDecompAttestation.copy(sigs = sorted)
validUnsignedDigitDecompAttestation.copy(unsortedSignatures =
sorted.toVector)
}
// this one was generated with a different public key
@ -62,7 +62,7 @@ class AttestationVerificationTest extends BitcoinSUnitTest {
val unsorted =
validSignedDigitDecompAttestation.sigs.map(_.copy(sig = FieldElement.one))
val sorted = OrderedSchnorrSignatures.fromUnsorted(unsorted.toVector)
validSignedDigitDecompAttestation.copy(sigs = sorted)
validSignedDigitDecompAttestation.copy(unsortedSignatures = sorted.toVector)
}
val invalidSignedDigitDecompAttestation1: OracleAttestmentV0TLV =
@ -132,4 +132,35 @@ class AttestationVerificationTest extends BitcoinSUnitTest {
invalidSignedDigitDecompAttestation1,
signingVersion))
}
it must "validate announcement/attesation with out of order nonces" in {
val annHex =
"fdd824fd01661aabd9bbcae0207aff9510f05099295f32ff72290cf5c494d3869f582f8c4a6cf1b7d832562047f68ce607eb39" +
"dcd7ec8ce64432dc51a8853dc5a3acd96a8bc5545aa0024da81c3fec63e56e07ee141cbefbd2c6e7d4dede124fe856ea453a85fdd822fd010" +
"000070652285e89487dc8ce816a81234082394d9602263d35a7322b77299082257767b559c622def4bba15a2ad7fc336edd71ace9b4c366b9" +
"eaba22b73df00589e74b7ca5b6c7301ef7dc62aeae1823018107868d8956677421e11ffd8f125f2fedf4a527003355640ee9333cda6c37a92" +
"d4989c6ab96eddc9266f0ddce0e2a3ffb77aa9eefa1fe40eddd0fa63f501e9b368eed6ab0cc0d2e5e6da1baa570ed9e857134bbc8a15dd594" +
"9eb1203b1d15ae701fe4b04707a1ea54c10fef16308bf806f2aa0b17f8673fe785f6b9ff0718e55b621c8e9d92839759a98b88bd6590a0ff8" +
"56011fe80fdd80a0f00020105756e697473000000000006067369676e6564"
val annV0 = OracleAnnouncementV0TLV.fromHex(annHex)
val attestationHex =
"fdd868fd01f7067369676e6564545aa0024da81c3fec63e56e07ee141cbefbd2c6e7d4dede124fe856ea453a8500" +
"070652285e89487dc8ce816a81234082394d9602263d35a7322b772990822577670ab288b31d99f56d18d4f34be875c0a4d73aae135c4f503" +
"49a1014b686d69841b559c622def4bba15a2ad7fc336edd71ace9b4c366b9eaba22b73df00589e74ba7b82eef2041bf6af1511016cadabe9d" +
"52e64d875caf5bfef85903dbc4fc00737ca5b6c7301ef7dc62aeae1823018107868d8956677421e11ffd8f125f2fedf469f40edbb7846274f" +
"46a973f5442ece91b5a6e450a8cdcef272058a27176dabba527003355640ee9333cda6c37a92d4989c6ab96eddc9266f0ddce0e2a3ffb7762" +
"f10e09f79273ab04d1549c1d60054738fe903575aa732760bd2668530459e9aa9eefa1fe40eddd0fa63f501e9b368eed6ab0cc0d2e5e6da1b" +
"aa570ed9e857188bae5c59c9ac89bec3fa00c8e1b725789e1af15f7b256ae7f169edfe7f3ef8834bbc8a15dd5949eb1203b1d15ae701fe4b0" +
"4707a1ea54c10fef16308bf806f2144d3e7aa63705924da607162f59bff757490469c2c8d4e62a1aa0bf27323bcdaa0b17f8673fe785f6b9f" +
"f0718e55b621c8e9d92839759a98b88bd6590a0ff85e072b65d258bbfdc653444b08714c2be395b7e645caa214567b22916ffb7ebeb012d01" +
"3001310130013101300130"
val attestationV0 = OracleAttestmentV0TLV.fromHex(attestationHex)
val result = OracleEvent.verifyAttestations(annV0,
attestationV0,
SigningVersion.latest)
assert(result)
}
}

View File

@ -11,7 +11,6 @@ import org.bitcoins.core.protocol.dlc.compute.SigningVersion
import org.bitcoins.core.protocol.script.P2WPKHWitnessSPKV0
import org.bitcoins.core.protocol.tlv._
import org.bitcoins.core.util.TimeUtil
import org.bitcoins.core.util.sorted.OrderedNonces
import org.bitcoins.crypto._
import org.bitcoins.testkit.fixtures.DLCOracleFixture
import org.bitcoins.testkitcore.Implicits._
@ -242,7 +241,7 @@ class DLCOracleTest extends DLCOracleFixture {
assert(event.maturationTime.getEpochSecond == time.getEpochSecond)
val expectedEventTLV =
OracleEventV0TLV(OrderedNonces(event.nonces.head),
OracleEventV0TLV(event.nonces.toVector,
UInt32(event.maturationTime.getEpochSecond),
testDescriptor,
eventName)
@ -560,7 +559,11 @@ class DLCOracleTest extends DLCOracleFixture {
_ = assert(beforeEvents.size == 1)
_ = assert(beforeEvents.head.isInstanceOf[PendingOracleEvent])
nonce = announcement.eventTLV.nonces.head
nonce = {
announcement.eventTLV match {
case v0: OracleEventV0TLV => v0.nonces.head
}
}
_ <- dlcOracle.createAttestation(nonce, EnumAttestation(outcome))
afterPending <- dlcOracle.listPendingEventDbs()
@ -589,7 +592,9 @@ class DLCOracleTest extends DLCOracleFixture {
futureTime,
enumOutcomes)
nonce = announcement.eventTLV.nonces.head
nonce = announcement.eventTLV match {
case v0: OracleEventV0TLV => v0.nonces.head
}
_ <- dlcOracle.createAttestation(
nonce,

View File

@ -248,7 +248,7 @@ case class DLCOracle()(implicit val conf: DLCOracleAppConfig)
nonces = rValueDbs.map(_.nonce)
eventTLV = OracleEventV0TLV(OrderedNonces.fromUnsorted(nonces),
eventTLV = OracleEventV0TLV(OrderedNonces.fromUnsorted(nonces).toVector,
epoch,
descriptor,
eventName)
@ -400,8 +400,10 @@ case class DLCOracle()(implicit val conf: DLCOracleAppConfig)
eventDescriptorTLV match {
case _: SignedDigitDecompositionEventDescriptor =>
val signOutcome = DigitDecompositionSignAttestation(num >= 0)
createAttestation(oracleEventTLV.nonces.head, signOutcome).map(db =>
Vector(db))
val signNonce = oracleEventTLV match {
case v0: OracleEventV0TLV => v0.nonces.head
}
createAttestation(signNonce, signOutcome).map(db => Vector(db))
case _: UnsignedDigitDecompositionEventDescriptor =>
FutureUtil.emptyVec[EventDb]
}
@ -420,11 +422,15 @@ case class DLCOracle()(implicit val conf: DLCOracleAppConfig)
eventDescriptorTLV.base.toInt,
eventDescriptorTLV.numDigits.toInt)
val oracleEventNonces = oracleEventTLV match {
case v0: OracleEventV0TLV =>
v0.nonces
}
val nonces = eventDescriptorTLV match {
case _: UnsignedDigitDecompositionEventDescriptor =>
oracleEventTLV.nonces
oracleEventNonces
case _: SignedDigitDecompositionEventDescriptor =>
oracleEventTLV.nonces.tail
oracleEventNonces.tail
}
val digitSigAVecF: Future[

View File

@ -2,9 +2,9 @@ package org.bitcoins.dlc.oracle.util
import org.bitcoins.core.api.dlcoracle._
import org.bitcoins.core.api.dlcoracle.db._
import org.bitcoins.core.protocol.dlc.compute.SigningVersion
import org.bitcoins.core.protocol.tlv._
import org.bitcoins.core.util.sorted.OrderedNonces
import org.bitcoins.crypto.SchnorrNonce
import org.bitcoins.core.protocol.dlc.compute.SigningVersion
trait EventDbUtil {
@ -13,7 +13,9 @@ trait EventDbUtil {
*/
def toEventOutcomeDbs(
descriptor: EventDescriptorTLV,
nonces: OrderedNonces,
nonces: Vector[
SchnorrNonce
], //ugh, can we enforce some sort of invariant here? can i make this method private?
signingVersion: SigningVersion): Vector[EventOutcomeDb] = {
descriptor match {
case enum: EnumEventDescriptorV0TLV =>
@ -59,9 +61,12 @@ trait EventDbUtil {
oracleAnnouncementV0TLV: OracleAnnouncementV0TLV,
signingVersion: SigningVersion = SigningVersion.latest): Vector[
EventOutcomeDb] = {
val oracleEventV0 = oracleAnnouncementV0TLV.eventTLV match {
case v0: OracleEventV0TLV => v0
}
toEventOutcomeDbs(descriptor =
oracleAnnouncementV0TLV.eventTLV.eventDescriptor,
nonces = oracleAnnouncementV0TLV.eventTLV.nonces,
nonces = oracleEventV0.nonces,
signingVersion = signingVersion)
}

View File

@ -16,7 +16,6 @@ import org.bitcoins.core.protocol.dlc.models.{
import org.bitcoins.core.protocol.tlv._
import org.bitcoins.core.script.interpreter.ScriptInterpreter
import org.bitcoins.core.script.util.PreviousOutputMap
import org.bitcoins.core.util.sorted.OrderedSchnorrSignatures
import org.bitcoins.core.wallet.fee.SatoshisPerVirtualByte
import org.bitcoins.testkit.wallet.DLCWalletUtil._
import org.bitcoins.testkit.wallet.{BitcoinSDualWalletTest, DLCWalletUtil}
@ -458,11 +457,12 @@ class DLCExecutionTest extends BitcoinSDualWalletTest {
//of invariants in OracleAttestmentV0TLV
badSigs = goodAttestment.sigs.dropRight(1)
badOutcomes = goodAttestment.outcomes.dropRight(1)
badAttestment = OracleAttestmentV0TLV(
eventId = goodAttestment.eventId,
publicKey = goodAttestment.publicKey,
sigs = OrderedSchnorrSignatures.fromUnsorted(badSigs.toVector),
outcomes = badOutcomes)
badAttestment = OracleAttestmentV0TLV(eventId = goodAttestment.eventId,
publicKey =
goodAttestment.publicKey,
unsortedSignatures =
badSigs.toVector,
outcomes = badOutcomes)
func = (wallet: DLCWallet) =>
wallet.executeDLC(contractId, badAttestment).map(_.get)

View File

@ -80,7 +80,7 @@ class DLCMultiOracleEnumExecutionTest extends BitcoinSDualWalletTest {
val initiatorWinSig = priv.schnorrSignWithNonce(hash, kValue)
OracleAttestmentV0TLV(eventId,
priv.schnorrPublicKey,
OrderedSchnorrSignatures(initiatorWinSig),
OrderedSchnorrSignatures(initiatorWinSig).toVector,
Vector(initiatorWinStr))
}
@ -101,7 +101,7 @@ class DLCMultiOracleEnumExecutionTest extends BitcoinSDualWalletTest {
val recipientWinSig = priv.schnorrSignWithNonce(hash, kValue)
OracleAttestmentV0TLV(eventId,
priv.schnorrPublicKey,
OrderedSchnorrSignatures(recipientWinSig),
OrderedSchnorrSignatures(recipientWinSig).toVector,
Vector(recipientWinStr))
}

View File

@ -243,10 +243,11 @@ class DLCMultiOracleExactNumericExecutionTest extends BitcoinSDualWalletTest {
require(kValues.length == sigs.length,
s"kValues.length=${kValues.length} sigs.length=${sigs.length}")
OracleAttestmentV0TLV(eventId,
priv.schnorrPublicKey,
OrderedSchnorrSignatures.fromUnsorted(sigs),
digitsPadded.map(_.toString))
OracleAttestmentV0TLV(
eventId,
priv.schnorrPublicKey,
OrderedSchnorrSignatures.fromUnsorted(sigs).toVector,
digitsPadded.map(_.toString))
}
}
}

View File

@ -253,10 +253,11 @@ class DLCMultiOracleNumericExecutionTest
require(kValues.length == sigs.length,
s"kValues.length=${kValues.length} sigs.length=${sigs.length}")
OracleAttestmentV0TLV(eventId,
priv.schnorrPublicKey,
OrderedSchnorrSignatures.fromUnsorted(sigs),
digitsPadded.map(_.toString))
OracleAttestmentV0TLV(
eventId,
priv.schnorrPublicKey,
OrderedSchnorrSignatures.fromUnsorted(sigs).toVector,
digitsPadded.map(_.toString))
}
}
}

View File

@ -79,11 +79,11 @@ class DLCNumericExecutionTest extends BitcoinSDualWalletTest {
(OracleAttestmentV0TLV(eventId,
publicKey,
OrderedSchnorrSignatures(initiatorWinSigs),
OrderedSchnorrSignatures(initiatorWinSigs).toVector,
initiatorWinVec.map(_.toString)),
OracleAttestmentV0TLV(eventId,
publicKey,
OrderedSchnorrSignatures(recipientWinSigs),
OrderedSchnorrSignatures(recipientWinSigs).toVector,
recipientWinVec.map(_.toString)))
}
@ -182,7 +182,8 @@ class DLCNumericExecutionTest extends BitcoinSDualWalletTest {
badAttestment = OracleAttestmentV0TLV(eventId = goodAttestment.eventId,
publicKey =
goodAttestment.publicKey,
sigs = badSigs,
unsortedSignatures =
badSigs.toVector,
outcomes = badOutcomes)
func = (wallet: DLCWallet) =>
wallet.executeDLC(contractId, badAttestment).map(_.get)

View File

@ -12,7 +12,7 @@ import org.bitcoins.core.protocol.dlc.sign.DLCTxSigner
import org.bitcoins.core.protocol.dlc.verify.DLCSignatureVerifier
import org.bitcoins.core.protocol.script._
import org.bitcoins.core.protocol.tlv._
import org.bitcoins.core.util.sorted.{OrderedAnnouncements, OrderedNonces}
import org.bitcoins.core.util.sorted.{OrderedAnnouncements}
import org.bitcoins.core.wallet.utxo._
import org.bitcoins.crypto.Sha256Digest
import org.bitcoins.db.SafeDatabase
@ -111,7 +111,7 @@ case class DLCDataManagement(dlcWalletDAOs: DLCWalletDAOs)(implicit
if (used) {
val nonces = nonceDbs.sortBy(_.index).map(_.nonce)
val eventTLV =
OracleEventV0TLV(OrderedNonces.fromUnsorted(nonces),
OracleEventV0TLV(nonces,
data.eventMaturity,
data.eventDescriptor,
data.eventId)
@ -152,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.fromUnsorted(nonces),
val eventTLV = OracleEventV0TLV(nonces,
data.eventMaturity,
data.eventDescriptor,
data.eventId)

View File

@ -1,6 +1,6 @@
package org.bitcoins.dlc.wallet.models
import org.bitcoins.core.protocol.tlv.OracleAnnouncementTLV
import org.bitcoins.core.protocol.tlv.{OracleAnnouncementTLV, OracleEventV0TLV}
import org.bitcoins.crypto._
case class OracleNonceDb(
@ -17,8 +17,16 @@ object OracleNonceDbHelper {
def fromAnnouncement(
id: Long,
tlv: OracleAnnouncementTLV): Vector[OracleNonceDb] = {
tlv.eventTLV.nonces.toVector.zipWithIndex.map { case (nonce, index) =>
OracleNonceDb(id, index, SchnorrDigitalSignature.dummy, nonce, None, None)
tlv.eventTLV match {
case v0: OracleEventV0TLV =>
v0.nonces.zipWithIndex.map { case (nonce, index) =>
OracleNonceDb(id,
index,
SchnorrDigitalSignature.dummy,
nonce,
None,
None)
}
}
}

View File

@ -134,7 +134,7 @@ trait TLVGen {
Gen
.listOfN(desc.noncesNeeded, CryptoGenerators.schnorrNonce)
.map(_.toVector)
} yield OracleEventV0TLV(OrderedNonces.fromUnsorted(nonces),
} yield OracleEventV0TLV(OrderedNonces.fromUnsorted(nonces).toVector,
maturity,
desc,
uri)
@ -162,7 +162,7 @@ trait TLVGen {
Gen
.listOfN(numSigs, StringGenerators.genUTF8String)
.map(_.toVector)
} yield OracleAttestmentV0TLV(eventId, pubkey, sigs, outcomes)
} yield OracleAttestmentV0TLV(eventId, pubkey, sigs.toVector, outcomes)
}
def contractDescriptorV0TLVWithTotalCollateral: Gen[

View File

@ -21,7 +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.util.sorted.OrderedNonces
import org.bitcoins.core.wallet.fee.SatoshisPerVirtualByte
import org.bitcoins.crypto._
import org.bitcoins.dlc.wallet.DLCWallet
@ -514,11 +514,11 @@ object DLCWalletUtil extends Logging {
(OracleAttestmentV0TLV(eventId,
publicKey,
OrderedSchnorrSignatures(initiatorWinSig),
Vector(initiatorWinSig),
Vector(initiatorWinStr)),
OracleAttestmentV0TLV(eventId,
publicKey,
OrderedSchnorrSignatures(recipientWinSig),
Vector(recipientWinSig),
Vector(recipientWinStr)))
}