decred.org/dcrdex@v1.0.3/dex/networks/zec/tx_test.go (about)

     1  package zec
     2  
     3  import (
     4  	"bytes"
     5  	_ "embed"
     6  	"encoding/binary"
     7  	"encoding/hex"
     8  	"fmt"
     9  	"testing"
    10  
    11  	"github.com/btcsuite/btcd/txscript"
    12  )
    13  
    14  var (
    15  	//go:embed test-data/shielded_sapling_tx.dat
    16  	shieldedSaplingTx []byte
    17  	//go:embed test-data/unshielded_sapling_tx.dat
    18  	unshieldedSaplingTx []byte // mainnet
    19  	//go:embed test-data/unshielded_orchard_tx.dat
    20  	unshieldedOrchardTx []byte // testnet
    21  	//go:embed test-data/v4_sighash_vector_tx.dat
    22  	v4SighashVectorTx []byte
    23  	//go:embed test-data/v3_tx.dat
    24  	v3Tx []byte
    25  	//go:embed test-data/v2_joinsplit_tx.dat
    26  	v2JoinSplit []byte
    27  )
    28  
    29  func TestTxDeserializeV2(t *testing.T) {
    30  	// testnet tx 66bd29f14043843327fae377bd47659c6f02efd3aa62992a6ffa15ddd5fcbaff
    31  	tx, err := DeserializeTx(v2JoinSplit)
    32  	if err != nil {
    33  		t.Fatalf("error decoding tx: %v", err)
    34  	}
    35  	if len(tx.VJoinSplit) != 1 {
    36  		t.Fatalf("expected 1 vJoinSplit. saw %d", len(tx.VJoinSplit))
    37  	}
    38  	if tx.SerializeSize() != uint64(len(v2JoinSplit)) {
    39  		t.Fatalf("wrong serialized size. wanted %d, got %d", len(v2JoinSplit), tx.SerializeSize())
    40  	}
    41  	js := tx.VJoinSplit[0]
    42  	const expNew = 5338489
    43  	if js.New != expNew {
    44  		t.Fatalf("wrong joinsplit new. expected %d, got %d", expNew, js.New)
    45  	}
    46  }
    47  
    48  func TestTxDeserializeV3(t *testing.T) {
    49  	tx, err := DeserializeTx(v3Tx)
    50  	if err != nil {
    51  		t.Fatalf("error decoding tx: %v", err)
    52  	}
    53  
    54  	const expHash = "fc546132ad9c7bee2a2390ccafc54f29c23bf2f311233f89294665a6c4b7cfa7"
    55  	if tx.TxHash().String() != expHash {
    56  		t.Fatalf("wrong v3 hash")
    57  	}
    58  	if tx.SerializeSize() != uint64(len(v3Tx)) {
    59  		t.Fatalf("wrong serialized size. wanted %d, got %d", len(v3Tx), tx.SerializeSize())
    60  	}
    61  }
    62  
    63  func TestTxDeserializeV4(t *testing.T) {
    64  	tx, err := DeserializeTx(unshieldedSaplingTx)
    65  	if err != nil {
    66  		t.Fatalf("error decoding tx: %v", err)
    67  	}
    68  
    69  	const expHash = "fb70397806afddcc07b9607e844ff29f2fb09e9972a051c3fe4d56fe18147e77"
    70  	if tx.TxHash().String() != expHash {
    71  		t.Fatalf("wrong v4 hash")
    72  	}
    73  	if tx.SerializeSize() != uint64(len(unshieldedSaplingTx)) {
    74  		t.Fatalf("wrong serialized size. wanted %d, got %d", len(unshieldedSaplingTx), tx.SerializeSize())
    75  	}
    76  
    77  	if len(tx.TxIn) != 1 {
    78  		t.Fatalf("expected 1 input, got %d", len(tx.TxIn))
    79  	}
    80  
    81  	txIn := tx.TxIn[0]
    82  	if txIn.PreviousOutPoint.Hash.String() != "df0547ac001d335441bd621779e8946a1224949a014871b5f2a349352a270d69" {
    83  		t.Fatal("wrong previous outpoint hash")
    84  	}
    85  	if txIn.PreviousOutPoint.Index != 0 {
    86  		t.Fatal("wrong previous outpoint index")
    87  	}
    88  	if hex.EncodeToString(txIn.SignatureScript) != "47304402201656a4834651f39ac52eb866042ca7ede052ac843a914da4790573122c8e2ab302200af617e856abf4f8fb8d8086825dc63766943b4866ad3d6b4c8f222017c9b402012102d547eb1c5672a4d212de3c797a87b2b8fe731c2b502db6d7ad044850fe11d78f" {
    89  		t.Fatal("wrong signature script")
    90  	}
    91  	if txIn.Sequence != 4294967295 {
    92  		t.Fatalf("wrong sequence")
    93  	}
    94  
    95  	if len(tx.TxOut) != 2 {
    96  		t.Fatalf("expected 2 outputs, got %d", len(tx.TxOut))
    97  	}
    98  	txOut := tx.TxOut[1]
    99  	if txOut.Value != 41408718 {
   100  		t.Fatal("wrong value")
   101  	}
   102  	if hex.EncodeToString(txOut.PkScript) != "76a9144ff496917bae33309a8ad70bec81355bbf92988988ac" {
   103  		t.Fatalf("wrong pk script")
   104  	}
   105  
   106  	if sz := CalcTxSize(tx.MsgTx); sz != uint64(len(unshieldedSaplingTx)) {
   107  		t.Fatalf("wrong calculated tx size. wanted %d, got %d", len(unshieldedSaplingTx), sz)
   108  	}
   109  
   110  	serializedTx, err := tx.Bytes()
   111  	if err != nil {
   112  		t.Fatalf("error re-serializing: %v", err)
   113  	}
   114  	if !bytes.Equal(serializedTx, unshieldedSaplingTx) {
   115  		t.Fatalf("re-encoding does not match original")
   116  	}
   117  }
   118  
   119  func TestTxDeserializeV5(t *testing.T) {
   120  	tx, err := DeserializeTx(unshieldedOrchardTx)
   121  	if err != nil {
   122  		t.Fatalf("error decoding tx: %v", err)
   123  	}
   124  
   125  	const expHash = "a2a3e99169bad144e490708bbd9d4daf8dc9017397ad11e7a1e75a62f9919324" // testnet
   126  	if tx.TxHash().String() != expHash {
   127  		t.Fatalf("wrong v5 hash")
   128  	}
   129  	if tx.SerializeSize() != uint64(len(unshieldedOrchardTx)) {
   130  		t.Fatalf("wrong serialized size. wanted %d, got %d", len(unshieldedOrchardTx), tx.SerializeSize())
   131  	}
   132  
   133  	serializedTx, err := tx.Bytes()
   134  	if err != nil {
   135  		t.Fatalf("error re-serializing: %v", err)
   136  	}
   137  	if !bytes.Equal(serializedTx, unshieldedOrchardTx) {
   138  		fmt.Println("original:", hex.EncodeToString(unshieldedOrchardTx))
   139  		fmt.Println("re-encode:", hex.EncodeToString(serializedTx))
   140  		t.Fatalf("re-encoding does not match original")
   141  	}
   142  }
   143  
   144  func TestShieldedTx(t *testing.T) {
   145  	// Just make sure it doesn't error.
   146  	tx, err := DeserializeTx(shieldedSaplingTx)
   147  	if err != nil {
   148  		t.Fatalf("error decoding tx: %v", err)
   149  	}
   150  	if tx.SerializeSize() != uint64(len(shieldedSaplingTx)) {
   151  		t.Fatalf("wrong serialized size. wanted %d, got %d", len(shieldedSaplingTx), tx.SerializeSize())
   152  	}
   153  }
   154  
   155  func TestV5SigDigest(t *testing.T) {
   156  	// test vector generated with github.com/zcash-hackworks/zcash-testvectors
   157  	txB, _ := hex.DecodeString("050000800a27a726b4d0d6c27a8f739a2d6f2c0201e152a" +
   158  		"8049e294c4d6e66b164939daffa2ef6ee6921481cdd86b3cc4318d9614fc820905d045" +
   159  		"3516aaca3f2498800000000")
   160  	sigDigest, _ := hex.DecodeString("19e9b271cf0b6f9d60b2834eb16802ce1aa41cd8e96f50bd38dd8f4c4c82616f")
   161  	transparentDigest, _ := hex.DecodeString("f31a4521a8d04d8e1f01a614ad0627278c870b7c9a48306cc74587a349dd92b9")
   162  
   163  	const vin = 0
   164  	prevScript, _ := hex.DecodeString("650051")
   165  	const prevValue = 1800841178198868
   166  
   167  	tx, err := DeserializeTx(txB)
   168  	if err != nil {
   169  		t.Fatalf("error decoding tx: %v", err)
   170  	}
   171  
   172  	prevs, _ := hex.DecodeString("223b625f83e3cd9c127ad107fdb5402bfcd5f10681867f2fde8bcfb2aa2447ae")
   173  	amts, _ := hex.DecodeString("765008be6611a6e2a6520aa72fb67dc2d944577c26544d924a00d50ea7c58855")
   174  	scripts, _ := hex.DecodeString("1e43079ba1fa40d65beee6dd9b77b48017283b16438a852def75a5096cfea9b7")
   175  	seqs, _ := hex.DecodeString("17de0287f8f0c573fe74c52d1bd0e6b429cc9201390ededf4a625f5769e41716")
   176  	outputs, _ := hex.DecodeString("25f311cc149ecccef0e8ca8c9facd897ef88806008bc15818069470db9f84a37")
   177  	txinDigest, _ := hex.DecodeString("bb4ab0249df12a12df3d0d160f9ca6fbb0658c30dd44fd62d237994e77f2c1c6")
   178  
   179  	prevoutsDigest, err := tx.hashPrevOutsSigV5(false)
   180  	if err != nil {
   181  		return
   182  	}
   183  	if !bytes.Equal(prevs, prevoutsDigest[:]) {
   184  		t.Fatalf("wrong prevoutsDigest")
   185  	}
   186  
   187  	amtsDigest, err := tx.hashAmountsSig(false, []int64{prevValue})
   188  	if err != nil {
   189  		return
   190  	}
   191  	if !bytes.Equal(amts, amtsDigest[:]) {
   192  		t.Fatalf("wrong amtsDigest")
   193  	}
   194  
   195  	prevScriptsDigest, err := tx.hashPrevScriptsSig(false, [][]byte{prevScript})
   196  	if err != nil {
   197  		return
   198  	}
   199  	if !bytes.Equal(scripts, prevScriptsDigest[:]) {
   200  		t.Fatalf("wrong prevScriptsDigest")
   201  	}
   202  
   203  	seqsDigest, err := tx.hashSequenceSigV5(false)
   204  	if err != nil {
   205  		return
   206  	}
   207  	if !bytes.Equal(seqs, seqsDigest[:]) {
   208  		t.Fatalf("wrong seqsDigest")
   209  	}
   210  
   211  	outputsDigest, err := tx.hashOutputsSigV5(false)
   212  	if err != nil {
   213  		return
   214  	}
   215  	if !bytes.Equal(outputs, outputsDigest[:]) {
   216  		t.Fatalf("wrong outputsDigest")
   217  	}
   218  
   219  	txInsDigest, err := tx.hashTxInSig(vin, prevValue, prevScript)
   220  	if err != nil {
   221  		return
   222  	}
   223  	if !bytes.Equal(txinDigest, txInsDigest[:]) {
   224  		t.Fatalf("wrong txInsDigest")
   225  	}
   226  
   227  	td, err := tx.transparentSigDigestV5(0, txscript.SigHashAll, []int64{prevValue}, [][]byte{prevScript})
   228  	if err != nil {
   229  		t.Fatalf("transparentSigDigest error: %v", err)
   230  	}
   231  
   232  	if !bytes.Equal(td[:], transparentDigest) {
   233  		t.Fatalf("wrong digest")
   234  	}
   235  
   236  	sd, err := tx.SignatureDigest(0, txscript.SigHashAll, nil, []int64{prevValue}, [][]byte{prevScript})
   237  	if err != nil {
   238  		t.Fatalf("transparentSigDigest error: %v", err)
   239  	}
   240  
   241  	if !bytes.Equal(sd[:], sigDigest) {
   242  		t.Fatalf("wrong signatureDigest")
   243  	}
   244  }
   245  
   246  func TestV4SigDigest(t *testing.T) {
   247  	// Test Vector 3 from ZIP-0243, but fixed.
   248  	// Preimage and test vector in ZIP-0243 are WRONG!!!!
   249  	// The test vector's preimage DOES NOT include a varint for script size, but
   250  	// it should, and I modified zclassicd to log the preimage just to make
   251  	// sure. I had run into this problem in the Zcash docs before too. When they
   252  	// say "(serialized as scripts inside CTxOuts)", that's apparently code for
   253  	// adding the varint, but the guy tasked with generating test vectors
   254  	// apparently didn't get it either.
   255  	tx, err := DeserializeTx(v4SighashVectorTx)
   256  	if err != nil {
   257  		t.Fatalf("error decoding tx: %v", err)
   258  	}
   259  	amtLE, _ := hex.DecodeString("80f0fa0200000000")
   260  	val := binary.LittleEndian.Uint64(amtLE)
   261  	vals := []int64{int64(val)}
   262  
   263  	script, _ := hex.DecodeString("1976a914507173527b4c3318a2aecd793bf1cfed705950cf88ac")
   264  	pimg, err := tx.sighashPreimageV4(txscript.SigHashAll, 0, vals, script)
   265  	if err != nil {
   266  		t.Fatalf("sighashPreimageV4 error: %v", err)
   267  	}
   268  
   269  	expPimg, _ := hex.DecodeString(
   270  		"0400008085202f89fae31b8dec7b0b77e2c8d6b6eb0e7e4e55abc6574c26dd44464d94" +
   271  			"08a8e33f116c80d37f12d89b6f17ff198723e7db1247c4811d1a695d74d930f99e9841" +
   272  			"8790d2b04118469b7810a0d1cc59568320aad25a84f407ecac40b4f605a4e686845400" +
   273  			"0000000000000000000000000000000000000000000000000000000000000000000000" +
   274  			"0000000000000000000000000000000000000000000000000000000000000000000000" +
   275  			"0000000000000000000000000000000000000000000000000029b0040048b004000000" +
   276  			"00000000000001000000a8c685478265f4c14dada651969c45a65e1aeb8cd6791f2f5b" +
   277  			"b6a1d9952104d9010000001a1976a914507173527b4c3318a2aecd793bf1cfed705950" +
   278  			"cf88ac80f0fa0200000000feffffff",
   279  	)
   280  	if !bytes.Equal(pimg, expPimg) {
   281  		fmt.Println("preimage:", hex.EncodeToString(pimg))
   282  		t.Fatal("wrong preimage")
   283  	}
   284  	// After fixing the vector's preimage, the sighash obviously changed, but
   285  	// I'll leave this here to maintain expected behavior in case of future code
   286  	// updates.
   287  	expSighash, _ := hex.DecodeString("a358eb2ce8b214facba92761be09cc3e889e91a2e301146e8e40b5a6417da3d8")
   288  	h, err := tx.SignatureDigest(0, txscript.SigHashAll, script, vals, nil)
   289  	if err != nil {
   290  		t.Fatalf("SignatureDigest error: %v", err)
   291  	}
   292  	if !bytes.Equal(expSighash, h[:]) {
   293  		fmt.Println("sighash:", hex.EncodeToString(h[:]))
   294  		t.Fatal("wrong sighash")
   295  	}
   296  }