libbtc
bitcoinclibrary
Functions
script.c File Reference
#include <btc/script.h>
#include <assert.h>
#include <string.h>
#include "buffer.h"
#include "serialize.h"

Go to the source code of this file.

Functions

btc_bool btc_script_copy_without_op_codeseperator (const cstring *script_in, cstring *script_out)
 
btc_script_opbtc_script_op_new ()
 
void btc_script_op_free (btc_script_op *script_op)
 
void btc_script_op_free_cb (void *data)
 
btc_bool btc_script_get_ops (const cstring *script_in, vector *ops_out)
 
static btc_bool btc_script_is_pushdata (enum opcodetype op)
 
static btc_bool btc_script_is_op (const btc_script_op *op, enum opcodetype opcode)
 
static btc_bool btc_script_is_op_pubkey (const btc_script_op *op)
 
static btc_bool btc_script_is_op_pubkeyhash (const btc_script_op *op)
 
btc_bool btc_script_is_pubkey (vector *ops)
 
btc_bool btc_script_is_pubkeyhash (vector *ops)
 
btc_bool btc_script_is_scripthash (vector *ops)
 
static btc_bool btc_script_is_op_smallint (const btc_script_op *op)
 
btc_bool btc_script_is_multisig (vector *ops)
 
enum btc_tx_out_type btc_script_classify (vector *ops)
 
static enum opcodetype btc_encode_op_n (int n)
 
static void btc_script_append_op (cstring *script_in, enum opcodetype op)
 
static void btc_script_append_pushdata (cstring *script_in, unsigned char *data, size_t datalen)
 
btc_bool btc_script_build_multisig (cstring *script_in, unsigned int required_signatures, vector *pubkeys_chars)
 
btc_bool btc_script_build_p2pkh (cstring *script_in, const uint8_t *hash160)
 
btc_bool btc_script_build_p2sh (cstring *script_in, const uint8_t *hash160)
 

Function Documentation

static enum opcodetype btc_encode_op_n ( int  n)
static

Definition at line 257 of file script.c.

References OP_0, and OP_1.

Referenced by btc_script_build_multisig().

258 {
259  assert(n >= 0 && n <= 16);
260  if (n == 0)
261  return OP_0;
262  return (enum opcodetype)(OP_1+n-1);
263 }
opcodetype
Definition: script.h:49
Definition: script.h:58
Definition: script.h:51
static void btc_script_append_op ( cstring script_in,
enum opcodetype  op 
)
static

Definition at line 266 of file script.c.

References cstr_append_buf().

Referenced by btc_script_append_pushdata(), btc_script_build_p2pkh(), and btc_script_build_p2sh().

267 {
268  cstr_append_buf(script_in, &op, 1);
269 }
btc_bool cstr_append_buf(cstring *s, const void *buf, size_t sz)
Definition: cstr.c:106
static void btc_script_append_pushdata ( cstring script_in,
unsigned char *  data,
size_t  datalen 
)
static

Definition at line 272 of file script.c.

References btc_script_append_op(), cstr_append_buf(), OP_PUSHDATA1, OP_PUSHDATA2, and OP_PUSHDATA4.

Referenced by btc_script_build_multisig(), btc_script_build_p2pkh(), and btc_script_build_p2sh().

273 {
274  if (datalen < OP_PUSHDATA1)
275  {
276  cstr_append_buf(script_in, (unsigned char *)&datalen, 1);
277  }
278  else if (datalen <= 0xff)
279  {
281  cstr_append_buf(script_in, (unsigned char *)&datalen, 1);
282  }
283  else if (datalen <= 0xffff)
284  {
286  uint16_t v = htole16(datalen);
287  cstr_append_buf(script_in, &v, sizeof(v));
288  }
289  else
290  {
292  uint32_t v = htole32(datalen);
293  cstr_append_buf(script_in, &v, sizeof(v));
294  }
295  cstr_append_buf(script_in, data, datalen);
296 }
static void btc_script_append_op(cstring *script_in, enum opcodetype op)
Definition: script.c:266
btc_bool cstr_append_buf(cstring *s, const void *buf, size_t sz)
Definition: cstr.c:106
btc_bool btc_script_build_multisig ( cstring script_in,
unsigned int  required_signatures,
vector pubkeys_chars 
)

Definition at line 298 of file script.c.

