Esempio n. 1
0
// createServerTester creates a server tester object that is ready for testing,
// including money in the wallet and all modules initialized.
func createServerTester(name string) (*serverTester, error) {
	// createServerTester is expensive, and therefore should not be called
	// during short tests.
	if testing.Short() {
		panic("createServerTester called during short tests")
	}

	// Create the testing directory.
	testdir := build.TempDir("api", name)

	key, err := crypto.GenerateTwofishKey()
	if err != nil {
		return nil, err
	}
	st, err := assembleServerTester(key, testdir)
	if err != nil {
		return nil, err
	}

	// Mine blocks until the wallet has confirmed money.
	for i := types.BlockHeight(0); i <= types.MaturityDelay; i++ {
		_, err := st.miner.AddBlock()
		if err != nil {
			return nil, err
		}
	}

	return st, nil
}
Esempio n. 2
0
// createAuthenticatedServerTester creates an authenticated server tester
// object that is ready for testing, including money in the wallet and all
// modules initalized.
func createAuthenticatedServerTester(name string, password string) (*serverTester, error) {
	// createAuthenticatedServerTester should not get called during short
	// tests, as it takes a long time to run.
	if testing.Short() {
		panic("assembleServerTester called during short tests")
	}

	// Create the testing directory.
	testdir := build.TempDir("authenticated-api", name)

	key, err := crypto.GenerateTwofishKey()
	if err != nil {
		return nil, err
	}
	st, err := assembleAuthenticatedServerTester(password, key, testdir)
	if err != nil {
		return nil, err
	}

	// Mine blocks until the wallet has confirmed money.
	for i := types.BlockHeight(0); i <= types.MaturityDelay; i++ {
		_, err := st.miner.AddBlock()
		if err != nil {
			return nil, err
		}
	}

	return st, nil
}
Esempio n. 3
0
// newRenterTester creates a ready-to-use renter tester with money in the
// wallet.
func newRenterTester(name string) (*renterTester, error) {
	// Create the modules.
	testdir := build.TempDir("renter", name)
	g, err := gateway.New("localhost:0", false, filepath.Join(testdir, modules.GatewayDir))
	if err != nil {
		return nil, err
	}
	cs, err := consensus.New(g, false, filepath.Join(testdir, modules.ConsensusDir))
	if err != nil {
		return nil, err
	}
	tp, err := transactionpool.New(cs, g, filepath.Join(testdir, modules.TransactionPoolDir))
	if err != nil {
		return nil, err
	}
	w, err := wallet.New(cs, tp, filepath.Join(testdir, modules.WalletDir))
	if err != nil {
		return nil, err
	}
	key, err := crypto.GenerateTwofishKey()
	if err != nil {
		return nil, err
	}
	_, err = w.Encrypt(key)
	if err != nil {
		return nil, err
	}
	err = w.Unlock(key)
	if err != nil {
		return nil, err
	}
	r, err := New(cs, w, tp, filepath.Join(testdir, modules.RenterDir))
	if err != nil {
		return nil, err
	}
	m, err := miner.New(cs, tp, w, filepath.Join(testdir, modules.MinerDir))
	if err != nil {
		return nil, err
	}

	// Assemble all pieces into a renter tester.
	rt := &renterTester{
		cs:      cs,
		gateway: g,
		miner:   m,
		tpool:   tp,
		wallet:  w,

		renter: r,
	}

	// Mine blocks until there is money in the wallet.
	for i := types.BlockHeight(0); i <= types.MaturityDelay; i++ {
		_, err := rt.miner.AddBlock()
		if err != nil {
			return nil, err
		}
	}
	return rt, nil
}
Esempio n. 4
0
// createExplorerTester creates a tester object for the explorer module.
func createExplorerTester(name string) (*explorerTester, error) {
	// Create and assemble the dependencies.
	testdir := build.TempDir(modules.HostDir, name)
	g, err := gateway.New(":0", filepath.Join(testdir, modules.GatewayDir))
	if err != nil {
		return nil, err
	}
	cs, err := consensus.New(g, filepath.Join(testdir, modules.ConsensusDir))
	if err != nil {
		return nil, err
	}
	tp, err := transactionpool.New(cs, g)
	if err != nil {
		return nil, err
	}
	w, err := wallet.New(cs, tp, filepath.Join(testdir, modules.WalletDir))
	if err != nil {
		return nil, err
	}
	key, err := crypto.GenerateTwofishKey()
	if err != nil {
		return nil, err
	}
	_, err = w.Encrypt(key)
	if err != nil {
		return nil, err
	}
	err = w.Unlock(key)
	if err != nil {
		return nil, err
	}
	m, err := miner.New(cs, tp, w, filepath.Join(testdir, modules.RenterDir))
	if err != nil {
		return nil, err
	}
	e, err := New(cs, filepath.Join(testdir, modules.ExplorerDir))
	if err != nil {
		return nil, err
	}
	et := &explorerTester{
		cs:        cs,
		gateway:   g,
		miner:     m,
		tpool:     tp,
		wallet:    w,
		walletKey: key,

		explorer: e,
	}

	// Mine until the wallet has money.
	for i := types.BlockHeight(0); i <= types.MaturityDelay; i++ {
		b, _ := et.miner.FindBlock()
		err = et.cs.AcceptBlock(b)
		if err != nil {
			return nil, err
		}
	}
	return et, nil
}
Esempio n. 5
0
// createConsensusSetTester creates a consensusSetTester that's ready for use.
func createConsensusSetTester(name string) (*consensusSetTester, error) {
	testdir := build.TempDir(modules.ConsensusDir, name)

	// Create modules.
	g, err := gateway.New(":0", filepath.Join(testdir, modules.GatewayDir))
	if err != nil {
		return nil, err
	}
	cs, err := New(g, filepath.Join(testdir, modules.ConsensusDir))
	if err != nil {
		return nil, err
	}
	tp, err := transactionpool.New(cs, g)
	if err != nil {
		return nil, err
	}
	w, err := wallet.New(cs, tp, filepath.Join(testdir, modules.WalletDir))
	if err != nil {
		return nil, err
	}
	key, err := crypto.GenerateTwofishKey()
	if err != nil {
		return nil, err
	}
	_, err = w.Encrypt(key)
	if err != nil {
		return nil, err
	}
	err = w.Unlock(key)
	if err != nil {
		return nil, err
	}
	m, err := miner.New(cs, tp, w, filepath.Join(testdir, modules.MinerDir))
	if err != nil {
		return nil, err
	}

	// Assemble all objects into a consensusSetTester.
	cst := &consensusSetTester{
		gateway:   g,
		miner:     m,
		tpool:     tp,
		wallet:    w,
		walletKey: key,

		cs: cs,

		persistDir: testdir,
	}

	// Mine until the wallet has money.
	for i := types.BlockHeight(0); i <= types.MaturityDelay; i++ {
		b, _ := cst.miner.FindBlock()
		err = cst.cs.AcceptBlock(b)
		if err != nil {
			return nil, err
		}
	}
	return cst, nil
}
Esempio n. 6
0
// newHostDBTester creates a ready-to-use hostdb tester with money in the
// wallet.
func newHostDBTester(name string) (*hostdbTester, error) {
	// Create the modules.
	testdir := build.TempDir("hostdb", name)
	g, err := gateway.New(":0", filepath.Join(testdir, modules.GatewayDir))
	if err != nil {
		return nil, err
	}
	cs, err := consensus.New(g, filepath.Join(testdir, modules.ConsensusDir))
	if err != nil {
		return nil, err
	}
	tp, err := transactionpool.New(cs, g)
	if err != nil {
		return nil, err
	}
	w, err := modWallet.New(cs, tp, filepath.Join(testdir, modules.WalletDir))
	if err != nil {
		return nil, err
	}
	key, err := crypto.GenerateTwofishKey()
	if err != nil {
		return nil, err
	}
	_, err = w.Encrypt(key)
	if err != nil {
		return nil, err
	}
	err = w.Unlock(key)
	if err != nil {
		return nil, err
	}
	hdb, err := New(cs, w, tp, filepath.Join(testdir, modules.RenterDir))
	if err != nil {
		return nil, err
	}
	m, err := miner.New(cs, tp, w, filepath.Join(testdir, modules.MinerDir))
	if err != nil {
		return nil, err
	}

	// Assemble all pieces into a hostdb tester.
	ht := &hostdbTester{
		cs:      cs,
		gateway: g,
		miner:   m,
		tpool:   tp,
		wallet:  w,

		hostdb: hdb,
	}

	// Mine blocks until there is money in the wallet.
	for i := types.BlockHeight(0); i <= types.MaturityDelay; i++ {
		_, err := ht.miner.AddBlock()
		if err != nil {
			return nil, err
		}
	}
	return ht, nil
}
Esempio n. 7
0
// newTestingWallet is a helper function that creates a ready-to-use wallet
// and mines some coins into it.
func newTestingWallet(testdir string, cs modules.ConsensusSet, tp modules.TransactionPool) (modules.Wallet, error) {
	w, err := modWallet.New(cs, tp, filepath.Join(testdir, modules.WalletDir))
	if err != nil {
		return nil, err
	}
	key, err := crypto.GenerateTwofishKey()
	if err != nil {
		return nil, err
	}
	if !w.Encrypted() {
		_, err = w.Encrypt(key)
		if err != nil {
			return nil, err
		}
	}
	err = w.Unlock(key)
	if err != nil {
		return nil, err
	}
	// give it some money
	m, err := miner.New(cs, tp, w, filepath.Join(testdir, modules.MinerDir))
	if err != nil {
		return nil, err
	}
	for i := types.BlockHeight(0); i <= types.MaturityDelay; i++ {
		_, err := m.AddBlock()
		if err != nil {
			return nil, err
		}
	}
	return w, nil
}
Esempio n. 8
0
// newFile creates a new file object.
func newFile(name string, code modules.ErasureCoder, pieceSize, fileSize uint64) *file {
	key, _ := crypto.GenerateTwofishKey()
	return &file{
		name:        name,
		size:        fileSize,
		contracts:   make(map[modules.NetAddress]fileContract),
		masterKey:   key,
		erasureCode: code,
		pieceSize:   pieceSize,
	}
}
Esempio n. 9
0
// createConsensusSetTester creates a consensusSetTester that's ready for use.
func createConsensusSetTester(name string) (*consensusSetTester, error) {
	testdir := build.TempDir(modules.ConsensusDir, name)

	// Create modules.
	g, err := gateway.New(":0", filepath.Join(testdir, modules.GatewayDir))
	if err != nil {
		return nil, err
	}
	cs, err := New(g, filepath.Join(testdir, modules.ConsensusDir))
	if err != nil {
		return nil, err
	}
	tp, err := transactionpool.New(cs, g)
	if err != nil {
		return nil, err
	}
	w, err := wallet.New(cs, tp, filepath.Join(testdir, modules.WalletDir))
	if err != nil {
		return nil, err
	}
	key, err := crypto.GenerateTwofishKey()
	if err != nil {
		return nil, err
	}
	_, err = w.Encrypt(key)
	if err != nil {
		return nil, err
	}
	err = w.Unlock(key)
	if err != nil {
		return nil, err
	}
	m, err := miner.New(cs, tp, w, filepath.Join(testdir, modules.MinerDir))
	if err != nil {
		return nil, err
	}

	// Assemble all objects into a consensusSetTester.
	cst := &consensusSetTester{
		gateway:   g,
		miner:     m,
		tpool:     tp,
		wallet:    w,
		walletKey: key,

		cs: cs,

		persistDir: testdir,
	}
	cst.addSiafunds()
	cst.mineSiacoins()

	return cst, nil
}
Esempio n. 10
0
// reorgToBlank creates a bunch of empty blocks on top of the genesis block
// that reorgs the explorer to a state of all blank blocks.
func (et *explorerTester) reorgToBlank() error {
	// Get a unique directory name to house the persistence of the miner
	// dependencies.
	dir := et.testdir + " - " + persist.RandomSuffix()

	// Create a miner and all dependencies to create an alternate chain.
	g, err := gateway.New("localhost:0", false, filepath.Join(dir, modules.GatewayDir))
	if err != nil {
		return err
	}
	cs, err := consensus.New(g, false, filepath.Join(dir, modules.ConsensusDir))
	if err != nil {
		return err
	}
	tp, err := transactionpool.New(cs, g, filepath.Join(dir, modules.TransactionPoolDir))
	if err != nil {
		return err
	}
	w, err := wallet.New(cs, tp, filepath.Join(dir, modules.WalletDir))
	if err != nil {
		return err
	}
	key, err := crypto.GenerateTwofishKey()
	if err != nil {
		return err
	}
	_, err = w.Encrypt(key)
	if err != nil {
		return err
	}
	err = w.Unlock(key)
	if err != nil {
		return err
	}
	m, err := miner.New(cs, tp, w, filepath.Join(dir, modules.RenterDir))
	if err != nil {
		return err
	}

	// Mine blocks until the height is higher than the existing consensus,
	// submitting each block to the explorerTester.
	currentHeight := cs.Height()
	for i := types.BlockHeight(0); i <= currentHeight+1; i++ {
		block, err := m.AddBlock()
		if err != nil {
			return err
		}
		et.cs.AcceptBlock(block) // error is not checked, will not always be nil
	}
	return nil
}
Esempio n. 11
0
// newTestingFile initializes a file object with random parameters.
func newTestingFile() *file {
	key, _ := crypto.GenerateTwofishKey()
	data, _ := crypto.RandBytes(8)
	nData, _ := crypto.RandIntn(10)
	nParity, _ := crypto.RandIntn(10)
	rsc, _ := NewRSCode(nData+1, nParity+1)

	return &file{
		name:        "testfile-" + strconv.Itoa(int(data[0])),
		size:        encoding.DecUint64(data[1:5]),
		masterKey:   key,
		erasureCode: rsc,
		pieceSize:   encoding.DecUint64(data[6:8]),
	}
}
Esempio n. 12
0
// initWallet creates a wallet key, initializes the host wallet, unlocks it,
// and then stores the key in the host tester.
func (ht *hostTester) initWallet() error {
	// Create the keys for the wallet and unlock it.
	key, err := crypto.GenerateTwofishKey()
	if err != nil {
		return err
	}
	ht.walletKey = key
	_, err = ht.wallet.Encrypt(key)
	if err != nil {
		return err
	}
	err = ht.wallet.Unlock(key)
	if err != nil {
		return err
	}
	return nil
}
Esempio n. 13
0
// blankServerTester creates a server tester object that is ready for testing,
// without any money in the wallet.
func blankServerTester(name string) (*serverTester, error) {
	// createServerTester is expensive, and therefore should not be called
	// during short tests.
	if testing.Short() {
		panic("blankServerTester called during short tests")
	}

	// Create the server tester with key.
	testdir := build.TempDir("api", name)
	key, err := crypto.GenerateTwofishKey()
	if err != nil {
		return nil, err
	}
	st, err := assembleServerTester(key, testdir)
	if err != nil {
		return nil, err
	}
	return st, nil
}
Esempio n. 14
0
// createServerTester creates a server tester object that is ready for testing,
// including money in the wallet and all modules initalized.
func createServerTester(name string) (*serverTester, error) {
	// Create the testing directory.
	testdir := build.TempDir("api", name)

	key, err := crypto.GenerateTwofishKey()
	if err != nil {
		return nil, err
	}
	st, err := assembleServerTester(key, testdir)
	if err != nil {
		return nil, err
	}

	// Mine blocks until the wallet has confirmed money.
	for i := types.BlockHeight(0); i <= types.MaturityDelay; i++ {
		_, err := st.miner.AddBlock()
		if err != nil {
			return nil, err
		}
	}

	return st, nil
}
Esempio n. 15
0
// TestIntegrationMinimumValidChildTimestamp probes the
// MinimumValidChildTimestamp method of the consensus type.
func TestIntegrationMinimumValidChildTimestamp(t *testing.T) {
	if testing.Short() {
		t.SkipNow()
	}
	t.Parallel()

	// Create a custom consensus set to control the blocks.
	testdir := build.TempDir(modules.ConsensusDir, "TestIntegrationMinimumValidChildTimestamp")
	g, err := gateway.New("localhost:0", false, filepath.Join(testdir, modules.GatewayDir))
	if err != nil {
		t.Fatal(err)
	}
	cs, err := New(g, false, filepath.Join(testdir, modules.ConsensusDir))
	if err != nil {
		t.Fatal(err)
	}
	tp, err := transactionpool.New(cs, g, filepath.Join(testdir, modules.TransactionPoolDir))
	if err != nil {
		t.Fatal(err)
	}
	w, err := wallet.New(cs, tp, filepath.Join(testdir, modules.WalletDir))
	if err != nil {
		t.Fatal(err)
	}
	key, err := crypto.GenerateTwofishKey()
	if err != nil {
		t.Fatal(err)
	}
	_, err = w.Encrypt(key)
	if err != nil {
		t.Fatal(err)
	}
	err = w.Unlock(key)
	if err != nil {
		t.Fatal(err)
	}
	m, err := miner.New(cs, tp, w, filepath.Join(testdir, modules.MinerDir))
	if err != nil {
		t.Fatal(err)
	}
	defer g.Close()

	// The earliest child timestamp of the genesis block should be the
	// timestamp of the genesis block.
	genesisTime := cs.blockRoot.Block.Timestamp
	earliest, ok := cs.MinimumValidChildTimestamp(cs.blockRoot.Block.ID())
	if !ok || genesisTime != earliest {
		t.Error("genesis block earliest timestamp producing unexpected results")
	}

	timestampOffsets := []types.Timestamp{1, 3, 2, 5, 4, 6, 7, 8, 9, 10}
	blockIDs := []types.BlockID{cs.blockRoot.Block.ID()}
	for _, offset := range timestampOffsets {
		bfw, target, err := m.BlockForWork()
		if err != nil {
			t.Fatal(err)
		}
		bfw.Timestamp = genesisTime + offset
		solvedBlock, _ := m.SolveBlock(bfw, target)
		err = cs.AcceptBlock(solvedBlock)
		if err != nil {
			t.Fatal(err)
		}
		blockIDs = append(blockIDs, solvedBlock.ID())
	}

	// Median should be genesisTime for 6th block.
	earliest, ok = cs.MinimumValidChildTimestamp(blockIDs[5])
	if !ok || earliest != genesisTime {
		t.Error("incorrect child timestamp")
	}
	// Median should be genesisTime+1 for 7th block.
	earliest, ok = cs.MinimumValidChildTimestamp(blockIDs[6])
	if !ok || earliest != genesisTime+1 {
		t.Error("incorrect child timestamp")
	}
	// Median should be genesisTime + 5 for pb11.
	earliest, ok = cs.MinimumValidChildTimestamp(blockIDs[10])
	if !ok || earliest != genesisTime+5 {
		t.Error("incorrect child timestamp")
	}
}
Esempio n. 16
0
// createServerTester creates a server tester object that is ready for testing,
// including money in the wallet and all modules initalized.
func createServerTester(name string) (*serverTester, error) {
	// Create the testing directory and assign the api port.
	testdir := build.TempDir("api", name)
	APIAddr := ":" + strconv.Itoa(APIPort)
	APIPort++

	// Create the modules.
	g, err := gateway.New(":0", filepath.Join(testdir, modules.GatewayDir))
	if err != nil {
		return nil, err
	}
	cs, err := consensus.New(g, filepath.Join(testdir, modules.ConsensusDir))
	if err != nil {
		return nil, err
	}
	tp, err := transactionpool.New(cs, g)
	if err != nil {
		return nil, err
	}
	w, err := wallet.New(cs, tp, filepath.Join(testdir, modules.WalletDir))
	if err != nil {
		return nil, err
	}
	key, err := crypto.GenerateTwofishKey()
	if err != nil {
		return nil, err
	}
	_, err = w.Encrypt(key)
	if err != nil {
		return nil, err
	}
	err = w.Unlock(key)
	if err != nil {
		return nil, err
	}
	m, err := miner.New(cs, tp, w, filepath.Join(testdir, modules.MinerDir))
	if err != nil {
		return nil, err
	}
	hdb, err := hostdb.New(cs, g)
	if err != nil {
		return nil, err
	}
	h, err := host.New(cs, hdb, tp, w, ":0", filepath.Join(testdir, modules.HostDir))
	if err != nil {
		return nil, err
	}
	r, err := renter.New(cs, hdb, w, filepath.Join(testdir, modules.RenterDir))
	if err != nil {
		return nil, err
	}
	exp, err := explorer.New(cs, filepath.Join(testdir, modules.ExplorerDir))
	if err != nil {
		return nil, err
	}
	srv, err := NewServer(APIAddr, cs, g, h, hdb, m, r, tp, w, exp)
	if err != nil {
		return nil, err
	}

	// Assemble the serverTester.
	st := &serverTester{
		cs:        cs,
		gateway:   g,
		host:      h,
		hostdb:    hdb,
		miner:     m,
		renter:    r,
		tpool:     tp,
		exp:       exp,
		wallet:    w,
		walletKey: key,

		server: srv,
	}

	// TODO: A more reasonable way of listening for server errors.
	go func() {
		listenErr := srv.Serve()
		if listenErr != nil {
			panic(listenErr)
		}
	}()

	// Mine blocks until the wallet has confirmed money.
	for i := types.BlockHeight(0); i <= types.MaturityDelay; i++ {
		_, err := st.miner.AddBlock()
		if err != nil {
			return nil, err
		}
	}

	return st, nil
}
Esempio n. 17
0
// CreateHostTester initializes a HostTester.
func CreateHostTester(name string, t *testing.T) *hostTester {
	testdir := build.TempDir(modules.HostDir, name)

	// Create the modules.
	g, err := gateway.New(":0", filepath.Join(testdir, modules.GatewayDir))
	if err != nil {
		t.Fatal(err)
	}
	cs, err := consensus.New(g, filepath.Join(testdir, modules.ConsensusDir))
	if err != nil {
		t.Fatal(err)
	}
	tp, err := transactionpool.New(cs, g)
	if err != nil {
		t.Fatal(err)
	}
	w, err := wallet.New(cs, tp, filepath.Join(testdir, modules.WalletDir))
	if err != nil {
		t.Fatal(err)
	}
	key, err := crypto.GenerateTwofishKey()
	if err != nil {
		t.Fatal(err)
	}
	_, err = w.Encrypt(key)
	if err != nil {
		t.Fatal(err)
	}
	err = w.Unlock(key)
	if err != nil {
		t.Fatal(err)
	}
	m, err := miner.New(cs, tp, w, filepath.Join(testdir, modules.MinerDir))
	if err != nil {
		t.Fatal(err)
	}
	h, err := New(cs, tp, w, ":0", filepath.Join(testdir, modules.HostDir))
	if err != nil {
		t.Fatal(err)
	}

	// Assemble all objects into a hostTester
	ht := &hostTester{
		cs:      cs,
		gateway: g,
		miner:   m,
		tpool:   tp,
		wallet:  w,

		host: h,

		t: t,
	}

	// Mine blocks until there is money in the wallet.
	for i := types.BlockHeight(0); i <= types.MaturityDelay; i++ {
		b, _ := m.FindBlock()
		err := cs.AcceptBlock(b)
		if err != nil {
			t.Fatal(err)
		}
	}
	return ht
}
Esempio n. 18
0
// negotiateContract creates a file contract for a host according to the
// requests of the host. There is an assumption that only hosts with acceptable
// terms will be put into the hostdb.
func (r *Renter) negotiateContract(host modules.HostSettings, up modules.FileUploadParams, piece *filePiece) error {
	lockID := r.mu.RLock()
	height := r.blockHeight
	r.mu.RUnlock(lockID)

	key, err := crypto.GenerateTwofishKey()
	if err != nil {
		return err
	}

	file, err := os.Open(up.Filename)
	if err != nil {
		return err
	}
	defer file.Close()

	info, err := file.Stat()
	if err != nil {
		return err
	}

	filesize := uint64(info.Size())

	// Get the price and payout.
	sizeCurrency := types.NewCurrency64(filesize)
	durationCurrency := types.NewCurrency64(uint64(up.Duration))
	clientCost := host.Price.Mul(sizeCurrency).Mul(durationCurrency)
	hostCollateral := host.Collateral.Mul(sizeCurrency).Mul(durationCurrency)
	payout := clientCost.Add(hostCollateral)
	validOutputValue := payout.Sub(types.FileContract{Payout: payout}.Tax())

	// Create the contract terms.
	terms := modules.ContractTerms{
		FileSize:      filesize,
		Duration:      up.Duration,
		DurationStart: height - 3,
		WindowSize:    defaultWindowSize,
		Price:         host.Price,
		Collateral:    host.Collateral,

		ValidProofOutputs: []types.SiacoinOutput{
			{Value: validOutputValue, UnlockHash: host.UnlockHash},
		},

		MissedProofOutputs: []types.SiacoinOutput{
			{Value: validOutputValue, UnlockHash: types.UnlockHash{}},
		},
	}

	// TODO: This is a hackish sleep, we need to be certain that all dependent
	// transactions have propgated to the host's transaction pool. Instead,
	// built into the protocol should be a step where any dependent
	// transactions are automatically provided.
	if build.Release == "standard" {
		time.Sleep(time.Minute)
	} else if build.Release == "testing" {
		time.Sleep(time.Second * 15)
	} else {
		time.Sleep(time.Second)
	}

	// Perform the negotiations with the host through a network call.
	conn, err := net.DialTimeout("tcp", string(host.IPAddress), 10e9)
	if err != nil {
		return err
	}
	defer conn.Close()
	err = encoding.WriteObject(conn, [8]byte{'C', 'o', 'n', 't', 'r', 'a', 'c', 't'})
	if err != nil {
		return err
	}

	// Send the contract terms and read the response.
	if err = encoding.WriteObject(conn, terms); err != nil {
		return err
	}
	var response string
	if err = encoding.ReadObject(conn, &response, 128); err != nil {
		return err
	}
	if response != modules.AcceptTermsResponse {
		return errors.New(response)
	}

	// Encrypt and transmit the file data while calculating its Merkle root.
	tee := io.TeeReader(
		// wrap file reader in encryption layer
		key.NewReader(file),
		// each byte we read from tee will also be written to conn;
		// the uploadWriter updates the piece's 'Transferred' field
		&uploadWriter{piece, conn},
	)
	merkleRoot, err := crypto.ReaderMerkleRoot(tee)
	if err != nil {
		return err
	}

	// Create the transaction holding the contract. This is done first so the
	// transaction is created sooner, which will impact the user's wallet
	// balance faster vs. waiting for the whole thing to upload before
	// affecting the user's balance.
	unsignedTxn, txnBuilder, err := r.createContractTransaction(terms, merkleRoot)
	if err != nil {
		return err
	}

	// Send the unsigned transaction to the host.
	err = encoding.WriteObject(conn, unsignedTxn)
	if err != nil {
		return err
	}

	// The host will respond with a transaction with the collateral added.
	// Add the collateral inputs from the host to the original wallet
	// transaction.
	var collateralTxn types.Transaction
	err = encoding.ReadObject(conn, &collateralTxn, 16e3)
	if err != nil {
		return err
	}
	for i := len(unsignedTxn.SiacoinInputs); i < len(collateralTxn.SiacoinInputs); i++ {
		txnBuilder.AddSiacoinInput(collateralTxn.SiacoinInputs[i])
	}
	signedTxn, err := txnBuilder.Sign(true)
	if err != nil {
		return err
	}

	// Send the signed transaction back to the host.
	err = encoding.WriteObject(conn, signedTxn)
	if err != nil {
		return err
	}

	// Read an ack from the host that all is well.
	var ack bool
	err = encoding.ReadObject(conn, &ack, 1)
	if err != nil {
		return err
	}
	if !ack {
		return errors.New("host negotiation failed")
	}

	// TODO: We don't actually watch the blockchain to make sure that the
	// file contract made it.

	// Negotiation was successful; update the filePiece.
	txIndex := len(signedTxn) - 1
	lockID = r.mu.Lock()
	piece.Active = true
	piece.Repairing = false
	piece.Contract = signedTxn[txIndex].FileContracts[0]
	piece.ContractID = signedTxn[txIndex].FileContractID(0)
	piece.HostIP = host.IPAddress
	piece.EncryptionKey = key
	r.save()
	r.mu.Unlock(lockID)

	return nil
}
Esempio n. 19
0
// newTestingTrio creates a Host, Contractor, and TestMiner that can be used
// for testing host/renter interactions.
func newTestingTrio(name string) (modules.Host, *Contractor, modules.TestMiner, error) {
	testdir := build.TempDir("contractor", name)

	// create miner
	g, err := gateway.New("localhost:0", false, filepath.Join(testdir, modules.GatewayDir))
	if err != nil {
		return nil, nil, nil, err
	}
	cs, err := consensus.New(g, false, filepath.Join(testdir, modules.ConsensusDir))
	if err != nil {
		return nil, nil, nil, err
	}
	tp, err := transactionpool.New(cs, g, filepath.Join(testdir, modules.TransactionPoolDir))
	if err != nil {
		return nil, nil, nil, err
	}
	w, err := modWallet.New(cs, tp, filepath.Join(testdir, modules.WalletDir))
	if err != nil {
		return nil, nil, nil, err
	}
	key, err := crypto.GenerateTwofishKey()
	if err != nil {
		return nil, nil, nil, err
	}
	if !w.Encrypted() {
		_, err = w.Encrypt(key)
		if err != nil {
			return nil, nil, nil, err
		}
	}
	err = w.Unlock(key)
	if err != nil {
		return nil, nil, nil, err
	}
	m, err := miner.New(cs, tp, w, filepath.Join(testdir, modules.MinerDir))
	if err != nil {
		return nil, nil, nil, err
	}

	// create host and contractor, using same consensus set and gateway
	h, err := newTestingHost(filepath.Join(testdir, "Host"), cs, tp)
	if err != nil {
		return nil, nil, nil, err
	}
	c, err := newTestingContractor(filepath.Join(testdir, "Contractor"), cs, tp)
	if err != nil {
		return nil, nil, nil, err
	}

	// announce the host
	err = h.Announce()
	if err != nil {
		return nil, nil, nil, err
	}

	// mine a block, processing the announcement
	m.AddBlock()

	// wait for hostdb to scan host
	for i := 0; i < 500 && len(c.hdb.RandomHosts(1, nil)) == 0; i++ {
		time.Sleep(time.Millisecond)
	}

	return h, c, m, nil
}