discreetlogcontracts / dlcspecs

Specification for Discreet Log Contracts
Creative Commons Attribution 4.0 International
239 stars 36 forks source link

Oracle Address proposal #99

Closed Christewart closed 3 years ago

Christewart commented 4 years ago

I wanted to open this up as an issue before i do a formal writeup to get this in front of people to see what people think:

All code can be found here: https://github.com/Christewart/bitcoin-s-core/tree/2020-09-17-oracle-address

The address that I am generating is based off of @Tibo-lg 's 'event descriptor': https://github.com/discreetlogcontracts/dlcspecs/blob/ac046f44f610bc7335a2853178d58e7a8b90423d/Oracle.md#event-descriptor

Here is what an address would look like:

oracle1gp50v8mlfermwpqyc5hpm29733s20wxr0kv8czj75vuecp3ahp07jtsep5h72c90989kkzxpx0y29up0hq6mtnaw4sz5dgn25mnw7x0fe2e7wqmqdqqqqqqzl5zwcq0qgwd6kumne0q2vdkx7aty0y0qgwfskjmnege9q2x

As you can see this is Bech32 encoded string that contains

  1. A Human Readable Part of oracle
  2. The bech32 separator of 1 between the HRP and payload (according to BIP173 this is the only separator)
  3. A payload of gp50v8mlfermwpqyc5hpm29733s20wxr0kv8czj75vuecp3ahp07jtsep5h72c90989kkzxpx0y29up0hq6mtnaw4sz5dgn25mnw7x0fe2e7wqmqdqqqqqqzl5zwcq0qgwd6kumne0q2vdkx7aty0y0qgwfskjmne
  4. a checksum of ge9q2x

Payload breakdown

Here are the fields I currently have encoded in the payload

  1. The oracle's Schnorr Public Key (7b0fbfa723db820262970ed45f463053dc61becc3e052f519cce031edc2ff497)
  2. The oracle's nonce (bf9582bca72dac2304cf228bc0bee0d6d73ebab0151a89aa9b9bbc67a72acf9c)
  3. The outcomes of the DLC ([sunny, cloudy, rainy])
  4. The maturation of the DLC (2020-11-03 or 1604361600) in seconds since the epoch.

Encoding/Decoding

For this initial work I've just coopted the Lightning Invoice encoding scheme. I've created new tagged fields according to the BOLT11 spec.

The new tags are Each Tagged Field is of the form:

  1. type (5 bits)
  2. data_length (10 bits, big-endian)
  3. data (data_length x 5 bits)

Finally from the address above here is the breakdown for each of the tags:

Schnorr Public Key

gp50v8mlfermwpqyc5hpm29733s20wxr0kv8czj75vuecp3ahp07jts

Schnorr Nonce

ep5h72c90989kkzxpx0y29up0hq6mtnaw4sz5dgn25mnw7x0fe2e7wq

Outcomes

0qgwd6kumne0q2vdkx7aty0y0qgwfskjmne

Reasoning for choosing the LN invoice format

  1. It seems to have all the features we require
  2. It will be compatible with LN invoices when we move up to Lightning (I choose unique tags for this reason)
  3. A lot of libaries already have this serializaiton code built already, we can just re-use that code like i did in bitcoin-s

Including a signature on the address?