References BTC_ECKEY_COMPRESSED_LENGTH, BTC_ECKEY_UNCOMPRESSED_LENGTH, btc_encode_op_n(), btc_script_append_pushdata(), btc_pubkey_::compressed, cstr_append_buf(), cstr_resize(), vector::data, vector::len, OP_CHECKMULTISIG, and btc_pubkey_::pubkey.

299 {
300  cstr_resize(script_in, 0); //clear script
301 
302  if(required_signatures > 16 || pubkeys_chars->len > 16)
303  return false;
304  enum opcodetype op_req_sig = btc_encode_op_n(required_signatures);
305  cstr_append_buf(script_in, &op_req_sig, 1);
306 
307  int i;
308  for (i = 0; i < (int)pubkeys_chars->len; i++)
309  {
310  btc_pubkey *pkey = pubkeys_chars->data[i];
312  }
313 
314  enum opcodetype op_pub_len = btc_encode_op_n(pubkeys_chars->len);
315  cstr_append_buf(script_in, &op_pub_len, 1);
316 
317  enum opcodetype op_checkmultisig = OP_CHECKMULTISIG;
318  cstr_append_buf(script_in, &op_checkmultisig, 1);
319 
320  return true;
321 }
void ** data
Definition: vector.h:41
static void btc_script_append_pushdata(cstring *script_in, unsigned char *data, size_t datalen)
Definition: script.c:272
#define BTC_ECKEY_COMPRESSED_LENGTH
Definition: btc.h:68
#define BTC_ECKEY_UNCOMPRESSED_LENGTH
Definition: btc.h:67
opcodetype
Definition: script.h:49
btc_bool cstr_resize(cstring *s, size_t new_sz)
Definition: cstr.c:81
static enum opcodetype btc_encode_op_n(int n)
Definition: script.c:257
size_t len
Definition: vector.h:42
btc_bool compressed
Definition: ecc_key.h:46
btc_bool cstr_append_buf(cstring *s, const void *buf, size_t sz)
Definition: cstr.c:106
uint8_t pubkey[BTC_ECKEY_UNCOMPRESSED_LENGTH]
Definition: ecc_key.h:47
btc_bool btc_script_build_p2pkh ( cstring script_in,
const uint8_t *  hash160 
)

Definition at line 323 of file script.c.

References btc_script_append_op(), btc_script_append_pushdata(), cstr_resize(), OP_CHECKSIG, OP_DUP, OP_EQUALVERIFY, and OP_HASH160.

Referenced by btc_tx_add_p2pkh_hash160_out().

324 {
325  cstr_resize(script_in, 0); //clear script
326 
327  btc_script_append_op(script_in, OP_DUP);
328  btc_script_append_op(script_in, OP_HASH160);
329 
330 
331  btc_script_append_pushdata(script_in, hash160, 20);
333  btc_script_append_op(script_in, OP_CHECKSIG);
334 
335  return true;
336 }
static void btc_script_append_pushdata(cstring *script_in, unsigned char *data, size_t datalen)
Definition: script.c:272
btc_bool cstr_resize(cstring *s, size_t new_sz)
Definition: cstr.c:81
static void btc_script_append_op(cstring *script_in, enum opcodetype op)
Definition: script.c:266
Definition: script.h:100
btc_bool btc_script_build_p2sh ( cstring script_in,
const uint8_t *  hash160 
)

Definition at line 338 of file script.c.

References btc_script_append_op(), btc_script_append_pushdata(), cstr_resize(), OP_EQUAL, and OP_HASH160.

Referenced by btc_tx_add_p2sh_hash160_out().

339 {
340  cstr_resize(script_in, 0); //clear script
341  btc_script_append_op(script_in, OP_HASH160);
342  btc_script_append_pushdata(script_in, hash160, 20);
343  btc_script_append_op(script_in, OP_EQUAL);
344 
345  return true;
346 }
static void btc_script_append_pushdata(cstring *script_in, unsigned char *data, size_t datalen)
Definition: script.c:272
btc_bool cstr_resize(cstring *s, size_t new_sz)
Definition: cstr.c:81
static void btc_script_append_op(cstring *script_in, enum opcodetype op)
Definition: script.c:266
enum btc_tx_out_type btc_script_classify ( vector ops)

Definition at line 243 of file script.c.

References btc_script_is_multisig(), btc_script_is_pubkey(), btc_script_is_pubkeyhash(), btc_script_is_scripthash(), BTC_TX_MULTISIG, BTC_TX_NONSTANDARD, BTC_TX_PUBKEY, BTC_TX_PUBKEYHASH, and BTC_TX_SCRIPTHASH.

