1

I have managed to get correct sighashes for situations in which there are no OP_CODESEPARATOR ops in the code. However, I cannot figure out, based on the UAHF documentation nor on the C++ code in the Bitcoin-ABC repository, how I am supposed to serialize the scriptCodes with the codeseparator OP. Here is my serialization function (from the Picocoin C library):

void uahf_ser_scriptCode(cstring *s, const cstring *scriptCode){

    if(scriptCode == NULL){
        cstr_append_c(s, 0);
        return;
    }
    struct const_buffer it = { scriptCode->str, scriptCode->len };


    struct const_buffer itBegin = it;
    struct bscript_op op;
    unsigned int nCodeSeparators = 0;
    struct bscript_parser bp;

    bsp_start(&bp, &it);
    while (bsp_getop(&op, &bp)) {
        if (op.op == OP_CODESEPARATOR){
            nCodeSeparators++;
            fprintf(stderr,"code separator\n");
        }

    }


    if(nCodeSeparators == 0){
        ser_varlen(s, scriptCode->len);
        ser_bytes(s, scriptCode->str, scriptCode->len);
        return;
    }



    //ser_varlen(s, scriptCode->len - nCodeSeparators);
    it = itBegin;
    bsp_start(&bp, &it);
    int count = 0;
    cstring *x = cstr_new_sz(1024*10);
    while (bsp_getop(&op, &bp) && count < nCodeSeparators) {
        if (op.op == OP_CODESEPARATOR) {
            count++;
            //ser_bytes(s, itBegin.p, it.p - itBegin.p - 1);
            /*if(count == nCodeSeparators){
                ser_bytes(x, itBegin.p, it.p - itBegin.p - 1);
            }*/
            itBegin  = it;
        }
    }


    if (itBegin.p != scriptCode->str + scriptCode->len)
        ser_bytes(x, itBegin.p, it.p - itBegin.p);

    ser_varlen(s,  x->len);
    cstr_append_buf(s,x->str,x->len);
    cstr_free(x, true);

}
2
  • Not a full answer, but perhaps it helps you already: bcash's sighash scheme is basically identical to BIP143. Sep 12 '17 at 0:40
  • I finally figured out what I was doing wrong. I just needed to include the OP_SEPARATORS when using the BIP143 scheme.
    – Joel D
    Sep 12 '17 at 5:28
0

I probably was too eager to ask this question, though perhaps someone can take a look at how I implemented the solution in this pull request. Here is the relevant code:

// from bp_tx_sigserializer function
void uahf_ser_scriptCode(cstring *s, const cstring *scriptCode){

    if(scriptCode == NULL){
        cstr_append_c(s, 0);
        return;
    }
    /** Serialize the passed scriptCode, skipping OP_CODESEPARATORs */
    struct const_buffer it = { scriptCode->str, scriptCode->len };
    struct const_buffer itBegin = it;
    struct bscript_op op;
    unsigned int nCodeSeparators = 0;

    struct bscript_parser bp;
    bsp_start(&bp, &it);

    while (bsp_getop(&op, &bp)) {
        if (op.op == OP_CODESEPARATOR)
            nCodeSeparators++;
    }
    cstring *x = cstr_new_sz(1024*8);

    it = itBegin;
    bsp_start(&bp, &it);

    while (bsp_getop(&op, &bp)) {
        if (op.op == OP_CODESEPARATOR) {
            ser_bytes(x, itBegin.p, it.p - itBegin.p - 1);
            itBegin  = it;
        }
    }

    if (itBegin.p != scriptCode->str + scriptCode->len)
        ser_bytes(x, itBegin.p, it.p - itBegin.p);

    if(0 < nCodeSeparators){
        cstr_free(x, true);
        x = cstr_new_sz(1024*8);
        cstr_append_buf(x,scriptCode->str,scriptCode->len);
    }
    ser_varlen(s, x->len);
    cstr_append_buf(s,x->str,x->len);
    cstr_free(x, true);
}

Not the answer you're looking for? Browse other questions tagged or ask your own question.