I'm not sure how I feel about this, you still need to validate the public key in some way, and as @nkohen mentioned can't do public key recovery from BIP340 signatures :-(.

Christewart commented 4 years ago

related to #89 and replaces #95 in my opinion

Christewart commented 4 years ago

Looking at this retrospectively, i should probably encode the timestamp the same way Lightning invoices do rather than allocating a unique tag. Give me a :+1: on this comment if you agree

EDIT: I remembered my original reasoning for not using the timestamp field -- if we want to be compatible with lightning invoices in the future this would re-purpose the timestamp semantic on Lightning invoices. The current timestamp on lightning invoices is meant for when the invoice was created, not when it expires. They have a separate tag in the invoice for when the invoice expires.

x (6): data_length variable. expiry time in seconds (big-endian). Default is 3600 (1 hour) if not specified.

NicolasDorier commented 4 years ago

Oracle and nonce should be encoded separately.

  1. Alice trusts Olivia and add Olivia to trusted oracles by adding her pubkey
  2. Bob trusts Olivia and add Olivia to trusted oracles by adding her pubkey
  3. Olivia release a new event, share the nonce/outcomes
  4. Alice add the nonce/outcomes to her app
  5. Bob add the nonce/outcomes to his app
  6. Alice create an offer
  7. Bob review the offer, see it is matching the same event he got from the oracle

There is two distinct UX step:

  1. Oracle is added to the trusted list of oracle
  2. The nonce/outcomes are added to the apps of the peers

Both steps are distinct, thus having a single address concatenating both the nonce and the oraclepubkey is useless, this is not how it will be actually used.

Christewart commented 4 years ago

Thus having a single address concatenating both the nonce and the oraclepubkey is useless, this is not how it will be actually used.

So this is discussed on #93, maybe we can make the pubkey optional?

Besides the pubkey encoding, do you have any other objections? What is your opinion on a signature?

benthecarman commented 4 years ago

Oracle and nonce should be encoded separately.

Given what you laid out, I think it is still fine to include the oracle public key. By including the pubkey you can have the user enter oracle address into the software and it can look up if that pubkey is considered trusted or not. If not then it can display a pop-up saying something like Oracle pubkey <key> is unknown, would you like to add it to your list of trusted oracles?

nkohen commented 4 years ago

So I think that you need some way of referencing the oracle in the address ... otherwise it is just a random nonce, and including the oracle pubkey seems a sane way to do this.

Furthermore, for both Nicolas' and Ben's considerations, it is vitally important to add the oracle's signature of this address as otherwise the entire concept of an address is useless and redundant. It could instead be replaced by communicating an oracle and that oracle's broadcast of the given event (whether that be a URI or otherwise) as there is no reason to trust someone's unsigned address for anything and you're going to have to go validate this data from the source if it is not covered by a signature.

nkohen commented 4 years ago

Furthermore, wrt #55

Event descriptors should be serialized using [TLV format](https://github.com/lightningnetwork/lightning-rfc/blob/master/01-messaging.md#type-length-value-format) (to be defined).
The oracle should provide a signature over the serialized descriptor together with the [unique identifier](#Unique-Resource-Identifier) to the client as an attestation that he committed to release a signature over the event outcome.

The descriptor's serialization should match that of the proposal, and a URI is missing from this proposal.

nkohen commented 4 years ago

With these three changes, this proposal will be compliant with @Tibo-lg's proposal and these addresses can be broadcasted by oracles under that scheme. Curious on your thoughts @Tibo-lg

nkohen commented 4 years ago

Oooh, another neat thing might be to allow for an optional contract info TLV field, meaning that users could take the "address" broadcasted by an oracle and add a tag with their bet parameters on there and then pass that along as a full oracle + contract info

NicolasDorier commented 4 years ago

Given what you laid out, I think it is still fine to include the oracle public key. By including the pubkey you can have the user enter oracle address into the software and it can look up if that pubkey is considered trusted or not

No you don't. The nonce has been fetched from the oracle in some way (be it by pulling some event descriptor on their server, or via twitter) When you fetch it, you know which oracle you are using, so there is no point for the oracle to add it in the address itself.

Basically right now in NDLC, I have

events add "Olivia/EventName" "nonce" "outcome1" "outcomen"....

When there is a oracle's feed, it would be something like

oracle pull "Olivia"

Your point is that we can replace

events add "Olivia/EventName" "nonce" "outcome1" "outcomen"....

with

events add "EventName" "oracleAddress" "outcome1" "outcomen"....

Not only the benefit is marginal, and only useful in the case there is no "oracle feed". But also I disagree that it is a good thing as the nonce should be fetched directly from the oracle, not from any other party, and it is useless for the oracle to repeat his pubkey for each events. From user perspective it obliges them to validate that it is the oracle that they know as Olivia, and not be tricked.

On top of this, as @nkohen indicated, this because complex because what if the user think the event is from Olivia, but instead it is from another oracle that he trusts. It would add the event without warning that it is not the oracle he meant to, and the signature would not even help on that.

Christewart commented 4 years ago

No you don't. The nonce has been fetched from the oracle in some way (be it by pulling some event descriptor on their server, or via twitter)

Yes, if you are directly fetching it from their website/twitter/official source of information why not let the oracle rotate a key if they chose? This exact same concept applies to bitcoin addresses. If you are not receiving it from the oracle itself you ask the oracle if this information is real. If you are about to send money to a bitcoin address, you should ask the intended recipient if the address is actually owned by them.

But also I disagree that it is a good thing as the nonce should be fetched directly from the oracle, not from any other party, and it is useless for the oracle to repeat his pubkey for each events. From user perspective it obliges them to validate that it is the oracle that they know as Olivia, and not be tricked.

I think we are all in agreement you should fetch oracle information directly from the oracle, this issue is about making it easier for user's to copy and paste this information into their wallet software. Just like with bitcoin addresses, your wallet software could make API calls out to an exchange/BTCPayServer to fetch addresses, but it's a lot easier in my opinion just to copy paste and this is what most users do.

events add "EventName" "oracleAddress" "outcome1" "outcomen"....

The outcomes are encoded in the oracle address as well so it would just look like

events add "EventName" "oracleAddress"

if I understand what you are doing. Maybe we can even add the Event Name into the address, but i haven't done that yet. That is probably a good idea.

NicolasDorier commented 4 years ago

why not let the oracle rotate a key if they chose?

Because in this case we don't need DLC. The whole point of DLC is that the private key of the oracle get revealed if there is two outcomes attested. If you don't need this feature, the protocol can be considerably simpler, and I would agree with the rest of the point you make.

But given DLC is done so that the oracle's identity is tied to the pubkey (so he has something big to lose if it is malicious), the identity is separate from the event.

Tibo-lg commented 4 years ago

With these three changes, this proposal will be compliant with @Tibo-lg's proposal and these addresses can be broadcasted by oracles under that scheme. Curious on your thoughts @Tibo-lg

@nkohen @Christewart Mainly it looks fine to me, though one concern I have is if it is really a good idea to include the full outcome list in the address. I though it would commit to it so that a user could verify if outcomes given to him are certified by the oracle (like just a hash of the TLV).

No you don't. The nonce has been fetched from the oracle in some way (be it by pulling some event descriptor on their server, or via twitter) When you fetch it, you know which oracle you are using, so there is no point for the oracle to add it in the address itself.

@NicolasDorier I might be wrong, but I think an advantage of having an address scheme + a signature of the oracle tvalidating it is that you could validate that information given to you from a third party (e.g. your counter-party) is actually from an oracle.

On top of this, as @nkohen indicated, this because complex because what if the user think the event is from Olivia, but instead it is from another oracle that he trusts. It would add the event without warning that it is not the oracle he meant to, and the signature would not even help on that.

That seems more like a UX concern, the application should probably display which oracle is being used in any case.

NicolasDorier commented 4 years ago

that you could validate that information given to you from a third party (e.g. your counter-party) is actually from an oracle.

The information should not be given by a third party in the first place. If it is delivered by a third party (say a future event aggregator), the best is a basic "event descriptor" which is signed by the public key of the oracle. This can be a file, no need of a string for that.

But even with this case, the oracle need to reveal his own public key separately.

Last point: The "Oracle|Nonce" address does not cover the case where there is multiple nonce for the same event, which you need for attesting a number.

Tibo-lg commented 4 years ago

The information should not be given by a third party in the first place.

The motivation for this would be to have oracle information shared across the network instead of accessed directly on a server as it would greatly improve privacy. Hard to hide that you're doing an event on X when you explicitly request information on it. It's not a short term objective but I think it's good to keep it in mind.

My understanding of the proposal is that the address would include the descriptor and signature over it inside the address, although I have reserved on this point and I might be misunderstanding.

The multiple nonce issue can probably be solved, I don't see that as a big issue.

Christewart commented 4 years ago

Because in this case we don't need DLC. The whole point of DLC is that the private key of the oracle get revealed if there is two outcomes attested. If you don't need this feature, the protocol can be considerably simpler, and I would agree with the rest of the point you make.

This property still holds true even if you rotate keys (the fresh private key gets revealed)

But given DLC is done so that the oracle's identity is tied to the pubkey (so he has something big to lose if it is malicious), the identity is separate from the event.

As we have said in previous threads, the oracle needs to allow the ability to for users to validate that they own the private key associated pubkey. Thus a business such as an exchange or an individual will still have their identity tied to this lie.

I still think it's regressive to punish all users of the oracle if they are incompetent in key management. If they are malicious, it will be cryptographically provable. Unfortunately there is no way to distinguish between incompetent and malicious as an external third party.

LLFourn commented 4 years ago

Just chiming in. I agree with https://github.com/discreetlogcontracts/dlcspecs/issues/99#issuecomment-701116248. I think oracles should have human readable identifiers. It's the software's job to associate the oracle id with the public key and parties engaging in the protocol shouldn't send the public key around to each other (or remember what they look like).

My preference for oracle id is just a hostname -- from there you can gets its public key via https. I know that people here have expressed a preference for not making a http endpoint for an oracle mandatory (they could publish stuff through twitter for example). I guess that's fine but maybe twitter.com/OutcomeObserver or something then with some very specific format for the public key in the bio. Of course you are trusting twitter.com in addition to the oracle then but I guess that's fine if that's what someone wants.

Implementations can always have a manual way to add an oracle id + public key but I don't see the need for a standardized format here. How to specify/serialize and sign/verify the announcement data (i.e. nonce and other stuff) does need a specification though but that's a separate issue.

Christewart commented 4 years ago

One thing that came out of #101 is that there really is two different steps here:

  1. Obtaining a long standing "identity" public key from an oracle
  2. Obtaining event specific information (which may be the same, may be different than an event specific public key?)
ghost commented 4 years ago

Here is what an address would look like:

oracle1gp50v8mlfermwpqyc5hpm29733s20wxr0kv8czj75vuecp3ahp07jtsep5h72c90989kkzxpx0y29up0hq6mtnaw4sz5dgn25mnw7x0fe2e7wqmqdqqqqqqzl5zwcq0qgwd6kumne0q2vdkx7aty0y0qgwfskjmnege9q2x

As you can see this is Bech32 encoded string that contains

  1. A Human Readable Part of oracle

Is it necessary to have the human readable part as oracle? Can we have random characters there? or use bc ?