github.com/myafeier/fabric@v1.0.1-0.20170722181825-3a4b1f2bce86/examples/chaincode/go/utxo/util/utxo_test.go (about)

     1  /*
     2  Copyright IBM Corp. 2016 All Rights Reserved.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8  		 http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package util
    18  
    19  import (
    20  	"encoding/base64"
    21  	"encoding/hex"
    22  	"fmt"
    23  	"io/ioutil"
    24  	"strings"
    25  	"sync"
    26  	"testing"
    27  
    28  	"github.com/golang/protobuf/proto"
    29  	"github.com/hyperledger/fabric/examples/chaincode/go/utxo/consensus"
    30  )
    31  
    32  // func TestMain(m *testing.M) {
    33  // 	// viper.Set("ledger.blockchain.deploy-system-chaincode", "false")
    34  //
    35  // 	os.Exit(m.Run())
    36  // }
    37  
    38  const txFileHashes = "./Hashes_for_first_500_transactions_on_testnet3.txt"
    39  const txFile = "./First_500_transactions_base64_encoded_on_testnet3.txt"
    40  
    41  const consensusScriptVerifyTx = "01000000017d01943c40b7f3d8a00a2d62fa1d560bf739a2368c180615b0a7937c0e883e7c000000006b4830450221008f66d188c664a8088893ea4ddd9689024ea5593877753ecc1e9051ed58c15168022037109f0d06e6068b7447966f751de8474641ad2b15ec37f4a9d159b02af68174012103e208f5403383c77d5832a268c9f71480f6e7bfbdfa44904becacfad66163ea31ffffffff01c8af0000000000001976a91458b7a60f11a904feef35a639b6048de8dd4d9f1c88ac00000000"
    42  const consensusScriptVerifyPreviousOutputScript = "76a914c564c740c6900b93afc9f1bdaef0a9d466adf6ee88ac"
    43  
    44  type block struct {
    45  	transactions []string
    46  }
    47  
    48  func makeBlock() *block {
    49  	//return &block{transactions: make([]string, 0)}
    50  	return &block{}
    51  }
    52  
    53  func (b *block) addTxAsBase64String(txAsString string) error {
    54  	b.transactions = append(b.transactions, txAsString)
    55  	return nil
    56  }
    57  
    58  //getTransactionsAsUTXOBytes returns a readonly channel of the transactions within this block as UTXO []byte
    59  func (b *block) getTransactionsAsUTXOBytes() <-chan []byte {
    60  	resChannel := make(chan []byte)
    61  	go func() {
    62  		defer close(resChannel)
    63  		for _, txAsText := range b.transactions {
    64  			data, err := base64.StdEncoding.DecodeString(txAsText)
    65  			if err != nil {
    66  				panic(fmt.Errorf("Could not decode transaction (%s) into bytes use base64 decoding:  %s\n", txAsText, err))
    67  			}
    68  			resChannel <- data
    69  		}
    70  	}()
    71  	return resChannel
    72  }
    73  
    74  var blocksFromFile []*block
    75  var once sync.Once
    76  
    77  // getBlocks returns the blocks parsed from txFile, but only parses once.
    78  func getBlocks() ([]*block, error) {
    79  	var err error
    80  	once.Do(func() {
    81  		contents, err := ioutil.ReadFile(txFile)
    82  		if err != nil {
    83  			return
    84  		}
    85  		lines := strings.Split(string(contents), string('\n'))
    86  		var currBlock *block
    87  		for _, line := range lines {
    88  			if strings.HasPrefix(line, "Block") {
    89  				currBlock = makeBlock()
    90  				blocksFromFile = append(blocksFromFile, currBlock)
    91  			} else {
    92  				// Trim out the 'Transacion XX:' part
    93  				//currBlock.addTxAsBase64String(strings.Split(line, ": ")[1])
    94  				currBlock.addTxAsBase64String(line)
    95  			}
    96  		}
    97  	})
    98  
    99  	return blocksFromFile, err
   100  }
   101  
   102  func TestVerifyScript_InvalidTranscation(t *testing.T) {
   103  	arg1 := []byte("arg1")
   104  	arg2 := int64(4)
   105  	arg3 := []byte("arg2")
   106  	arg4 := int64(4)
   107  	arg5 := uint(100)
   108  	arg6 := uint(1)
   109  	//func Verify_script(arg1 *byte, arg2 int64, arg3 *byte, arg4 int64, arg5 uint, arg6 uint) (_swig_ret LibbitcoinConsensusVerify_result_type)
   110  	result := consensus.Verify_script(&arg1[0], arg2, &arg3[0], arg4, arg5, arg6)
   111  	t.Log(result)
   112  	t.Log(consensus.Verify_result_tx_invalid)
   113  	if result != consensus.Verify_result_tx_invalid {
   114  		t.Fatalf("Should have failed to verify transaction")
   115  	}
   116  }
   117  
   118  func TestParse_GetBlocksFromFile(t *testing.T) {
   119  	blocks, err := getBlocks()
   120  	if err != nil {
   121  		t.Fatalf("Error getting blocks from tx file: %s", err)
   122  	}
   123  	for index, b := range blocks {
   124  		t.Logf("block %d has len transactions = %d", index, len(b.transactions))
   125  	}
   126  	t.Logf("Number of blocks = %d from file %s", len(blocks), txFile)
   127  }
   128  
   129  //TestBlocks_GetTransactionsAsUTXOBytes will range over blocks and then transactions in UTXO bytes form.
   130  func TestBlocks_GetTransactionsAsUTXOBytes(t *testing.T) {
   131  	blocks, err := getBlocks()
   132  	if err != nil {
   133  		t.Fatalf("Error getting blocks from tx file: %s", err)
   134  	}
   135  	// Loop through the blocks and then range over their transactions in UTXO bytes form.
   136  	for index, b := range blocks {
   137  		t.Logf("block %d has len transactions = %d", index, len(b.transactions))
   138  		for txAsUTXOBytes := range b.getTransactionsAsUTXOBytes() {
   139  			//t.Logf("Tx as bytes = %v", txAsUTXOBytes)
   140  			_ = len(txAsUTXOBytes)
   141  		}
   142  	}
   143  }
   144  
   145  func TestParse_UTXOTransactionBytes(t *testing.T) {
   146  	blocks, err := getBlocks()
   147  	if err != nil {
   148  		t.Fatalf("Error getting blocks from tx file: %s", err)
   149  	}
   150  	utxo := MakeUTXO(MakeInMemoryStore())
   151  	// Loop through the blocks and then range over their transactions in UTXO bytes form.
   152  	for index, b := range blocks {
   153  		t.Logf("block %d has len transactions = %d", index, len(b.transactions))
   154  		for txAsUTXOBytes := range b.getTransactionsAsUTXOBytes() {
   155  
   156  			newTX := ParseUTXOBytes(txAsUTXOBytes)
   157  			t.Logf("Block = %d, txInputCount = %d, outputCount=%d", index, len(newTX.Txin), len(newTX.Txout))
   158  
   159  			// Now store the HEX of txHASH
   160  			execResult, err := utxo.Execute(txAsUTXOBytes)
   161  			if err != nil {
   162  				t.Fatalf("Error executing TX:  %s", err)
   163  			}
   164  			if execResult.IsCoinbase == false {
   165  				if execResult.SumCurrentOutputs > execResult.SumPriorOutputs {
   166  					t.Fatalf("sumOfCurrentOutputs > sumOfPriorOutputs: sumOfCurrentOutputs = %d, sumOfPriorOutputs = %d", execResult.SumCurrentOutputs, execResult.SumPriorOutputs)
   167  				}
   168  			}
   169  
   170  			txHash := utxo.GetTransactionHash(txAsUTXOBytes)
   171  			retrievedTx := utxo.Query(hex.EncodeToString(txHash))
   172  			if !proto.Equal(newTX, retrievedTx) {
   173  				t.Fatal("Expected TX to be equal. ")
   174  			}
   175  		}
   176  	}
   177  
   178  }
   179  
   180  func TestParse_LibbitconTX(t *testing.T) {
   181  	txData, err := hex.DecodeString(consensusScriptVerifyTx)
   182  	if err != nil {
   183  		t.Fatalf("Error decoding HEX tx from libbitcoin:  %s", err)
   184  		return
   185  	}
   186  
   187  	prevTxScript, err := hex.DecodeString(consensusScriptVerifyPreviousOutputScript)
   188  	if err != nil {
   189  		t.Fatalf("Error decoding HEX tx from libbitcoin:  %s", err)
   190  		return
   191  	}
   192  
   193  	t.Logf("TX data from libbitcoin: %v", txData)
   194  
   195  	tx := ParseUTXOBytes(txData)
   196  
   197  	// Call Verify_script
   198  	txInputIndex := uint(0)
   199  	result := consensus.Verify_script(&txData[0], int64(len(txData)), &prevTxScript[0], int64(len(prevTxScript)), txInputIndex, uint(consensus.Verify_flags_p2sh))
   200  	if result != consensus.Verify_result_eval_true {
   201  		t.Fatalf("Unexpected result from verify_script, expected %d, got %d", consensus.Verify_result_eval_true, result)
   202  	}
   203  	t.Log(result)
   204  	t.Log(consensus.Verify_result_eval_true)
   205  	t.Logf("TX from %v", tx)
   206  }