コード例 #1
0
ファイル: unconfirmed.go プロジェクト: skycoin/skycoin
// 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
}
コード例 #2
0
ファイル: skycoin.go プロジェクト: keepwalking1234/skycoin
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
}
コード例 #3
0
ファイル: blockchain_test.go プロジェクト: skycoin/skycoin
func makeTransactionForChainWithHoursFee(t *testing.T, bc *Blockchain,
	ux coin.UxOut, sec cipher.SecKey, hours, fee uint64) (coin.Transaction, cipher.SecKey) {
	chrs := ux.CoinHours(bc.Time())
	if chrs < hours+fee {
		log.Panicf("CoinHours underflow. Have %d, need at least %d", chrs,
			hours+fee)
	}
	assert.Equal(t, cipher.AddressFromPubKey(cipher.PubKeyFromSecKey(sec)), ux.Body.Address)
	knownUx, exists := bc.GetUnspent().Get(ux.Hash())
	assert.True(t, exists)
	assert.Equal(t, knownUx, ux)
	tx := coin.Transaction{}
	tx.PushInput(ux.Hash())
	p, newSec := cipher.GenerateKeyPair()
	addr := cipher.AddressFromPubKey(p)
	tx.PushOutput(addr, 1e6, hours)
	coinsOut := ux.Body.Coins - 1e6
	if coinsOut > 0 {
		tx.PushOutput(genAddress, coinsOut, chrs-hours-fee)
	}
	tx.SignInputs([]cipher.SecKey{sec})
	assert.Equal(t, len(tx.Sigs), 1)
	assert.Nil(t, cipher.ChkSig(ux.Body.Address, cipher.AddSHA256(tx.HashInner(), tx.In[0]), tx.Sigs[0]))
	tx.UpdateHeader()
	assert.Nil(t, tx.Verify())
	err := bc.VerifyTransaction(tx)
	assert.Nil(t, err)
	return tx, newSec
}
コード例 #4
0
ファイル: blockchain.go プロジェクト: skycoin/skycoin
// 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
}
コード例 #5
0
ファイル: visor.go プロジェクト: keepwalking1234/skycoin
//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
}
コード例 #6
0
ファイル: visor.go プロジェクト: skycoin/skycoin
//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
}
コード例 #7
0
ファイル: blockchain_test.go プロジェクト: skycoin/skycoin
func makeMultipleOutputs(t *testing.T, bc *Blockchain) {
	txn := coin.Transaction{}
	ux := bc.GetUnspent().Array()[0]
	txn.PushInput(ux.Hash())
	txn.PushOutput(genAddress, 1e6, 100)
	txn.PushOutput(genAddress, 2e6, 100)
	txn.PushOutput(genAddress, _genCoins-3e6, 100)
	txn.SignInputs([]cipher.SecKey{genSecret})
	txn.UpdateHeader()
	assert.Nil(t, txn.Verify())
	assert.Nil(t, bc.VerifyTransaction(txn))
	b, err := bc.NewBlockFromTransactions(coin.Transactions{txn},
		bc.Time()+_incTime)
	assert.Nil(t, err)
	assertExecuteBlock(t, bc, b, txn)
}
コード例 #8
0
ファイル: readable.go プロジェクト: keepwalking1234/skycoin
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)
}
コード例 #9
0
ファイル: readable.go プロジェクト: keepwalking1234/skycoin
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
}