Merge pull request #22 from jl777/jl777

Jl777
This commit is contained in:
blackjok3rtt
2019-02-23 11:40:34 +08:00
committed by GitHub
12 changed files with 619 additions and 289 deletions

View File

@@ -32,9 +32,9 @@ build:ubuntu:
variables: variables:
DOCKER_DRIVER: overlay2 DOCKER_DRIVER: overlay2
cache: cache:
key: "${CI_JOB_NAME}${CI_COMMIT_REF_NAME}" key: ${CI_COMMIT_REF_SLUG}
paths: paths:
- depends/built - depends/
script: script:
- zcutil/build.sh -j$(nproc) - zcutil/build.sh -j$(nproc)
- mkdir ${PACKAGE_DIR_LINUX} - mkdir ${PACKAGE_DIR_LINUX}

View File

@@ -72,12 +72,11 @@ CClib_methods[] =
{ (char *)"sudoku", (char *)"pending", (char *)"<no args>", 0, 0, 'U', EVAL_SUDOKU }, { (char *)"sudoku", (char *)"pending", (char *)"<no args>", 0, 0, 'U', EVAL_SUDOKU },
{ (char *)"sudoku", (char *)"solution", (char *)"txid solution timestamps[81]", 83, 83, 'S', EVAL_SUDOKU }, { (char *)"sudoku", (char *)"solution", (char *)"txid solution timestamps[81]", 83, 83, 'S', EVAL_SUDOKU },
{ (char *)"musig", (char *)"calcmsg", (char *)"sendtxid scriptPubKey", 2, 2, 'C', EVAL_MUSIG }, { (char *)"musig", (char *)"calcmsg", (char *)"sendtxid scriptPubKey", 2, 2, 'C', EVAL_MUSIG },
{ (char *)"musig", (char *)"combine", (char *)"pubkeys ...", 2, 256, 'P', EVAL_MUSIG }, { (char *)"musig", (char *)"combine", (char *)"pubkeys ...", 2, 999999999, 'P', EVAL_MUSIG },
{ (char *)"musig", (char *)"session", (char *)"msg pkhash", 2, 2, 'R', EVAL_MUSIG }, { (char *)"musig", (char *)"session", (char *)"myindex,numsigners,combined_pk,pkhash,msg32", 5, 5, 'R', EVAL_MUSIG },
{ (char *)"musig", (char *)"commit", (char *)"pubkeys ...", 2, 256, 'H', EVAL_MUSIG }, { (char *)"musig", (char *)"commit", (char *)"pkhash,ind,commitment", 3, 3, 'H', EVAL_MUSIG },
{ (char *)"musig", (char *)"nonce", (char *)"pubkeys ...", 2, 256, 'N', EVAL_MUSIG }, { (char *)"musig", (char *)"nonce", (char *)"pkhash,ind,nonce", 3, 3, 'N', EVAL_MUSIG },
{ (char *)"musig", (char *)"partialsign", (char *)"pubkeys ...", 2, 256, 'S', EVAL_MUSIG }, { (char *)"musig", (char *)"partialsig", (char *)"pkhash,ind,partialsig", 3, 3, 'S', EVAL_MUSIG },
{ (char *)"musig", (char *)"sigcombine", (char *)"pubkeys ...", 2, 256, 'M', EVAL_MUSIG },
{ (char *)"musig", (char *)"verify", (char *)"msg sig pubkey", 3, 3, 'V', EVAL_MUSIG }, { (char *)"musig", (char *)"verify", (char *)"msg sig pubkey", 3, 3, 'V', EVAL_MUSIG },
{ (char *)"musig", (char *)"send", (char *)"combined_pk amount", 2, 2, 'x', EVAL_MUSIG }, { (char *)"musig", (char *)"send", (char *)"combined_pk amount", 2, 2, 'x', EVAL_MUSIG },
{ (char *)"musig", (char *)"spend", (char *)"sendtxid sig destpubkey", 3, 3, 'y', EVAL_MUSIG }, { (char *)"musig", (char *)"spend", (char *)"sendtxid sig destpubkey", 3, 3, 'y', EVAL_MUSIG },
@@ -116,8 +115,7 @@ UniValue musig_combine(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
UniValue musig_session(uint64_t txfee,struct CCcontract_info *cp,cJSON *params); UniValue musig_session(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
UniValue musig_commit(uint64_t txfee,struct CCcontract_info *cp,cJSON *params); UniValue musig_commit(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
UniValue musig_nonce(uint64_t txfee,struct CCcontract_info *cp,cJSON *params); UniValue musig_nonce(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
UniValue musig_partialsign(uint64_t txfee,struct CCcontract_info *cp,cJSON *params); UniValue musig_partialsig(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
UniValue musig_sigcombine(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
UniValue musig_verify(uint64_t txfee,struct CCcontract_info *cp,cJSON *params); UniValue musig_verify(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
UniValue musig_send(uint64_t txfee,struct CCcontract_info *cp,cJSON *params); UniValue musig_send(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
UniValue musig_spend(uint64_t txfee,struct CCcontract_info *cp,cJSON *params); UniValue musig_spend(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
@@ -229,10 +227,8 @@ UniValue CClib_method(struct CCcontract_info *cp,char *method,char *jsonstr)
return(musig_commit(txfee,cp,params)); return(musig_commit(txfee,cp,params));
else if ( strcmp(method,"nonce") == 0 ) // returns combined nonce if ready else if ( strcmp(method,"nonce") == 0 ) // returns combined nonce if ready
return(musig_nonce(txfee,cp,params)); return(musig_nonce(txfee,cp,params));
else if ( strcmp(method,"partialsign") == 0 ) else if ( strcmp(method,"partialsig") == 0 )
return(musig_partialsign(txfee,cp,params)); return(musig_partialsig(txfee,cp,params));
else if ( strcmp(method,"sigcombine") == 0 )
return(musig_sigcombine(txfee,cp,params));
else if ( strcmp(method,"verify") == 0 ) else if ( strcmp(method,"verify") == 0 )
return(musig_verify(txfee,cp,params)); return(musig_verify(txfee,cp,params));
else if ( strcmp(method,"send") == 0 ) else if ( strcmp(method,"send") == 0 )
@@ -584,37 +580,7 @@ uint256 juint256(cJSON *obj)
#else #else
#include "sudoku.cpp" #include "sudoku.cpp"
/*
#include "../secp256k1/src/util.h"
#include "../secp256k1/src/num_impl.h"
#include "../secp256k1/src/field_impl.h"
#include "../secp256k1/src/scalar_impl.h"
#include "../secp256k1/src/group_impl.h"
#include "../secp256k1/src/scratch_impl.h"
#include "../secp256k1/src/ecmult_impl.h"
#include "../secp256k1/src/ecmult_const_impl.h"
#include "../secp256k1/src/ecmult_gen_impl.h"
#include "../secp256k1/src/ecdsa_impl.h"
#include "../secp256k1/src/eckey_impl.h"
#include "../secp256k1/src/hash_impl.h"
typedef int (secp256k1_ecmult_multi_callback)(secp256k1_scalar *sc, secp256k1_ge *pt, size_t idx, void *data);
extern "C" void secp256k1_pubkey_save(secp256k1_pubkey* pubkey, secp256k1_ge* ge);
extern "C" int secp256k1_nonce_function_bipschnorr(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *algo16, void *data, unsigned int counter);
extern "C" int secp256k1_pubkey_load(const secp256k1_context* ctx, secp256k1_ge* ge, const secp256k1_pubkey* pubkey);
extern "C" void secp256k1_scalar_chacha20(secp256k1_scalar *r1, secp256k1_scalar *r2, const unsigned char *seed, uint64_t idx);
#define ARG_CHECK(cond) do { \
if (EXPECT(!(cond), 0)) { \
secp256k1_callback_call(&ctx->illegal_callback, #cond); \
return 0; \
} \
} while(0)*/
//#include "../secp256k1/src/secp256k1.c"
#include "musig.cpp" #include "musig.cpp"
#include "../secp256k1/src/modules/musig/example.c"
#endif #endif

View File

@@ -124,9 +124,9 @@ bool FaucetValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx
//int height = it->first.blockHeight; //int height = it->first.blockHeight;
if ( CCduration(numblocks,it->first.txhash) > 0 && numblocks > 3 ) if ( CCduration(numblocks,it->first.txhash) > 0 && numblocks > 3 )
{ {
//fprintf(stderr,"would return error %s numblocks.%d ago\n",uint256_str(str,it->first.txhash),numblocks);
return eval->Invalid("faucet is only for brand new addresses"); return eval->Invalid("faucet is only for brand new addresses");
} }
//fprintf(stderr,"txid %s numblocks.%d ago\n",uint256_str(str,it->first.txhash),numblocks);
} }
retval = PreventCC(eval,tx,preventCCvins,numvins,preventCCvouts,numvouts); retval = PreventCC(eval,tx,preventCCvins,numvins,preventCCvouts,numvouts);
if ( retval != 0 ) if ( retval != 0 )

View File

@@ -3,10 +3,14 @@ cd rogue;
if [ "$HOST" = "x86_64-w64-mingw32" ]; then if [ "$HOST" = "x86_64-w64-mingw32" ]; then
echo building rogue.exe... echo building rogue.exe...
./configure --host=x86_64-w64-mingw32
mkdir ncurses && cd ncurses mkdir ncurses && cd ncurses
echo $PWD
wget https://invisible-island.net/datafiles/release/mingw32.zip wget https://invisible-island.net/datafiles/release/mingw32.zip
unzip mingw32.zip && delete mingw32.zip unzip mingw32.zip && rm mingw32.zip
echo lib archive cleaned
cd .. cd ..
echo $PWD
if make -f Makefile_win "$@"; then if make -f Makefile_win "$@"; then
echo rogue.exe build SUCCESSFUL echo rogue.exe build SUCCESSFUL
cd .. cd ..

View File

@@ -20,13 +20,14 @@
"combined_pk": "032ddac56613cd0667b589bd7f32b665e2d2ce0247e337a5a0bca6c72e3d9d057b", "combined_pk": "032ddac56613cd0667b589bd7f32b665e2d2ce0247e337a5a0bca6c72e3d9d057b",
"result": "success" "result": "success"
} }
the combined_pk and pkhash will be needed for various other rpc calls
*/ */
/* second, send 0.777 coins to the combined_pk /* second, send 0.777 coins to the combined_pk
./c cclib send 18 \"[%22032ddac56613cd0667b589bd7f32b665e2d2ce0247e337a5a0bca6c72e3d9d057b%22,0.777]\" ./c cclib send 18 \"[%22032ddac56613cd0667b589bd7f32b665e2d2ce0247e337a5a0bca6c72e3d9d057b%22,0.777]\"
{ {
"hex": "0400008085202f8901bf7afcbbab7a5e1ba20c8010325e199305afa7d15b4bc86a589a512201d39924000000004847304402203e0cff8aaa831dd990afd979bbc0a648316f77407cb5e02780d18e0670f5172a0220283d5c52d0406b10c508cc2b19dd6dbe2420e7c5cf431a1d41072d0eec28edb901ffffffff03b0c2a10400000000302ea22c8020c71ddb3aac7f9b9e4bdacf032aaa8b8e4433c4ff9f8a43cebb9c1f5da96928a48103120c008203000401cca91e223700000000232102aff51dad774a1c612dc82e63f85f07b992b665836b0f0efbcb26ee679f4f4848ac0000000000000000266a24127821032ddac56613cd0667b589bd7f32b665e2d2ce0247e337a5a0bca6c72e3d9d057b00000000900000000000000000000000000000", "hex": "0400008085202f8908018bbc4a0acf0f896680b84cc1000ec5530042fa3cf7471ab5c11cde56f6d0e60000000048473044022041a900fa57e54f939b797d09f0cee81ab9a79d978cd473ef3fc9f09c7678ad6b02206386bd15ee7ee8224a984fdd1d2a094738d082aec06028a5846d7bc61ddf16ca01ffffffff0b969f0e1ea787f0cc4e81d128353bd1cb670ab89bd1db4b47fbb7e872cd39fb00000000494830450221008c5de4b196e57b0dd94aa415950adf274e3e6859b82cf218729af84c1f15e76c022024aeab7eda63e6a652ef488bf26a8dc4ef8d2d4aa5746726085bfe5f169a5db701ffffffff0b36b70b43457fab377f28fb22da5a3e9d8186a37daae18cf0f710a221ab26250000000048473044022004ec20ae7490e7adabf9a3f78e4a58df84a3245485bfdd40f421cafe61d19c340220456d2b6f3c6e88632027c02606a0af1c21208d05f2de0826fbf4dfe7391ec83901ffffffff0aaff3cfe4ca22b97b6179a6f7cfac91945e5440e9438b89d1ec09500167176a0000000048473044022074dcad30c8ab9ed79a3ac69169611fc9e5f4b76a561b183461d968249316997f022063b25decaa285f494d277b9c8c2bcf6445b7929a304542e89c0645828d30a1a901ffffffff090e1bb92e9bf404a0d6455701b21af3dbf6765e61a1dc28b7c0f608ec4f12da000000004847304402202f9182c532c66138a6bdfcbb85a06cf1bf1532f2bf8f63170ef20843e4a81d0202207612a4353eb9606e84621c444ec7db1b683ff29c56127bda2d5e9c0eb13dbbc001ffffffff08a57005c7a40a923b1a510820b07f7318d760fe2a233b077d918cce357ad3af00000000484730440220643d60c68634fb2e0f6656389fc70c9f84c7086fc6e35b0fa26297e844f6c5fc02201d79669e073efe738d47de0130fdcba875e284e18fd478c0e6834d46632d8b8101ffffffff068cfd0ea6c0f5d401c67ec38f92425a9e59b0d5ade55bb2971ea955675a17bd00000000484730440220747139724248da4bcc1e5e3828e0ea811756e1fad0ebc40aeb006fd8079d46e402200d8f1c229c79494b5617e4373a3e083966dcd74571323f9d334be901d53871fa01ffffffff0200382fb6984b6128bb75115346242809c6555274e0cacef822825a2b4d231700000000484730440220454fcac398f6913fb4d8ed330f110f9cf62eec6c8cdb67d5df1effd2cf8222d5022017f6323630669777573e342e870c88727a917cc06c33611ebbd9d1fccc1dcd3701ffffffff03b0c2a10400000000302ea22c8020c71ddb3aac7f9b9e4bdacf032aaa8b8e4433c4ff9f8a43cebb9c1f5da96928a48103120c008203000401cc40ca220000000000232102aff51dad774a1c612dc82e63f85f07b992b665836b0f0efbcb26ee679f4f4848ac0000000000000000266a24127821032ddac56613cd0667b589bd7f32b665e2d2ce0247e337a5a0bca6c72e3d9d057b00000000460100000000000000000000000000",
"txid": "cb5309ed249da95e2b5696eb763a8736e2fff1d14922ada737b931494ca3d2be", "txid": "2c4159bb19212dcaa412ae37de7d72398f063194053e04a65b0facf767ebcc68",
"result": "success" "result": "success"
} }
@@ -45,17 +46,104 @@
} }
change script: 2102aff51dad774a1c612dc82e63f85f07b992b665836b0f0efbcb26ee679f4f4848ac change script: 2102aff51dad774a1c612dc82e63f85f07b992b665836b0f0efbcb26ee679f4f4848ac
sendtxid: cb5309ed249da95e2b5696eb763a8736e2fff1d14922ada737b931494ca3d2be sendtxid: 2c4159bb19212dcaa412ae37de7d72398f063194053e04a65b0facf767ebcc68
broadcast sendtxid and wait for it to be confirmed. then get the msg we need to sign: broadcast sendtxid and wait for it to be confirmed. then get the msg we need to sign:
./c cclib calcmsg 18 \"[%22cb5309ed249da95e2b5696eb763a8736e2fff1d14922ada737b931494ca3d2be%22,%222102aff51dad774a1c612dc82e63f85f07b992b665836b0f0efbcb26ee679f4f4848ac%22]\" ./c cclib calcmsg 18 \"[%222c4159bb19212dcaa412ae37de7d72398f063194053e04a65b0facf767ebcc68%22,%222102aff51dad774a1c612dc82e63f85f07b992b665836b0f0efbcb26ee679f4f4848ac%22]\"
{ {
"result": "success", "result": "success",
"msg": "63b799913d4c9487f321b32d6ae8614f653f38e0b50d4df4bc1d36339ea18485" "msg": "caa64ba398ddfe5c33d8c70a61e556caa0e69b19d93110c5a458a1b37ad44cb0"
}
the "msg" is what needs to be signed to create a valid spend
now on each signing node, a session needs to be created:
5 args: ind, numsigners, combined_pk, pkhash, message to be signed
on node with pubkey: 02aff51dad774a1c612dc82e63f85f07b992b665836b0f0efbcb26ee679f4f4848
./c cclib session 18 \"[0,2,%22032ddac56613cd0667b589bd7f32b665e2d2ce0247e337a5a0bca6c72e3d9d057b%22,%225be117f3c5ce87e7dc6882c24b8231e0652ee82054bf7b9f94aef1f45e055cba%22,%22caa64ba398ddfe5c33d8c70a61e556caa0e69b19d93110c5a458a1b37ad44cb0%22]\"
{
"myind": 0,
"numsigners": 2,
"commitment": "e82228c10d0e100477630349150dea744d3b2790dcd347511a1a98199840cda4",
"result": "success"
}
on node with pubkey: 039433dc3749aece1bd568f374a45da3b0bc6856990d7da3cd175399577940a775
./c cclib session 18 \"[1,2,%22032ddac56613cd0667b589bd7f32b665e2d2ce0247e337a5a0bca6c72e3d9d057b%22,%225be117f3c5ce87e7dc6882c24b8231e0652ee82054bf7b9f94aef1f45e055cba%22,%22caa64ba398ddfe5c33d8c70a61e556caa0e69b19d93110c5a458a1b37ad44cb0%22]\"
{
"myind": 1,
"numsigners": 2,
"commitment": "6e426e850ddc45e7742cfb6321781c00ee69a995ab12fa1f9ded7fe43658babf",
"result": "success"
}
now we need to get the commitment from each node to the other one. the session already put the commitment for each node into the global struct. Keep in mind there is a single global struct with session unique to each cclib session call. that means no restarting any deamon in the middle of the process on any of the nodes and only call cclib session a single time. this is an artificial restriction just to simplify the initial implementation of musig
./c cclib commit 18 \"[%225be117f3c5ce87e7dc6882c24b8231e0652ee82054bf7b9f94aef1f45e055cba%22,1,%226e426e850ddc45e7742cfb6321781c00ee69a995ab12fa1f9ded7fe43658babf%22]\"
{
"added_index": 1,
"myind": 0,
"nonce": "0261671b0a6de416938cf035c98f8af37c6ca88bbbd1bcce693d709d4919b010e1",
"result": "success"
}
./c cclib commit 18 \"[%225be117f3c5ce87e7dc6882c24b8231e0652ee82054bf7b9f94aef1f45e055cba%22,0,%22e82228c10d0e100477630349150dea744d3b2790dcd347511a1a98199840cda4%22]\"
{
"added_index": 0,
"myind": 1,
"nonce": "02570f62a625ceb19a754a053152b162810c3e403df63f3d443e85bdacc74bfdfe",
"result": "success"
}
Now exchange the revealed nonces to each node:
./c cclib nonce 18 \"[%225be117f3c5ce87e7dc6882c24b8231e0652ee82054bf7b9f94aef1f45e055cba%22,1,%2202570f62a625ceb19a754a053152b162810c3e403df63f3d443e85bdacc74bfdfe%22]\"
{
"added_index": 1,
"myind": 0,
"partialsig": "3f21885e6d2d020e1473435ccd148a61cdcb1d1105867fed45913185dc0acf59",
"result": "success"
}
./c cclib nonce 18 \"[%225be117f3c5ce87e7dc6882c24b8231e0652ee82054bf7b9f94aef1f45e055cba%22,0,%220261671b0a6de416938cf035c98f8af37c6ca88bbbd1bcce693d709d4919b010e1%22]\"
{
"added_index": 0,
"myind": 0,
"myind": 1,
"partialsig": "af7f28455fb2e988d81068cd9d800879cd334036a8300118dc307b777a38c1ed",
"result": "success"
}
Almost there! final step is to exchange the partial sigs between signers
./c cclib partialsig 18 \"[%225be117f3c5ce87e7dc6882c24b8231e0652ee82054bf7b9f94aef1f45e055cba%22,1,%22af7f28455fb2e988d81068cd9d800879cd334036a8300118dc307b777a38c1ed%22]\"
{
"added_index": 1,
"result": "success",
"combinedsig": "5e64dc5dda93b2d3f25fe44b2aaca69b8f15d21f70e2bc1c2c53e17262d941bbeea0b0a3ccdfeb96ec83ac2a6a9492db9afe5d47adb6810621c1acfd56439146"
} }
./c cclib partialsig 18 \"[%225be117f3c5ce87e7dc6882c24b8231e0652ee82054bf7b9f94aef1f45e055cba%22,0,%223f21885e6d2d020e1473435ccd148a61cdcb1d1105867fed45913185dc0acf59%22]\"
{
"added_index": 0,
"result": "success",
"combinedsig": "5e64dc5dda93b2d3f25fe44b2aaca69b8f15d21f70e2bc1c2c53e17262d941bbeea0b0a3ccdfeb96ec83ac2a6a9492db9afe5d47adb6810621c1acfd56439146"
}
Notice both nodes generated the same combined signature!
Now for a sanity test, we can use the verify call to make sure this sig will work with the msg needed for the spend:
./c cclib verify 18 \"[%22caa64ba398ddfe5c33d8c70a61e556caa0e69b19d93110c5a458a1b37ad44cb0%22,%22032ddac56613cd0667b589bd7f32b665e2d2ce0247e337a5a0bca6c72e3d9d057b%22,%225e64dc5dda93b2d3f25fe44b2aaca69b8f15d21f70e2bc1c2c53e17262d941bbeea0b0a3ccdfeb96ec83ac2a6a9492db9afe5d47adb6810621c1acfd56439146%22]\"
and finally the spend: sendtxid, scriptPubKey, musig
./c cclib spend 18 \"[%222c4159bb19212dcaa412ae37de7d72398f063194053e04a65b0facf767ebcc68%22,%222102aff51dad774a1c612dc82e63f85f07b992b665836b0f0efbcb26ee679f4f4848ac%22,%225e64dc5dda93b2d3f25fe44b2aaca69b8f15d21f70e2bc1c2c53e17262d941bbeea0b0a3ccdfeb96ec83ac2a6a9492db9afe5d47adb6810621c1acfd56439146%22]\"
*/ */
@@ -74,20 +162,79 @@ struct secp256k1_context_struct {
secp256k1_callback error_callback; secp256k1_callback error_callback;
}; };
extern "C" int secp256k1_ecmult_multi_var(const secp256k1_ecmult_context *ctx, secp256k1_scratch *scratch, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n);
extern "C" int secp256k1_schnorrsig_verify(const secp256k1_context* ctx, const secp256k1_schnorrsig *sig, const unsigned char *msg32, const secp256k1_pubkey *pk);
extern "C" int secp256k1_schnorrsig_parse(const secp256k1_context* ctx, secp256k1_schnorrsig* sig, const unsigned char *in64);
extern "C" int secp256k1_musig_pubkey_combine(const secp256k1_context* ctx, secp256k1_scratch_space *scratch, secp256k1_pubkey *combined_pk, unsigned char *pk_hash32, const secp256k1_pubkey *pubkeys, size_t n_pubkeys);
//#include "../secp256k1/include/secp256k1.h" //#include "../secp256k1/include/secp256k1.h"
//#include "../secp256k1/include/secp256k1_schnorrsig.h" //#include "../secp256k1/include/secp256k1_schnorrsig.h"
#include "../secp256k1/include/secp256k1_musig.h" #include "../secp256k1/include/secp256k1_musig.h"
extern "C" int secp256k1_ecmult_multi_var(const secp256k1_ecmult_context *ctx, secp256k1_scratch *scratch, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n);
extern "C" int secp256k1_schnorrsig_verify(const secp256k1_context* ctx, const secp256k1_schnorrsig *sig, const unsigned char *msg32, const secp256k1_pubkey *pk);
extern "C" int secp256k1_schnorrsig_parse(const secp256k1_context* ctx, secp256k1_schnorrsig* sig, const unsigned char *in64);
extern "C" int secp256k1_musig_pubkey_combine(const secp256k1_context* ctx, secp256k1_scratch_space *scratch, secp256k1_pubkey *combined_pk, unsigned char *pk_hash32, const secp256k1_pubkey *pubkeys, size_t n_pubkeys);
extern "C" int secp256k1_musig_session_initialize(const secp256k1_context* ctx, secp256k1_musig_session *session, secp256k1_musig_session_signer_data *signers, unsigned char *nonce_commitment32, const unsigned char *session_id32, const unsigned char *msg32, const secp256k1_pubkey *combined_pk, const unsigned char *pk_hash32, size_t n_signers, size_t my_index, const unsigned char *seckey);
extern "C" int secp256k1_schnorrsig_serialize(const secp256k1_context* ctx, unsigned char *out64, const secp256k1_schnorrsig* sig);
#define MUSIG_PREVN 0 // for now, just use vout0 for the musig output #define MUSIG_PREVN 0 // for now, just use vout0 for the musig output
#define MUSIG_TXFEE 10000 #define MUSIG_TXFEE 10000
struct musig_info
{
secp256k1_musig_session session;
secp256k1_pubkey combined_pk;
uint8_t *nonce_commitments,**commitment_ptrs; // 32*N_SIGNERS
secp256k1_musig_session_signer_data *signer_data; //[N_SIGNERS];
secp256k1_pubkey *nonces; //[N_SIGNERS];
secp256k1_musig_partial_signature *partial_sig; //[N_SIGNERS];
int32_t myind,num;
uint8_t msg[32],pkhash[32],combpk[33];
} *MUSIG;
struct musig_info *musig_infocreate(int32_t myind,int32_t num)
{
int32_t i; struct musig_info *mp = (struct musig_info *)calloc(1,sizeof(*mp));
mp->myind = myind, mp->num = num;
mp->nonce_commitments = (uint8_t *)calloc(num,32);
mp->commitment_ptrs = (uint8_t **)calloc(num,sizeof(*mp->commitment_ptrs));
for (i=0; i<num; i++)
mp->commitment_ptrs[i] = &mp->nonce_commitments[i*32];
mp->signer_data = (secp256k1_musig_session_signer_data *)calloc(num,sizeof(*mp->signer_data));
mp->nonces = (secp256k1_pubkey *)calloc(num,sizeof(*mp->nonces));
mp->partial_sig = (secp256k1_musig_partial_signature *)calloc(num,sizeof(*mp->partial_sig));
return(mp);
}
void musig_infofree(struct musig_info *mp)
{
if ( mp->partial_sig != 0 )
{
GetRandBytes((uint8_t *)mp->partial_sig,mp->num*sizeof(*mp->partial_sig));
free(mp->partial_sig);
}
if ( mp->nonces != 0 )
{
GetRandBytes((uint8_t *)mp->nonces,mp->num*sizeof(*mp->nonces));
free(mp->nonces);
}
if ( mp->signer_data != 0 )
{
GetRandBytes((uint8_t *)mp->signer_data,mp->num*sizeof(*mp->signer_data));
free(mp->signer_data);
}
if ( mp->nonce_commitments != 0 )
{
GetRandBytes((uint8_t *)mp->nonce_commitments,mp->num*32);
free(mp->nonce_commitments);
}
if ( mp->commitment_ptrs != 0 )
{
GetRandBytes((uint8_t *)mp->commitment_ptrs,mp->num*sizeof(*mp->commitment_ptrs));
free(mp->commitment_ptrs);
}
GetRandBytes((uint8_t *)mp,sizeof(*mp));
free(mp);
}
CScript musig_sendopret(uint8_t funcid,CPubKey pk) CScript musig_sendopret(uint8_t funcid,CPubKey pk)
{ {
CScript opret; uint8_t evalcode = EVAL_MUSIG; CScript opret; uint8_t evalcode = EVAL_MUSIG;
@@ -173,6 +320,27 @@ UniValue musig_calcmsg(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
} else return(cclib_error(result,"couldnt parse params")); } else return(cclib_error(result,"couldnt parse params"));
} }
int32_t musig_parsepubkey(secp256k1_context *ctx,secp256k1_pubkey &spk,cJSON *item)
{
char *hexstr;
if ( (hexstr= jstr(item,0)) != 0 && is_hexstr(hexstr,0) == 66 )
{
CPubKey pk(ParseHex(hexstr));
if ( secp256k1_ec_pubkey_parse(ctx,&spk,pk.begin(),33) > 0 )
return(1);
} else return(-1);
}
int32_t musig_parsehash(uint8_t *hash32,cJSON *item,int32_t len)
{
char *hexstr;
if ( (hexstr= jstr(item,0)) != 0 && is_hexstr(hexstr,0) == len*2 )
{
decode_hex(hash32,len,hexstr);
return(0);
} else return(-1);
}
UniValue musig_combine(uint64_t txfee,struct CCcontract_info *cp,cJSON *params) UniValue musig_combine(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
{ {
static secp256k1_context *ctx; static secp256k1_context *ctx;
@@ -185,13 +353,9 @@ UniValue musig_combine(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
//fprintf(stderr,"n.%d args.(%s)\n",n,jprint(params,0)); //fprintf(stderr,"n.%d args.(%s)\n",n,jprint(params,0));
for (i=0; i<n; i++) for (i=0; i<n; i++)
{ {
if ( (hexstr= jstr(jitem(params,i),0)) != 0 && is_hexstr(hexstr,0) == 66 ) if ( musig_parsepubkey(ctx,spk,jitem(params,i)) < 0 )
{ return(cclib_error(result,"error parsing pk"));
CPubKey pk(ParseHex(hexstr)); pubkeys.push_back(spk);
if ( secp256k1_ec_pubkey_parse(ctx,&spk,pk.begin(),33) > 0 )
pubkeys.push_back(spk);
else return(cclib_error(result,"error parsing pk"));
} else return(cclib_error(result,"all pubkeys must be 33 bytes hexdata"));
} }
if ( secp256k1_musig_pubkey_combine(ctx,NULL,&combined_pk,pkhash,&pubkeys[0],n) > 0 ) if ( secp256k1_musig_pubkey_combine(ctx,NULL,&combined_pk,pkhash,&pubkeys[0],n) > 0 )
{ {
@@ -215,191 +379,278 @@ UniValue musig_combine(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
UniValue musig_session(uint64_t txfee,struct CCcontract_info *cp,cJSON *params) UniValue musig_session(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
{ {
UniValue result(UniValue::VOBJ); static secp256k1_context *ctx;
result.push_back(Pair("result","success")); UniValue result(UniValue::VOBJ); int32_t i,n,myind,num; char *pkstr,*pkhashstr,*msgstr; uint8_t session[32],msg[32],pkhash[32],privkey[32],pub33[33]; CPubKey pk; char str[67];
/** Initializes a signing session for a signer if ( ctx == 0 )
* ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
* Returns: 1: session is successfully initialized if ( params != 0 && (n= cJSON_GetArraySize(params)) == 5 )
* 0: session could not be initialized: secret key or secret nonce overflow {
* Args: ctx: pointer to a context object, initialized for signing (cannot myind = juint(jitem(params,0),0);
* be NULL) num = juint(jitem(params,1),0);
* Out: session: the session structure to initialize (cannot be NULL) if ( myind < 0 || myind >= num || num <= 0 )
* signers: an array of signers' data to be initialized. Array length must return(cclib_error(result,"illegal myindex and numsigners"));
* equal to `n_signers` (cannot be NULL) if ( MUSIG != 0 )
* nonce_commitment32: filled with a 32-byte commitment to the generated nonce musig_infofree(MUSIG), MUSIG = 0;
* (cannot be NULL) MUSIG = musig_infocreate(myind,num);
* In: session_id32: a *unique* 32-byte ID to assign to this session (cannot be if ( musig_parsepubkey(ctx,MUSIG->combined_pk,jitem(params,2)) < 0 )
* NULL). If a non-unique session_id32 was given then a partial return(cclib_error(result,"error parsing combined_pubkey"));
* signature will LEAK THE SECRET KEY. else if ( musig_parsehash(MUSIG->pkhash,jitem(params,3),32) < 0 )
* msg32: the 32-byte message to be signed. Shouldn't be NULL unless you return(cclib_error(result,"error parsing pkhash"));
* require sharing public nonces before the message is known else if ( musig_parsehash(MUSIG->msg,jitem(params,4),32) < 0 )
* because it reduces nonce misuse resistance. If NULL, must be return(cclib_error(result,"error parsing msg"));
* set with `musig_session_set_msg` before signing and verifying. Myprivkey(privkey);
* combined_pk: the combined public key of all signers (cannot be NULL) GetRandBytes(session,32);
* pk_hash32: the 32-byte hash of the signers' individual keys (cannot be /** Initializes a signing session for a signer
* NULL) *
* n_signers: length of signers array. Number of signers participating in * Returns: 1: session is successfully initialized
* the MuSig. Must be greater than 0 and at most 2^32 - 1. * 0: session could not be initialized: secret key or secret nonce overflow
* my_index: index of this signer in the signers array * Args: ctx: pointer to a context object, initialized for signing (cannot
* seckey: the signer's 32-byte secret key (cannot be NULL) * be NULL)
*/ * Out: session: the session structure to initialize (cannot be NULL)
//if (!secp256k1_musig_session_initialize(ctx, &musig_session[i], signer_data[i], nonce_commitment[i], session_id32, msg32, &combined_pk, pk_hash, N_SIGNERS, i, seckeys[i])) * signers: an array of signers' data to be initialized. Array length must
//return 0; * equal to `n_signers` (cannot be NULL)
// randombytes_buf(buf, num); * nonce_commitment32: filled with a 32-byte commitment to the generated nonce
* (cannot be NULL)
//nonce_commitment_ptr[i] = &nonce_commitment[i][0]; * In: session_id32: a *unique* 32-byte ID to assign to this session (cannot be
return(result); * NULL). If a non-unique session_id32 was given then a partial
* signature will LEAK THE SECRET KEY.
* msg32: the 32-byte message to be signed. Shouldn't be NULL unless you
* require sharing public nonces before the message is known
* because it reduces nonce misuse resistance. If NULL, must be
* set with `musig_session_set_msg` before signing and verifying.
* combined_pk: the combined public key of all signers (cannot be NULL)
* pk_hash32: the 32-byte hash of the signers' individual keys (cannot be
* NULL)
* n_signers: length of signers array. Number of signers participating in
* the MuSig. Must be greater than 0 and at most 2^32 - 1.
* my_index: index of this signer in the signers array
* seckey: the signer's 32-byte secret key (cannot be NULL)
*/
if ( secp256k1_musig_session_initialize(ctx,&MUSIG->session,MUSIG->signer_data, &MUSIG->nonce_commitments[MUSIG->myind * 32],session,MUSIG->msg,&MUSIG->combined_pk,MUSIG->pkhash,MUSIG->num,MUSIG->myind,privkey) > 0 )
{
memset(session,0,sizeof(session));
result.push_back(Pair("myind",(int64_t)myind));
result.push_back(Pair("numsigners",(int64_t)num));
for (i=0; i<32; i++)
sprintf(&str[i<<1],"%02x",MUSIG->nonce_commitments[MUSIG->myind*32 + i]);
str[64] = 0;
result.push_back(Pair("commitment",str));
result.push_back(Pair("result","success"));
return(result);
}
else
{
memset(session,0,sizeof(session));
return(cclib_error(result,"couldnt initialize session"));
}
} else return(cclib_error(result,"wrong number of params, need 5: myindex, numsigners, combined_pk, pkhash, msg32"));
} }
UniValue musig_commit(uint64_t txfee,struct CCcontract_info *cp,cJSON *params) UniValue musig_commit(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
{ {
UniValue result(UniValue::VOBJ); static secp256k1_context *ctx;
result.push_back(Pair("result","success")); size_t clen = CPubKey::PUBLIC_KEY_SIZE;
/** Gets the signer's public nonce given a list of all signers' data with commitments UniValue result(UniValue::VOBJ); int32_t i,n,ind; uint8_t pkhash[32]; CPubKey pk; char str[67];
* if ( ctx == 0 )
* Returns: 1: public nonce is written in nonce ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
* 0: signer data is missing commitments or session isn't initialized if ( params != 0 && (n= cJSON_GetArraySize(params)) == 3 )
* for signing {
* Args: ctx: pointer to a context object (cannot be NULL) if ( musig_parsehash(pkhash,jitem(params,0),32) < 0 )
* session: the signing session to get the nonce from (cannot be NULL) return(cclib_error(result,"error parsing pkhash"));
* signers: an array of signers' data initialized with else if ( memcmp(MUSIG->pkhash,pkhash,32) != 0 )
* `musig_session_initialize`. Array length must equal to return(cclib_error(result,"pkhash doesnt match session pkhash"));
* `n_commitments` (cannot be NULL) else if ( (ind= juint(jitem(params,1),0)) < 0 || ind >= MUSIG->num )
* Out: nonce: the nonce (cannot be NULL) return(cclib_error(result,"illegal ind for session"));
* In: commitments: array of 32-byte nonce commitments (cannot be NULL) else if ( musig_parsehash(&MUSIG->nonce_commitments[ind*32],jitem(params,2),32) < 0 )
* n_commitments: the length of commitments and signers array. Must be the total return(cclib_error(result,"error parsing commitment"));
* number of signers participating in the MuSig. /** Gets the signer's public nonce given a list of all signers' data with commitments
*/ *
// Set nonce commitments in the signer data and get the own public nonce * Returns: 1: public nonce is written in nonce
//if (!secp256k1_musig_session_get_public_nonce(ctx, &musig_session[i], signer_data[i], &nonce[i], nonce_commitment_ptr, N_SIGNERS)) * 0: signer data is missing commitments or session isn't initialized
// return 0; * for signing
* Args: ctx: pointer to a context object (cannot be NULL)
return(result); * session: the signing session to get the nonce from (cannot be NULL)
* signers: an array of signers' data initialized with
* `musig_session_initialize`. Array length must equal to
* `n_commitments` (cannot be NULL)
* Out: nonce: the nonce (cannot be NULL)
* In: commitments: array of 32-byte nonce commitments (cannot be NULL)
* n_commitments: the length of commitments and signers array. Must be the total
* number of signers participating in the MuSig.
*/
result.push_back(Pair("added_index",ind));
if ( secp256k1_musig_session_get_public_nonce(ctx,&MUSIG->session,MUSIG->signer_data,&MUSIG->nonces[MUSIG->myind],MUSIG->commitment_ptrs,MUSIG->num) > 0 )
{
if ( secp256k1_ec_pubkey_serialize(ctx,(uint8_t *)pk.begin(),&clen,&MUSIG->nonces[MUSIG->myind],SECP256K1_EC_COMPRESSED) > 0 && clen == 33 )
{
for (i=0; i<33; i++)
sprintf(&str[i<<1],"%02x",((uint8_t *)pk.begin())[i]);
str[66] = 0;
result.push_back(Pair("myind",MUSIG->myind));
result.push_back(Pair("nonce",str));
result.push_back(Pair("result","success"));
} else return(cclib_error(result,"error serializing nonce (pubkey)"));
}
else
{
result.push_back(Pair("status","not enough commitments"));
result.push_back(Pair("result","success"));
}
return(result);
} else return(cclib_error(result,"wrong number of params, need 3: pkhash, ind, commitment"));
} }
UniValue musig_nonce(uint64_t txfee,struct CCcontract_info *cp,cJSON *params) UniValue musig_nonce(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
{ {
UniValue result(UniValue::VOBJ); static secp256k1_context *ctx;
result.push_back(Pair("result","success")); UniValue result(UniValue::VOBJ); int32_t i,n,ind; uint8_t pkhash[32],psig[32]; CPubKey pk; char str[67];
/** Checks a signer's public nonce against a commitment to said nonce, and update if ( ctx == 0 )
* data structure if they match ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
* if ( params != 0 && (n= cJSON_GetArraySize(params)) == 3 )
* Returns: 1: commitment was valid, data structure updated {
* 0: commitment was invalid, nothing happened if ( musig_parsehash(pkhash,jitem(params,0),32) < 0 )
* Args: ctx: pointer to a context object (cannot be NULL) return(cclib_error(result,"error parsing pkhash"));
* signer: pointer to the signer data to update (cannot be NULL). Must have else if ( memcmp(MUSIG->pkhash,pkhash,32) != 0 )
* been used with `musig_session_get_public_nonce` or initialized return(cclib_error(result,"pkhash doesnt match session pkhash"));
* with `musig_session_initialize_verifier`. else if ( (ind= juint(jitem(params,1),0)) < 0 || ind >= MUSIG->num )
* In: nonce: signer's alleged public nonce (cannot be NULL) return(cclib_error(result,"illegal ind for session"));
*/ else if ( musig_parsepubkey(ctx,MUSIG->nonces[ind],jitem(params,2)) < 0 )
//if (!secp256k1_musig_set_nonce(ctx, &signer_data[i][j], &nonce[j])) { return(cclib_error(result,"error parsing nonce"));
result.push_back(Pair("added_index",ind));
/** Checks a signer's public nonce against a commitment to said nonce, and update
/** Updates a session with the combined public nonce of all signers. The combined * data structure if they match
* public nonce is the sum of every signer's public nonce. *
* * Returns: 1: commitment was valid, data structure updated
* Returns: 1: nonces are successfully combined * 0: commitment was invalid, nothing happened
* 0: a signer's nonce is missing * Args: ctx: pointer to a context object (cannot be NULL)
* Args: ctx: pointer to a context object (cannot be NULL) * signer: pointer to the signer data to update (cannot be NULL). Must have
* session: session to update with the combined public nonce (cannot be * been used with `musig_session_get_public_nonce` or initialized
* NULL) * with `musig_session_initialize_verifier`.
* signers: an array of signers' data, which must have had public nonces * In: nonce: signer's alleged public nonce (cannot be NULL)
* set with `musig_set_nonce`. Array length must equal to `n_signers` */
* (cannot be NULL) for (i=0; i<MUSIG->num; i++)
* n_signers: the length of the signers array. Must be the total number of {
* signers participating in the MuSig. if ( secp256k1_musig_set_nonce(ctx,&MUSIG->signer_data[i],&MUSIG->nonces[i]) == 0 )
* Out: nonce_is_negated: a pointer to an integer that indicates if the combined return(cclib_error(result,"error setting nonce"));
* public nonce had to be negated. }
* adaptor: point to add to the combined public nonce. If NULL, nothing is /** Updates a session with the combined public nonce of all signers. The combined
* added to the combined nonce. * public nonce is the sum of every signer's public nonce.
*/ *
// after all nonces: if (!secp256k1_musig_session_combine_nonces(ctx, &musig_session[i], signer_data[i], N_SIGNERS, NULL, NULL)) { * Returns: 1: nonces are successfully combined
* 0: a signer's nonce is missing
* Args: ctx: pointer to a context object (cannot be NULL)
* session: session to update with the combined public nonce (cannot be
* NULL)
* signers: an array of signers' data, which must have had public nonces
* set with `musig_set_nonce`. Array length must equal to `n_signers`
* (cannot be NULL)
* n_signers: the length of the signers array. Must be the total number of
* signers participating in the MuSig.
* Out: nonce_is_negated: a pointer to an integer that indicates if the combined
* public nonce had to be negated.
* adaptor: point to add to the combined public nonce. If NULL, nothing is
* added to the combined nonce.
*/
if ( secp256k1_musig_session_combine_nonces(ctx,&MUSIG->session,MUSIG->signer_data,MUSIG->num,NULL,NULL) > 0 )
{
if ( secp256k1_musig_partial_sign(ctx,&MUSIG->session,&MUSIG->partial_sig[MUSIG->myind]) > 0 )
{
if ( secp256k1_musig_partial_signature_serialize(ctx,psig,&MUSIG->partial_sig[MUSIG->myind]) > 0 )
{
for (i=0; i<32; i++)
sprintf(&str[i<<1],"%02x",psig[i]);
str[64] = 0;
result.push_back(Pair("myind",MUSIG->myind));
result.push_back(Pair("partialsig",str));
result.push_back(Pair("result","success"));
return(result);
} else return(cclib_error(result,"error serializing partial sig"));
} else return(cclib_error(result,"error making partial sig"));
} else return(cclib_error(result,"error combining nonces"));
} else return(cclib_error(result,"wrong number of params, need 3: pkhash, ind, nonce"));
}
UniValue musig_partialsig(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
{
static secp256k1_context *ctx;
UniValue result(UniValue::VOBJ); int32_t i,ind,n; uint8_t pkhash[32],psig[32],out64[64]; char str[129]; secp256k1_schnorrsig sig;
if ( ctx == 0 )
ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
if ( params != 0 && (n= cJSON_GetArraySize(params)) == 3 )
{
if ( musig_parsehash(pkhash,jitem(params,0),32) < 0 )
return(cclib_error(result,"error parsing pkhash"));
else if ( memcmp(MUSIG->pkhash,pkhash,32) != 0 )
return(cclib_error(result,"pkhash doesnt match session pkhash"));
else if ( (ind= juint(jitem(params,1),0)) < 0 || ind >= MUSIG->num )
return(cclib_error(result,"illegal ind for session"));
else if ( musig_parsehash(psig,jitem(params,2),32) < 0 )
return(cclib_error(result,"error parsing psig"));
else if ( secp256k1_musig_partial_signature_parse(ctx,&MUSIG->partial_sig[ind],psig) == 0 )
return(cclib_error(result,"error parsing partialsig"));
result.push_back(Pair("added_index",ind));
if ( secp256k1_musig_partial_sig_combine(ctx,&MUSIG->session,&sig,MUSIG->partial_sig,MUSIG->num) > 0 )
{
if ( secp256k1_schnorrsig_serialize(ctx,out64,&sig) > 0 )
{
result.push_back(Pair("result","success"));
for (i=0; i<64; i++)
sprintf(&str[i<<1],"%02x",out64[i]);
str[128] = 0;
result.push_back(Pair("combinedsig",str));
} else return(cclib_error(result,"error serializing combinedsig"));
}
else
{
if ( secp256k1_musig_partial_signature_serialize(ctx,psig,&MUSIG->partial_sig[MUSIG->myind]) > 0 )
{
result.push_back(Pair("myind",ind));
for (i=0; i<32; i++)
sprintf(&str[i<<1],"%02x",psig[i]);
str[64] = 0;
result.push_back(Pair("partialsig",str));
result.push_back(Pair("result","success"));
result.push_back(Pair("status","need more partialsigs"));
} else return(cclib_error(result,"error generating my partialsig"));
}
return(result); return(result);
} else return(cclib_error(result,"wrong number of params, need 3: pkhash, ind, partialsig"));
} }
UniValue musig_partialsign(uint64_t txfee,struct CCcontract_info *cp,cJSON *params) int testmain(void);
{
UniValue result(UniValue::VOBJ);
result.push_back(Pair("result","success"));
/** Produces a partial signature
*
* Returns: 1: partial signature constructed
* 0: session in incorrect or inconsistent state
* Args: ctx: pointer to a context object (cannot be NULL)
* session: active signing session for which the combined nonce has been
* computed (cannot be NULL)
* Out: partial_sig: partial signature (cannot be NULL)
*/
//if (!secp256k1_musig_partial_sign(ctx, &musig_session[i], &partial_sig[i])) {
/** Parse and verify a MuSig partial signature.
*
* Returns: 1 when the signature could be parsed, 0 otherwise.
* Args: ctx: a secp256k1 context object
* Out: sig: pointer to a signature object
* In: in32: pointer to the 32-byte signature to be parsed
*
* After the call, sig will always be initialized. If parsing failed or the
* encoded numbers are out of range, signature verification with it is
* guaranteed to fail for every message and public key.
*/
//SECP256K1_API int secp256k1_musig_partial_signature_parse(
return(result);
}
UniValue musig_sigcombine(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
{
UniValue result(UniValue::VOBJ);
result.push_back(Pair("result","success"));
/** Checks that an individual partial signature verifies
*
* This function is essential when using protocols with adaptor signatures.
* However, it is not essential for regular MuSig's, in the sense that if any
* partial signatures does not verify, the full signature will also not verify, so the
* problem will be caught. But this function allows determining the specific party
* who produced an invalid signature, so that signing can be restarted without them.
*
* Returns: 1: partial signature verifies
* 0: invalid signature or bad data
* Args: ctx: pointer to a context object (cannot be NULL)
* session: active session for which the combined nonce has been computed
* (cannot be NULL)
* signer: data for the signer who produced this signature (cannot be NULL)
* In: partial_sig: signature to verify (cannot be NULL)
* pubkey: public key of the signer who produced the signature (cannot be NULL)
*/
//if (!secp256k1_musig_partial_sig_verify(ctx, &musig_session[i], &signer_data[i][j], &partial_sig[j], &pubkeys[j])) {
return 0;
/** Combines partial signatures
*
* Returns: 1: all partial signatures have values in range. Does NOT mean the
* resulting signature verifies.
* 0: some partial signature had s/r out of range
* Args: ctx: pointer to a context object (cannot be NULL)
* session: initialized session for which the combined nonce has been
* computed (cannot be NULL)
* Out: sig: complete signature (cannot be NULL)
* In: partial_sigs: array of partial signatures to combine (cannot be NULL)
* n_sigs: number of signatures in the partial_sigs array
*/
// after all partials: return secp256k1_musig_partial_sig_combine(ctx, &musig_session[0], sig, partial_sig, N_SIGNERS return(result);
}
UniValue musig_verify(uint64_t txfee,struct CCcontract_info *cp,cJSON *params) UniValue musig_verify(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
{ {
UniValue result(UniValue::VOBJ); static secp256k1_context *ctx;
result.push_back(Pair("result","success")); UniValue result(UniValue::VOBJ); int32_t i,n; uint8_t msg[32],musig64[64]; secp256k1_pubkey combined_pk; secp256k1_schnorrsig musig; char str[129];
/** Verify a Schnorr signature. testmain();
* if ( ctx == 0 )
* Returns: 1: correct signature ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
* 0: incorrect or unparseable signature if ( params != 0 && (n= cJSON_GetArraySize(params)) == 3 )
* Args: ctx: a secp256k1 context object, initialized for verification. {
* In: sig: the signature being verified (cannot be NULL) if ( musig_parsehash(msg,jitem(params,0),32) < 0 )
* msg32: the 32-byte message hash being verified (cannot be NULL) return(cclib_error(result,"error parsing pkhash"));
* pubkey: pointer to a public key to verify with (cannot be NULL) else if ( musig_parsepubkey(ctx,combined_pk,jitem(params,1)) < 0 )
*/ return(cclib_error(result,"error parsing combined_pk"));
// if (!secp256k1_schnorrsig_verify(ctx, &sig, msg, &combined_pk)) { else if ( musig_parsehash(musig64,jitem(params,2),64) < 0 )
return(result); return(cclib_error(result,"error parsing musig64"));
for (i=0; i<32; i++)
sprintf(&str[i*2],"%02x",msg[i]);
str[64] = 0;
result.push_back(Pair("msg",str));
result.push_back(Pair("combined_pk",jstr(jitem(params,1),0)));
for (i=0; i<64; i++)
sprintf(&str[i*2],"%02x",musig64[i]);
str[128] = 0;
result.push_back(Pair("combinedsig",str));
if ( secp256k1_schnorrsig_parse(ctx,&musig,&musig64[0]) > 0 )
{
if ( secp256k1_schnorrsig_verify(ctx,&musig,msg,&combined_pk) > 0 )
{
result.push_back(Pair("result","success"));
return(result);
} else return(cclib_error(result,"musig didnt verify"));
} else return(cclib_error(result,"couldnt parse musig64"));
} else return(cclib_error(result,"wrong number of params, need 3: msg, combined_pk, combinedsig"));
} }
// helpers for rpc calls that generate/validate onchain tx // helpers for rpc calls that generate/validate onchain tx
@@ -449,7 +700,7 @@ UniValue musig_spend(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
{ {
static secp256k1_context *ctx; static secp256k1_context *ctx;
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
UniValue result(UniValue::VOBJ); std::string rawtx; CPubKey mypk,pk; secp256k1_pubkey combined_pk; char *scriptstr,*musigstr; uint8_t msg[32]; CTransaction vintx; uint256 prevhash,hashBlock; int32_t n,numvouts; CTxOut vout; secp256k1_schnorrsig musig; UniValue result(UniValue::VOBJ); std::string rawtx; CPubKey mypk,pk; secp256k1_pubkey combined_pk; char *scriptstr,*musigstr; uint8_t msg[32]; CTransaction vintx; uint256 prevhash,hashBlock; int32_t i,n,numvouts; char str[129]; CTxOut vout; secp256k1_schnorrsig musig;
if ( ctx == 0 ) if ( ctx == 0 )
ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
if ( params != 0 && (n= cJSON_GetArraySize(params)) > 0 ) if ( params != 0 && (n= cJSON_GetArraySize(params)) > 0 )
@@ -459,13 +710,15 @@ UniValue musig_spend(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
prevhash = juint256(jitem(params,0)); prevhash = juint256(jitem(params,0));
scriptstr = jstr(jitem(params,1),0); scriptstr = jstr(jitem(params,1),0);
musigstr = jstr(jitem(params,2),0); musigstr = jstr(jitem(params,2),0);
if ( is_hexstr(scriptstr,0) != 0 && is_hexstr(musigstr,0) != 128 ) if ( is_hexstr(scriptstr,0) != 0 && is_hexstr(musigstr,0) == 128 )
{ {
if ( txfee == 0 ) if ( txfee == 0 )
txfee = MUSIG_TXFEE; txfee = MUSIG_TXFEE;
mypk = pubkey2pk(Mypubkey()); mypk = pubkey2pk(Mypubkey());
std::vector<uint8_t> musig64(ParseHex(musigstr)); std::vector<uint8_t> musig64(ParseHex(musigstr));
CScript scriptPubKey(ParseHex(scriptstr)); CScript scriptPubKey;
scriptPubKey.resize(strlen(scriptstr)/2);
decode_hex(&scriptPubKey[0],strlen(scriptstr)/2,scriptstr);
if ( myGetTransaction(prevhash,vintx,hashBlock) != 0 && (numvouts= vintx.vout.size()) > 1 ) if ( myGetTransaction(prevhash,vintx,hashBlock) != 0 && (numvouts= vintx.vout.size()) > 1 )
{ {
vout.nValue = vintx.vout[0].nValue - txfee; vout.nValue = vintx.vout[0].nValue - txfee;
@@ -476,8 +729,24 @@ UniValue musig_spend(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
secp256k1_ec_pubkey_parse(ctx,&combined_pk,pk.begin(),33) > 0 ) secp256k1_ec_pubkey_parse(ctx,&combined_pk,pk.begin(),33) > 0 )
{ {
musig_prevoutmsg(msg,prevhash,vout.scriptPubKey); musig_prevoutmsg(msg,prevhash,vout.scriptPubKey);
{
for (i=0; i<32; i++)
sprintf(&str[i*2],"%02x",msg[i]);
str[64] = 0;
result.push_back(Pair("msg",str));
for (i=0; i<33; i++)
sprintf(&str[i*2],"%02x",((uint8_t *)pk.begin())[i]);
str[66] = 0;
result.push_back(Pair("combined_pk",str));
for (i=0; i<64; i++)
sprintf(&str[i*2],"%02x",musig64[i]);
str[128] = 0;
result.push_back(Pair("combinedsig",str));
}
if ( !secp256k1_schnorrsig_verify((const secp256k1_context *)ctx,&musig,(const uint8_t *)msg,(const secp256k1_pubkey *)&combined_pk) ) if ( !secp256k1_schnorrsig_verify((const secp256k1_context *)ctx,&musig,(const uint8_t *)msg,(const secp256k1_pubkey *)&combined_pk) )
{
return(cclib_error(result,"musig didnt validate")); return(cclib_error(result,"musig didnt validate"));
}
mtx.vin.push_back(CTxIn(prevhash,MUSIG_PREVN)); mtx.vin.push_back(CTxIn(prevhash,MUSIG_PREVN));
mtx.vout.push_back(vout); mtx.vout.push_back(vout);
rawtx = FinalizeCCTx(0,cp,mtx,mypk,txfee,musig_spendopret('y',pk,musig64)); rawtx = FinalizeCCTx(0,cp,mtx,mypk,txfee,musig_spendopret('y',pk,musig64));
@@ -486,7 +755,7 @@ UniValue musig_spend(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
} else return(cclib_error(result,"couldnt decode send opret")); } else return(cclib_error(result,"couldnt decode send opret"));
} else return(cclib_error(result,"couldnt find vin0")); } else return(cclib_error(result,"couldnt find vin0"));
} else return(cclib_error(result,"script or musig is not hex")); } else return(cclib_error(result,"script or musig is not hex"));
} else return(cclib_error(result,"need to have exactly 3 params prevhash, scriptPubKey, musig")); } else return(cclib_error(result,"need to have exactly 3 params sendtxid, scriptPubKey, musig"));
} else return(cclib_error(result,"params parse error")); } else return(cclib_error(result,"params parse error"));
} }

View File

@@ -26,10 +26,10 @@ O=o
CC = x86_64-w64-mingw32-gcc CC = x86_64-w64-mingw32-gcc
#CFLAGS=-O2 #CFLAGS=-O2
CFLAGS= -g -O2 -I./ncurses/include CFLAGS= -g -O2 -I./ncurses/include -I./ncurses/include/ncursesw -I../../../depends/x86_64-w64-mingw32/include
#LIBS=-lcurses #LIBS=-lcurses
LIBS = -L./ncurses/lib -lncursesw LIBS = -L./ncurses/lib -lncursesw -lcurl
#RM=rm -f #RM=rm -f
RM = rm -f RM = rm -f

View File

@@ -41,7 +41,11 @@ typedef union _bits256 bits256;
double OS_milliseconds() double OS_milliseconds()
{ {
struct timeval tv; double millis; struct timeval tv; double millis;
#ifdef __MINGW32__
mingw_gettimeofday(&tv,NULL);
#else
gettimeofday(&tv,NULL); gettimeofday(&tv,NULL);
#endif
millis = ((double)tv.tv_sec * 1000. + (double)tv.tv_usec / 1000.); millis = ((double)tv.tv_sec * 1000. + (double)tv.tv_usec / 1000.);
//printf("tv_sec.%ld usec.%d %f\n",tv.tv_sec,tv.tv_usec,millis); //printf("tv_sec.%ld usec.%d %f\n",tv.tv_sec,tv.tv_usec,millis);
return(millis); return(millis);

View File

@@ -705,7 +705,9 @@ md_erasechar()
#elif defined(VERASE) #elif defined(VERASE)
return(_tty.c_cc[VERASE]); /* process erase character */ return(_tty.c_cc[VERASE]); /* process erase character */
#else #else
#ifndef __MINGW32__
return(_tty.sg_erase); /* process erase character */ return(_tty.sg_erase); /* process erase character */
#endif
#endif #endif
} }
@@ -717,7 +719,9 @@ md_killchar()
#elif defined(VKILL) #elif defined(VKILL)
return(_tty.c_cc[VKILL]); return(_tty.c_cc[VKILL]);
#else #else
#ifndef __MINGW32__
return(_tty.sg_kill); return(_tty.sg_kill);
#endif
#endif #endif
} }

View File

@@ -833,7 +833,7 @@ UniValue rogue_keystrokes(uint64_t txfee,struct CCcontract_info *cp,cJSON *param
} else return(cclib_error(result,"couldnt reparse params")); } else return(cclib_error(result,"couldnt reparse params"));
} }
char *rogue_extractgame(char *str,int32_t *numkeysp,std::vector<uint8_t> &newdata,uint64_t &seed,uint256 &playertxid,struct CCcontract_info *cp,uint256 gametxid,char *rogueaddr) char *rogue_extractgame(int32_t makefiles,char *str,int32_t *numkeysp,std::vector<uint8_t> &newdata,uint64_t &seed,uint256 &playertxid,struct CCcontract_info *cp,uint256 gametxid,char *rogueaddr)
{ {
CPubKey roguepk; int32_t i,num,maxplayers,gameheight,batonht,batonvout,numplayers,regslot,numkeys,err; std::string symbol,pname; CTransaction gametx; int64_t buyin,batonvalue; char fname[64],*keystrokes = 0; std::vector<uint8_t> playerdata; uint256 batontxid; FILE *fp; uint8_t newplayer[10000]; struct rogue_player P,endP; CPubKey roguepk; int32_t i,num,maxplayers,gameheight,batonht,batonvout,numplayers,regslot,numkeys,err; std::string symbol,pname; CTransaction gametx; int64_t buyin,batonvalue; char fname[64],*keystrokes = 0; std::vector<uint8_t> playerdata; uint256 batontxid; FILE *fp; uint8_t newplayer[10000]; struct rogue_player P,endP;
roguepk = GetUnspendable(cp,0); roguepk = GetUnspendable(cp,0);
@@ -854,19 +854,22 @@ char *rogue_extractgame(char *str,int32_t *numkeysp,std::vector<uint8_t> &newdat
} }
if ( keystrokes != 0 ) if ( keystrokes != 0 )
{ {
sprintf(fname,"rogue.%llu.0",(long long)seed); if ( makefiles != 0 )
if ( (fp= fopen(fname,"wb")) != 0 )
{ {
if ( fwrite(keystrokes,1,numkeys,fp) != numkeys ) sprintf(fname,"rogue.%llu.0",(long long)seed);
fprintf(stderr,"error writing %s\n",fname); if ( (fp= fopen(fname,"wb")) != 0 )
fclose(fp); {
} if ( fwrite(keystrokes,1,numkeys,fp) != numkeys )
sprintf(fname,"rogue.%llu.player",(long long)seed); fprintf(stderr,"error writing %s\n",fname);
if ( (fp= fopen(fname,"wb")) != 0 ) fclose(fp);
{ }
if ( fwrite(&playerdata[0],1,(int32_t)playerdata.size(),fp) != playerdata.size() ) sprintf(fname,"rogue.%llu.player",(long long)seed);
fprintf(stderr,"error writing %s\n",fname); if ( (fp= fopen(fname,"wb")) != 0 )
fclose(fp); {
if ( fwrite(&playerdata[0],1,(int32_t)playerdata.size(),fp) != playerdata.size() )
fprintf(stderr,"error writing %s\n",fname);
fclose(fp);
}
} }
num = rogue_replay2(newplayer,seed,keystrokes,numkeys,playerdata.size()==0?0:&P,0); num = rogue_replay2(newplayer,seed,keystrokes,numkeys,playerdata.size()==0?0:&P,0);
newdata.resize(num); newdata.resize(num);
@@ -914,7 +917,7 @@ UniValue rogue_extract(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
GetCCaddress1of2(cp,rogueaddr,roguepk,pk); GetCCaddress1of2(cp,rogueaddr,roguepk,pk);
result.push_back(Pair("rogueaddr",rogueaddr)); result.push_back(Pair("rogueaddr",rogueaddr));
str[0] = 0; str[0] = 0;
if ( (keystrokes= rogue_extractgame(str,&numkeys,newdata,seed,playertxid,cp,gametxid,rogueaddr)) != 0 ) if ( (keystrokes= rogue_extractgame(1,str,&numkeys,newdata,seed,playertxid,cp,gametxid,rogueaddr)) != 0 )
{ {
result.push_back(Pair("status","success")); result.push_back(Pair("status","success"));
flag = 1; flag = 1;
@@ -1240,7 +1243,7 @@ int32_t rogue_playerdata_validate(uint256 &playertxid,struct CCcontract_info *cp
roguepk = GetUnspendable(cp,0); roguepk = GetUnspendable(cp,0);
GetCCaddress1of2(cp,rogueaddr,roguepk,pk); GetCCaddress1of2(cp,rogueaddr,roguepk,pk);
//fprintf(stderr,"call extractgame\n"); //fprintf(stderr,"call extractgame\n");
if ( (keystrokes= rogue_extractgame(str,&numkeys,newdata,seed,playertxid,cp,gametxid,rogueaddr)) != 0 ) if ( (keystrokes= rogue_extractgame(0,str,&numkeys,newdata,seed,playertxid,cp,gametxid,rogueaddr)) != 0 )
{ {
free(keystrokes); free(keystrokes);
//fprintf(stderr,"extracted.(%s)\n",str); //fprintf(stderr,"extracted.(%s)\n",str);

View File

@@ -132,7 +132,12 @@ typedef struct {
* key (cannot be NULL) * key (cannot be NULL)
* n_pubkeys: length of pubkeys array * n_pubkeys: length of pubkeys array
*/ */
SECP256K1_API int secp256k1_musig_pubkey_combine( #ifdef __cplusplus
extern "C"
#else
SECP256K1_API
#endif
int secp256k1_musig_pubkey_combine(
const secp256k1_context* ctx, const secp256k1_context* ctx,
secp256k1_scratch_space *scratch, secp256k1_scratch_space *scratch,
secp256k1_pubkey *combined_pk, secp256k1_pubkey *combined_pk,
@@ -167,7 +172,12 @@ SECP256K1_API int secp256k1_musig_pubkey_combine(
* my_index: index of this signer in the signers array * my_index: index of this signer in the signers array
* seckey: the signer's 32-byte secret key (cannot be NULL) * seckey: the signer's 32-byte secret key (cannot be NULL)
*/ */
SECP256K1_API int secp256k1_musig_session_initialize( #ifdef __cplusplus
extern "C"
#else
SECP256K1_API
#endif
int secp256k1_musig_session_initialize(
const secp256k1_context* ctx, const secp256k1_context* ctx,
secp256k1_musig_session *session, secp256k1_musig_session *session,
secp256k1_musig_session_signer_data *signers, secp256k1_musig_session_signer_data *signers,
@@ -196,7 +206,12 @@ SECP256K1_API int secp256k1_musig_session_initialize(
* n_commitments: the length of commitments and signers array. Must be the total * n_commitments: the length of commitments and signers array. Must be the total
* number of signers participating in the MuSig. * number of signers participating in the MuSig.
*/ */
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_session_get_public_nonce( #ifdef __cplusplus
extern "C"
#else
SECP256K1_API
#endif
SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_session_get_public_nonce(
const secp256k1_context* ctx, const secp256k1_context* ctx,
secp256k1_musig_session *session, secp256k1_musig_session *session,
secp256k1_musig_session_signer_data *signers, secp256k1_musig_session_signer_data *signers,
@@ -225,7 +240,12 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_session_get_publi
* participating in the MuSig. Must be greater than 0 and at most * participating in the MuSig. Must be greater than 0 and at most
* 2^32 - 1. * 2^32 - 1.
*/ */
SECP256K1_API int secp256k1_musig_session_initialize_verifier( #ifdef __cplusplus
extern "C"
#else
SECP256K1_API
#endif
int secp256k1_musig_session_initialize_verifier(
const secp256k1_context* ctx, const secp256k1_context* ctx,
secp256k1_musig_session *session, secp256k1_musig_session *session,
secp256k1_musig_session_signer_data *signers, secp256k1_musig_session_signer_data *signers,
@@ -247,7 +267,12 @@ SECP256K1_API int secp256k1_musig_session_initialize_verifier(
* with `musig_session_initialize_verifier`. * with `musig_session_initialize_verifier`.
* In: nonce: signer's alleged public nonce (cannot be NULL) * In: nonce: signer's alleged public nonce (cannot be NULL)
*/ */
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_set_nonce( #ifdef __cplusplus
extern "C"
#else
SECP256K1_API
#endif
SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_set_nonce(
const secp256k1_context* ctx, const secp256k1_context* ctx,
secp256k1_musig_session_signer_data *signer, secp256k1_musig_session_signer_data *signer,
const secp256k1_pubkey *nonce const secp256k1_pubkey *nonce
@@ -271,7 +296,12 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_set_nonce(
* adaptor: point to add to the combined public nonce. If NULL, nothing is * adaptor: point to add to the combined public nonce. If NULL, nothing is
* added to the combined nonce. * added to the combined nonce.
*/ */
SECP256K1_API int secp256k1_musig_session_combine_nonces( #ifdef __cplusplus
extern "C"
#else
SECP256K1_API
#endif
int secp256k1_musig_session_combine_nonces(
const secp256k1_context* ctx, const secp256k1_context* ctx,
secp256k1_musig_session *session, secp256k1_musig_session *session,
const secp256k1_musig_session_signer_data *signers, const secp256k1_musig_session_signer_data *signers,
@@ -288,7 +318,12 @@ SECP256K1_API int secp256k1_musig_session_combine_nonces(
* session: the session structure to update with the message (cannot be NULL) * session: the session structure to update with the message (cannot be NULL)
* In: msg32: the 32-byte message to be signed (cannot be NULL) * In: msg32: the 32-byte message to be signed (cannot be NULL)
*/ */
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_session_set_msg( #ifdef __cplusplus
extern "C"
#else
SECP256K1_API
#endif
SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_session_set_msg(
const secp256k1_context* ctx, const secp256k1_context* ctx,
secp256k1_musig_session *session, secp256k1_musig_session *session,
const unsigned char *msg32 const unsigned char *msg32
@@ -301,7 +336,12 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_session_set_msg(
* Out: out32: pointer to a 32-byte array to store the serialized signature * Out: out32: pointer to a 32-byte array to store the serialized signature
* In: sig: pointer to the signature * In: sig: pointer to the signature
*/ */
SECP256K1_API int secp256k1_musig_partial_signature_serialize( #ifdef __cplusplus
extern "C"
#else
SECP256K1_API
#endif
int secp256k1_musig_partial_signature_serialize(
const secp256k1_context* ctx, const secp256k1_context* ctx,
unsigned char *out32, unsigned char *out32,
const secp256k1_musig_partial_signature* sig const secp256k1_musig_partial_signature* sig
@@ -318,7 +358,12 @@ SECP256K1_API int secp256k1_musig_partial_signature_serialize(
* encoded numbers are out of range, signature verification with it is * encoded numbers are out of range, signature verification with it is
* guaranteed to fail for every message and public key. * guaranteed to fail for every message and public key.
*/ */
SECP256K1_API int secp256k1_musig_partial_signature_parse( #ifdef __cplusplus
extern "C"
#else
SECP256K1_API
#endif
int secp256k1_musig_partial_signature_parse(
const secp256k1_context* ctx, const secp256k1_context* ctx,
secp256k1_musig_partial_signature* sig, secp256k1_musig_partial_signature* sig,
const unsigned char *in32 const unsigned char *in32
@@ -333,7 +378,12 @@ SECP256K1_API int secp256k1_musig_partial_signature_parse(
* computed (cannot be NULL) * computed (cannot be NULL)
* Out: partial_sig: partial signature (cannot be NULL) * Out: partial_sig: partial signature (cannot be NULL)
*/ */
SECP256K1_API int secp256k1_musig_partial_sign( #ifdef __cplusplus
extern "C"
#else
SECP256K1_API
#endif
int secp256k1_musig_partial_sign(
const secp256k1_context* ctx, const secp256k1_context* ctx,
const secp256k1_musig_session *session, const secp256k1_musig_session *session,
secp256k1_musig_partial_signature *partial_sig secp256k1_musig_partial_signature *partial_sig
@@ -356,7 +406,12 @@ SECP256K1_API int secp256k1_musig_partial_sign(
* In: partial_sig: signature to verify (cannot be NULL) * In: partial_sig: signature to verify (cannot be NULL)
* pubkey: public key of the signer who produced the signature (cannot be NULL) * pubkey: public key of the signer who produced the signature (cannot be NULL)
*/ */
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_partial_sig_verify( #ifdef __cplusplus
extern "C"
#else
SECP256K1_API
#endif
SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_partial_sig_verify(
const secp256k1_context* ctx, const secp256k1_context* ctx,
const secp256k1_musig_session *session, const secp256k1_musig_session *session,
const secp256k1_musig_session_signer_data *signer, const secp256k1_musig_session_signer_data *signer,
@@ -376,7 +431,12 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_partial_sig_verif
* In: partial_sigs: array of partial signatures to combine (cannot be NULL) * In: partial_sigs: array of partial signatures to combine (cannot be NULL)
* n_sigs: number of signatures in the partial_sigs array * n_sigs: number of signatures in the partial_sigs array
*/ */
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_partial_sig_combine( #ifdef __cplusplus
extern "C"
#else
SECP256K1_API
#endif
SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_partial_sig_combine(
const secp256k1_context* ctx, const secp256k1_context* ctx,
const secp256k1_musig_session *session, const secp256k1_musig_session *session,
secp256k1_schnorrsig *sig, secp256k1_schnorrsig *sig,
@@ -396,7 +456,12 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_partial_sig_combi
* be NULL) * be NULL)
* nonce_is_negated: the `nonce_is_negated` output of `musig_session_combine_nonces` * nonce_is_negated: the `nonce_is_negated` output of `musig_session_combine_nonces`
*/ */
SECP256K1_API int secp256k1_musig_partial_sig_adapt( #ifdef __cplusplus
extern "C"
#else
SECP256K1_API
#endif
int secp256k1_musig_partial_sig_adapt(
const secp256k1_context* ctx, const secp256k1_context* ctx,
secp256k1_musig_partial_signature *adaptor_sig, secp256k1_musig_partial_signature *adaptor_sig,
const secp256k1_musig_partial_signature *partial_sig, const secp256k1_musig_partial_signature *partial_sig,
@@ -419,7 +484,12 @@ SECP256K1_API int secp256k1_musig_partial_sig_adapt(
* n_partial_sigs: number of elements in partial_sigs array * n_partial_sigs: number of elements in partial_sigs array
* nonce_is_negated: the `nonce_is_negated` output of `musig_session_combine_nonces` * nonce_is_negated: the `nonce_is_negated` output of `musig_session_combine_nonces`
*/ */
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_extract_secret_adaptor( #ifdef __cplusplus
extern "C"
#else
SECP256K1_API
#endif
SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_extract_secret_adaptor(
const secp256k1_context* ctx, const secp256k1_context* ctx,
unsigned char *sec_adaptor32, unsigned char *sec_adaptor32,
const secp256k1_schnorrsig *sig, const secp256k1_schnorrsig *sig,

View File

@@ -28,7 +28,12 @@ typedef struct {
* *
* See secp256k1_schnorrsig_parse for details about the encoding. * See secp256k1_schnorrsig_parse for details about the encoding.
*/ */
SECP256K1_API int secp256k1_schnorrsig_serialize( #ifdef __cplusplus
extern "C"
#else
SECP256K1_API
#endif
int secp256k1_schnorrsig_serialize(
const secp256k1_context* ctx, const secp256k1_context* ctx,
unsigned char *out64, unsigned char *out64,
const secp256k1_schnorrsig* sig const secp256k1_schnorrsig* sig
@@ -50,7 +55,12 @@ SECP256K1_API int secp256k1_schnorrsig_serialize(
* encoded numbers are out of range, signature validation with it is * encoded numbers are out of range, signature validation with it is
* guaranteed to fail for every message and public key. * guaranteed to fail for every message and public key.
*/ */
SECP256K1_API int secp256k1_schnorrsig_parse( #ifdef __cplusplus
extern "C"
#else
SECP256K1_API
#endif
int secp256k1_schnorrsig_parse(
const secp256k1_context* ctx, const secp256k1_context* ctx,
secp256k1_schnorrsig* sig, secp256k1_schnorrsig* sig,
const unsigned char *in64 const unsigned char *in64

View File

@@ -9,11 +9,11 @@
* Additionally, see the documentation in include/secp256k1_musig.h. * Additionally, see the documentation in include/secp256k1_musig.h.
*/ */
#include <stdio.h> /*#include <stdio.h>
#include <assert.h> #include <assert.h>
#include <secp256k1.h> #include <secp256k1.h>
#include <secp256k1_schnorrsig.h> #include <secp256k1_schnorrsig.h>
#include <secp256k1_musig.h> #include <secp256k1_musig.h>*/
/* Number of public keys involved in creating the aggregate signature */ /* Number of public keys involved in creating the aggregate signature */
#define N_SIGNERS 3 #define N_SIGNERS 3
@@ -122,43 +122,43 @@ int sign(const secp256k1_context* ctx, unsigned char seckeys[][32], const secp25
return secp256k1_musig_partial_sig_combine(ctx, &musig_session[0], sig, partial_sig, N_SIGNERS); return secp256k1_musig_partial_sig_combine(ctx, &musig_session[0], sig, partial_sig, N_SIGNERS);
} }
int main(void) { int testmain(void) {
secp256k1_context* ctx; secp256k1_context* ctx;
int i; int i;
unsigned char seckeys[N_SIGNERS][32]; unsigned char seckeys[N_SIGNERS][32];
secp256k1_pubkey pubkeys[N_SIGNERS]; secp256k1_pubkey pubkeys[N_SIGNERS];
secp256k1_pubkey combined_pk; secp256k1_pubkey combined_pk;
unsigned char msg[32] = "this_could_be_the_hash_of_a_msg!"; unsigned char msg[32] = "this_could_be_the_hash_of_a_msg";
secp256k1_schnorrsig sig; secp256k1_schnorrsig sig;
/* Create a context for signing and verification */ /* Create a context for signing and verification */
ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
printf("Creating key pairs......"); fprintf(stderr,"Creating key pairs......");
for (i = 0; i < N_SIGNERS; i++) { for (i = 0; i < N_SIGNERS; i++) {
if (!create_key(ctx, seckeys[i], &pubkeys[i])) { if (!create_key(ctx, seckeys[i], &pubkeys[i])) {
printf("FAILED\n"); fprintf(stderr,"FAILED\n");
return 1; return 1;
} }
} }
printf("ok\n"); fprintf(stderr,"ok\n");
printf("Combining public keys..."); fprintf(stderr,"Combining public keys...");
if (!secp256k1_musig_pubkey_combine(ctx, NULL, &combined_pk, NULL, pubkeys, N_SIGNERS)) { if (!secp256k1_musig_pubkey_combine(ctx, NULL, &combined_pk, NULL, pubkeys, N_SIGNERS)) {
printf("FAILED\n"); fprintf(stderr,"FAILED\n");
return 1; return 1;
} }
printf("ok\n"); fprintf(stderr,"ok\n");
printf("Signing message........."); fprintf(stderr,"Signing message.........");
if (!sign(ctx, seckeys, pubkeys, msg, &sig)) { if (!sign(ctx, seckeys, pubkeys, msg, &sig)) {
printf("FAILED\n"); fprintf(stderr,"FAILED\n");
return 1; return 1;
} }
printf("ok\n"); fprintf(stderr,"ok\n");
printf("Verifying signature....."); fprintf(stderr,"Verifying signature.....");
if (!secp256k1_schnorrsig_verify(ctx, &sig, msg, &combined_pk)) { if (!secp256k1_schnorrsig_verify(ctx, &sig, msg, &combined_pk)) {
printf("FAILED\n"); fprintf(stderr,"FAILED\n");
return 1; return 1;
} }
printf("ok\n"); fprintf(stderr,"ok\n");
secp256k1_context_destroy(ctx); secp256k1_context_destroy(ctx);
return 0; return 0;
} }