Example #1
0
// InjectTxn adds a coin.Transaction to the pool, or updates an existing one's timestamps
// Returns an error if txn is invalid, and whether the transaction already
// existed in the pool.
func (utp *UnconfirmedTxnPool) InjectTxn(bc *Blockchain,
	t coin.Transaction) (error, bool) {

	if err := t.Verify(); err != nil {
		return err, false
	}

	if err := VerifyTransactionFee(bc, &t); err != nil {
		return err, false
	}
	if err := bc.VerifyTransaction(t); err != nil {
		return err, false
	}

	// Update if we already have this txn
	h := t.Hash()
	ut, ok := utp.Txns[h]
	if ok {
		now := util.Now()
		ut.Received = now
		ut.Checked = now
		utp.Txns[h] = ut
		return nil, true
	}

	// Add txn to index
	unspent := bc.GetUnspent()
	utp.Txns[h] = utp.createUnconfirmedTxn(unspent, t)
	// Add predicted unspents
	utp.Unspent[h] = coin.CreateUnspents(bc.Head().Head, t)

	return nil, false
}
Example #2
0
func (fg fakeGateway) InjectTransaction(txn coin.Transaction) (coin.Transaction, error) {
	if _, v := fg.injectRawTxMap[txn.Hash().Hex()]; v {
		return txn, nil
	}

	return txn, errors.New("inject transaction failed")
}
Example #3
0
func NewReadableTransaction(t *coin.Transaction) ReadableTransaction {

	sigs := make([]string, len(t.Sigs))
	for i, _ := range t.Sigs {
		sigs[i] = t.Sigs[i].Hex()
	}

	in := make([]string, len(t.In))
	for i, _ := range t.In {
		in[i] = t.In[i].Hex()
	}
	out := make([]ReadableTransactionOutput, len(t.Out))
	for i, _ := range t.Out {
		out[i] = NewReadableTransactionOutput(&t.Out[i])
	}
	return ReadableTransaction{
		Length:    t.Length,
		Type:      t.Type,
		Hash:      t.Hash().Hex(),
		InnerHash: t.InnerHash.Hex(),

		Sigs: sigs,
		In:   in,
		Out:  out,
	}
}
Example #4
0
// Adds a coin.Transaction to the pool, or updates an existing one's timestamps
// Returns an error if txn is invalid, and whether the transaction already
// existed in the pool.
func (self *UnconfirmedTxnPool) RecordTxn(bc *coin.Blockchain,
	t coin.Transaction, addrs map[coin.Address]byte, maxSize int,
	burnFactor uint64) (error, bool) {
	if err := VerifyTransaction(bc, &t, maxSize, burnFactor); err != nil {
		return err, false
	}
	if err := bc.VerifyTransaction(t); err != nil {
		return err, false
	}

	// Update if we already have this txn
	ut, ok := self.Txns[t.Hash()]
	if ok {
		now := util.Now()
		ut.Received = now
		ut.Checked = now
		self.Txns[ut.Txn.Hash()] = ut
		return nil, true
	}

	// Add txn to index
	self.Txns[t.Hash()] = self.createUnconfirmedTxn(&bc.Unspent, t, addrs)
	// Add predicted unspents
	uxs := coin.CreateExpectedUnspents(t)
	for i, _ := range uxs {
		self.Unspent.Add(uxs[i])
	}

	return nil, false
}
Example #5
0
func InitTransaction() coin.Transaction {
	var tx coin.Transaction

	output := cipher.MustSHA256FromHex("043836eb6f29aaeb8b9bfce847e07c159c72b25ae17d291f32125e7f1912e2a0")
	tx.PushInput(output)

	for i := 0; i < 100; i++ {
		addr := cipher.MustDecodeBase58Address(AddrList[i])
		tx.PushOutput(addr, 1e12, 1) // 10e6*10e6
	}
	/*
		seckeys := make([]cipher.SecKey, 1)
		seckey := ""
		seckeys[0] = cipher.MustSecKeyFromHex(seckey)
		tx.SignInputs(seckeys)
	*/

	txs := make([]cipher.Sig, 1)
	sig := "ed9bd7a31fe30b9e2d53b35154233dfdf48aaaceb694a07142f84cdf4f5263d21b723f631817ae1c1f735bea13f0ff2a816e24a53ccb92afae685fdfc06724de01"
	txs[0] = cipher.MustSigFromHex(sig)
	tx.Sigs = txs

	tx.UpdateHeader()

	err := tx.Verify()

	if err != nil {
		log.Panic(err)
	}

	log.Printf("signature= %s", tx.Sigs[0].Hex())
	return tx
}
Example #6
0
// Adds a coin.Transaction to the pool, or updates an existing one's timestamps
// Returns an error if txn is invalid, and whether the transaction already
// existed in the pool.
func (self *UnconfirmedTxnPool) RecordTxn(bc *coin.Blockchain,
	t coin.Transaction, addrs map[cipher.Address]byte, maxSize int,
	burnFactor uint64) (error, bool) {
	if err := VerifyTransaction(bc, &t, maxSize, burnFactor); err != nil {
		return err, false
	}
	if err := bc.VerifyTransaction(t); err != nil {
		return err, false
	}

	// Update if we already have this txn
	h := t.Hash()
	ut, ok := self.Txns[h]
	if ok {
		now := util.Now()
		ut.Received = now
		ut.Checked = now
		self.Txns[h] = ut
		return nil, true
	}

	// Add txn to index
	self.Txns[h] = self.createUnconfirmedTxn(&bc.Unspent, t, addrs)
	// Add predicted unspents
	self.Unspent[h] = coin.CreateUnspents(bc.Head().Head, t)

	return nil, false
}
Example #7
0
func (fbc *fakeBlockchain) CreateGenesisBlock(genesisAddr cipher.Address, genesisCoins, timestamp uint64) coin.Block {
	txn := coin.Transaction{}
	txn.PushOutput(genesisAddr, genesisCoins, genesisCoins)
	body := coin.BlockBody{coin.Transactions{txn}}
	prevHash := cipher.SHA256{}
	head := coin.BlockHeader{
		Time:     timestamp,
		BodyHash: body.Hash(),
		PrevHash: prevHash,
		BkSeq:    0,
		Version:  0,
		Fee:      0,
		UxHash:   coin.NewUnspentPool().GetUxHash(),
	}
	b := coin.Block{
		Head: head,
		Body: body,
	}
	// b.Body.Transactions[0].UpdateHeader()
	fbc.blocks = append(fbc.blocks, b)
	ux := coin.UxOut{
		Head: coin.UxHead{
			Time:  timestamp,
			BkSeq: 0,
		},
		Body: coin.UxBody{
			SrcTransaction: txn.InnerHash, //user inner hash
			Address:        genesisAddr,
			Coins:          genesisCoins,
			Hours:          genesisCoins, // Allocate 1 coin hour per coin
		},
	}
	fbc.unspent.Add(ux)
	return b
}
Example #8
0
// VerifyTransaction checks that the inputs to the transaction exist,
// that the transaction does not create or destroy coins and that the
// signatures on the transaction are valid
func (bc Blockchain) VerifyTransaction(tx coin.Transaction) error {
	//CHECKLIST: DONE: check for duplicate ux inputs/double spending
	//CHECKLIST: DONE: check that inputs of transaction have not been spent
	//CHECKLIST: DONE: check there are no duplicate outputs

	// Q: why are coin hours based on last block time and not
	// current time?
	// A: no two computers will agree on system time. Need system clock
	// indepedent timing that everyone agrees on. fee values would depend on
	// local clock

	// Check transaction type and length
	// Check for duplicate outputs
	// Check for duplicate inputs
	// Check for invalid hash
	// Check for no inputs
	// Check for no outputs
	// Check for non 1e6 multiple coin outputs
	// Check for zero coin outputs
	// Check valid looking signatures
	if err := tx.Verify(); err != nil {
		return err
	}

	uxIn, err := bc.unspent.GetMultiple(tx.In)
	if err != nil {
		return err
	}
	// Checks whether ux inputs exist,
	// Check that signatures are allowed to spend inputs
	if err := tx.VerifyInput(uxIn); err != nil {
		return err
	}

	// Get the UxOuts we expect to have when the block is created.
	uxOut := coin.CreateUnspents(bc.Head().Head, tx)
	// Check that there are any duplicates within this set
	if uxOut.HasDupes() {
		return errors.New("Duplicate unspent outputs in transaction")
	}
	if DebugLevel1 {
		// Check that new unspents don't collide with existing.  This should
		// also be checked in verifyTransactions
		for i := range uxOut {
			if bc.unspent.Has(uxOut[i].Hash()) {
				return errors.New("New unspent collides with existing unspent")
			}
		}
	}

	// Check that no coins are lost, and sufficient coins and hours are spent
	err = coin.VerifyTransactionSpending(bc.Time(), uxIn, uxOut)
	if err != nil {
		return err
	}
	return nil
}
Example #9
0
func assertValidUnconfirmed(t *testing.T, txns map[cipher.SHA256]UnconfirmedTxn,
	txn coin.Transaction) {
	ut, ok := txns[txn.Hash()]
	assert.True(t, ok)
	assert.Equal(t, ut.Txn, txn)
	assert.True(t, ut.Announced.IsZero())
	assert.False(t, ut.Received.IsZero())
	assert.False(t, ut.Checked.IsZero())
}
Example #10
0
func TestBlockchainVerifyBlock(t *testing.T) {
	ft := FakeTree{}
	bc := NewBlockchain(&ft, nil)
	gb := bc.CreateGenesisBlock(genAddress, _genCoins, _genTime)
	// Genesis block not valid after the fact
	assert.NotNil(t, bc.verifyBlock(gb))
	assert.Equal(t, bc.Len(), uint64(1))
	_, ux := addBlockToBlockchain(t, bc)
	assert.Equal(t, bc.Len(), uint64(3))

	// Valid block
	tx := coin.Transaction{}
	tx.PushInput(ux.Hash())
	tx.PushOutput(genAddress, ux.Body.Coins, ux.CoinHours(bc.Time()))
	tx.SignInputs([]cipher.SecKey{genSecret})
	tx.UpdateHeader()
	b, err := bc.NewBlockFromTransactions(coin.Transactions{tx}, bc.Time()+_incTime)
	assert.Equal(t, len(b.Body.Transactions), 1)
	assert.Equal(t, len(b.Body.Transactions[0].Out), 1)
	assert.Nil(t, err)
	assert.Nil(t, bc.verifyBlock(b))

	// Invalid block header
	b.Head.BkSeq = gb.Head.BkSeq
	assert.Equal(t, len(b.Body.Transactions), 1)
	assert.Equal(t, len(b.Body.Transactions[0].Out), 1)
	assertError(t, bc.verifyBlock(b), "BkSeq invalid")

	// Invalid transactions, makes duplicate outputs
	b.Head.BkSeq = bc.Head().Head.BkSeq + 1
	b.Body.Transactions = append(b.Body.Transactions, b.Body.Transactions[0])
	b.Head.BodyHash = b.HashBody()
	assertError(t, bc.verifyBlock(b),
		"Duplicate unspent output across transactions")
}
Example #11
0
func splitUnspent(t *testing.T, bc *Blockchain, ux coin.UxOut) coin.UxArray {
	tx := coin.Transaction{}
	hrs := ux.CoinHours(bc.Time())
	if hrs < 2 {
		log.Panic("Not enough hours, would generate duplicate output")
	}
	assert.Equal(t, ux.Body.Address, genAddress)
	tx.PushInput(ux.Hash())
	coinsA := ux.Body.Coins / 2
	coinsB := coinsA
	if (ux.Body.Coins/1e6)%2 == 1 {
		coinsA = (ux.Body.Coins - 1e6) / 2
		coinsB = coinsA + 1e6
	}
	tx.PushOutput(genAddress, coinsA, hrs/4)
	tx.PushOutput(genAddress, coinsB, hrs/2)
	tx.SignInputs([]cipher.SecKey{genSecret})
	tx.UpdateHeader()
	b, err := bc.NewBlockFromTransactions(coin.Transactions{tx}, bc.Time()+_incTime)
	assert.Nil(t, err)
	uxs, err := bc.ExecuteBlock(&b)
	assert.Nil(t, err)
	assert.Equal(t, len(uxs), 2)
	return uxs
}
Example #12
0
func TestCreateUnspents(t *testing.T) {
	ft := FakeTree{}
	bc := NewBlockchain(&ft, nil)
	bc.CreateGenesisBlock(genAddress, _genCoins, _genTime)
	// 1 out
	tx := coin.Transaction{}
	tx.PushOutput(genAddress, 11e6, 255)
	bh := coin.BlockHeader{
		Time:  tNow(),
		BkSeq: uint64(1),
	}
	uxout := coin.CreateUnspents(bh, tx)
	assert.Equal(t, len(uxout), 1)
	assertValidUnspents(t, bh, tx, uxout)

	// Multiple outs.  Should work regardless of validity
	tx = coin.Transaction{}
	ux := makeUxOut(t)
	tx.PushInput(ux.Hash())
	tx.PushOutput(genAddress, 100, 150)
	tx.PushOutput(genAddress, 200, 77)
	bh.BkSeq++
	uxout = coin.CreateUnspents(bh, tx)
	assert.Equal(t, len(uxout), 2)
	assertValidUnspents(t, bh, tx, uxout)

	// No outs
	tx = coin.Transaction{}
	uxout = coin.CreateUnspents(bh, tx)
	assertValidUnspents(t, bh, tx, uxout)
}
Example #13
0
//InjectTransaction makes the blockchain server aware of raw transactions
//InjectTransaction inserts the transaction into the unconfirmed set
// TODO: lock for thread safety
func (self *Blockchain) InjectTransaction(txn coin.Transaction) error {
	//strict filter would disallow transactions that cant be executed from unspent output set
	if txn.Size() > MaxTransactionSize { //16 KB/max size
		return errors.New("transaction over size limit")
	}
	if err := self.blockchain.VerifyTransaction(txn); err != nil {
		return err
	}
	self.Unconfirmed.RecordTxn(txn)
	return nil
}
func assertValidUnconfirmed(t *testing.T, txns map[coin.SHA256]UnconfirmedTxn,
	txn coin.Transaction, didAnnounce, isOurReceive, isOurSpend bool) {
	ut, ok := txns[txn.Hash()]
	assert.True(t, ok)
	assert.Equal(t, ut.Txn, txn)
	assert.Equal(t, ut.IsOurReceive, isOurReceive)
	assert.Equal(t, ut.IsOurSpend, isOurSpend)
	assert.Equal(t, ut.Announced.IsZero(), !didAnnounce)
	assert.False(t, ut.Received.IsZero())
	assert.False(t, ut.Checked.IsZero())
}
Example #15
0
func assertValidUnspents(t *testing.T, bh coin.BlockHeader, tx coin.Transaction,
	uxo coin.UxArray) {
	assert.Equal(t, len(tx.Out), len(uxo))
	for i, ux := range uxo {
		assert.Equal(t, bh.Time, ux.Head.Time)
		assert.Equal(t, bh.BkSeq, ux.Head.BkSeq)
		assert.Equal(t, tx.Hash(), ux.Body.SrcTransaction)
		assert.Equal(t, tx.Out[i].Address, ux.Body.Address)
		assert.Equal(t, tx.Out[i].Coins, ux.Body.Coins)
		assert.Equal(t, tx.Out[i].Hours, ux.Body.Hours)
	}
}
Example #16
0
// Performs additional transaction verification at the unconfirmed pool level.
// This checks tunable parameters that should prevent the transaction from
// entering the blockchain, but cannot be done at the blockchain level because
// they may be changed.
func VerifyTransaction(bc *coin.Blockchain, t *coin.Transaction, maxSize int,
	burnFactor uint64) error {
	if t.Size() > maxSize {
		return errors.New("Transaction too large")
	}
	if fee, err := bc.TransactionFee(t); err != nil {
		return err
	} else if burnFactor != 0 && t.OutputHours()/burnFactor > fee {
		return errors.New("Transaction fee minimum not met")
	}
	return nil
}
Example #17
0
func makeTransactionWithSecret(t *testing.T) (coin.Transaction, cipher.SecKey) {
	tx := coin.Transaction{}
	ux, s := makeUxOutWithSecret(t)
	tx.PushInput(ux.Hash())
	tx.SignInputs([]cipher.SecKey{s})
	tx.PushOutput(makeAddress(), 10e6, 100)
	tx.UpdateHeader()
	return tx, s
}
Example #18
0
//move into visor
//DEPRECATE
func (self *Visor) InjectTransaction(txn coin.Transaction, pool *Pool) (coin.Transaction, error) {

	err := txn.Verify()

	if err != nil {
		return txn, errors.New("Transaction Verification Failed")
	}

	err, _ = self.Visor.InjectTxn(txn)
	if err == nil {
		self.BroadcastTransaction(txn, pool)
	}
	return txn, err
}
Example #19
0
// VerifyTransactionFee performs additional transaction verification at the unconfirmed pool level.
// This checks tunable parameters that should prevent the transaction from
// entering the blockchain, but cannot be done at the blockchain level because
// they may be changed.
func VerifyTransactionFee(bc *Blockchain, t *coin.Transaction) error {
	fee, err := bc.TransactionFee(t)
	if err != nil {
		return err
	}

	//calculate total number of coinhours
	var total = t.OutputHours() + fee
	//make sure at least half the coin hours are destroyed
	if fee < total/BurnFactor {
		return errors.New("Transaction coinhour fee minimum not met")
	}
	return nil
}
Example #20
0
func TestSpendsForAddresses(t *testing.T) {
	up := NewUnconfirmedTxnPool()
	unspent := coin.NewUnspentPool()
	addrs := make(map[cipher.Address]byte, 0)
	n := 4
	useAddrs := make([]cipher.Address, n)
	for i, _ := range useAddrs {
		useAddrs[i] = makeAddress()
	}
	useAddrs[1] = useAddrs[0]
	for _, a := range useAddrs {
		addrs[a] = byte(1)
	}
	// Make confirmed transactions to add to unspent pool
	uxs := make(coin.UxArray, 0)
	for i := 0; i < n; i++ {
		txn := coin.Transaction{}
		txn.PushInput(randSHA256())
		txn.PushOutput(useAddrs[i], 10e6, 1000)
		uxa := coin.CreateUnspents(coin.BlockHeader{}, txn)
		for _, ux := range uxa {
			unspent.Add(ux)
		}
		uxs = append(uxs, uxa...)
	}
	assert.Equal(t, len(uxs), 4)

	// Make unconfirmed txns that spend those unspents
	for i := 0; i < n; i++ {
		txn := coin.Transaction{}
		txn.PushInput(uxs[i].Hash())
		txn.PushOutput(makeAddress(), 10e6, 1000)
		ut := UnconfirmedTxn{
			Txn: txn,
		}
		up.Txns[ut.Hash()] = ut
	}

	// Now look them up
	assert.Equal(t, len(addrs), 3)
	assert.Equal(t, len(up.Txns), 4)
	auxs := up.SpendsForAddresses(&unspent, addrs)
	assert.Equal(t, len(auxs), 3)
	assert.Equal(t, len(auxs[useAddrs[0]]), 2)
	assert.Equal(t, len(auxs[useAddrs[2]]), 1)
	assert.Equal(t, len(auxs[useAddrs[3]]), 1)
	assert.Equal(t, auxs[useAddrs[0]], coin.UxArray{uxs[0], uxs[1]})
	assert.Equal(t, auxs[useAddrs[2]], coin.UxArray{uxs[2]})
	assert.Equal(t, auxs[useAddrs[3]], coin.UxArray{uxs[3]})
}
Example #21
0
// Adds a coin.Transaction to the pool
//func (self *UnconfirmedTxnPool) InjectTxn(bc *coin.Blockchain,
//    t coin.Transaction, addrs map[cipher.Address]byte, didAnnounce bool) error {
func (self *UnconfirmedTxnPool) InjectTxn(t coin.Transaction) error {

	now := time.Now().Unix()
	//announcedAt := util.ZeroTime()

	ut := UnconfirmedTxn{
		Txn:       t,
		Received:  now,
		Checked:   now,
		Announced: 0, //set to 0 until announced
	}
	self.Txns[t.Hash()] = ut
	return nil
}
Example #22
0
//move into visor
//DEPRECATE
func (self *Visor) InjectTransaction(txn coin.Transaction, pool *Pool) (coin.Transaction, error) {
	if err := visor.VerifyTransactionFee(self.Visor.Blockchain, &txn); err != nil {
		return txn, err
	}

	if err := txn.Verify(); err != nil {
		return txn, fmt.Errorf("Transaction Verification Failed, %v", err)
	}

	err, _ := self.Visor.InjectTxn(txn)
	if err == nil {
		self.BroadcastTransaction(txn, pool)
	}
	return txn, err
}
Example #23
0
func assertValidUnspent(t *testing.T, bc *coin.Blockchain,
	unspent TxnUnspents, tx coin.Transaction) {
	expect := coin.CreateUnspents(bc.Head().Head, tx)
	assert.NotEqual(t, len(expect), 0)
	sum := 0
	for _, uxs := range unspent {
		sum += len(uxs)
	}
	assert.Equal(t, len(expect), sum)
	uxs := unspent[tx.Hash()]
	for _, ux := range expect {
		found := false
		for _, u := range uxs {
			if u.Hash() == ux.Hash() {
				found = true
				break
			}
		}
		assert.True(t, found)
	}
}
Example #24
0
// NewTransaction create skycoin transaction.
func newTransaction(utxos []unspentOut, keys []cipher.SecKey, outs []coin.TransactionOutput) (*coin.Transaction, error) {
	tx := coin.Transaction{}
	// keys := make([]cipher.SecKey, len(utxos))
	for _, u := range utxos {
		tx.PushInput(cipher.MustSHA256FromHex(u.Hash))
	}

	for _, o := range outs {
		if (o.Coins % 1e6) != 0 {
			return nil, errors.New("skycoin coins must be multiple of 1e6")
		}
		tx.PushOutput(o.Address, o.Coins, o.Hours)
	}
	// tx.Verify()

	tx.SignInputs(keys)
	tx.UpdateHeader()
	return &tx, nil
}
Example #25
0
func addBlock(bc historydb.Blockchainer, td testData, tm uint64) (*coin.Block, *coin.Transaction, error) {
	tx := coin.Transaction{}
	// get unspent output
	ux, err := getUx(bc, td.Vin.BlockSeq, td.Vin.TxID, td.Vin.Addr)
	if err != nil {
		return nil, nil, err
	}
	if ux == nil {
		return nil, nil, errors.New("no unspent output")
	}

	tx.PushInput(ux.Hash())
	for _, o := range td.Vouts {
		addr, err := cipher.DecodeBase58Address(o.ToAddr)
		if err != nil {
			return nil, nil, err
		}
		tx.PushOutput(addr, o.Coins, o.Hours)
	}

	sigKey := cipher.MustSecKeyFromHex(td.Vin.SigKey)
	tx.SignInputs([]cipher.SecKey{sigKey})
	tx.UpdateHeader()
	if err := bc.VerifyTransaction(tx); err != nil {
		return nil, nil, err
	}
	preBlock := bc.GetBlock(td.PreBlockHash)
	b := newBlock(*preBlock, tm, *bc.GetUnspent(), coin.Transactions{tx}, _feeCalc)

	// uxs, err := bc.ExecuteBlock(&b)
	_, err = bc.ExecuteBlock(&b)
	if err != nil {
		return nil, nil, err
	}
	return &b, &tx, nil
}
Example #26
0
func TransactionToJSON(tx coin.Transaction) string {

	var o TransactionJSON

	if err := tx.Verify(); err != nil {
		log.Panic("Input Transaction Invalid: Cannot serialize to JSON, fails verify")
	}

	o.Hash = tx.Hash().Hex()
	o.InnerHash = tx.InnerHash.Hex()

	if tx.InnerHash != tx.HashInner() {
		log.Panic("TransactionToJSON called with invalid transaction, inner hash mising")
	}

	o.Sigs = make([]string, len(tx.Sigs))
	o.In = make([]string, len(tx.In))
	o.Out = make([]TransactionOutputJSON, len(tx.Out))

	for i, sig := range tx.Sigs {
		o.Sigs[i] = sig.Hex()
	}
	for i, x := range tx.In {
		o.In[i] = x.Hex() //hash to hex
	}
	for i, y := range tx.Out {
		o.Out[i] = NewTransactionOutputJSON(y, tx.InnerHash)
	}

	b, err := json.MarshalIndent(o, "", "  ")
	if err != nil {
		log.Panic("Cannot serialize transaction as JSON")
	}

	return string(b)
}
Example #27
0
func TestProcessTransactions(t *testing.T) {
	ft := FakeTree{}
	bc := NewBlockchain(&ft, nil)
	bc.CreateGenesisBlock(genAddress, _genCoins, _genTime)
	fmt.Println("genesis time:", bc.GetGenesisBlock().Time())
	assert.Equal(t, bc.Len(), uint64(1))
	_, ux := addBlockToBlockchain(t, bc)
	assert.Equal(t, bc.Len(), uint64(3))

	// Invalid, no transactions in block
	// arbitrating=false
	txns, err := bc.processTransactions(coin.Transactions{}, false)
	assert.Nil(t, txns)
	assertError(t, err, "No transactions")
	// arbitrating=true
	txns, err = bc.processTransactions(coin.Transactions{}, true)
	assert.Equal(t, len(txns), 0)
	assert.Nil(t, err)

	// Invalid, txn.Verify() fails
	// TODO -- combine all txn.Verify() failures into one test
	// method, and call it from here, from ExecuteBlock(), from
	// Verify(), from VerifyTransaction()
	txns = coin.Transactions{}
	txn := coin.Transaction{}
	txn.PushInput(ux.Hash())
	txn.PushOutput(genAddress, 777, 100)
	txn.SignInputs([]cipher.SecKey{genSecret})
	txn.UpdateHeader()
	txns = append(txns, txn)
	// arbitrating=false
	txns2, err := bc.processTransactions(txns, false)
	assert.Nil(t, txns2)
	assertError(t, err,
		"Transaction outputs must be multiple of 1e6 base units")
	// arbitrating=true
	txns2, err = bc.processTransactions(txns, true)
	assert.NotNil(t, txns2)
	assert.Nil(t, err)
	assert.Equal(t, len(txns2), 0)

	// Invalid, duplicate unspent will be created by these txns
	txn, _ = makeTransactionForChainWithHoursFee(t, bc, ux, genSecret, 100,
		100)
	txns = coin.Transactions{txn, txn}
	// arbitrating=false
	txns2, err = bc.processTransactions(txns, false)
	assertError(t, err, "Duplicate unspent output across transactions")
	assert.Nil(t, txns2)
	// arbitrating=true.  One of the offending transactions should be removed
	txns2, err = bc.processTransactions(txns, true)
	assert.Nil(t, err)
	assert.Equal(t, len(txns2), 1)
	assert.Equal(t, txns2[0], txn)

	// Check that a new output will not collide with the existing pool
	txn, _ = makeTransactionForChainWithHoursFee(t, bc, ux, genSecret, 100,
		100)
	txns = coin.Transactions{txn}
	uxb := coin.UxBody{
		SrcTransaction: txn.Hash(),
		Coins:          txn.Out[0].Coins,
		Hours:          txn.Out[0].Hours,
		Address:        txn.Out[0].Address,
	}
	bc.GetUnspent().Add(coin.UxOut{Body: uxb})
	// arbitrating=false
	txns2, err = bc.processTransactions(txns, false)
	assertError(t, err, "New unspent collides with existing unspent")
	assert.Nil(t, txns2)
	// arbitrating=true
	txns2, err = bc.processTransactions(txns, true)
	assert.Equal(t, len(txns2), 0)
	assert.NotNil(t, txns2)
	assert.Nil(t, err)

	// Spending of duplicate inputs being spent across txns
	txn, _ = makeTransactionForChainWithHoursFee(t, bc, ux, genSecret, 100,
		100)
	txn2, _ := makeTransactionForChainWithHoursFee(t, bc, ux, genSecret, 100,
		100)
	txn2.Out = nil
	txn2.PushOutput(makeAddress(), 1e6, 100)
	txn2.PushOutput(makeAddress(), ux.Body.Coins-1e6, 100)
	txn2.Sigs = nil
	txn2.SignInputs([]cipher.SecKey{genSecret})
	txn2.UpdateHeader()
	txns = coin.SortTransactions(coin.Transactions{txn, txn2}, bc.TransactionFee)
	// arbitrating=false
	txns2, err = bc.processTransactions(txns, false)
	assertError(t, err, "Cannot spend output twice in the same block")
	assert.Nil(t, txns2)
	// arbitrating=true
	txns2, err = bc.processTransactions(txns, true)
	assert.Nil(t, err)
	assert.Equal(t, len(txns2), 1)
	assert.Equal(t, txns2[0], txns[0])
}
Example #28
0
// Creates a Transaction spending coins and hours from our coins
func CreateSpendingTransaction(wallet Wallet, unconfirmed *UnconfirmedTxnPool,
	unspent *coin.UnspentPool, headTime uint64, amt Balance,
	fee, burnFactor uint64, dest coin.Address) (coin.Transaction, error) {
	txn := coin.Transaction{}
	auxs := unspent.AllForAddresses(wallet.GetAddresses())
	// Subtract pending spends from available
	puxs := unconfirmed.SpendsForAddresses(unspent, wallet.GetAddressSet())
	auxs = auxs.Sub(puxs)

	// Determine which unspents to spend
	spends, err := createSpends(headTime, auxs.Flatten(), amt, fee, burnFactor)
	if err != nil {
		return txn, err
	}

	// Add these unspents as tx inputs
	toSign := make([]coin.SecKey, len(spends))
	spending := Balance{0, 0}
	for i, au := range spends {
		entry, exists := wallet.GetEntry(au.Body.Address)
		if !exists {
			log.Panic("On second thought, the wallet entry does not exist")
		}
		txn.PushInput(au.Hash())
		toSign[i] = entry.Secret
		spending.Coins += au.Body.Coins
		spending.Hours += au.CoinHours(headTime)
	}

	// Determine how much change we get back, if any
	_, changeHours, err := calculateBurnAndChange(spending.Hours,
		amt.Hours, fee, burnFactor)
	if err != nil {
		// This should not occur, else createSpends is broken
		return txn, err
	}
	change := NewBalance(spending.Coins-amt.Coins, changeHours)
	// TODO -- send change to a new address
	changeAddr := spends[0].Body.Address
	if change.Coins == 0 {
		if change.Hours > 0 {
			msg := ("Have enough coins, but not enough to send coin hours " +
				"change back. Would spend %d more hours than requested.")
			return txn, fmt.Errorf(msg, change.Hours)
		}
	} else {
		txn.PushOutput(changeAddr, change.Coins, change.Hours)
	}

	// Finalize the the transaction
	txn.PushOutput(dest, amt.Coins, amt.Hours)
	txn.SignInputs(toSign)
	txn.UpdateHeader()
	return txn, nil
}
Example #29
0
//DEPRECATE
//deprecate dependency on wallet
// Creates a Transaction spending coins and hours from our coins
//MOVE SOMEWHERE ELSE
//Move to wallet or move to ???
func CreateSpendingTransaction(wlt wallet.Wallet,
	unconfirmed *UnconfirmedTxnPool, unspent *coin.UnspentPool,
	headTime uint64, amt wallet.Balance,
	dest cipher.Address) (coin.Transaction, error) {
	txn := coin.Transaction{}
	auxs := unspent.AllForAddresses(wlt.GetAddresses())
	// Subtract pending spends from available
	puxs := unconfirmed.SpendsForAddresses(unspent, wlt.GetAddressSet())
	auxs = auxs.Sub(puxs)

	// Determine which unspents to spend
	spends, err := createSpends(headTime, auxs.Flatten(), amt)
	if err != nil {
		return txn, err
	}

	// Add these unspents as tx inputs
	toSign := make([]cipher.SecKey, len(spends))
	spending := wallet.Balance{0, 0}
	for i, au := range spends {
		entry, exists := wlt.GetEntry(au.Body.Address)
		if !exists {
			log.Panic("On second thought, the wallet entry does not exist")
		}
		txn.PushInput(au.Hash())
		toSign[i] = entry.Secret
		spending.Coins += au.Body.Coins
		spending.Hours += au.CoinHours(headTime)
	}

	//keep 1/4th of hours as change
	//send half to each address
	var changeHours uint64 = spending.Hours / 4

	if amt.Coins == spending.Coins {
		txn.PushOutput(dest, amt.Coins, changeHours/2)
		txn.SignInputs(toSign)
		txn.UpdateHeader()
		return txn, nil
	}

	change := wallet.NewBalance(spending.Coins-amt.Coins, changeHours/2)
	// TODO -- send change to a new address
	changeAddr := spends[0].Body.Address

	//create transaction
	txn.PushOutput(changeAddr, change.Coins, change.Hours)
	txn.PushOutput(dest, amt.Coins, changeHours/2)
	txn.SignInputs(toSign)
	txn.UpdateHeader()
	return txn, nil
}
Example #30
0
func TransactionFromJSON(str string) (coin.Transaction, error) {

	var TxIn TransactionJSON
	err := json.Unmarshal([]byte(str), TxIn)

	if err != nil {
		errors.New("cannot deserialize")
	}

	var tx coin.Transaction

	tx.Sigs = make([]cipher.Sig, len(TxIn.Sigs))
	tx.In = make([]cipher.SHA256, len(TxIn.In))
	tx.Out = make([]coin.TransactionOutput, len(TxIn.Out))

	for i, _ := range tx.Sigs {
		sig2, err := cipher.SigFromHex(TxIn.Sigs[i])
		if err != nil {
			return coin.Transaction{}, errors.New("invalid signature")
		}
		tx.Sigs[i] = sig2
	}

	for i, _ := range tx.In {
		hash, err := cipher.SHA256FromHex(TxIn.In[i])
		if err != nil {
			return coin.Transaction{}, errors.New("invalid signature")
		}
		tx.In[i] = hash
	}

	for i, _ := range tx.Out {
		out, err := TransactionOutputFromJSON(TxIn.Out[i])
		if err != nil {
			return coin.Transaction{}, errors.New("invalid output")
		}
		tx.Out[i] = out
	}

	tx.Length = uint32(tx.Size())
	tx.Type = 0

	hash, err := cipher.SHA256FromHex(TxIn.Hash)
	if err != nil {
		return coin.Transaction{}, errors.New("invalid hash")
	}
	if hash != tx.Hash() {

	}

	InnerHash, err := cipher.SHA256FromHex(TxIn.Hash)

	if InnerHash != tx.InnerHash {
		return coin.Transaction{}, errors.New("inner hash")
	}

	err = tx.Verify()
	if err != nil {
		return coin.Transaction{}, errors.New("transaction failed verification")
	}

	return tx, nil
}