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 }