// 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 }
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 }
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 }
// 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 }
//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 }
//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 }
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) }
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) }
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 }