Example #1
0
func TestBadSpending(t *testing.T) {
	_, err := createSpends(coin.Now(), coin.UxArray{},
		Balance{1e6 + 1, 1000}, 0, 1)
	assertError(t, err, "Coins must be multiple of 1e6")
	_, err = createSpends(coin.Now(), coin.UxArray{},
		Balance{0, 100}, 0, 1)
	assertError(t, err, "Zero spend amount")
}
Example #2
0
func TestCreateSpendsWithBurn(t *testing.T) {
	now := coin.Now()
	amt := Balance{10e6, 100}
	uxs := makeUxBalances([]Balance{
		Balance{1e6, 50},
		Balance{8e6, 40},
		Balance{2e6, 60},
	}, now)
	// Force them to get sorted
	uxs[2].Head.BkSeq = uint64(0)
	uxs[1].Head.BkSeq = uint64(1)
	uxs[0].Head.BkSeq = uint64(2)
	cuxs := append(coin.UxArray{}, uxs...)
	// Should spend 8e6,2e6 for the exact amount, but have to add 1e6 to
	// obtain +50 for a 50% fee
	spends, err := createSpends(now, uxs, amt, 0, 2)
	assert.Nil(t, err)
	assert.Equal(t, len(spends), 3)
	assert.Equal(t, spends, coin.UxArray{cuxs[2], cuxs[1], cuxs[0]})

	have := Balance{0, 0}
	for _, ux := range spends {
		have = have.Add(NewBalanceFromUxOut(now, &ux))
	}
	burn, change, err := calculateBurnAndChange(have.Hours, amt.Hours, 0, 2)
	assert.Equal(t, burn, uint64(50))
	assert.Equal(t, change, uint64(0))
	assert.Nil(t, err)
}
Example #3
0
func TestCreateSpendsNotEnoughHours(t *testing.T) {
	now := coin.Now()
	amt := Balance{10e6, 110}
	uxs := makeUxBalances([]Balance{
		Balance{2e6, 100},
		Balance{8e6, 0},
	}, now)
	_, err := createSpends(now, uxs, amt, 0, 0)
	assertError(t, err, "Not enough hours")
}
Example #4
0
func TestIgnoreBadCoins(t *testing.T) {
	// We would satisfy this spend if the bad coins were not skipped
	now := coin.Now()
	amt := Balance{10e6, 100}
	uxs := makeUxBalances([]Balance{
		Balance{2e6, 50},
		Balance{8e6, 0},
		Balance{0, 100},
		Balance{1e6 + 1, 100},
	}, now)
	_, err := createSpends(now, uxs, amt, 0, 0)
	assertError(t, err, "Not enough hours")
}
Example #5
0
func makeUxOut(t *testing.T) coin.UxOut {
	return coin.UxOut{
		Head: coin.UxHead{
			BkSeq: 1,
			Time:  coin.Now(),
		},
		Body: coin.UxBody{
			SrcTransaction: randSHA256(),
			Address:        makeAddress(),
			Coins:          1e6,
			Hours:          1024,
		},
	}
}
Example #6
0
func TestCreateSpendsNotEnoughBurn(t *testing.T) {
	now := coin.Now()
	amt := Balance{10e6, 100}
	uxs := makeUxBalances([]Balance{
		Balance{1e6, 40},
		Balance{8e6, 40},
		Balance{2e6, 60},
	}, now)
	// Force them to get sorted
	uxs[2].Head.BkSeq = uint64(0)
	uxs[1].Head.BkSeq = uint64(1)
	uxs[0].Head.BkSeq = uint64(2)
	_, err := createSpends(now, uxs, amt, 0, 2)
	assertError(t, err, "Not enough hours to burn")
}
Example #7
0
func TestCreateSpends(t *testing.T) {
	now := coin.Now()
	amt := Balance{12e6, 125}
	uxs := makeUxBalances([]Balance{
		Balance{1e6, 50},
		Balance{8e6, 10}, // 3
		Balance{2e6, 80}, // 2
		Balance{5e6, 15}, // 4
		Balance{7e6, 20}, // 1
	}, now)
	uxs[4].Head.BkSeq = uint64(1)
	uxs[3].Head.BkSeq = uint64(4)
	uxs[2].Head.BkSeq = uint64(2)
	uxs[1].Head.BkSeq = uint64(3)
	uxs[0].Head.BkSeq = uint64(5)
	if sort.IsSorted(OldestUxOut(uxs)) {
		uxs[0], uxs[1] = uxs[1], uxs[0]
	}
	assert.False(t, sort.IsSorted(OldestUxOut(uxs)))
	expectedSorting := coin.UxArray{uxs[4], uxs[2], uxs[1], uxs[3], uxs[0]}
	cuxs := append(coin.UxArray{}, uxs...)
	sort.Sort(OldestUxOut(cuxs))
	assert.Equal(t, expectedSorting, cuxs)
	assert.True(t, sort.IsSorted(OldestUxOut(cuxs)))
	assert.False(t, sort.IsSorted(OldestUxOut(uxs)))

	ouxs := append(coin.UxArray{}, uxs...)
	spends, err := createSpends(now, uxs, amt, 0, 0)
	assert.True(t, sort.IsSorted(OldestUxOut(uxs)))
	assert.Nil(t, err)
	assert.Equal(t, spends, cuxs[:len(spends)])
	assert.Equal(t, len(spends), 4)
	assert.Equal(t, spends, coin.UxArray{ouxs[4], ouxs[2], ouxs[1], ouxs[3]})

	// Recalculate what it should be
	b := Balance{0, 0}
	ouxs = make(coin.UxArray, 0, len(spends))
	for _, ux := range cuxs {
		if b.Coins > amt.Coins && b.Hours >= amt.Hours {
			break
		}
		b = b.Add(NewBalanceFromUxOut(now, &ux))
		ouxs = append(ouxs, ux)
	}
	assert.Equal(t, len(ouxs), len(spends))
	assert.Equal(t, ouxs, spends)
}
Example #8
0
func TestCreateSpendsExact(t *testing.T) {
	now := coin.Now()
	amt := Balance{10e6, 100}
	uxs := makeUxBalances([]Balance{
		Balance{1e6, 50},
		Balance{8e6, 40},
		Balance{2e6, 60},
	}, now)
	// Force them to get sorted
	uxs[2].Head.BkSeq = uint64(0)
	uxs[1].Head.BkSeq = uint64(1)
	uxs[0].Head.BkSeq = uint64(2)
	cuxs := append(coin.UxArray{}, uxs...)
	spends, err := createSpends(now, uxs, amt, 0, 0)
	assert.Nil(t, err)
	assert.Equal(t, len(spends), 2)
	assert.Equal(t, spends, coin.UxArray{cuxs[2], cuxs[1]})
}
Example #9
0
func TestCreateSpendingTransaction(t *testing.T) {
	// Setup
	w := NewSimpleWallet()
	w.Populate(4)
	uncf := NewUnconfirmedTxnPool()
	now := coin.Now()
	a := makeAddress()

	// Failing createSpends
	amt := Balance{0, 0}
	unsp := coin.NewUnspentPool()
	_, err := CreateSpendingTransaction(w, uncf, &unsp, now, amt, 0, 0, a)
	assert.NotNil(t, err)

	// Valid txn, fee, no change
	uxs := makeUxBalancesForAddresses([]Balance{
		Balance{10e6, 150},
		Balance{15e6, 150},
	}, now, w.GetAddresses()[:2])
	unsp = coin.NewUnspentPool()
	addUxArrayToUnspentPool(&unsp, uxs)
	amt = Balance{25e6, 200}
	tx, err := CreateSpendingTransaction(w, uncf, &unsp, now, amt, 100, 0, a)
	assert.Nil(t, err)
	assert.Equal(t, len(tx.Out), 1)
	assert.Equal(t, tx.Out[0], coin.TransactionOutput{
		Coins:   25e6,
		Hours:   200,
		Address: a,
	})
	assert.Equal(t, len(tx.In), 2)
	assert.Equal(t, tx.In, []coin.SHA256{uxs[0].Hash(), uxs[1].Hash()})
	assert.Nil(t, tx.Verify())

	// Valid txn, change
	uxs = makeUxBalancesForAddresses([]Balance{
		Balance{10e6, 150},
		Balance{15e6, 200},
		Balance{1e6, 125},
	}, now, w.GetAddresses()[:3])
	unsp = coin.NewUnspentPool()
	addUxArrayToUnspentPool(&unsp, uxs)
	amt = Balance{25e6, 200}
	tx, err = CreateSpendingTransaction(w, uncf, &unsp, now, amt, 100, 0, a)
	assert.Nil(t, err)
	assert.Equal(t, len(tx.Out), 2)
	assert.Equal(t, tx.Out[0], coin.TransactionOutput{
		Coins:   1e6,
		Hours:   (150 + 200 + 125) - (200 + 100),
		Address: w.GetAddresses()[0],
	})
	assert.Equal(t, tx.Out[1], coin.TransactionOutput{
		Coins:   25e6,
		Hours:   200,
		Address: a,
	})
	assert.Equal(t, len(tx.In), 3)
	assert.Equal(t, tx.In, []coin.SHA256{
		uxs[0].Hash(), uxs[1].Hash(), uxs[2].Hash(),
	})
	assert.Nil(t, tx.Verify())

	// Valid txn, but wastes coin hours
	uxs = makeUxBalancesForAddresses([]Balance{
		Balance{10e6, 150},
		Balance{15e6, 200},
	}, now, w.GetAddresses()[:2])
	unsp = coin.NewUnspentPool()
	addUxArrayToUnspentPool(&unsp, uxs)
	amt = Balance{25e6, 200}
	_, err = CreateSpendingTransaction(w, uncf, &unsp, now, amt, 100, 0, a)
	assertError(t, err, "Have enough coins, but not enough to send coin "+
		"hours change back. Would spend 50 more hours than requested.")

	// Would be valid, but unconfirmed subtraction causes it to not be
	// First, make a txn to subtract
	uxs = makeUxBalancesForAddresses([]Balance{
		Balance{10e6, 150},
		Balance{15e6, 150},
	}, now, w.GetAddresses()[:2])
	unsp = coin.NewUnspentPool()
	addUxArrayToUnspentPool(&unsp, uxs)
	amt = Balance{25e6, 200}
	tx, err = CreateSpendingTransaction(w, uncf, &unsp, now, amt, 100, 0, a)
	assert.Nil(t, err)
	// Add it to the unconfirmed pool (bypass RecordTxn to avoid blockchain)
	uncf.Txns[tx.Hash()] = uncf.createUnconfirmedTxn(&unsp, tx,
		w.GetAddressSet())
	// Make a spend that must not reuse previous addresses
	_, err = CreateSpendingTransaction(w, uncf, &unsp, now, amt, 100, 0, a)
	assertError(t, err, "Not enough coins")
}