@ -8,12 +8,14 @@ use bdk::SignOptions;
use bitcoin ::util ::psbt ::PartiallySignedTransaction ;
use cfd_protocol ::{
close_transaction , commit_descriptor , compute_adaptor_pk , create_cfd_transactions ,
finalize_spend_transaction , interval , lock_descriptor , punish_transaction ,
renew_cfd_transactions , spending_tx_sighash , CfdTransactions , Payout , PunishParams ,
TransactionExt , WalletExt ,
finalize_spend_transaction , generate_payouts , interval , lock_descriptor , punish_transaction ,
renew_cfd_transactions , spending_tx_sighash , Announcement , Cets , CfdTransactions , Payout ,
PunishParams , TransactionExt , WalletExt ,
} ;
use rand ::{ thread_rng , CryptoRng , RngCore } ;
use secp256k1_zkp ::{ schnorrsig , EcdsaAdaptorSignature , SecretKey , Signature , SECP256K1 } ;
use std ::collections ::HashMap ;
use std ::iter ::FromIterator ;
use std ::str ::FromStr ;
#[ test ]
@ -26,25 +28,38 @@ fn create_cfd() {
let maker_wallet = build_wallet ( & mut rng , Amount ::from_btc ( 0.4 ) . unwrap ( ) , 5 ) . unwrap ( ) ;
let taker_wallet = build_wallet ( & mut rng , Amount ::from_btc ( 0.4 ) . unwrap ( ) , 5 ) . unwrap ( ) ;
let oracle_data = OliviaData ::example ( ) ;
let oracle_pk = oracle_data . pk ;
let nonce_pks = oracle_data . nonce_pks . clone ( ) ;
let oracle_data_0 = OliviaData ::example_0 ( ) ;
let oracle_data_1 = OliviaData ::example_1 ( ) ;
let payouts = vec ! [
Payout ::new (
0 . . = 40_000 ,
Amount ::from_btc ( 1.5 ) . unwrap ( ) ,
Amount ::from_btc ( 0.5 ) . unwrap ( ) ,
)
. unwrap ( ) ,
Payout ::new (
40_001 . . = 70_000 ,
Amount ::ZERO ,
Amount ::from_btc ( 2.0 ) . unwrap ( ) ,
)
. unwrap ( ) ,
]
. concat ( ) ;
let oracle_pk = oracle_data_0 . pk ;
let event_0 = oracle_data_0 . announcement ( ) ;
let event_1 = oracle_data_1 . announcement ( ) ;
let payouts_per_event = HashMap ::from_iter ( [
(
event_0 . clone ( ) ,
generate_payouts ( 0 . . = 50_000 , Amount ::ZERO , Amount ::from_btc ( 2.0 ) . unwrap ( ) ) . unwrap ( ) ,
) ,
(
event_1 . clone ( ) ,
[
generate_payouts (
40_001 . . = 70_000 ,
Amount ::from_btc ( 0.5 ) . unwrap ( ) ,
Amount ::from_btc ( 1.5 ) . unwrap ( ) ,
)
. unwrap ( ) ,
generate_payouts (
70_001 . . = 100_000 ,
Amount ::from_btc ( 1.5 ) . unwrap ( ) ,
Amount ::from_btc ( 0.5 ) . unwrap ( ) ,
)
. unwrap ( ) ,
]
. concat ( ) ,
) ,
] ) ;
let cet_timelock = 0 ;
let refund_timelock = 0 ;
@ -53,11 +68,16 @@ fn create_cfd() {
& mut rng ,
( & maker_wallet , maker_lock_amount ) ,
( & taker_wallet , taker_lock_amount ) ,
( oracle_pk , & nonce_pks ) ,
payouts ,
oracle_pk ,
payouts_per_event ,
( cet_timelock , refund_timelock ) ,
) ;
assert_contains_cets_for_event ( & maker_cfd_txs . cets , & event_0 ) ;
assert_contains_cets_for_event ( & maker_cfd_txs . cets , & event_1 ) ;
assert_contains_cets_for_event ( & taker_cfd_txs . cets , & event_0 ) ;
assert_contains_cets_for_event ( & taker_cfd_txs . cets , & event_1 ) ;
let lock_desc = lock_descriptor ( maker . pk , taker . pk ) ;
let lock_amount = maker_lock_amount + taker_lock_amount ;
@ -70,7 +90,7 @@ fn create_cfd() {
verify_cfd_sigs (
( & maker_cfd_txs , maker . pk , maker . pub_pk ) ,
( & taker_cfd_txs , taker . pk , taker . pub_pk ) ,
( oracle_pk , & nonce_pks ) ,
( oracle_pk , vec ! [ event_0 , event_1 ] ) ,
( & lock_desc , lock_amount ) ,
( & commit_desc , commit_amount ) ,
) ;
@ -96,7 +116,7 @@ fn create_cfd() {
taker . rev_sk ,
taker_addr ,
) ,
oracle_data ,
& [ oracle_data_0 , oracle_data_1 ] ,
( lock_desc , lock_amount ) ,
( commit_desc , commit_amount ) ,
) ;
@ -112,20 +132,23 @@ fn renew_cfd() {
let maker_wallet = build_wallet ( & mut rng , Amount ::from_btc ( 0.4 ) . unwrap ( ) , 5 ) . unwrap ( ) ;
let taker_wallet = build_wallet ( & mut rng , Amount ::from_btc ( 0.4 ) . unwrap ( ) , 5 ) . unwrap ( ) ;
let oracle_data = OliviaData ::example ( ) ;
let oracle_data = OliviaData ::example_0 ( ) ;
let oracle_pk = oracle_data . pk ;
let nonce_pks = oracle_data . nonce_pks . clone ( ) ;
let payouts = vec ! [
Payout ::new ( 0 . . = 10_000 , Amount ::from_btc ( 2.0 ) . unwrap ( ) , Amount ::ZERO ) . unwrap ( ) ,
Payout ::new (
10_001 . . = 50_000 ,
Amount ::ZERO ,
Amount ::from_btc ( 2.0 ) . unwrap ( ) ,
)
. unwrap ( ) ,
]
. concat ( ) ;
let event = oracle_data . announcement ( ) ;
let payouts_per_event = HashMap ::from_iter ( [ (
event ,
vec ! [
generate_payouts ( 0 . . = 10_000 , Amount ::from_btc ( 2.0 ) . unwrap ( ) , Amount ::ZERO ) . unwrap ( ) ,
generate_payouts (
10_001 . . = 50_000 ,
Amount ::ZERO ,
Amount ::from_btc ( 2.0 ) . unwrap ( ) ,
)
. unwrap ( ) ,
]
. concat ( ) ,
) ] ) ;
let cet_timelock = 0 ;
let refund_timelock = 0 ;
@ -134,8 +157,8 @@ fn renew_cfd() {
& mut rng ,
( & maker_wallet , maker_lock_amount ) ,
( & taker_wallet , taker_lock_amount ) ,
( oracle_pk , & nonce_pks ) ,
payouts ,
oracle_pk ,
payouts_per_event ,
( cet_timelock , refund_timelock ) ,
) ;
@ -147,21 +170,28 @@ fn renew_cfd() {
let ( taker_rev_sk , taker_rev_pk ) = make_keypair ( & mut rng ) ;
let ( taker_pub_sk , taker_pub_pk ) = make_keypair ( & mut rng ) ;
let payouts = vec ! [
Payout ::new (
0 . . = 50_000 ,
Amount ::from_btc ( 1.5 ) . unwrap ( ) ,
Amount ::from_btc ( 0.5 ) . unwrap ( ) ,
)
. unwrap ( ) ,
Payout ::new (
50_001 . . = 70_000 ,
Amount ::from_btc ( 0.5 ) . unwrap ( ) ,
Amount ::from_btc ( 1.5 ) . unwrap ( ) ,
)
. unwrap ( ) ,
]
. concat ( ) ;
let oracle_data = OliviaData ::example_1 ( ) ;
let oracle_pk = oracle_data . pk ;
let event = oracle_data . announcement ( ) ;
let payouts_per_event = HashMap ::from_iter ( [ (
event . clone ( ) ,
vec ! [
generate_payouts (
0 . . = 50_000 ,
Amount ::from_btc ( 1.5 ) . unwrap ( ) ,
Amount ::from_btc ( 0.5 ) . unwrap ( ) ,
)
. unwrap ( ) ,
generate_payouts (
50_001 . . = 70_000 ,
Amount ::from_btc ( 0.5 ) . unwrap ( ) ,
Amount ::from_btc ( 1.5 ) . unwrap ( ) ,
)
. unwrap ( ) ,
]
. concat ( ) ,
) ] ) ;
let maker_cfd_txs = renew_cfd_transactions (
maker_cfd_txs . lock ,
@ -183,9 +213,9 @@ fn renew_cfd() {
publish_pk : taker_pub_pk ,
} ,
) ,
( oracle_pk , & nonce_pks ) ,
oracle_pk ,
( cet_timelock , refund_timelock ) ,
payouts . clone ( ) ,
payouts_per_event . clone ( ) ,
maker . sk ,
)
. unwrap ( ) ;
@ -210,13 +240,16 @@ fn renew_cfd() {
publish_pk : taker_pub_pk ,
} ,
) ,
( oracle_pk , & nonce_pks ) ,
oracle_pk ,
( cet_timelock , refund_timelock ) ,
payouts ,
payouts_per_event ,
taker . sk ,
)
. unwrap ( ) ;
assert_contains_cets_for_event ( & maker_cfd_txs . cets , & event ) ;
assert_contains_cets_for_event ( & taker_cfd_txs . cets , & event ) ;
let lock_desc = lock_descriptor ( maker . pk , taker . pk ) ;
let lock_amount = maker_lock_amount + taker_lock_amount ;
@ -229,7 +262,7 @@ fn renew_cfd() {
verify_cfd_sigs (
( & maker_cfd_txs , maker . pk , maker_pub_pk ) ,
( & taker_cfd_txs , taker . pk , taker_pub_pk ) ,
( oracle_pk , & nonce_pks ) ,
( oracle_pk , vec ! [ event ] ) ,
( & lock_desc , lock_amount ) ,
( & commit_desc , commit_amount ) ,
) ;
@ -255,7 +288,7 @@ fn renew_cfd() {
taker_rev_sk ,
taker_addr ,
) ,
oracle_data ,
& [ oracle_data ] ,
( lock_desc , lock_amount ) ,
( commit_desc , commit_amount ) ,
)
@ -271,17 +304,19 @@ fn collaboratively_close_cfd() {
let maker_wallet = build_wallet ( & mut rng , Amount ::from_btc ( 0.4 ) . unwrap ( ) , 5 ) . unwrap ( ) ;
let taker_wallet = build_wallet ( & mut rng , Amount ::from_btc ( 0.4 ) . unwrap ( ) , 5 ) . unwrap ( ) ;
let oracle_data = OliviaData ::example ( ) ;
let oracle_data = OliviaData ::example_0 ( ) ;
let oracle_pk = oracle_data . pk ;
let nonce_pks = oracle_data . nonce_pks ;
let event = oracle_data . announcement ( ) ;
let payouts = vec ! [ Payout ::new (
0 . . = 100_000 ,
Amount ::from_btc ( 1.5 ) . unwrap ( ) ,
Amount ::from_btc ( 0.5 ) . unwrap ( ) ,
)
. unwrap ( ) ]
. concat ( ) ;
let payouts_per_event = HashMap ::from_iter ( [ (
event ,
generate_payouts (
0 . . = 100_000 ,
Amount ::from_btc ( 1.5 ) . unwrap ( ) ,
Amount ::from_btc ( 0.5 ) . unwrap ( ) ,
)
. unwrap ( ) ,
) ] ) ;
let cet_timelock = 0 ;
let refund_timelock = 0 ;
@ -290,8 +325,8 @@ fn collaboratively_close_cfd() {
& mut rng ,
( & maker_wallet , maker_lock_amount ) ,
( & taker_wallet , taker_lock_amount ) ,
( oracle_pk , & nonce_pks ) ,
payouts ,
oracle_pk ,
payouts_per_event ,
( cet_timelock , refund_timelock ) ,
) ;
@ -335,8 +370,8 @@ fn create_cfd_txs(
rng : & mut ( impl RngCore + CryptoRng ) ,
( maker_wallet , maker_lock_amount ) : ( & bdk ::Wallet < ( ) , bdk ::database ::MemoryDatabase > , Amount ) ,
( taker_wallet , taker_lock_amount ) : ( & bdk ::Wallet < ( ) , bdk ::database ::MemoryDatabase > , Amount ) ,
( oracle_pk , nonce_pks ) : ( schnorrsig ::PublicKey , & [ schnorrsig ::PublicKey ] ) ,
payouts : Vec < Payout > ,
oracle_pk : schnorrsig ::PublicKey ,
payouts_per_event : HashMap < Announcement , Vec < Payout > > ,
( cet_timelock , refund_timelock ) : ( u32 , u32 ) ,
) -> (
CfdTransactions ,
@ -362,6 +397,7 @@ fn create_cfd_txs(
let taker_params = taker_wallet
. build_party_params ( taker_lock_amount , taker_pk )
. unwrap ( ) ;
let maker_cfd_txs = create_cfd_transactions (
(
maker_params . clone ( ) ,
@ -377,9 +413,9 @@ fn create_cfd_txs(
publish_pk : taker_pub_pk ,
} ,
) ,
( oracle_pk , nonce_pks ) ,
oracle_pk ,
( cet_timelock , refund_timelock ) ,
payouts . clone ( ) ,
payouts_per_event . clone ( ) ,
maker_sk ,
)
. unwrap ( ) ;
@ -398,9 +434,9 @@ fn create_cfd_txs(
publish_pk : taker_pub_pk ,
} ,
) ,
( oracle_pk , nonce_pks ) ,
oracle_pk ,
( cet_timelock , refund_timelock ) ,
payouts ,
payouts_per_event ,
taker_sk ,
)
. unwrap ( ) ;
@ -440,7 +476,7 @@ struct CfdKeys {
fn verify_cfd_sigs (
( maker_cfd_txs , maker_pk , maker_publish_pk ) : ( & CfdTransactions , PublicKey , PublicKey ) ,
( taker_cfd_txs , taker_pk , taker_publish_pk ) : ( & CfdTransactions , PublicKey , PublicKey ) ,
( oracle_pk , nonce_pk s) : ( schnorrsig ::PublicKey , & [ schnorrsig ::PublicKey ] ) ,
( oracle_pk , event s) : ( schnorrsig ::PublicKey , Vec < Announcement > ) ,
( lock_desc , lock_amount ) : ( & Descriptor < PublicKey > , Amount ) ,
( commit_desc , commit_amount ) : ( & Descriptor < PublicKey > , Amount ) ,
) {
@ -460,44 +496,69 @@ fn verify_cfd_sigs(
& taker_pk . key ,
)
. expect ( "valid taker refund sig" ) ;
for ( tx , _ , digits ) in taker_cfd_txs . cets . iter ( ) {
maker_cfd_txs
for grouped_taker_cets in taker_cfd_txs . cets . iter ( ) {
let grouped_maker_cets = maker_cfd_txs
. cets
. iter ( )
. find ( | ( maker_tx , maker_encsig , _ ) | {
maker_tx . txid ( ) = = tx . txid ( )
& & verify_cet_encsig (
tx ,
maker_encsig ,
digits ,
& maker_pk . key ,
( oracle_pk , nonce_pks ) ,
commit_desc ,
commit_amount ,
)
. is_ok ( )
} )
. expect ( "one valid maker cet encsig per cet" ) ;
. find ( | grouped_maker_cets | grouped_maker_cets . event = = grouped_taker_cets . event )
. expect ( "both parties to have the same set of payouts" ) ;
let event = events
. iter ( )
. find ( | event | event . id = = grouped_maker_cets . event . id )
. expect ( "event to exist" ) ;
for ( tx , _ , digits ) in grouped_taker_cets . cets . iter ( ) {
grouped_maker_cets
. cets
. iter ( )
. find ( | ( maker_tx , maker_encsig , _ ) | {
maker_tx . txid ( ) = = tx . txid ( )
& & verify_cet_encsig (
tx ,
maker_encsig ,
digits ,
& maker_pk . key ,
( oracle_pk , event . nonce_pks . as_slice ( ) ) ,
commit_desc ,
commit_amount ,
)
. is_ok ( )
} )
. expect ( "one valid maker cet encsig per cet" ) ;
}
}
for ( tx , _ , msg_nonce_pairs ) in maker_cfd_txs . cets . iter ( ) {
taker_cfd_txs
for grouped_maker_cets in maker_cfd_txs . cets . iter ( ) {
let grouped_taker_cets = taker_cfd_txs
. cets
. iter ( )
. find ( | ( taker_tx , taker_encsig , _ ) | {
taker_tx . txid ( ) = = tx . txid ( )
& & verify_cet_encsig (
tx ,
taker_encsig ,
msg_nonce_pairs ,
& taker_pk . key ,
( oracle_pk , nonce_pks ) ,
commit_desc ,
commit_amount ,
)
. is_ok ( )
} )
. expect ( "one valid taker cet encsig per cet" ) ;
. find ( | grouped_taker_cets | grouped_taker_cets . event = = grouped_maker_cets . event )
. expect ( "both parties to have the same set of payouts" ) ;
let event = events
. iter ( )
. find ( | event | event . id = = grouped_maker_cets . event . id )
. expect ( "event to exist" ) ;
for ( tx , _ , digits ) in grouped_maker_cets . cets . iter ( ) {
grouped_taker_cets
. cets
. iter ( )
. find ( | ( taker_tx , taker_encsig , _ ) | {
taker_tx . txid ( ) = = tx . txid ( )
& & verify_cet_encsig (
tx ,
taker_encsig ,
digits ,
& taker_pk . key ,
( oracle_pk , event . nonce_pks . as_slice ( ) ) ,
commit_desc ,
commit_amount ,
)
. is_ok ( )
} )
. expect ( "one valid taker cet encsig per cet" ) ;
}
}
encverify_spend (
& taker_cfd_txs . commit . 0 ,
& maker_cfd_txs . commit . 1 ,
@ -557,7 +618,7 @@ fn check_cfd_txs(
SecretKey ,
Address ,
) ,
oracle_data : OliviaData ,
oracle_data_list : & [ OliviaData ] ,
( lock_desc , lock_amount ) : ( Descriptor < PublicKey > , Amount ) ,
( commit_desc , commit_amount ) : ( Descriptor < PublicKey > , Amount ) ,
) {
@ -604,51 +665,77 @@ fn check_cfd_txs(
// CETs:
let unlocked_cets = maker_cfd_txs . cets . clone ( ) . into_iter ( ) . filter_map ( {
| ( tx , _ , digits ) | {
let price = oracle_data . price ;
for Cets { event , cets } in maker_cfd_txs . cets . clone ( ) . into_iter ( ) {
let oracle_data = oracle_data_list
. iter ( )
. find ( | data | data . id = = event . id )
. expect ( "every cet to correspond to an existing event" ) ;
let price = oracle_data . price ;
let oracle_attestations = oracle_data . attestations . clone ( ) ;
let taker_cets = taker_cfd_txs
. cets
. iter ( )
. find_map (
| Cets {
event : other_event ,
cets ,
} | ( other_event . id = = event . id ) . then ( | | cets ) ,
)
. expect ( "same events for taker and maker" ) ;
cets . into_iter ( ) . for_each ( | ( tx , _ , digits ) | {
if ! digits . range ( ) . contains ( & price ) {
return None ;
return ;
}
let oracle_attestations = oracle_data . attestations . clone ( ) ;
build_and_check_cet (
tx ,
& taker_cfd_txs . cets ,
taker_cets ,
( & maker_sk , & maker_pk ) ,
& taker_pk ,
( price , & oracle_attestations ) ,
( & signed_commit_tx_maker , & commit_desc , commit_amount ) ,
)
. expect ( "valid maker cet" ) ;
. expect ( "valid unlocked maker cet" ) ;
} ) ;
}
Some ( ( ) )
}
} ) ;
assert_eq ! ( unlocked_cets . count ( ) , 1 , "Expected to unlock only 1 CET" ) ;
for Cets { event , cets } in taker_cfd_txs . cets . clone ( ) . into_iter ( ) {
let oracle_data = oracle_data_list
. iter ( )
. find ( | data | data . id = = event . id )
. expect ( "every cet to correspond to an existing event" ) ;
let price = oracle_data . price ;
let oracle_attestations = oracle_data . attestations . clone ( ) ;
let unlocked_cets = taker_cfd_txs
. cets
. into_iter ( )
. filter_map ( | ( tx , _ , digits ) | {
let price = oracle_data . price ;
let maker_cets = maker_cfd_txs
. cets
. iter ( )
. find_map (
| Cets {
event : other_event ,
cets ,
} | ( other_event . id = = event . id ) . then ( | | cets ) ,
)
. expect ( "same events for taker and maker" ) ;
cets . into_iter ( ) . for_each ( | ( tx , _ , digits ) | {
if ! digits . range ( ) . contains ( & price ) {
return None ;
return ;
}
build_and_check_cet (
tx ,
& maker_cfd_txs . cets ,
maker_cets ,
( & taker_sk , & taker_pk ) ,
& maker_pk ,
( price , & oracle_data . attestations ) ,
( & signed_commit_tx_m aker , & commit_desc , commit_amount ) ,
( price , & oracle_attestations ) ,
( & signed_commit_tx_t aker , & commit_desc , commit_amount ) ,
)
. expect ( "valid taker cet" ) ;
Some ( ( ) )
. expect ( "valid unlocked taker cet" ) ;
} ) ;
assert_eq ! ( unlocked_cets . count ( ) , 1 , "Expected to unlock only 1 CET" ) ;
}
// Punish transactions:
@ -930,6 +1017,7 @@ fn make_keypair(rng: &mut (impl RngCore + CryptoRng)) -> (SecretKey, PublicKey)
}
struct OliviaData {
id : String ,
pk : schnorrsig ::PublicKey ,
nonce_pks : Vec < schnorrsig ::PublicKey > ,
price : u64 ,
@ -937,74 +1025,163 @@ struct OliviaData {
}
impl OliviaData {
fn example_0 ( ) -> Self {
Self ::example (
Self ::EVENT_ID_0 ,
Self ::PRICE_0 ,
& Self ::NONCE_PKS_0 ,
& Self ::ATTESTATIONS_0 ,
)
}
fn example_1 ( ) -> Self {
Self ::example (
Self ::EVENT_ID_1 ,
Self ::PRICE_1 ,
& Self ::NONCE_PKS_1 ,
& Self ::ATTESTATIONS_1 ,
)
}
/// An example of all the data necessary from `olivia` to test the
/// CFD protocol.
///
/// Data comes from this event:
/// https://outcome.observer/h00.ooo/x/BitMEX/BXBT/2021-10-05T02:00:00.price[n:20].
pub fn example ( ) -> Self {
let pk = schnorrsig ::PublicKey ::from_str (
"ddd4636845a90185991826be5a494cde9f4a6947b1727217afedc6292fa4caf7" ,
)
. unwrap ( ) ;
fn example ( id : & str , price : u64 , nonce_pks : & [ & str ] , attestations : & [ & str ] ) -> Self {
let oracle_pk = schnorrsig ::PublicKey ::from_str ( Self ::OLIVIA_PK ) . unwrap ( ) ;
let nonce_pks = [
"d02d163cf9623f567c4e3faf851a9266ac1ede13da4ca4141f3a7717fba9a739" ,
"bc310f26aa5addbc382f653d8530aaead7c25e3546abc24639f490e36d4bdb88" ,
"2661375f570dcc32300d442e85b6d72dfa3232dccda45e8fb4a2d1e758d1d374" ,
"fcc68fbf071d391b14c0867cb4defb5a8abc12418dff3dfc2f84fd4025cb2716" ,
"cf5c2b7fe3851c64a7ff9635a9bfc50cdd301401d002f2da049f4c6a20e8457b" ,
"14f1005d8c2832a2c4666dd732dd9bb3af9c8f70ebcdaec96869b1ca0c8e0de6" ,
"299ee1c9c20fab8b067adf452a7d7661b5e7f5dd6bc707562805002e7cb8443e" ,
"bcb4e5a594346de298993a7a31762f598b5224b977e23182369e9ed3e5127f78" ,
"25e09a16ee5d469069abfb62cd5e1f20af50cf15241f571e64fa28b127304574" ,
"3ed5a1422f43299caf281123aba88bd4bc61ec863f4afb79c7ce7663ad44db5d" ,
"a7e0f61212735c192c4bf16e0a3e925e65f9f3feb6f1e5e8d6f5c18cf2dbb5a8" ,
"a36a631015d9036d0c321fea7cf12f589aa196e7279b4a290de5112c2940e540" ,
"b5bdd931f81970139e7301ac654b378077c3ed993ca7893ed93fee5fc6f7a782" ,
"00090816e256b41e042dce38bde99ab3cf9482f9b066836988d3ed54833638e8" ,
"3530408e93c251f5f488d3b1c608157177c459d6fab1966abebf765bcc9338d2" ,
"603269ce88d112ff7fcfcaab82f228be97deca37f8190084d509c71b51a30432" ,
"f0587414fcc6c56aef11d4a1d287ad6b55b237c5b8a5d5d93eb9ca06f6466ccf" ,
"763009afb0ffd99c7b835488cb3b0302f3b78f59bbfd5292bedab8ef9da8c1b7" ,
"3867af9048309a05004a164bdea09899f23ff1d83b6491b2b53a1b7b92e0eb2e" ,
"688118e6b59e27944c277513db2711a520f4283c7c53a11f58d9f6a46d82c964" ,
]
. iter ( )
. map ( | pk | schnorrsig ::PublicKey ::from_str ( pk ) . unwrap ( ) )
. collect ( ) ;
let attestations = [
"5bc7663195971daaa1e3e6a81b4bca65882791644bc446fc060cbc118a3ace0f" ,
"721d0cb56a0778a1ca7907f81a0787f34385b13f854c845c4c5539f7f6267958" ,
"044aeef0d525c8ff48758c80939e95807bc640990cc03f53ab6fc0b262045221" ,
"79f5175423ec6ee69c8d0e55251db85f3015c2edfa5a03095443fbbf35eb2282" ,
"233b9ec549e9cc7c702109d29636db85a3ec63a66f3b53444bcc7586d36ca439" ,
"2961a00320b7c9a70220060019a6ca88e18c205fadd2f873c174e5ccbbed527e" ,
"bdb76e8f81c39ade4205ead9b68118757fc49ec22769605f26ef904b235283d6" ,
"6e75dafedf4ed685513ec1f5c93508de4fad2be05b46001ac00c03474f4690e1" ,
"cfcfc27eb9273b343b3042f0386e77efe329066be079788bb00ab47d72f26780" ,
"2d931ffd2963e74566365674583abc427bdb6ae571c4887d81f1920f0850665d" ,
"33b6f1112fa046cbc04be44c615e70519702662c1f72d8d49b3c4613614a8a46" ,
"19e569b15410fa9a758c1a6c211eae8c1547efbe0ac6a7709902be93415f2f09" ,
"d859dd5c9a58e1836d1eea3ebe7f48198a681d29e5a5cd6922532d2e94a53a1d" ,
"3387eb2ad5e64cd102167766bb72b447f4a2e5129d161e422f9d41cd7d1cc281" ,
"db35a9778a1e3abc8d8ab2f4a79346ae2154c9e0b4932d859d1f3e244f67ae76" ,
"c3be969e8b889cfb2ece71123e6be5538a2d3a1229637b18bccc179073c38059" ,
"6f73263f430e10b82d0fd06c4ddd3b8a6b58c3e756745bd0d9e71a399e517921" ,
"0818c9c245d7d2162cd393c562a121f80405a27d22ae465e95030c31ebb4bd24" ,
"b7c03f0bd6d63bd78ad4ea0f3452ff9717ba65ca42038e6e90a1aa558b7942dc" ,
"90c4d8ec9f408ccb62a62daa993c20f2f86799e1fdea520c6d060418e55fd216" ,
]
. iter ( )
. map ( | pk | SecretKey ::from_str ( pk ) . unwrap ( ) )
. collect ( ) ;
let id = id . to_string ( ) ;
let nonce_pks = nonce_pks
. iter ( )
. map ( | pk | schnorrsig ::PublicKey ::from_str ( pk ) . unwrap ( ) )
. collect ( ) ;
let attestations = attestations
. iter ( )
. map ( | pk | SecretKey ::from_str ( pk ) . unwrap ( ) )
. collect ( ) ;
Self {
pk ,
id ,
pk : oracle_pk ,
nonce_pks ,
attestations ,
price : 49262 ,
price ,
}
}
fn announcement ( & self ) -> Announcement {
Announcement {
id : self . id . clone ( ) ,
nonce_pks : self . nonce_pks . clone ( ) ,
}
}
const OLIVIA_PK : & 'static str =
"ddd4636845a90185991826be5a494cde9f4a6947b1727217afedc6292fa4caf7" ;
const EVENT_ID_0 : & 'static str = "/x/BitMEX/BXBT/2021-10-05T02:00:00.price[n:20]" ;
const NONCE_PKS_0 : [ & 'static str ; 20 ] = [
"d02d163cf9623f567c4e3faf851a9266ac1ede13da4ca4141f3a7717fba9a739" ,
"bc310f26aa5addbc382f653d8530aaead7c25e3546abc24639f490e36d4bdb88" ,
"2661375f570dcc32300d442e85b6d72dfa3232dccda45e8fb4a2d1e758d1d374" ,
"fcc68fbf071d391b14c0867cb4defb5a8abc12418dff3dfc2f84fd4025cb2716" ,
"cf5c2b7fe3851c64a7ff9635a9bfc50cdd301401d002f2da049f4c6a20e8457b" ,
"14f1005d8c2832a2c4666dd732dd9bb3af9c8f70ebcdaec96869b1ca0c8e0de6" ,
"299ee1c9c20fab8b067adf452a7d7661b5e7f5dd6bc707562805002e7cb8443e" ,
"bcb4e5a594346de298993a7a31762f598b5224b977e23182369e9ed3e5127f78" ,
"25e09a16ee5d469069abfb62cd5e1f20af50cf15241f571e64fa28b127304574" ,
"3ed5a1422f43299caf281123aba88bd4bc61ec863f4afb79c7ce7663ad44db5d" ,
"a7e0f61212735c192c4bf16e0a3e925e65f9f3feb6f1e5e8d6f5c18cf2dbb5a8" ,
"a36a631015d9036d0c321fea7cf12f589aa196e7279b4a290de5112c2940e540" ,
"b5bdd931f81970139e7301ac654b378077c3ed993ca7893ed93fee5fc6f7a782" ,
"00090816e256b41e042dce38bde99ab3cf9482f9b066836988d3ed54833638e8" ,
"3530408e93c251f5f488d3b1c608157177c459d6fab1966abebf765bcc9338d2" ,
"603269ce88d112ff7fcfcaab82f228be97deca37f8190084d509c71b51a30432" ,
"f0587414fcc6c56aef11d4a1d287ad6b55b237c5b8a5d5d93eb9ca06f6466ccf" ,
"763009afb0ffd99c7b835488cb3b0302f3b78f59bbfd5292bedab8ef9da8c1b7" ,
"3867af9048309a05004a164bdea09899f23ff1d83b6491b2b53a1b7b92e0eb2e" ,
"688118e6b59e27944c277513db2711a520f4283c7c53a11f58d9f6a46d82c964" ,
] ;
const PRICE_0 : u64 = 49262 ;
const ATTESTATIONS_0 : [ & 'static str ; 20 ] = [
"5bc7663195971daaa1e3e6a81b4bca65882791644bc446fc060cbc118a3ace0f" ,
"721d0cb56a0778a1ca7907f81a0787f34385b13f854c845c4c5539f7f6267958" ,
"044aeef0d525c8ff48758c80939e95807bc640990cc03f53ab6fc0b262045221" ,
"79f5175423ec6ee69c8d0e55251db85f3015c2edfa5a03095443fbbf35eb2282" ,
"233b9ec549e9cc7c702109d29636db85a3ec63a66f3b53444bcc7586d36ca439" ,
"2961a00320b7c9a70220060019a6ca88e18c205fadd2f873c174e5ccbbed527e" ,
"bdb76e8f81c39ade4205ead9b68118757fc49ec22769605f26ef904b235283d6" ,
"6e75dafedf4ed685513ec1f5c93508de4fad2be05b46001ac00c03474f4690e1" ,
"cfcfc27eb9273b343b3042f0386e77efe329066be079788bb00ab47d72f26780" ,
"2d931ffd2963e74566365674583abc427bdb6ae571c4887d81f1920f0850665d" ,
"33b6f1112fa046cbc04be44c615e70519702662c1f72d8d49b3c4613614a8a46" ,
"19e569b15410fa9a758c1a6c211eae8c1547efbe0ac6a7709902be93415f2f09" ,
"d859dd5c9a58e1836d1eea3ebe7f48198a681d29e5a5cd6922532d2e94a53a1d" ,
"3387eb2ad5e64cd102167766bb72b447f4a2e5129d161e422f9d41cd7d1cc281" ,
"db35a9778a1e3abc8d8ab2f4a79346ae2154c9e0b4932d859d1f3e244f67ae76" ,
"c3be969e8b889cfb2ece71123e6be5538a2d3a1229637b18bccc179073c38059" ,
"6f73263f430e10b82d0fd06c4ddd3b8a6b58c3e756745bd0d9e71a399e517921" ,
"0818c9c245d7d2162cd393c562a121f80405a27d22ae465e95030c31ebb4bd24" ,
"b7c03f0bd6d63bd78ad4ea0f3452ff9717ba65ca42038e6e90a1aa558b7942dc" ,
"90c4d8ec9f408ccb62a62daa993c20f2f86799e1fdea520c6d060418e55fd216" ,
] ;
const EVENT_ID_1 : & 'static str = "/x/BitMEX/BXBT/2021-10-05T08:00:00.price[n:20]" ;
const NONCE_PKS_1 : [ & 'static str ; 20 ] = [
"150df2e64f39706e726eaa1fe081af3edf376d9644723e135a99328fd194caca" ,
"b90629cedc7cb8430b4d15c84bbe1fe173e70e626d40c465e64de29d4879e20f" ,
"ae14ffb8701d3e224b6632a1bb7b099c8aa90979c3fb788422daa08bca25fa68" ,
"3717940a7e8c35b48b3596498ed93e4d54ba01a2bcbb645d30dae2fc98f087a8" ,
"91beb5da91cc8b4ee6ae603e7ae41cc041d5ea2c13bae9f0e630c69f6c0adfad" ,
"c51cafb450b01f30ec8bd2b4b5fed6f7e179f49945959f0d7609b4b9c5ab3781" ,
"75f2d9332aa1b2d84446a4b2aa276b4c2853659ab0ba74f0881289d3ab700f0c" ,
"5367de73acb53e69b0a4f777e564f87055fede5d4492ddafae876a815fa6166c" ,
"2087a513adb1aa2cc8506ca58306723ed13ba82e054f5bf29fcbeef1ab915c5a" ,
"71c980fb6adae9c121405628c91daffcc5ab52a8a0b6f53c953e8a0236b05782" ,
"d370d22f06751fc649f6ee930ac7f8f3b00389fdad02883a8038a81c46c33b19" ,
"fa6f7d37dc88b510c250dcae1023cce5009d5beb85a75f5b8b10c973b62348aa" ,
"a658077f9c963d1f41cf63b7ebf6e08331f5d201554b3af7814673108abe1bf3" ,
"8a816bf4caa2d6114b2e4d3ab9bff0d470ee0b90163c78c9b67f90238ead9319" ,
"c2519a4e764a65204c469062e260d8565f7730847c507b92c987e478ca91abe1" ,
"59cb6b5beac6511a671076530cc6cc9f1926f54c640828f38c363b110dd8a0cd" ,
"4625b1f3ab9ee01455fa1a98d15fc8d73a7cf41becb4ca5c6eab88db0ba7c114" ,
"82a4de403c604fe40aa3804c5ada6af54c425c0576980b50f259d32dc1a0fcff" ,
"5c4fb87b3812982759ed7264676e713e4e477a41759261515b04797db393ef62" ,
"f3f6b9134c0fdd670767fbf478fd0dd3430f195ce9c21cabb84f3c1dd4848a11" ,
] ;
const PRICE_1 : u64 = 49493 ;
const ATTESTATIONS_1 : [ & 'static str ; 20 ] = [
"605f458e9a7bd216ff522e45f6cd14378c03ccfd4d35a69b9b6ce5c4ebfc89fa" ,
"edc7215277d2c24a7a4659ff8831352db609fcc467fead5e27fdada172cdfd86" ,
"1c2d76fcbe724b1fabd2622b991e90bbb2ea9244489de960747134c9fd695dcb" ,
"26b4f078c9ca2233b18b0e42c4bb9867e5de8ee35b500e30b28d9b1742322e49" ,
"2b59aeaacb80056b45dc12d6525d5c75343ef75730623c8d9893e2b681bf4b85" ,
"782e38e777d527e7cb0028a6d03e8f760c6202dbc5ac605f67f995919dee6182" ,
"a902f37f71a78e4bcf431a778024bd775db6d7ade0626a9e7bc4cdf0b1e52dfd" ,
"3927eb5ef3b56817c08709e0af1bb643ad4d95dbf5a92a49e1e9c8c811e929c4" ,
"9ff44fa9d8377a3531792cd6362e4a5b24b86d85602749d301f8449859065b77" ,
"6a2156ff0aaef174b36d5f8adc597fdcb26f306f7ef6e9a485faabc8eb29da2e" ,
"53445b507c0de312959fe4566b82db93987dd0b854f1a33bbad7768512bcaf69" ,
"793c40e0ec3a830c46658bfaed7df74e3fc6781e421e00db5b5f46b26ce4d092" ,
"db7f800da2f22878c8fc8368047308146e1ebd6316c389303c07ebeed7488fc9" ,
"73921d09e0d567a03f3a411c0f3455f9f652bbede808a694cca0fa94619f5ba9" ,
"3d4bd70d93f20aa6b1621ccd077c90bcdee47ce2bae15155434a77a3153a3235" ,
"90fc10577ab737e311b43288a266490f222a6ecb9f9667e01d7a54c0437d145f" ,
"51d350616c6fdf90254240b757184fc0dd226328adb42be214ec25832854950e" ,
"bab3a6269e172ac590fd36683724f087b4add293bb0ee4ef3d21fb5929985c75" ,
"d65a4c71062fc0b0210bb3e239f60d826a37d28caadfc52edd7afde6e91ff818" ,
"ea5dfd972784808a15543f850c7bc86bff2b51cff81ec68fc4c3977d5e7d38de" ,
] ;
}
fn assert_contains_cets_for_event ( cets : & [ Cets ] , event : & Announcement ) {
assert ! ( ! cets
. iter ( )
. find ( | cet | cet . event . id = = event . id )
. expect ( "cet to correspond to existing event" )
. cets
. is_empty ( ) ) ;
}