github.com/piotrnar/gocoin@v0.0.0-20240512203912-faa0448c5e96/lib/script/libbitcoinconsensus/consensus_darwin.go (about)

     1  package script
     2  
     3  /*
     4  #cgo LDFLAGS:
     5  
     6  #include <stdio.h>
     7  #include <dlfcn.h>
     8  
     9  unsigned int (*_bitcoinconsensus_version)();
    10  
    11  int (*_bitcoinconsensus_verify_script_with_amount)(const unsigned char *scriptPubKey, unsigned int scriptPubKeyLen, int64_t amount,
    12                                      const unsigned char *txTo        , unsigned int txToLen,
    13                                      unsigned int nIn, unsigned int flags, int* err);
    14  
    15  int (*_bitcoinconsensus_verify_script_with_spent_outputs)(const unsigned char *scriptPubKey, unsigned int scriptPubKeyLen, int64_t amount,
    16                                      const unsigned char *txTo        , unsigned int txToLen,
    17                                      const unsigned char *spentOutputs, unsigned int spentOutputsLen,
    18                                      unsigned int nIn, unsigned int flags, int* err);
    19  
    20  
    21  int init_bitcoinconsensus_dylib() {
    22  	void *so = dlopen("libbitcoinconsensus.dylib", RTLD_LAZY);
    23  	if (so) {
    24  		*(void **)(&_bitcoinconsensus_version) = dlsym(so, "bitcoinconsensus_version");
    25  		*(void **)(&_bitcoinconsensus_verify_script_with_amount) = dlsym(so, "bitcoinconsensus_verify_script_with_amount");
    26  		*(void **)(&_bitcoinconsensus_verify_script_with_spent_outputs) = dlsym(so, "bitcoinconsensus_verify_script_with_spent_outputs");
    27  		if (!_bitcoinconsensus_version) {
    28  			printf("libbitcoinconsensus.dylib not found\n");
    29  			return 0;
    30  		}
    31  		printf("bitcoinconsensus_version %d\n", _bitcoinconsensus_version());
    32  		if (!_bitcoinconsensus_verify_script_with_amount) {
    33  			printf("libbitcoinconsensus.dylib is too old. Use one of bitcoin-core 0.13.1\n");
    34  			return 0;
    35  		}
    36  		if (!_bitcoinconsensus_verify_script_with_spent_outputs) {
    37  			printf("libbitcoinconsensus.dylib is too old. Use one of bitcoin-core 0.22.0\n");
    38  			return 0;
    39  		}
    40  		return 1;
    41  	}
    42  	return 0;
    43  }
    44  
    45  int bitcoinconsensus_verify_script_with_amount(const unsigned char *scriptPubKey, unsigned int scriptPubKeyLen, int64_t amount,
    46                                      const unsigned char *txTo        , unsigned int txToLen,
    47                                      unsigned int nIn, unsigned int flags, int *err) {
    48  	return _bitcoinconsensus_verify_script_with_amount(scriptPubKey, scriptPubKeyLen, amount, txTo, txToLen, nIn, flags, err);
    49  }
    50  
    51  
    52  int bitcoinconsensus_verify_script_with_spent_outputs(const unsigned char *scriptPubKey, unsigned int scriptPubKeyLen, int64_t amount,
    53                                      const unsigned char *txTo        , unsigned int txToLen,
    54                                      const unsigned char *spentOutputs, unsigned int spentOutputsLen,
    55                                      unsigned int nIn, unsigned int flags, int* err) {
    56  	return _bitcoinconsensus_verify_script_with_spent_outputs(scriptPubKey, scriptPubKeyLen, amount,
    57                                      txTo, txToLen, spentOutputs, spentOutputsLen, nIn, flags, err);
    58  }
    59  
    60  
    61  unsigned int bitcoinconsensus_version() {
    62  	return _bitcoinconsensus_version();
    63  }
    64  */
    65  import "C"
    66  
    67  import (
    68  	//"os"
    69  	"bytes"
    70  	"encoding/binary"
    71  	"fmt"
    72  	"github.com/piotrnar/gocoin/lib/btc"
    73  	"unsafe"
    74  )
    75  
    76  func verify_script_with_amount(pkScr []byte, amount uint64, i int, tx *btc.Tx, ver_flags uint32) (result bool) {
    77  	var bcerr int
    78  	txTo := tx.Raw
    79  	if txTo == nil {
    80  		txTo = tx.SerializeNew()
    81  	}
    82  	var pkscr_ptr *C.uchar // default to null
    83  	var pkscr_len C.uint   // default to 0
    84  	if pkScr != nil {
    85  		pkscr_ptr = (*C.uchar)(unsafe.Pointer(&pkScr[0]))
    86  		pkscr_len = C.uint(len(pkScr))
    87  	}
    88  	r1 := int(C.bitcoinconsensus_verify_script_with_amount(pkscr_ptr, pkscr_len, C.int64_t(amount),
    89  		(*C.uchar)(unsafe.Pointer(&txTo[0])), C.uint(len(txTo)), C.uint(i), C.uint(ver_flags),
    90  		(*C.int)(unsafe.Pointer(&bcerr))))
    91  
    92  	//println("res:", bcerr, r1)
    93  	result = bcerr == 0 && r1 == 1
    94  	return
    95  }
    96  
    97  func verify_script_with_spent_outputs(pkScr []byte, amount uint64, outs []byte, i int, tx *btc.Tx, ver_flags uint32) (result bool) {
    98  	var bcerr int
    99  	txTo := tx.Raw
   100  	if txTo == nil {
   101  		txTo = tx.SerializeNew()
   102  	}
   103  	var pkscr_ptr *C.uchar // default to null
   104  	var pkscr_len C.uint   // default to 0
   105  	if pkScr != nil {
   106  		pkscr_ptr = (*C.uchar)(unsafe.Pointer(&pkScr[0]))
   107  		pkscr_len = C.uint(len(pkScr))
   108  	}
   109  	var outs_ptr *C.uchar // default to null
   110  	var outs_len C.uint   // default to 0
   111  	if outs != nil {
   112  		outs_ptr = (*C.uchar)(unsafe.Pointer(&outs[0]))
   113  		outs_len = C.uint(len(outs))
   114  	}
   115  	r1 := int(C.bitcoinconsensus_verify_script_with_spent_outputs(pkscr_ptr, pkscr_len, C.int64_t(amount),
   116  		(*C.uchar)(unsafe.Pointer(&txTo[0])), C.uint(len(txTo)), outs_ptr, outs_len,
   117  		C.uint(i), C.uint(ver_flags), (*C.int)(unsafe.Pointer(&bcerr))))
   118  
   119  	//println("reS:", bcerr, r1)
   120  	result = bcerr == 0 && r1 == 1
   121  	return
   122  }
   123  
   124  func txout_serialize(to *btc.TxOut) []byte {
   125  	b := new(bytes.Buffer)
   126  	binary.Write(b, binary.LittleEndian, to.Value)
   127  	btc.WriteVlen(b, uint64(len(to.Pk_script)))
   128  	b.Write(to.Pk_script)
   129  	return b.Bytes()
   130  }
   131  
   132  func myVerifyTxScript(pkScr []byte, checker *SigChecker, ver_flags uint32) (result bool) {
   133  	tx := checker.Tx
   134  	i := checker.Idx
   135  	
   136  	if (ver_flags & VER_TAPROOT) != 0 {
   137  		_b := new(bytes.Buffer)
   138  		btc.WriteVlen(_b, uint64(len(tx.Spent_outputs)))
   139  		outs := _b.Bytes()
   140  		for _, to := range tx.Spent_outputs {
   141  			outs = append(outs, txout_serialize(to)...)
   142  		}
   143  
   144  		return verify_script_with_spent_outputs(pkScr, checker.Amount, outs, i, tx, ver_flags)
   145  	}
   146  	
   147  	return verify_script_with_amount(pkScr, checker.Amount, i, tx, ver_flags)
   148  }
   149  
   150  func init() {
   151  	if C.init_bitcoinconsensus_dylib() != 0 {
   152  		fmt.Println("Using bitcoinconsensus lib to verify transactions")
   153  		HookVerifyTxScript = myVerifyTxScript
   154  	} else {
   155  		panic("libbitcoinconsensus.dylib not found")
   156  	}
   157  }