add secp256k1 condition type to cryptoconditions
This commit is contained in:
2
.gitmodules
vendored
2
.gitmodules
vendored
@@ -1,4 +1,4 @@
|
||||
[submodule "cryptoconditions"]
|
||||
path = src/cryptoconditions
|
||||
url = https://github.com/libscott/libcryptoconditions.git
|
||||
branch = komodo-integration
|
||||
branch = komodo
|
||||
|
||||
@@ -7,6 +7,9 @@ import struct
|
||||
from testsupport import *
|
||||
|
||||
|
||||
SCRIPT_FALSE = 'Script evaluated without error but finished with a false/empty top stack element'
|
||||
|
||||
|
||||
@fanout_input(0)
|
||||
def test_basic_spend(inp):
|
||||
spend = {'inputs': [inp], "outputs": [nospend]}
|
||||
@@ -27,7 +30,7 @@ def test_fulfillment_wrong_signature(inp):
|
||||
try:
|
||||
assert not submit(signed), 'should raise an error'
|
||||
except RPCError as e:
|
||||
assert 'Script evaluated without error but finished with a false/empty top stack element' in str(e), str(e)
|
||||
assert SCRIPT_FALSE in str(e), str(e)
|
||||
|
||||
|
||||
@fanout_input(2)
|
||||
@@ -41,7 +44,7 @@ def test_fulfillment_wrong_pubkey(inp):
|
||||
try:
|
||||
assert not submit(signed), 'should raise an error'
|
||||
except RPCError as e:
|
||||
assert 'Script evaluated without error but finished with a false/empty top stack element' in str(e), str(e)
|
||||
assert SCRIPT_FALSE in str(e), str(e)
|
||||
|
||||
|
||||
@fanout_input(3)
|
||||
@@ -71,7 +74,7 @@ def test_invalid_condition(inp):
|
||||
try:
|
||||
assert not submit(sign(spend1)), 'should raise an error'
|
||||
except RPCError as e:
|
||||
assert 'Script evaluated without error but finished with a false/empty top stack element' in str(e), str(e)
|
||||
assert SCRIPT_FALSE in str(e), str(e)
|
||||
|
||||
|
||||
@fanout_input(5)
|
||||
@@ -124,7 +127,7 @@ def test_aux_basic(inp):
|
||||
try:
|
||||
assert not submit(sign(spend2)), 'should raise an error'
|
||||
except RPCError as e:
|
||||
assert 'Script evaluated without error but finished with a false/empty top stack element' in str(e), str(e)
|
||||
assert SCRIPT_FALSE in str(e), str(e)
|
||||
|
||||
|
||||
@fanout_input(7)
|
||||
@@ -168,7 +171,47 @@ def test_aux_complex(inp):
|
||||
try:
|
||||
assert not submit(sign(spend2)), 'should raise an error'
|
||||
except RPCError as e:
|
||||
assert 'Script evaluated without error but finished with a false/empty top stack element' in str(e), str(e)
|
||||
assert SCRIPT_FALSE in str(e), str(e)
|
||||
|
||||
|
||||
@fanout_input(8)
|
||||
def test_secp256k1_condition(inp):
|
||||
ec_cond = {
|
||||
'type': 'secp256k1-sha-256',
|
||||
'publicKey': notary_pk
|
||||
}
|
||||
|
||||
# Create some secp256k1 outputs
|
||||
spend0 = {
|
||||
'inputs': [inp],
|
||||
'outputs': [
|
||||
{'amount': 500, 'script': {'condition': ec_cond}},
|
||||
{'amount': 500, 'script': {'condition': ec_cond}}
|
||||
]
|
||||
}
|
||||
spend0_txid = submit(sign(spend0))
|
||||
assert rpc.getrawtransaction(spend0_txid)
|
||||
|
||||
# Test a good fulfillment
|
||||
spend1 = {
|
||||
'inputs': [{'txid': spend0_txid, 'idx': 0, 'script': {'fulfillment': ec_cond}}],
|
||||
'outputs': [{'amount': 500, 'script': {'condition': ec_cond}}]
|
||||
}
|
||||
spend1_txid = submit(sign(spend1))
|
||||
assert rpc.getrawtransaction(spend1_txid)
|
||||
|
||||
# Test a bad fulfillment
|
||||
spend2 = {
|
||||
'inputs': [{'txid': spend0_txid, 'idx': 1, 'script': {'fulfillment': ec_cond}}],
|
||||
'outputs': [{'amount': 500, 'script': {'condition': ec_cond}}]
|
||||
}
|
||||
signed = sign(spend2)
|
||||
signed['tx']['inputs'][0]['script']['fulfillment']['publicKey'] = \
|
||||
'0275cef12fc5c49be64f5aab3d1fbba08cd7b0d02908b5112fbd8504218d14bc7d'
|
||||
try:
|
||||
assert not submit(signed), 'should raise an error'
|
||||
except RPCError as e:
|
||||
assert SCRIPT_FALSE in str(e), str(e)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -74,7 +74,8 @@ def wait_for_block(height):
|
||||
|
||||
def sign(tx):
|
||||
signed = hoek.signTxBitcoin({'tx': tx, 'privateKeys': [notary_sk]})
|
||||
return hoek.signTxEd25519({'tx': signed['tx'], 'privateKeys': [alice_sk, bob_sk]})
|
||||
signed = hoek.signTxEd25519({'tx': signed['tx'], 'privateKeys': [alice_sk, bob_sk]})
|
||||
return hoek.signTxSecp256k1({'tx': signed['tx'], 'privateKeys': [notary_sk]})
|
||||
|
||||
|
||||
def submit(tx):
|
||||
@@ -96,14 +97,14 @@ def get_fanout_txid():
|
||||
reward_tx = hoek.decodeTx({'hex': reward_tx_raw})
|
||||
balance = reward_tx['tx']['outputs'][0]['amount']
|
||||
|
||||
n_outs = 100
|
||||
n_outs = 16
|
||||
remainder = balance - n_outs * 1000
|
||||
|
||||
fanout = {
|
||||
'inputs': [
|
||||
{'txid': reward_txid, 'idx': 0, 'script': {'pubkey': notary_pk}}
|
||||
],
|
||||
"outputs": (100 * [
|
||||
"outputs": (n_outs * [
|
||||
{"amount": 1000, "script": {"condition": cond_alice}}
|
||||
] + [{"amount": remainder, 'script': {'address': notary_addr}}])
|
||||
}
|
||||
@@ -122,6 +123,21 @@ def fanout_input(n):
|
||||
return decorate
|
||||
|
||||
|
||||
def decode_base64(data):
|
||||
"""Decode base64, padding being optional.
|
||||
|
||||
:param data: Base64 data as an ASCII byte string
|
||||
:returns: The decoded byte string.
|
||||
"""
|
||||
missing_padding = len(data) % 4
|
||||
if missing_padding:
|
||||
data += '=' * (4 - missing_padding)
|
||||
return base64.urlsafe_b64decode(data)
|
||||
|
||||
|
||||
def encode_base64(data):
|
||||
return base64.urlsafe_b64encode(data).rstrip(b'=')
|
||||
|
||||
|
||||
notary_addr = 'RXSwmXKtDURwXP7sdqNfsJ6Ga8RaxTchxE'
|
||||
notary_pk = '0205a8ad0c1dbc515f149af377981aab58b836af008d4d7ab21bd76faf80550b47'
|
||||
|
||||
Submodule src/cryptoconditions updated: 0dcac79cf9...863d926614
@@ -3,8 +3,8 @@
|
||||
#include "script/interpreter.h"
|
||||
|
||||
|
||||
int TransactionSignatureChecker::CheckAuxCondition(const CC *cond) const {
|
||||
|
||||
int TransactionSignatureChecker::CheckAuxCondition(const CC *cond) const
|
||||
{
|
||||
// Check that condition is equal to fulfillment
|
||||
if (0 == strcmp((const char*)cond->method, "equals")) {
|
||||
return (cond->conditionAuxLength == cond->fulfillmentAuxLength) &&
|
||||
|
||||
@@ -1164,7 +1164,7 @@ static int komodoCCAux(CC *cond, void *checker) {
|
||||
bool TransactionSignatureChecker::CheckCryptoCondition(const CC *cond, const std::vector<unsigned char>& condBin, const CScript& scriptCode) const
|
||||
{
|
||||
uint256 message = SignatureHash(scriptCode, *txTo, nIn, SIGHASH_ALL);
|
||||
return cc_verify(cond, (const unsigned char*)&message, 32,
|
||||
return cc_verify(cond, (const unsigned char*)&message, 32, 0,
|
||||
condBin.data(), condBin.size(), komodoCCAux, (void*)this);
|
||||
}
|
||||
|
||||
|
||||
@@ -47,12 +47,20 @@ static const secp256k1_fe_t secp256k1_ecdsa_const_p_minus_order = SECP256K1_FE_C
|
||||
);
|
||||
|
||||
static int secp256k1_ecdsa_sig_parse(secp256k1_ecdsa_sig_t *r, const unsigned char *sig, int size) {
|
||||
|
||||
/* libscott had to add this to get this version of the library to read compact sigs */
|
||||
int overflow = 0;
|
||||
if (size == 64) {
|
||||
secp256k1_scalar_set_b32(&r->r, sig, &overflow);
|
||||
secp256k1_scalar_set_b32(&r->s, sig+32, &overflow);
|
||||
return 1;
|
||||
}
|
||||
|
||||
unsigned char ra[32] = {0}, sa[32] = {0};
|
||||
const unsigned char *rp;
|
||||
const unsigned char *sp;
|
||||
int lenr;
|
||||
int lens;
|
||||
int overflow;
|
||||
if (sig[0] != 0x30) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user