244 {
245  if (btc_script_is_pubkeyhash(ops))
246  return BTC_TX_PUBKEYHASH;
247  if (btc_script_is_scripthash(ops))
248  return BTC_TX_SCRIPTHASH;
249  if (btc_script_is_pubkey(ops))
250  return BTC_TX_PUBKEY;
251  if (btc_script_is_multisig(ops))
252  return BTC_TX_MULTISIG;
253 
254  return BTC_TX_NONSTANDARD;
255 }
btc_bool btc_script_is_scripthash(vector *ops)
Definition: script.c:213
btc_bool btc_script_is_multisig(vector *ops)
Definition: script.c:227
btc_bool btc_script_is_pubkey(vector *ops)
Definition: script.c:194
btc_bool btc_script_is_pubkeyhash(vector *ops)
Definition: script.c:202
btc_bool btc_script_copy_without_op_codeseperator ( const cstring script_in,
cstring script_out 
)

Definition at line 36 of file script.c.

References cstr_append_buf(), deser_bytes(), deser_skip(), deser_u16(), deser_u32(), const_buffer::len, cstring::len, OP_CODESEPARATOR, OP_PUSHDATA1, OP_PUSHDATA2, OP_PUSHDATA4, const_buffer::p, and cstring::str.

Referenced by btc_tx_sighash().

37 {
38  if (script_in->len == 0)
39  return false; /* EOF */
40 
41  struct const_buffer buf = {script_in->str, script_in->len};
42  unsigned char opcode;
43  while (buf.len > 0) {
44  if (!deser_bytes(&opcode, &buf, 1))
45  goto err_out;
46 
47  uint32_t data_len;
48 
49  if (opcode == OP_CODESEPARATOR)
50  continue;
51 
52  else if (opcode == OP_PUSHDATA1) {
53  uint8_t v8;
54  if (!deser_bytes(&v8, &buf, 1))
55  goto err_out;
56  data_len = v8;
57  } else if (opcode == OP_PUSHDATA2) {
58  uint16_t v16;
59  if (!deser_u16(&v16, &buf))
60  goto err_out;
61  data_len = v16;
62  } else if (opcode == OP_PUSHDATA4) {
63  uint32_t v32;
64  if (!deser_u32(&v32, &buf))
65  goto err_out;
66  data_len = v32;
67  } else {
68  cstr_append_buf(script_out, &opcode, 1);
69  continue;
70  }
71 
72  cstr_append_buf(script_out, buf.p, data_len);
73  if (!deser_skip(&buf, data_len))
74  goto err_out;
75  }
76 
77 err_out:
78  return false;
79 }
char * str
Definition: cstr.h:43
size_t len
Definition: buffer.h:22
btc_bool deser_skip(struct const_buffer *buf, size_t len)
Definition: serialize.c:92
const void * p
Definition: buffer.h:21
btc_bool deser_u32(uint32_t *vo, struct const_buffer *buf)
Definition: serialize.c:126
btc_bool deser_bytes(void *po, struct const_buffer *buf, size_t len)
Definition: serialize.c:103
btc_bool deser_u16(uint16_t *vo, struct const_buffer *buf)
Definition: serialize.c:115
size_t len
Definition: cstr.h:44
btc_bool cstr_append_buf(cstring *s, const void *buf, size_t sz)
Definition: cstr.c:106
btc_bool btc_script_get_ops ( const cstring script_in,
vector ops_out 
)

Definition at line 108 of file script.c.

References btc_script_op_free(), btc_script_op_new(), btc_script_op_::data, btc_script_op_::datalen, deser_bytes(), deser_skip(), deser_u16(), deser_u32(), const_buffer::len, cstring::len, btc_script_op_::op, OP_PUSHDATA1, OP_PUSHDATA2, OP_PUSHDATA4, const_buffer::p, cstring::str, and vector_add().

