mirror of
https://github.com/bitcoin-s/bitcoin-s.git
synced 2025-02-23 22:56:52 +01:00
Add signed outcome to getevent
rpc, fix other small api bugs (#2757)
* Add signed outcome to get event rpc, fix other small api bugs * Create separate type for decomp DLCAttestationType * Add DLCOutcomeType to Oracle Event * Calculate dlcOutcome, add invariant * Fix test
This commit is contained in:
parent
aed21f02c7
commit
4bf4f0a027
13 changed files with 135 additions and 48 deletions
|
@ -416,6 +416,8 @@ object Picklers {
|
||||||
val numericOracles =
|
val numericOracles =
|
||||||
oracles.map(_.asInstanceOf[NumericSingleOracleInfo])
|
oracles.map(_.asInstanceOf[NumericSingleOracleInfo])
|
||||||
NumericOracleOutcome(numericOracles.zip(numericOutcomes))
|
NumericOracleOutcome(numericOracles.zip(numericOutcomes))
|
||||||
|
case signed: SignedNumericOutcome =>
|
||||||
|
throw new IllegalArgumentException(s"Unexpected outcome $signed")
|
||||||
}
|
}
|
||||||
|
|
||||||
state match {
|
state match {
|
||||||
|
|
|
@ -1053,7 +1053,7 @@ object ConsoleCli {
|
||||||
.text(s"Get oracle's staking address"),
|
.text(s"Get oracle's staking address"),
|
||||||
cmd("listevents")
|
cmd("listevents")
|
||||||
.action((_, conf) => conf.copy(command = ListEvents))
|
.action((_, conf) => conf.copy(command = ListEvents))
|
||||||
.text(s"Lists all event announcements"),
|
.text(s"Lists all event names"),
|
||||||
cmd("createenumevent")
|
cmd("createenumevent")
|
||||||
.action((_, conf) =>
|
.action((_, conf) =>
|
||||||
conf.copy(command = CreateEnumEvent("", new Date(), Seq.empty)))
|
conf.copy(command = CreateEnumEvent("", new Date(), Seq.empty)))
|
||||||
|
|
|
@ -10,15 +10,11 @@ import org.bitcoins.core.protocol.Bech32Address
|
||||||
import org.bitcoins.core.protocol.dlc.SigningVersion
|
import org.bitcoins.core.protocol.dlc.SigningVersion
|
||||||
import org.bitcoins.core.protocol.tlv.{
|
import org.bitcoins.core.protocol.tlv.{
|
||||||
EnumEventDescriptorV0TLV,
|
EnumEventDescriptorV0TLV,
|
||||||
|
NormalizedString,
|
||||||
OracleAnnouncementV0TLV,
|
OracleAnnouncementV0TLV,
|
||||||
OracleAttestmentV0TLV
|
OracleAttestmentV0TLV
|
||||||
}
|
}
|
||||||
import org.bitcoins.crypto.{
|
import org.bitcoins.crypto._
|
||||||
ECPublicKey,
|
|
||||||
FieldElement,
|
|
||||||
SchnorrDigitalSignature,
|
|
||||||
SchnorrPublicKey
|
|
||||||
}
|
|
||||||
import org.bitcoins.dlc.oracle.config.DLCOracleAppConfig
|
import org.bitcoins.dlc.oracle.config.DLCOracleAppConfig
|
||||||
import org.bitcoins.server.routes.ServerCommand
|
import org.bitcoins.server.routes.ServerCommand
|
||||||
import org.bitcoins.testkit.BitcoinSTestAppConfig
|
import org.bitcoins.testkit.BitcoinSTestAppConfig
|
||||||
|
@ -44,18 +40,28 @@ class OracleRoutesSpec
|
||||||
val testAddressStr = "bc1qvrctqwa6g70z5vtxsyft7xvsyyt749trlm80al"
|
val testAddressStr = "bc1qvrctqwa6g70z5vtxsyft7xvsyyt749trlm80al"
|
||||||
val testAddress: Bech32Address = Bech32Address.fromString(testAddressStr)
|
val testAddress: Bech32Address = Bech32Address.fromString(testAddressStr)
|
||||||
|
|
||||||
val dummyKey: ECPublicKey = ECPublicKey.freshPublicKey
|
val kVal: ECPrivateKey = ECPrivateKey.freshPrivateKey
|
||||||
|
|
||||||
|
val dummyPrivKey: ECPrivateKey = ECPrivateKey.freshPrivateKey
|
||||||
|
val dummyKey: ECPublicKey = dummyPrivKey.publicKey
|
||||||
|
|
||||||
|
val outcome: NormalizedString = EnumEventDescriptorV0TLV.dummy.outcomes.head
|
||||||
|
|
||||||
|
val hash: Sha256Digest = CryptoUtil.sha256DLCAttestation(outcome)
|
||||||
|
|
||||||
|
val sig: SchnorrDigitalSignature =
|
||||||
|
dummyPrivKey.schnorrSignWithNonce(hash.bytes, kVal)
|
||||||
|
|
||||||
val dummyEventDb: EventDb = EventDb(
|
val dummyEventDb: EventDb = EventDb(
|
||||||
nonce = dummyKey.schnorrNonce,
|
nonce = kVal.schnorrNonce,
|
||||||
pubkey = dummyKey.schnorrPublicKey,
|
pubkey = dummyKey.schnorrPublicKey,
|
||||||
nonceIndex = 0,
|
nonceIndex = 0,
|
||||||
eventName = "id",
|
eventName = "id",
|
||||||
numOutcomes = 2,
|
numOutcomes = 2,
|
||||||
signingVersion = SigningVersion.latest,
|
signingVersion = SigningVersion.latest,
|
||||||
maturationTime = Instant.ofEpochSecond(0),
|
maturationTime = Instant.ofEpochSecond(0),
|
||||||
attestationOpt = Some(FieldElement.one),
|
attestationOpt = Some(sig.sig),
|
||||||
outcomeOpt = Some("outcome"),
|
outcomeOpt = Some(outcome),
|
||||||
announcementSignature = SchnorrDigitalSignature(
|
announcementSignature = SchnorrDigitalSignature(
|
||||||
"1efe41fa42ea1dcd103a0251929dd2b192d2daece8a4ce4d81f68a183b750d92d6f02d796965dc79adf4e7786e08f861a1ecc897afbba2dab9cff6eb0a81937e"),
|
"1efe41fa42ea1dcd103a0251929dd2b192d2daece8a4ce4d81f68a183b750d92d6f02d796965dc79adf4e7786e08f861a1ecc897afbba2dab9cff6eb0a81937e"),
|
||||||
eventDescriptorTLV = EnumEventDescriptorV0TLV.dummy
|
eventDescriptorTLV = EnumEventDescriptorV0TLV.dummy
|
||||||
|
@ -113,8 +119,8 @@ class OracleRoutesSpec
|
||||||
|
|
||||||
Get() ~> route ~> check {
|
Get() ~> route ~> check {
|
||||||
assert(contentType == `application/json`)
|
assert(contentType == `application/json`)
|
||||||
assert(responseAs[
|
assert(
|
||||||
String] == s"""{"result":["${dummyOracleEvent.announcementTLV.hex}"],"error":null}""")
|
responseAs[String] == s"""{"result":["${dummyOracleEvent.eventName}"],"error":null}""")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,7 @@ case class OracleRoutes(oracle: DLCOracleApi)(implicit
|
||||||
case ServerCommand("listevents", _) =>
|
case ServerCommand("listevents", _) =>
|
||||||
complete {
|
complete {
|
||||||
oracle.listEvents().map { events =>
|
oracle.listEvents().map { events =>
|
||||||
val strs = events.map(_.announcementTLV.hex)
|
val strs = events.map(_.eventName)
|
||||||
val json = Arr.from(strs)
|
val json = Arr.from(strs)
|
||||||
|
|
||||||
Server.httpSuccess(json)
|
Server.httpSuccess(json)
|
||||||
|
@ -127,13 +127,6 @@ case class OracleRoutes(oracle: DLCOracleApi)(implicit
|
||||||
case enum: EnumEventDescriptorV0TLV =>
|
case enum: EnumEventDescriptorV0TLV =>
|
||||||
enum.outcomes.map(outcome => Str(outcome.normStr))
|
enum.outcomes.map(outcome => Str(outcome.normStr))
|
||||||
case decomp: DigitDecompositionEventDescriptorV0TLV =>
|
case decomp: DigitDecompositionEventDescriptorV0TLV =>
|
||||||
val sign = decomp match {
|
|
||||||
case _: UnsignedDigitDecompositionEventDescriptor =>
|
|
||||||
Vector.empty
|
|
||||||
case _: SignedDigitDecompositionEventDescriptor =>
|
|
||||||
Vector(Str("+"), Str("-"))
|
|
||||||
}
|
|
||||||
|
|
||||||
val digits = 0.until(decomp.numDigits.toInt).map { _ =>
|
val digits = 0.until(decomp.numDigits.toInt).map { _ =>
|
||||||
0
|
0
|
||||||
.until(decomp.base.toInt)
|
.until(decomp.base.toInt)
|
||||||
|
@ -141,7 +134,12 @@ case class OracleRoutes(oracle: DLCOracleApi)(implicit
|
||||||
.toVector
|
.toVector
|
||||||
}
|
}
|
||||||
|
|
||||||
val vecs = digits :+ sign
|
val vecs = decomp match {
|
||||||
|
case _: UnsignedDigitDecompositionEventDescriptor =>
|
||||||
|
digits
|
||||||
|
case _: SignedDigitDecompositionEventDescriptor =>
|
||||||
|
Vector(Str("+"), Str("-")) +: digits
|
||||||
|
}
|
||||||
vecs.map(vec => Arr.from(vec))
|
vecs.map(vec => Arr.from(vec))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,6 +150,15 @@ case class OracleRoutes(oracle: DLCOracleApi)(implicit
|
||||||
ujson.Null
|
ujson.Null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val signedOutcomeJs = event match {
|
||||||
|
case _: PendingOracleEvent =>
|
||||||
|
ujson.Null
|
||||||
|
case emum: CompletedEnumV0OracleEvent =>
|
||||||
|
Str(emum.outcome.outcomeString)
|
||||||
|
case decomp: CompletedDigitDecompositionV0OracleEvent =>
|
||||||
|
Num(decomp.outcomeBase10.toDouble)
|
||||||
|
}
|
||||||
|
|
||||||
val json = Obj(
|
val json = Obj(
|
||||||
"nonces" -> event.nonces.map(n => Str(n.hex)),
|
"nonces" -> event.nonces.map(n => Str(n.hex)),
|
||||||
"eventName" -> Str(event.eventName),
|
"eventName" -> Str(event.eventName),
|
||||||
|
@ -165,7 +172,8 @@ case class OracleRoutes(oracle: DLCOracleApi)(implicit
|
||||||
"eventTLV" -> Str(event.eventTLV.hex),
|
"eventTLV" -> Str(event.eventTLV.hex),
|
||||||
"announcementTLV" -> Str(event.announcementTLV.hex),
|
"announcementTLV" -> Str(event.announcementTLV.hex),
|
||||||
"attestations" -> attestationJson,
|
"attestations" -> attestationJson,
|
||||||
"outcomes" -> outcomesJson
|
"outcomes" -> outcomesJson,
|
||||||
|
"signedOutcome" -> signedOutcomeJs
|
||||||
)
|
)
|
||||||
Server.httpSuccess(json)
|
Server.httpSuccess(json)
|
||||||
case None =>
|
case None =>
|
||||||
|
|
|
@ -13,14 +13,16 @@ case class EnumAttestation(outcomeString: String) extends DLCAttestationType {
|
||||||
def bytes: ByteVector = CryptoUtil.serializeForHash(outcomeString)
|
def bytes: ByteVector = CryptoUtil.serializeForHash(outcomeString)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sealed trait DigitDecompositionAttestationType extends DLCAttestationType
|
||||||
|
|
||||||
case class DigitDecompositionSignAttestation(positive: Boolean)
|
case class DigitDecompositionSignAttestation(positive: Boolean)
|
||||||
extends DLCAttestationType {
|
extends DigitDecompositionAttestationType {
|
||||||
override def outcomeString: String = if (positive) "+" else "-"
|
override def outcomeString: String = if (positive) "+" else "-"
|
||||||
def bytes: ByteVector = CryptoUtil.serializeForHash(outcomeString)
|
def bytes: ByteVector = CryptoUtil.serializeForHash(outcomeString)
|
||||||
}
|
}
|
||||||
|
|
||||||
case class DigitDecompositionAttestation(outcome: Int)
|
case class DigitDecompositionAttestation(outcome: Int)
|
||||||
extends DLCAttestationType {
|
extends DigitDecompositionAttestationType {
|
||||||
override def outcomeString: String = outcome.toString
|
override def outcomeString: String = outcome.toString
|
||||||
def bytes: ByteVector = CryptoUtil.serializeForHash(outcomeString)
|
def bytes: ByteVector = CryptoUtil.serializeForHash(outcomeString)
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import org.bitcoins.core.api.dlcoracle.db.EventDb
|
||||||
import org.bitcoins.core.number.UInt32
|
import org.bitcoins.core.number.UInt32
|
||||||
import org.bitcoins.core.protocol.dlc.SigningVersion
|
import org.bitcoins.core.protocol.dlc.SigningVersion
|
||||||
import org.bitcoins.core.protocol.tlv._
|
import org.bitcoins.core.protocol.tlv._
|
||||||
|
import org.bitcoins.core.util.NumberUtil
|
||||||
import org.bitcoins.crypto._
|
import org.bitcoins.crypto._
|
||||||
|
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
|
@ -70,6 +71,8 @@ sealed trait CompletedOracleEvent extends OracleEvent {
|
||||||
outcomes.map(_.outcomeString))
|
outcomes.map(_.outcomeString))
|
||||||
|
|
||||||
def outcomes: Vector[DLCAttestationType]
|
def outcomes: Vector[DLCAttestationType]
|
||||||
|
|
||||||
|
def dlcOutcome: DLCOutcomeType
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed trait EnumV0OracleEvent extends OracleEvent {
|
sealed trait EnumV0OracleEvent extends OracleEvent {
|
||||||
|
@ -102,9 +105,16 @@ case class CompletedEnumV0OracleEvent(
|
||||||
attestation: FieldElement)
|
attestation: FieldElement)
|
||||||
extends CompletedOracleEvent
|
extends CompletedOracleEvent
|
||||||
with EnumV0OracleEvent {
|
with EnumV0OracleEvent {
|
||||||
|
require(OracleEvent.verifyAttestations(announcementTLV,
|
||||||
|
oracleAttestmentV0TLV,
|
||||||
|
signingVersion),
|
||||||
|
"Signatures given are invalid")
|
||||||
|
|
||||||
override def attestations: Vector[FieldElement] = Vector(attestation)
|
override def attestations: Vector[FieldElement] = Vector(attestation)
|
||||||
|
|
||||||
override def outcomes: Vector[DLCAttestationType] = Vector(outcome)
|
override def outcomes: Vector[DLCAttestationType] = Vector(outcome)
|
||||||
|
|
||||||
|
override def dlcOutcome: DLCOutcomeType = EnumOutcome(outcome.outcomeString)
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed trait DigitDecompositionV0OracleEvent extends OracleEvent {
|
sealed trait DigitDecompositionV0OracleEvent extends OracleEvent {
|
||||||
|
@ -130,10 +140,42 @@ case class CompletedDigitDecompositionV0OracleEvent(
|
||||||
maturationTime: Instant,
|
maturationTime: Instant,
|
||||||
announcementSignature: SchnorrDigitalSignature,
|
announcementSignature: SchnorrDigitalSignature,
|
||||||
eventDescriptorTLV: DigitDecompositionEventDescriptorV0TLV,
|
eventDescriptorTLV: DigitDecompositionEventDescriptorV0TLV,
|
||||||
outcomes: Vector[DLCAttestationType],
|
dlcOutcome: NumericDLCOutcomeType,
|
||||||
attestations: Vector[FieldElement])
|
attestations: Vector[FieldElement])
|
||||||
extends CompletedOracleEvent
|
extends CompletedOracleEvent
|
||||||
with DigitDecompositionV0OracleEvent
|
with DigitDecompositionV0OracleEvent {
|
||||||
|
|
||||||
|
require(OracleEvent.verifyAttestations(announcementTLV,
|
||||||
|
oracleAttestmentV0TLV,
|
||||||
|
signingVersion),
|
||||||
|
"Signatures given are invalid")
|
||||||
|
|
||||||
|
val outcomeBase10: Long = {
|
||||||
|
val (digits, positive) = dlcOutcome match {
|
||||||
|
case UnsignedNumericOutcome(digits) =>
|
||||||
|
(digits, true)
|
||||||
|
case SignedNumericOutcome(positive, digits) =>
|
||||||
|
(digits, positive)
|
||||||
|
}
|
||||||
|
|
||||||
|
val base = eventDescriptorTLV.base.toInt
|
||||||
|
val numDigits = eventDescriptorTLV.numDigits.toInt
|
||||||
|
|
||||||
|
val num = NumberUtil.fromDigits(digits, base, numDigits)
|
||||||
|
|
||||||
|
if (positive) num
|
||||||
|
else num * -1
|
||||||
|
}
|
||||||
|
|
||||||
|
override def outcomes: Vector[DigitDecompositionAttestationType] =
|
||||||
|
dlcOutcome match {
|
||||||
|
case UnsignedNumericOutcome(digits) =>
|
||||||
|
digits.map(DigitDecompositionAttestation)
|
||||||
|
case SignedNumericOutcome(positive, digits) =>
|
||||||
|
val sign = DigitDecompositionSignAttestation(positive)
|
||||||
|
sign +: digits.map(DigitDecompositionAttestation)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
object OracleEvent {
|
object OracleEvent {
|
||||||
|
|
||||||
|
@ -172,18 +214,18 @@ object OracleEvent {
|
||||||
|
|
||||||
val attestations = sortedEventDbs.flatMap(_.attestationOpt)
|
val attestations = sortedEventDbs.flatMap(_.attestationOpt)
|
||||||
|
|
||||||
val outcomes = decomp match {
|
val dlcOutcome = decomp match {
|
||||||
case _: SignedDigitDecompositionEventDescriptor =>
|
case _: SignedDigitDecompositionEventDescriptor =>
|
||||||
val sign = DigitDecompositionSignAttestation(
|
val positive = sortedEventDbs.head.outcomeOpt.get == "+"
|
||||||
sortedEventDbs.head.outcomeOpt.get == "+")
|
|
||||||
val digits = sortedEventDbs.tail.map { eventDb =>
|
val digits = sortedEventDbs.tail.map { eventDb =>
|
||||||
DigitDecompositionAttestation(eventDb.outcomeOpt.get.toInt)
|
eventDb.outcomeOpt.get.toInt
|
||||||
}
|
}
|
||||||
sign +: digits
|
SignedNumericOutcome(positive, digits)
|
||||||
case _: UnsignedDigitDecompositionEventDescriptor =>
|
case _: UnsignedDigitDecompositionEventDescriptor =>
|
||||||
sortedEventDbs.map { eventDb =>
|
val digits = sortedEventDbs.map { eventDb =>
|
||||||
DigitDecompositionAttestation(eventDb.outcomeOpt.get.toInt)
|
eventDb.outcomeOpt.get.toInt
|
||||||
}
|
}
|
||||||
|
UnsignedNumericOutcome(digits)
|
||||||
}
|
}
|
||||||
|
|
||||||
CompletedDigitDecompositionV0OracleEvent(
|
CompletedDigitDecompositionV0OracleEvent(
|
||||||
|
@ -194,7 +236,7 @@ object OracleEvent {
|
||||||
eventDb.maturationTime,
|
eventDb.maturationTime,
|
||||||
eventDb.announcementSignature,
|
eventDb.announcementSignature,
|
||||||
decomp,
|
decomp,
|
||||||
outcomes,
|
dlcOutcome,
|
||||||
attestations
|
attestations
|
||||||
)
|
)
|
||||||
case (decomp: DigitDecompositionEventDescriptorV0TLV, None) =>
|
case (decomp: DigitDecompositionEventDescriptorV0TLV, None) =>
|
||||||
|
|
|
@ -4,6 +4,7 @@ import org.bitcoins.core.currency.Satoshis
|
||||||
import org.bitcoins.core.protocol.tlv.{
|
import org.bitcoins.core.protocol.tlv.{
|
||||||
DLCOutcomeType,
|
DLCOutcomeType,
|
||||||
EnumOutcome,
|
EnumOutcome,
|
||||||
|
SignedNumericOutcome,
|
||||||
UnsignedNumericOutcome
|
UnsignedNumericOutcome
|
||||||
}
|
}
|
||||||
import org.bitcoins.core.util.{Indexed, NumberUtil}
|
import org.bitcoins.core.util.{Indexed, NumberUtil}
|
||||||
|
@ -281,7 +282,7 @@ object CETCalculator {
|
||||||
digits: Digits,
|
digits: Digits,
|
||||||
outcomes: Vector[DLCOutcomeType]): Option[UnsignedNumericOutcome] = {
|
outcomes: Vector[DLCOutcomeType]): Option[UnsignedNumericOutcome] = {
|
||||||
searchForPrefix(digits, outcomes) {
|
searchForPrefix(digits, outcomes) {
|
||||||
case outcome: EnumOutcome =>
|
case outcome @ (_: EnumOutcome | _: SignedNumericOutcome) =>
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
s"Expected Numeric Outcome, got $outcome")
|
s"Expected Numeric Outcome, got $outcome")
|
||||||
case UnsignedNumericOutcome(digits) => digits
|
case UnsignedNumericOutcome(digits) => digits
|
||||||
|
|
|
@ -132,7 +132,7 @@ case class EnumSingleOracleInfo(announcement: OracleAnnouncementTLV)
|
||||||
sig)
|
sig)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case UnsignedNumericOutcome(_) =>
|
case UnsignedNumericOutcome(_) | _: SignedNumericOutcome =>
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
s"Expected EnumOutcome, got $outcome")
|
s"Expected EnumOutcome, got $outcome")
|
||||||
}
|
}
|
||||||
|
@ -177,7 +177,7 @@ case class NumericSingleOracleInfo(announcement: OracleAnnouncementTLV)
|
||||||
s"Too many signatures (expected at most ${nonces.length}), got $sigs")
|
s"Too many signatures (expected at most ${nonces.length}), got $sigs")
|
||||||
|
|
||||||
outcome match {
|
outcome match {
|
||||||
case EnumOutcome(_) =>
|
case EnumOutcome(_) | _: SignedNumericOutcome =>
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
s"Expected numeric outcome, got $outcome")
|
s"Expected numeric outcome, got $outcome")
|
||||||
case UnsignedNumericOutcome(digits) =>
|
case UnsignedNumericOutcome(digits) =>
|
||||||
|
|
|
@ -17,6 +17,8 @@ case class EnumOutcome(outcome: String) extends DLCOutcomeType {
|
||||||
Vector(CryptoUtil.serializeForHash(outcome))
|
Vector(CryptoUtil.serializeForHash(outcome))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sealed trait NumericDLCOutcomeType extends DLCOutcomeType
|
||||||
|
|
||||||
/** An outcome from a multi-nonce unsigned numeric event type.
|
/** An outcome from a multi-nonce unsigned numeric event type.
|
||||||
*
|
*
|
||||||
* If digits.length is less than the the total number of digits to be
|
* If digits.length is less than the the total number of digits to be
|
||||||
|
@ -25,8 +27,27 @@ case class EnumOutcome(outcome: String) extends DLCOutcomeType {
|
||||||
*
|
*
|
||||||
* I.e. the Vector[Int] is always the most significant digits.
|
* I.e. the Vector[Int] is always the most significant digits.
|
||||||
*/
|
*/
|
||||||
case class UnsignedNumericOutcome(digits: Vector[Int]) extends DLCOutcomeType {
|
case class UnsignedNumericOutcome(digits: Vector[Int])
|
||||||
|
extends NumericDLCOutcomeType {
|
||||||
|
|
||||||
override lazy val serialized: Vector[ByteVector] =
|
override lazy val serialized: Vector[ByteVector] =
|
||||||
digits.map(digit => CryptoUtil.serializeForHash(digit.toString))
|
digits.map(digit => CryptoUtil.serializeForHash(digit.toString))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** An outcome from a multi-nonce signed numeric event type.
|
||||||
|
*
|
||||||
|
* If digits.length is less than the the total number of digits to be
|
||||||
|
* signed by the oracle then this outcome represents all outcomes prefixed
|
||||||
|
* by the given digits.
|
||||||
|
*
|
||||||
|
* I.e. the Vector[Int] is always the most significant digits.
|
||||||
|
*/
|
||||||
|
case class SignedNumericOutcome(positive: Boolean, digits: Vector[Int])
|
||||||
|
extends NumericDLCOutcomeType {
|
||||||
|
|
||||||
|
private val signOutcomeStr = if (positive) "+" else "-"
|
||||||
|
|
||||||
|
override lazy val serialized: Vector[ByteVector] =
|
||||||
|
CryptoUtil.serializeForHash(signOutcomeStr) +:
|
||||||
|
digits.map(digit => CryptoUtil.serializeForHash(digit.toString))
|
||||||
|
}
|
||||||
|
|
|
@ -278,6 +278,8 @@ class DbCommonsColumnMappers(val profile: JdbcProfile) {
|
||||||
s"$enumStr$outcome"
|
s"$enumStr$outcome"
|
||||||
case UnsignedNumericOutcome(digits) =>
|
case UnsignedNumericOutcome(digits) =>
|
||||||
s"$unsignedNumStr" + digits.mkString("|")
|
s"$unsignedNumStr" + digits.mkString("|")
|
||||||
|
case _: SignedNumericOutcome =>
|
||||||
|
throw new RuntimeException("Unknown outcome type")
|
||||||
},
|
},
|
||||||
str => {
|
str => {
|
||||||
if (str.startsWith(enumStr)) {
|
if (str.startsWith(enumStr)) {
|
||||||
|
@ -307,6 +309,8 @@ class DbCommonsColumnMappers(val profile: JdbcProfile) {
|
||||||
s"$enumStr$outcome"
|
s"$enumStr$outcome"
|
||||||
case UnsignedNumericOutcome(digits) =>
|
case UnsignedNumericOutcome(digits) =>
|
||||||
s"$unsignedNumStr" + digits.mkString("|")
|
s"$unsignedNumStr" + digits.mkString("|")
|
||||||
|
case _: SignedNumericOutcome =>
|
||||||
|
throw new RuntimeException("Unknown outcome type")
|
||||||
}
|
}
|
||||||
}.mkString,
|
}.mkString,
|
||||||
str => {
|
str => {
|
||||||
|
|
|
@ -106,6 +106,7 @@ If you use the `getevent` rpc along the oracle announcement, you can see the eve
|
||||||
"Republican_win",
|
"Republican_win",
|
||||||
"Democrat_win",
|
"Democrat_win",
|
||||||
"other"
|
"other"
|
||||||
]
|
],
|
||||||
|
"signedOutcome": "Democrat_win"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
|
@ -257,9 +257,7 @@ If you use the `getevent` rpc along the oracle announcement, you can see the eve
|
||||||
"0",
|
"0",
|
||||||
"1"
|
"1"
|
||||||
],
|
],
|
||||||
[
|
"signedOutcome": 42069
|
||||||
|
|
||||||
]
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
|
@ -14,7 +14,7 @@ checkout [this page](build-oracle-server.md).
|
||||||
|
|
||||||
- `getpublickey` - Get oracle's public key
|
- `getpublickey` - Get oracle's public key
|
||||||
- `getstakingaddress` - Get oracle's staking address
|
- `getstakingaddress` - Get oracle's staking address
|
||||||
- `listevents` - Lists all oracle announcement TLVs
|
- `listevents` - Lists all event names
|
||||||
- `createenumevent` `label` `maturationtime` `outcomes` - Registers an oracle enum event
|
- `createenumevent` `label` `maturationtime` `outcomes` - Registers an oracle enum event
|
||||||
- `label` - Label for this event
|
- `label` - Label for this event
|
||||||
- `maturationtime` - The earliest expected time an outcome will be signed, given in ISO 8601 format
|
- `maturationtime` - The earliest expected time an outcome will be signed, given in ISO 8601 format
|
||||||
|
@ -70,7 +70,8 @@ $ bitcoin-s-cli getevent test
|
||||||
"outcome1",
|
"outcome1",
|
||||||
"outcome2",
|
"outcome2",
|
||||||
"outcome3"
|
"outcome3"
|
||||||
]
|
],
|
||||||
|
"signedOutcome": null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -87,7 +88,7 @@ $ curl --data-binary '{"jsonrpc": "1.0", "id": "curltest", "method": "createenum
|
||||||
{"result":"fdd824b0ba0f08e9becbf77019e246ca8a80c027585634dc1aed4b7f67442ada394b40dcb242d8a8c84893a752b93f30ff07525b0604382255ec7392fcc6f230140feb905f6f49e116de8cb57856bacdd9997d8dfb73877f64a4ec8d45fc0e73a0e52115fdd8224c000180e550759cb6275f6db3fad2b616ed51bdcccc204d0d978cd921cafae9fc1d6f657131d1fdd8061d0003086f7574636f6d6531086f7574636f6d6532086f7574636f6d65330474657374","error":null}
|
{"result":"fdd824b0ba0f08e9becbf77019e246ca8a80c027585634dc1aed4b7f67442ada394b40dcb242d8a8c84893a752b93f30ff07525b0604382255ec7392fcc6f230140feb905f6f49e116de8cb57856bacdd9997d8dfb73877f64a4ec8d45fc0e73a0e52115fdd8224c000180e550759cb6275f6db3fad2b616ed51bdcccc204d0d978cd921cafae9fc1d6f657131d1fdd8061d0003086f7574636f6d6531086f7574636f6d6532086f7574636f6d65330474657374","error":null}
|
||||||
|
|
||||||
$ curl --data-binary '{"jsonrpc": "1.0", "id": "curltest", "method": "getevent", "params": ["testEvent"]}' -H "Content-Type: application/json" http://127.0.0.1:9998/
|
$ curl --data-binary '{"jsonrpc": "1.0", "id": "curltest", "method": "getevent", "params": ["testEvent"]}' -H "Content-Type: application/json" http://127.0.0.1:9998/
|
||||||
{"result":{"nonces":["80e550759cb6275f6db3fad2b616ed51bdcccc204d0d978cd921cafae9fc1d6f"],"eventName":"test","signingVersion":"DLCOracleV0SigningVersion","maturationTime":"2030-01-03T00:30:00.000Z","announcementSignature":"ba0f08e9becbf77019e246ca8a80c027585634dc1aed4b7f67442ada394b40dcb242d8a8c84893a752b93f30ff07525b0604382255ec7392fcc6f230140feb90","eventDescriptorTLV":"fdd8061d0003086f7574636f6d6531086f7574636f6d6532086f7574636f6d6533","eventTLV":"fdd8224c000180e550759cb6275f6db3fad2b616ed51bdcccc204d0d978cd921cafae9fc1d6f657131d1fdd8061d0003086f7574636f6d6531086f7574636f6d6532086f7574636f6d65330474657374","announcementTLV":"fdd824b0ba0f08e9becbf77019e246ca8a80c027585634dc1aed4b7f67442ada394b40dcb242d8a8c84893a752b93f30ff07525b0604382255ec7392fcc6f230140feb905f6f49e116de8cb57856bacdd9997d8dfb73877f64a4ec8d45fc0e73a0e52115fdd8224c000180e550759cb6275f6db3fad2b616ed51bdcccc204d0d978cd921cafae9fc1d6f657131d1fdd8061d0003086f7574636f6d6531086f7574636f6d6532086f7574636f6d65330474657374","attestations":["33fd84ba8eea0a75f1568149f42e8466e1bc3422ea449532d4eeffad8586d14e"],"signatures":["80e550759cb6275f6db3fad2b616ed51bdcccc204d0d978cd921cafae9fc1d6f33fd84ba8eea0a75f1568149f42e8466e1bc3422ea449532d4eeffad8586d14e"],"outcomes":["outcome1","outcome2","outcome3"]},"error":null}
|
{"result":{"nonces":["80e550759cb6275f6db3fad2b616ed51bdcccc204d0d978cd921cafae9fc1d6f"],"eventName":"test","signingVersion":"DLCOracleV0SigningVersion","maturationTime":"2030-01-03T00:30:00.000Z","announcementSignature":"ba0f08e9becbf77019e246ca8a80c027585634dc1aed4b7f67442ada394b40dcb242d8a8c84893a752b93f30ff07525b0604382255ec7392fcc6f230140feb90","eventDescriptorTLV":"fdd8061d0003086f7574636f6d6531086f7574636f6d6532086f7574636f6d6533","eventTLV":"fdd8224c000180e550759cb6275f6db3fad2b616ed51bdcccc204d0d978cd921cafae9fc1d6f657131d1fdd8061d0003086f7574636f6d6531086f7574636f6d6532086f7574636f6d65330474657374","announcementTLV":"fdd824b0ba0f08e9becbf77019e246ca8a80c027585634dc1aed4b7f67442ada394b40dcb242d8a8c84893a752b93f30ff07525b0604382255ec7392fcc6f230140feb905f6f49e116de8cb57856bacdd9997d8dfb73877f64a4ec8d45fc0e73a0e52115fdd8224c000180e550759cb6275f6db3fad2b616ed51bdcccc204d0d978cd921cafae9fc1d6f657131d1fdd8061d0003086f7574636f6d6531086f7574636f6d6532086f7574636f6d65330474657374","attestations":["33fd84ba8eea0a75f1568149f42e8466e1bc3422ea449532d4eeffad8586d14e"],"signatures":["80e550759cb6275f6db3fad2b616ed51bdcccc204d0d978cd921cafae9fc1d6f33fd84ba8eea0a75f1568149f42e8466e1bc3422ea449532d4eeffad8586d14e"],"outcomes":["outcome1","outcome2","outcome3",],"signedOutcome": null},"error":null}
|
||||||
|
|
||||||
$ curl --data-binary '{"jsonrpc": "1.0", "id": "curltest", "method": "signevent", "params": ["testEvent", "outcome1"]}' -H "Content-Type: application/json" http://127.0.0.1:9998/
|
$ curl --data-binary '{"jsonrpc": "1.0", "id": "curltest", "method": "signevent", "params": ["testEvent", "outcome1"]}' -H "Content-Type: application/json" http://127.0.0.1:9998/
|
||||||
{"result":"fdd8687004746573745f6f49e116de8cb57856bacdd9997d8dfb73877f64a4ec8d45fc0e73a0e52115000180e550759cb6275f6db3fad2b616ed51bdcccc204d0d978cd921cafae9fc1d6f33fd84ba8eea0a75f1568149f42e8466e1bc3422ea449532d4eeffad8586d14e086f7574636f6d6531","error":null}
|
{"result":"fdd8687004746573745f6f49e116de8cb57856bacdd9997d8dfb73877f64a4ec8d45fc0e73a0e52115000180e550759cb6275f6db3fad2b616ed51bdcccc204d0d978cd921cafae9fc1d6f33fd84ba8eea0a75f1568149f42e8466e1bc3422ea449532d4eeffad8586d14e086f7574636f6d6531","error":null}
|
||||||
|
@ -162,7 +163,8 @@ $ bitcoins-cli getevent exampleNumeric
|
||||||
"+",
|
"+",
|
||||||
"-"
|
"-"
|
||||||
]
|
]
|
||||||
]
|
],
|
||||||
|
"signedOutcome": null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -177,7 +179,7 @@ $ curl --data-binary '{"jsonrpc": "1.0", "id": "curltest", "method": "createnume
|
||||||
{"result":"fdd824fd0110647c85d333aa6fc0d7808201da9d1010b815710dc25c3d73e9cc7a7f372a7342c99144ba74d70be72920f4515daa6565bce12aedfc5a828ee37b5453454c1b575f6f49e116de8cb57856bacdd9997d8dfb73877f64a4ec8d45fc0e73a0e52115fdd822ac0004d72282a2e9532924dc8cd79685a501202332ad0d118166328cb76138414fccf37051e50fd1ab30df4717da8905e400a32c5f4d793a4ac5433ed416165dd286c47446ab1d71a550a0d604c3e86c40a3c9b12de8f08a86639068707822cd4756217139d7cabd19d6b0b9e827cdf84a4fc18c88d1882e4e096d8dfeff58759504d2657131d1fdd80a0f000a0105756e697473000000000003126578616d706c6544696769744465636f6d70","error":null}
|
{"result":"fdd824fd0110647c85d333aa6fc0d7808201da9d1010b815710dc25c3d73e9cc7a7f372a7342c99144ba74d70be72920f4515daa6565bce12aedfc5a828ee37b5453454c1b575f6f49e116de8cb57856bacdd9997d8dfb73877f64a4ec8d45fc0e73a0e52115fdd822ac0004d72282a2e9532924dc8cd79685a501202332ad0d118166328cb76138414fccf37051e50fd1ab30df4717da8905e400a32c5f4d793a4ac5433ed416165dd286c47446ab1d71a550a0d604c3e86c40a3c9b12de8f08a86639068707822cd4756217139d7cabd19d6b0b9e827cdf84a4fc18c88d1882e4e096d8dfeff58759504d2657131d1fdd80a0f000a0105756e697473000000000003126578616d706c6544696769744465636f6d70","error":null}
|
||||||
|
|
||||||
$ curl --data-binary '{"jsonrpc": "1.0", "id": "curltest", "method": "getevent", "params": ["numericExample"]}' -H "Content-Type: application/json" http://127.0.0.1:9998/
|
$ curl --data-binary '{"jsonrpc": "1.0", "id": "curltest", "method": "getevent", "params": ["numericExample"]}' -H "Content-Type: application/json" http://127.0.0.1:9998/
|
||||||
{"result":{"nonces":["7051e50fd1ab30df4717da8905e400a32c5f4d793a4ac5433ed416165dd286c4","7139d7cabd19d6b0b9e827cdf84a4fc18c88d1882e4e096d8dfeff58759504d2","7446ab1d71a550a0d604c3e86c40a3c9b12de8f08a86639068707822cd475621","d72282a2e9532924dc8cd79685a501202332ad0d118166328cb76138414fccf3"],"eventName":"numericExample","signingVersion":"DLCOracleV0SigningVersion","maturationTime":"2030-01-03T00:30:00.000Z","announcementSignature":"647c85d333aa6fc0d7808201da9d1010b815710dc25c3d73e9cc7a7f372a7342c99144ba74d70be72920f4515daa6565bce12aedfc5a828ee37b5453454c1b57","eventDescriptorTLV":"fdd80a0f000a0105756e697473000000000003","eventTLV":"fdd822ac00047051e50fd1ab30df4717da8905e400a32c5f4d793a4ac5433ed416165dd286c47139d7cabd19d6b0b9e827cdf84a4fc18c88d1882e4e096d8dfeff58759504d27446ab1d71a550a0d604c3e86c40a3c9b12de8f08a86639068707822cd475621d72282a2e9532924dc8cd79685a501202332ad0d118166328cb76138414fccf3657131d1fdd80a0f000a0105756e697473000000000003126578616d706c6544696769744465636f6d70","announcementTLV":"fdd824fd0110647c85d333aa6fc0d7808201da9d1010b815710dc25c3d73e9cc7a7f372a7342c99144ba74d70be72920f4515daa6565bce12aedfc5a828ee37b5453454c1b575f6f49e116de8cb57856bacdd9997d8dfb73877f64a4ec8d45fc0e73a0e52115fdd822ac00047051e50fd1ab30df4717da8905e400a32c5f4d793a4ac5433ed416165dd286c47139d7cabd19d6b0b9e827cdf84a4fc18c88d1882e4e096d8dfeff58759504d27446ab1d71a550a0d604c3e86c40a3c9b12de8f08a86639068707822cd475621d72282a2e9532924dc8cd79685a501202332ad0d118166328cb76138414fccf3657131d1fdd80a0f000a0105756e697473000000000003126578616d706c6544696769744465636f6d70","attestations":null,"signatures":null,"outcomes":[["0","1","2","3","4","5","6","7","8","9"],["0","1","2","3","4","5","6","7","8","9"],["0","1","2","3","4","5","6","7","8","9"],["+","-"]]},"error":null}
|
{"result":{"nonces":["7051e50fd1ab30df4717da8905e400a32c5f4d793a4ac5433ed416165dd286c4","7139d7cabd19d6b0b9e827cdf84a4fc18c88d1882e4e096d8dfeff58759504d2","7446ab1d71a550a0d604c3e86c40a3c9b12de8f08a86639068707822cd475621","d72282a2e9532924dc8cd79685a501202332ad0d118166328cb76138414fccf3"],"eventName":"numericExample","signingVersion":"DLCOracleV0SigningVersion","maturationTime":"2030-01-03T00:30:00.000Z","announcementSignature":"647c85d333aa6fc0d7808201da9d1010b815710dc25c3d73e9cc7a7f372a7342c99144ba74d70be72920f4515daa6565bce12aedfc5a828ee37b5453454c1b57","eventDescriptorTLV":"fdd80a0f000a0105756e697473000000000003","eventTLV":"fdd822ac00047051e50fd1ab30df4717da8905e400a32c5f4d793a4ac5433ed416165dd286c47139d7cabd19d6b0b9e827cdf84a4fc18c88d1882e4e096d8dfeff58759504d27446ab1d71a550a0d604c3e86c40a3c9b12de8f08a86639068707822cd475621d72282a2e9532924dc8cd79685a501202332ad0d118166328cb76138414fccf3657131d1fdd80a0f000a0105756e697473000000000003126578616d706c6544696769744465636f6d70","announcementTLV":"fdd824fd0110647c85d333aa6fc0d7808201da9d1010b815710dc25c3d73e9cc7a7f372a7342c99144ba74d70be72920f4515daa6565bce12aedfc5a828ee37b5453454c1b575f6f49e116de8cb57856bacdd9997d8dfb73877f64a4ec8d45fc0e73a0e52115fdd822ac00047051e50fd1ab30df4717da8905e400a32c5f4d793a4ac5433ed416165dd286c47139d7cabd19d6b0b9e827cdf84a4fc18c88d1882e4e096d8dfeff58759504d27446ab1d71a550a0d604c3e86c40a3c9b12de8f08a86639068707822cd475621d72282a2e9532924dc8cd79685a501202332ad0d118166328cb76138414fccf3657131d1fdd80a0f000a0105756e697473000000000003126578616d706c6544696769744465636f6d70","attestations":null,"signatures":null,"outcomes":[["0","1","2","3","4","5","6","7","8","9"],["0","1","2","3","4","5","6","7","8","9"],["0","1","2","3","4","5","6","7","8","9"],["+","-"]],"signedOutcome": null},"error":null}
|
||||||
|
|
||||||
$ curl --data-binary '{"jsonrpc": "1.0", "id": "curltest", "method": "signdigits", "params": ["numericExample", 123]}' -H "Content-Type: application/json" http://127.0.0.1:9998/
|
$ curl --data-binary '{"jsonrpc": "1.0", "id": "curltest", "method": "signdigits", "params": ["numericExample", 123]}' -H "Content-Type: application/json" http://127.0.0.1:9998/
|
||||||
{"result":"fdd868fd013d126578616d706c6544696769744465636f6d705f6f49e116de8cb57856bacdd9997d8dfb73877f64a4ec8d45fc0e73a0e521150004d72282a2e9532924dc8cd79685a501202332ad0d118166328cb76138414fccf3d0646c9efd9523274014841ba24bf63219d5650d1682209d7e48af009d58e6d87051e50fd1ab30df4717da8905e400a32c5f4d793a4ac5433ed416165dd286c4c025dfd1e39de77e0418fa7d39abf2e9daf55d7fe34f8e312368cb4d45b4d4b97446ab1d71a550a0d604c3e86c40a3c9b12de8f08a86639068707822cd475621700347c52af088eda9a0245385094518134e73bb997102e11f6de0aeb36af7237139d7cabd19d6b0b9e827cdf84a4fc18c88d1882e4e096d8dfeff58759504d2f9e7a9e183b0836ad58dd646d9ab123132397109e4f51c5842958932a81bacd1012b013101320133","error":null}
|
{"result":"fdd868fd013d126578616d706c6544696769744465636f6d705f6f49e116de8cb57856bacdd9997d8dfb73877f64a4ec8d45fc0e73a0e521150004d72282a2e9532924dc8cd79685a501202332ad0d118166328cb76138414fccf3d0646c9efd9523274014841ba24bf63219d5650d1682209d7e48af009d58e6d87051e50fd1ab30df4717da8905e400a32c5f4d793a4ac5433ed416165dd286c4c025dfd1e39de77e0418fa7d39abf2e9daf55d7fe34f8e312368cb4d45b4d4b97446ab1d71a550a0d604c3e86c40a3c9b12de8f08a86639068707822cd475621700347c52af088eda9a0245385094518134e73bb997102e11f6de0aeb36af7237139d7cabd19d6b0b9e827cdf84a4fc18c88d1882e4e096d8dfeff58759504d2f9e7a9e183b0836ad58dd646d9ab123132397109e4f51c5842958932a81bacd1012b013101320133","error":null}
|
||||||
|
|
Loading…
Add table
Reference in a new issue