mirror of
https://github.com/bitcoin-s/bitcoin-s.git
synced 2024-11-19 01:40:55 +01:00
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:
parent
2c85f92b18
commit
34e023e93f
@ -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"
|
||||
|
@ -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 ||
|
||||
|
@ -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 =>
|
||||
|
@ -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 =>
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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(
|
||||
|
@ -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))
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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[
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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))
|
||||
}
|
||||
|
||||
|
@ -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))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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[
|
||||
|
@ -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)))
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user