109 {
110  if (script_in->len == 0)
111  return false; /* EOF */
112 
113  struct const_buffer buf = {script_in->str, script_in->len};
114  unsigned char opcode;
115 
116  btc_script_op* op = NULL;
117  while (buf.len > 0) {
118  op = btc_script_op_new();
119 
120  if (!deser_bytes(&opcode, &buf, 1))
121  goto err_out;
122 
123  op->op = opcode;
124 
125  uint32_t data_len;
126 
127  if (opcode < OP_PUSHDATA1) {
128  data_len = opcode;
129  } else if (opcode == OP_PUSHDATA1) {
130  uint8_t v8;
131  if (!deser_bytes(&v8, &buf, 1))
132  goto err_out;
133  data_len = v8;
134  } else if (opcode == OP_PUSHDATA2) {
135  uint16_t v16;
136  if (!deser_u16(&v16, &buf))
137  goto err_out;
138  data_len = v16;
139  } else if (opcode == OP_PUSHDATA4) {
140  uint32_t v32;
141  if (!deser_u32(&v32, &buf))
142  goto err_out;
143  data_len = v32;
144  } else {
145  vector_add(ops_out, op);
146  continue;
147  }
148 
149  op->data = calloc(1, data_len);
150  memcpy(op->data, &buf.p, data_len);
151  op->datalen = data_len;
152 
153  vector_add(ops_out, op);
154 
155  if (!deser_skip(&buf, data_len))
156  goto err_out;
157  }
158 
159  return true;
160 err_out:
161  btc_script_op_free(op);
162  return false;
163 }
char * str
Definition: cstr.h:43
size_t len
Definition: buffer.h:22
btc_bool deser_skip(struct const_buffer *buf, size_t len)
Definition: serialize.c:92
btc_script_op * btc_script_op_new()
Definition: script.c:81
size_t datalen
Definition: script.h:206
const void * p
Definition: buffer.h:21
btc_bool deser_u32(uint32_t *vo, struct const_buffer *buf)
Definition: serialize.c:126
void btc_script_op_free(btc_script_op *script_op)
Definition: script.c:90
btc_bool deser_bytes(void *po, struct const_buffer *buf, size_t len)
Definition: serialize.c:103
btc_bool vector_add(vector *vec, void *data)
Definition: vector.c:113
btc_bool deser_u16(uint16_t *vo, struct const_buffer *buf)
Definition: serialize.c:115
size_t len
Definition: cstr.h:44
enum opcodetype op
Definition: script.h:204
unsigned char * data
Definition: script.h:205
btc_bool btc_script_is_multisig ( vector ops)

Definition at line 227 of file script.c.

References btc_script_is_op(), btc_script_is_op_pubkey(), btc_script_is_op_smallint(), vector::len, OP_CHECKMULTISIG, and vector_idx.

Referenced by btc_script_classify().

