Example #1
0
func (inv *Inventory) handleTransaction(tx *messages.Transaction) {
	if !tx.MatchesFilter(inv.filter.Filter()) {
		log.Printf("Received transaction %x not matching the filter.", tx.Hash())

	} else {
		log.Printf("Received transaction %x matching the filter: %x", tx.Hash(), tx.Data())
	}
	inv.addTxData(tx.Hash(), tx)

	w := inv.config.Wallet
	if w != nil {
		if w.HasNewAddressesToWatch() {
			// A wallet has had its address space expand and we
			// need to add these new addresses to the filter and
			// unless we're certain this is a fresh transaction (as
			// opposed to a historic one), we need to rescan
			// history.
			for _, o := range w.WatchObjects() {
				inv.filter.Watch(o, filterMayNeedUpdate)
			}
			// TODO Decide whether or not to rescan history. This
			// can be done easily (but slowely) by setting height
			// back to 0.
		}
	}
}
Example #2
0
func (inv *Inventory) VerifyTransaction(tx *messages.Transaction) (bool, error) {
	var inputValue, outputValue uint64
	for index, input := range tx.Inputs {
		stack := script.Stack{}
		err := stack.Execute(input.Signature, nil)
		if err != nil {
			return false, fmt.Errorf("Failed to push signature: %v", err)
		}
		prev := input.PreviousOutput
		d, found := inv.txHashes[string(prev.Hash)]
		if !found {
			return false, fmt.Errorf("Input tx %x not found in map.", prev.Hash)
		}
		inputTx := d.tx
		output := inputTx.Outputs[prev.Index]
		inputValue += output.Value

		data := &script.Data{
			Hasher: func(c uint32) []byte {
				return utils.DoubleHash(tx.SignSerialize(
					index, output.Script, c))
			}}
		err = stack.Execute(output.Script, data)
		if err != nil {
			return false, fmt.Errorf("Failed to execute script: %v", err)
		}
		if !stack.CheckSuccess() {
			return false, fmt.Errorf("Signature on input %d not valid.", index)
		}
	}
	for _, output := range tx.Outputs {
		outputValue += output.Value
	}
	if outputValue > inputValue {
		return false, fmt.Errorf("Outputs have higher value (%d) than inputs (%d).",
			outputValue, inputValue)
	}
	return true, nil
}
Example #3
0
func (inv *Inventory) addTxData(hash []byte, data *messages.Transaction) {
	version, found := inv.txHashes[string(hash)]
	if !found {
		id := data.Fingerprint()
		log.Printf("Adding transaction hash %x for transaction %x", hash, id)
		version = &TxVersion{Hash: hash, tx: data}
		inv.txHashes[string(hash)] = version
		inv.config.Database.StoreNewTransaction(version)
	} else if version.tx == nil {
		version.tx = data
		inv.config.Database.StoreNewTransaction(version)
		if version.Block != nil {
			// This tx was confirmed earlier, but couldn't
			// invalidate duplicates until now; confirm it again.
			inv.transactionVersionConfirmed(version)
		}
	}
	tx, found := inv.transactions[string(version.Id())]
	if !found {
		log.Printf("Adding hash %x to transaction %x", hash, version.Id())
		tx = &Transaction{
			id:        version.Id(),
			timestamp: time.Now(),
			versions:  make(map[string]*messages.Transaction),
			block:     version.Block,
		}
		inv.transactions[string(version.Id())] = tx
	} else if tx.block != nil {
		// Another version of this transaction has already been confirmed.
		return
	}
	tx.versions[string(hash)] = data
	inv.UpdateTxOutputs(version)

	// Add transaction to filter. Remote nodes will do the same, so there's
	// no need to update them.
	inv.filter.Watch(hash, filterNoUpdateNeeded)
	// TODO verify TX
}