Beispiel #1
0
func (a *SellActivity) HandleWork(log bitwrk.Logger, workFile cafs.File, buyerSecret bitwrk.Thash) (io.ReadCloser, error) {
	// Wait for buyer to establish
	active := true
	var workHash, workSecretHash *bitwrk.Thash
	log.Printf("Watching transaction state...")
	a.waitWhile(func() bool {
		active = a.tx.State == bitwrk.StateActive
		workHash, workSecretHash = a.tx.WorkHash, a.tx.WorkSecretHash
		log.Printf("  state: %v    phase: %v", a.tx.State, a.tx.Phase)
		return active && a.tx.Phase != bitwrk.PhaseTransmitting
	})

	if !active {
		return nil, fmt.Errorf("Transaction timed out waiting for buyer to establish")
	}

	// Verify work hash
	if *workHash != bitwrk.Thash(workFile.Key()) {
		return nil, fmt.Errorf("WorkHash and received data do not match")
	}

	if err := verifyBuyerSecret(workHash, workSecretHash, &buyerSecret); err != nil {
		return nil, err
	}

	log.Println("Got valid work data. Publishing buyer's secret.")
	if err := SendTxMessagePublishBuyerSecret(a.txId, a.identity, &buyerSecret); err != nil {
		return nil, fmt.Errorf("Error publishing buyer's secret: %v", err)
	}

	log.Println("Starting to work...")
	r, err := a.dispatchWork(log, workFile)
	if err != nil {
		log.Printf("Rejecting work because of error '%v'", err)
		if err := SendTxMessageRejectWork(a.txId, a.identity); err != nil {
			log.Printf("Rejecting work failed: %v", err)
		}
	}
	return r, err
}
Beispiel #2
0
func (a *BuyActivity) doPerformBuy(log bitwrk.Logger, interrupt <-chan bool) (cafs.File, error) {
	if err := a.beginTrade(log, interrupt); err != nil {
		return nil, err
	}

	// draw random bytes for buyer's secret
	var secret bitwrk.Thash
	if _, err := rand.Reader.Read(secret[:]); err != nil {
		return nil, err
	}
	a.execSync(func() { a.buyerSecret = &secret })
	log.Printf("Computed buyer's secret.")

	// Get work hash
	var workHash, workSecretHash bitwrk.Thash
	workHash = bitwrk.Thash(a.workFile.Key())

	// compute workSecretHash = hash(workHash | secret)
	hash := sha256.New()
	hash.Write(workHash[:])
	hash.Write(secret[:])
	hash.Sum(workSecretHash[:0])

	// Start polling for transaction state changes in background
	abortPolling := make(chan bool)
	defer func() {
		abortPolling <- true // Stop polling when sell has ended
	}()
	go func() {
		a.pollTransaction(log, abortPolling)
	}()

	if err := SendTxMessageEstablishBuyer(a.txId, a.identity, workHash, workSecretHash); err != nil {
		return nil, fmt.Errorf("Error establishing buyer: %v", err)
	}

	if err := a.waitForTransactionPhase(log.New("establishing"), bitwrk.PhaseTransmitting, bitwrk.PhaseEstablishing, bitwrk.PhaseSellerEstablished, bitwrk.PhaseBuyerEstablished); err != nil {
		return nil, fmt.Errorf("Error awaiting TRANSMITTING phase: %v", err)
	}

	var sellerErr error
	if err := a.interactWithSeller(log.New("transmitting")); err != nil {
		sellerErr = fmt.Errorf("Error transmitting work and receiving encrypted result: %v", err)
	}

	var phaseErr error
	if err := a.waitForTransactionPhase(log, bitwrk.PhaseUnverified, bitwrk.PhaseTransmitting, bitwrk.PhaseWorking); err != nil {
		phaseErr = fmt.Errorf("Error awaiting UNVERIFIED phase: %v", err)
	}

	if sellerErr == nil && phaseErr == nil {
		// Everythong went fine, continue
	} else if sellerErr == nil {
		return nil, phaseErr
	} else if phaseErr == nil {
		return nil, sellerErr
	} else {
		return nil, fmt.Errorf("%v. Additionally: %v", phaseErr, sellerErr)
	}

	a.execSync(func() { a.encResultKey = a.tx.ResultDecryptionKey })

	if err := a.decryptResult(); err != nil {
		return nil, fmt.Errorf("Error decrypting result: %v", err)
	}

	// In normal buys (without verifying), we can leave the rest as homework
	// for a goroutine and exit here.
	go func() {
		if err := a.finishBuy(log); err != nil {
			log.Printf("Error finishing buy: %v", err)
		}
	}()

	return a.resultFile, nil
}