func (u *UTXO) Execute(txData []byte) (*ExecResult, error) { newTX := ParseUTXOBytes(txData) txHash := u.GetTransactionHash(txData) execResult := &ExecResult{} // Loop through outputs first for index, output := range newTX.Txout { currKey := &Key{TxHashAsHex: hex.EncodeToString(txHash[:]), TxIndex: uint32(index)} _, ok, err := u.Store.GetState(*currKey) if err != nil { return nil, fmt.Errorf("Error getting state from store: %s", err) } if ok == true { // COLLISION return nil, fmt.Errorf("COLLISION detected for key = %v, with output script length = ", currKey, len(output.Script)) } // Store the ouput in utxo u.Store.PutState(*currKey, &TX_TXOUT{Script: output.Script, Value: output.Value}) execResult.SumCurrentOutputs += output.Value } // Now loop over inputs, for index, input := range newTX.Txin { prevTxHash := input.SourceHash prevOutputIx := input.Ix if u.IsCoinbase(prevOutputIx) { execResult.IsCoinbase = true //fmt.Println("COINBASE!!") } else { //fmt.Println("NOT COINBASE!!") // NOT coinbase, need to verify keyToPrevOutput := &Key{TxHashAsHex: hex.EncodeToString(prevTxHash), TxIndex: prevOutputIx} value, ok, err := u.Store.GetState(*keyToPrevOutput) if err != nil { return nil, fmt.Errorf("Error getting state from store: %s", err) } if !ok { // Previous output not fouund, return nil, fmt.Errorf("Could not find previous transaction output with key = %v", keyToPrevOutput) } // Call Verify_script tx_input_index := uint(index) result := consensus.Verify_script(&txData[0], int64(len(txData)), &value.Script[0], int64(len(value.Script)), tx_input_index, uint(standardFlags)) if result != consensus.Verify_result_eval_true { result = consensus.Verify_script(&txData[0], int64(len(txData)), &value.Script[0], int64(len(value.Script)), tx_input_index, uint(mandatoryFlags)) if result != consensus.Verify_result_eval_true { return nil, fmt.Errorf("Unexpected result from verify_script, expected %d, got %d, perhaps it is %d", consensus.Verify_result_eval_true, result, consensus.Verify_result_invalid_stack_operation) } } // Verified, now remove prior outputs u.Store.DelState(*keyToPrevOutput) execResult.SumPriorOutputs += value.Value } hex := hex.EncodeToString(txHash[:]) fmt.Printf("PUT TRAN %s", hex) u.Store.PutTran(hex, txData) } return execResult, nil }
func TestParse_LibbitconTX(t *testing.T) { txData, err := hex.DecodeString(consensusScriptVerifyTx) if err != nil { t.Fatalf("Error decoding HEX tx from libbitcoin: %s", err) return } prevTxScript, err := hex.DecodeString(consensusScriptVerifyPreviousOutputScript) if err != nil { t.Fatalf("Error decoding HEX tx from libbitcoin: %s", err) return } t.Logf("TX data from libbitcoin: %v", txData) tx := ParseUTXOBytes(txData) // Call Verify_script txInputIndex := uint(0) result := consensus.Verify_script(&txData[0], int64(len(txData)), &prevTxScript[0], int64(len(prevTxScript)), txInputIndex, uint(consensus.Verify_flags_p2sh)) if result != consensus.Verify_result_eval_true { t.Fatalf("Unexpected result from verify_script, expected %d, got %d", consensus.Verify_result_eval_true, result) } t.Log(result) t.Log(consensus.Verify_result_eval_true) t.Logf("TX from %v", tx) }
func TestVerifyScript_InvalidTranscation(t *testing.T) { arg1 := []byte("arg1") arg2 := int64(4) arg3 := []byte("arg2") arg4 := int64(4) arg5 := uint(100) arg6 := uint(1) //func Verify_script(arg1 *byte, arg2 int64, arg3 *byte, arg4 int64, arg5 uint, arg6 uint) (_swig_ret LibbitcoinConsensusVerify_result_type) result := consensus.Verify_script(&arg1[0], arg2, &arg3[0], arg4, arg5, arg6) t.Log(result) t.Log(consensus.Verify_result_tx_invalid) if result != consensus.Verify_result_tx_invalid { t.Fatalf("Should have failed to verify transaction") } }