228 {
229  if ((ops->len < 3) || (ops->len > (16 + 3)) ||
231  !btc_script_is_op_smallint(vector_idx(ops, ops->len - 2)) ||
233  return false;
234 
235  unsigned int i;
236  for (i = 1; i < (ops->len - 2); i++)
237  if (!btc_script_is_op_pubkey(vector_idx(ops, i)))
238  return false;
239 
240  return true;
241 }
static btc_bool btc_script_is_op_pubkey(const btc_script_op *op)
Definition: script.c:175
#define vector_idx(vec, idx)
Definition: vector.h:59
static btc_bool btc_script_is_op_smallint(const btc_script_op *op)
Definition: script.c:221
size_t len
Definition: vector.h:42
static btc_bool btc_script_is_op(const btc_script_op *op, enum opcodetype opcode)
Definition: script.c:170
static btc_bool btc_script_is_op ( const btc_script_op op,
enum opcodetype  opcode 
)
static

Definition at line 170 of file script.c.

References btc_script_op_::op.

Referenced by btc_script_is_multisig(), btc_script_is_pubkey(), btc_script_is_pubkeyhash(), and btc_script_is_scripthash().

171 {
172  return (op->op == opcode);
173 }
enum opcodetype op
Definition: script.h:204
static btc_bool btc_script_is_op_pubkey ( const btc_script_op op)
static

Definition at line 175 of file script.c.

References btc_script_is_pushdata(), btc_script_op_::datalen, and btc_script_op_::op.

Referenced by btc_script_is_multisig(), and btc_script_is_pubkey().

176 {
177  if (!btc_script_is_pushdata(op->op))
178  return false;
179  if (op->datalen < 33 || op->datalen > 120)
180  return false;
181  return true;
182 }
size_t datalen
Definition: script.h:206
static btc_bool btc_script_is_pushdata(enum opcodetype op)
Definition: script.c:165
enum opcodetype op
Definition: script.h:204
static btc_bool btc_script_is_op_pubkeyhash ( const btc_script_op op)
static

Definition at line 184 of file script.c.

References btc_script_is_pushdata(), btc_script_op_::datalen, and btc_script_op_::op.

Referenced by btc_script_is_pubkeyhash(), and btc_script_is_scripthash().

185 {
186  if (!btc_script_is_pushdata(op->op))
187  return false;
188  if (op->datalen != 20)
189  return false;
190  return true;
191 }
size_t datalen
Definition: script.h:206
static btc_bool btc_script_is_pushdata(enum opcodetype op)
Definition: script.c:165
enum opcodetype op
Definition: script.h:204
static btc_bool btc_script_is_op_smallint ( const btc_script_op op)
static

Definition at line 221 of file script.c.

References btc_script_op_::op, OP_0, OP_1, and OP_16.

Referenced by btc_script_is_multisig().

222 {
223  return ((op->op == OP_0) ||
224  (op->op >= OP_1 && op->op <= OP_16));
225 }
Definition: script.h:74
Definition: script.h:58
enum opcodetype op
Definition: script.h:204
Definition: script.h:51
btc_bool btc_script_is_pubkey ( vector ops)

Definition at line 194 of file script.c.

References btc_script_is_op(), btc_script_is_op_pubkey(), vector::len, OP_CHECKSIG, and vector_idx.

Referenced by btc_script_classify().

195 {
196  return ((ops->len == 2) &&
199 }
static btc_bool btc_script_is_op_pubkey(const btc_script_op *op)
Definition: script.c:175
#define vector_idx(vec, idx)
Definition: vector.h:59
size_t len
Definition: vector.h:42
static btc_bool btc_script_is_op(const btc_script_op *op, enum opcodetype opcode)
Definition: script.c:170
btc_bool btc_script_is_pubkeyhash ( vector ops)

Definition at line 202 of file script.c.

References btc_script_is_op(), btc_script_is_op_pubkeyhash(), vector::len, OP_CHECKSIG, OP_DUP, OP_EQUALVERIFY, OP_HASH160, and vector_idx.

Referenced by btc_script_classify().

203 {
204  return ((ops->len == 5) &&
205  btc_script_is_op(vector_idx(ops, 0), OP_DUP) &&
210 }
#define vector_idx(vec, idx)
Definition: vector.h:59
size_t len
Definition: vector.h:42
static btc_bool btc_script_is_op(const btc_script_op *op, enum opcodetype opcode)
Definition: script.c:170
static btc_bool btc_script_is_op_pubkeyhash(const btc_script_op *op)
Definition: script.c:184
Definition: script.h:100
static btc_bool btc_script_is_pushdata ( enum opcodetype  op)
inlinestatic

Definition at line 165 of file script.c.

References OP_PUSHDATA4.

Referenced by btc_script_is_op_pubkey(), and btc_script_is_op_pubkeyhash().

166 {
167  return (op <= OP_PUSHDATA4);
168 }
btc_bool btc_script_is_scripthash ( vector ops)

Definition at line 213 of file script.c.

References btc_script_is_op(), btc_script_is_op_pubkeyhash(), vector::len, OP_EQUAL, OP_HASH160, and vector_idx.

Referenced by btc_script_classify().

214 {
215  return ((ops->len == 3) &&
219 }
#define vector_idx(vec, idx)
Definition: vector.h:59
size_t len
Definition: vector.h:42
static btc_bool btc_script_is_op(const btc_script_op *op, enum opcodetype opcode)
Definition: script.c:170
static btc_bool btc_script_is_op_pubkeyhash(const btc_script_op *op)
Definition: script.c:184
void btc_script_op_free ( btc_script_op script_op)

Definition at line 90 of file script.c.

References btc_script_op_::data, btc_script_op_::datalen, btc_script_op_::op, and OP_0.

Referenced by btc_script_get_ops(), and btc_script_op_free_cb().

91 {
92  if (script_op->data) {
93  free(script_op->data);
94  script_op->data = NULL;
95  }
96  script_op->datalen = 0;
97  script_op->op = OP_0;
98 }
size_t datalen
Definition: script.h:206
enum opcodetype op
Definition: script.h:204
Definition: script.h:51
unsigned char * data
Definition: script.h:205
void btc_script_op_free_cb ( void *  data)

Definition at line 100 of file script.c.

References btc_script_op_free().

101 {
102  btc_script_op* script_op = data;
103  btc_script_op_free(script_op);
104 
105  free(script_op);
106 }
void btc_script_op_free(btc_script_op *script_op)
Definition: script.c:90
btc_script_op* btc_script_op_new ( )

Definition at line 81 of file script.c.

Referenced by btc_script_get_ops().

82 {
83  btc_script_op* script_op;
84  script_op = calloc(1, sizeof(*script_op));
85 
86  return script_op;
87 }