github.com/piotrnar/gocoin@v0.0.0-20240512203912-faa0448c5e96/client/usif/textui/consensus/consensus_windows.go (about)

     1  // +build windows
     2  
     3  // On Windows OS copy this file to gocoin\client\usif\textui to enable consensus checking
     4  // Make sure you have proper "libbitcoinconsensus-0.dll" in a folder where OS can find it.
     5  
     6  package textui
     7  
     8  import (
     9  	"encoding/hex"
    10  	"fmt"
    11  	"github.com/piotrnar/gocoin/client/common"
    12  	"github.com/piotrnar/gocoin/lib/btc"
    13  	"github.com/piotrnar/gocoin/lib/script"
    14  	"sync"
    15  	"sync/atomic"
    16  	"syscall"
    17  	"unsafe"
    18  )
    19  
    20  const (
    21  	DllName = "libbitcoinconsensus-0.dll"
    22  )
    23  
    24  /*
    25  EXPORT_SYMBOL int bitcoinconsensus_verify_script(const unsigned char *scriptPubKey, unsigned int scriptPubKeyLen,
    26                                                   const unsigned char *txTo        , unsigned int txToLen,
    27                                                   unsigned int nIn, unsigned int flags, bitcoinconsensus_error* err);
    28  
    29  EXPORT_SYMBOL int bitcoinconsensus_verify_script_with_amount(const unsigned char *scriptPubKey, unsigned int scriptPubKeyLen, int64_t amount,
    30                                      const unsigned char *txTo        , unsigned int txToLen,
    31                                      unsigned int nIn, unsigned int flags, bitcoinconsensus_error* err);
    32  
    33  EXPORT_SYMBOL unsigned int bitcoinconsensus_version();
    34  }
    35  */
    36  
    37  var (
    38  	bitcoinconsensus_verify_script_with_amount *syscall.Proc
    39  	bitcoinconsensus_version                   *syscall.Proc
    40  
    41  	ConsensusChecks uint64
    42  	ConsensusExpErr uint64
    43  	ConsensusErrors uint64
    44  
    45  	mut sync.Mutex
    46  )
    47  
    48  func check_consensus(pkScr []byte, amount uint64, i int, tx *btc.Tx, ver_flags uint32, result bool) {
    49  	var tmp []byte
    50  	if len(pkScr) != 0 {
    51  		tmp = make([]byte, len(pkScr))
    52  		copy(tmp, pkScr)
    53  	}
    54  	tx_raw := tx.Raw
    55  	if tx_raw == nil {
    56  		tx_raw = tx.Serialize()
    57  	}
    58  	go func(pkScr []byte, txTo []byte, i int, ver_flags uint32, result bool) {
    59  		var pkscr_ptr, pkscr_len uintptr // default to 0/null
    60  		if pkScr != nil {
    61  			pkscr_ptr = uintptr(unsafe.Pointer(&pkScr[0]))
    62  			pkscr_len = uintptr(len(pkScr))
    63  		}
    64  		r1, _, _ := syscall.Syscall9(bitcoinconsensus_verify_script_with_amount.Addr(), 8,
    65  			pkscr_ptr, pkscr_len, uintptr(amount),
    66  			uintptr(unsafe.Pointer(&txTo[0])), uintptr(len(txTo)),
    67  			uintptr(i), uintptr(ver_flags), 0, 0)
    68  
    69  		res := r1 == 1
    70  		atomic.AddUint64(&ConsensusChecks, 1)
    71  		if !result {
    72  			atomic.AddUint64(&ConsensusExpErr, 1)
    73  		}
    74  		if res != result {
    75  			atomic.AddUint64(&ConsensusErrors, 1)
    76  			common.CountSafe("TxConsensusERR")
    77  			mut.Lock()
    78  			println("Compare to consensus failed!")
    79  			println("Gocoin:", result, "   ConsLIB:", res)
    80  			println("pkScr", hex.EncodeToString(pkScr))
    81  			println("txTo", hex.EncodeToString(txTo))
    82  			println("amount:", amount, "  input_idx:", i, "  ver_flags:", ver_flags)
    83  			println()
    84  			mut.Unlock()
    85  		}
    86  	}(tmp, tx_raw, i, ver_flags, result)
    87  }
    88  
    89  func verify_script_with_amount(pkScr []byte, amount uint64, i int, tx *btc.Tx, ver_flags uint32) (result bool) {
    90  	var pkscr_ptr, pkscr_len uintptr // default to 0/null
    91  	txTo := tx.Raw
    92  	if txTo == nil {
    93  		txTo = tx.Serialize()
    94  	}
    95  	if pkScr != nil {
    96  		pkscr_ptr = uintptr(unsafe.Pointer(&pkScr[0]))
    97  		pkscr_len = uintptr(len(pkScr))
    98  	}
    99  	r1, _, _ := syscall.Syscall9(bitcoinconsensus_verify_script_with_amount.Addr(), 8,
   100  		pkscr_ptr, pkscr_len, uintptr(amount),
   101  		uintptr(unsafe.Pointer(&txTo[0])), uintptr(len(txTo)),
   102  		uintptr(i), uintptr(ver_flags), 0, 0)
   103  
   104  	result = (r1 == 1)
   105  	return
   106  }
   107  
   108  func consensus_stats(s string) {
   109  	fmt.Println("Consensus Checks:", atomic.LoadUint64(&ConsensusChecks))
   110  	fmt.Println("Consensus ExpErr:", atomic.LoadUint64(&ConsensusExpErr))
   111  	fmt.Println("Consensus Errors:", atomic.LoadUint64(&ConsensusErrors))
   112  }
   113  
   114  func init() {
   115  	dll, er := syscall.LoadDLL(DllName)
   116  	if er != nil {
   117  		//common.Log.Println(er.Error())
   118  		common.Log.Println("Not using", DllName, "to cross-check consensus rules")
   119  		return
   120  	}
   121  	bitcoinconsensus_verify_script_with_amount, er = dll.FindProc("bitcoinconsensus_verify_script_with_amount")
   122  	if er == nil {
   123  		bitcoinconsensus_version, er = dll.FindProc("bitcoinconsensus_version")
   124  	}
   125  	if er != nil {
   126  		common.Log.Println(er.Error())
   127  		common.Log.Println(DllName, "is probably too old. Use one of bitcoin-core 0.13.1 or later")
   128  		common.Log.Println("WARNING: Consensus cross-checking disabled")
   129  		return
   130  	}
   131  	r1, _, _ := syscall.Syscall(bitcoinconsensus_version.Addr(), 0, 0, 0, 0)
   132  	common.Log.Println("Using", DllName, "version", r1, "to cross-check consensus rules")
   133  	script.VerifyConsensus = check_consensus
   134  	newUi("cons", false, consensus_stats, "See statistics of the consensus cross-checks")
   135  }