func (a *BuyActivity) transmitWorkChunked(log bitwrk.Logger, client *http.Client, compressed bool) (io.ReadCloser, error) { if r, err := a.requestMissingChunks(log.New("request missing chunks"), client); err != nil { return nil, err } else { defer r.Close() numChunks := a.workFile.NumChunks() if numChunks > MaxNumberOfChunksInWorkFile { return nil, fmt.Errorf("Work file too big: %d chunks (only %d allowed).", numChunks, MaxNumberOfChunksInWorkFile) } wishList := make([]byte, int(numChunks+7)/8) if _, err := io.ReadFull(r, wishList); err != nil { return nil, fmt.Errorf("Error decoding list of missing chunks: %v", err) } return a.sendMissingChunksAndReturnResult(log.New("send work chunk data"), client, wishList, compressed) } }
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 }