func FactoidAddInput(trans fct.ITransaction, key string, address fct.IAddress, amount uint64) error { ok := Utility.IsValidKey(key) if !ok { return fmt.Errorf("Invalid name for transaction") } // First look if this is really an update for _, input := range trans.GetInputs() { if input.GetAddress().IsSameAs(address) { input.SetAmount(amount) return nil } } // Add our new input err := factoidState.GetWallet().AddInput(trans, address, amount) if err != nil { return fmt.Errorf("Failed to add input") } // Update our map with our new transaction to the same key. Otherwise, all // of our work will go away! factoidState.GetDB().PutRaw([]byte(fct.DB_BUILD_TRANS), []byte(key), trans) return nil }
func (w *SCWallet) SignInputs(trans fct.ITransaction) (bool, error) { data, err := trans.MarshalBinarySig() // Get the part of the transaction we sign if err != nil { return false, err } var numSigs int = 0 inputs := trans.GetInputs() rcds := trans.GetRCDs() for i, rcd := range rcds { rcd1, ok := rcd.(*fct.RCD_1) if ok { pub := rcd1.GetPublicKey() we := w.db.GetRaw([]byte(fct.W_ADDRESS_PUB_KEY), pub).(*WalletEntry) if we != nil { var pri [fct.SIGNATURE_LENGTH]byte copy(pri[:], we.private[0]) bsig := ed25519.Sign(&pri, data) sig := new(fct.Signature) sig.SetSignature(bsig[:]) sigblk := new(fct.SignatureBlock) sigblk.AddSignature(sig) trans.SetSignatureBlock(i, sigblk) numSigs += 1 } } } return numSigs == len(inputs), nil }
func filtertransaction(trans fct.ITransaction, addresses [][]byte) bool { if addresses == nil || len(addresses) == 0 { return true } if len(trans.GetInputs()) == 0 && len(trans.GetOutputs()) == 0 { return false } if len(addresses) == 1 && bytes.Equal(addresses[0], trans.GetSigHash().Bytes()) { return true } Search: for _, adr := range addresses { for _, in := range trans.GetInputs() { if bytes.Equal(adr, in.GetAddress().Bytes()) { continue Search } } for _, out := range trans.GetOutputs() { if bytes.Equal(adr, out.GetAddress().Bytes()) { continue Search } } for _, ec := range trans.GetECOutputs() { if bytes.Equal(adr, ec.GetAddress().Bytes()) { continue Search } } return false } return true }
// Assumes validation has already been done. func (fs *FactoidState) UpdateTransaction(trans fct.ITransaction) error { for _, input := range trans.GetInputs() { err := fs.UpdateBalance(input.GetAddress(), -int64(input.GetAmount())) if err != nil { return err } } for _, output := range trans.GetOutputs() { err := fs.UpdateBalance(output.GetAddress(), int64(output.GetAmount())) if err != nil { return err } } for _, ecoutput := range trans.GetECOutputs() { err := fs.UpdateECBalance(ecoutput.GetAddress(), int64(ecoutput.GetAmount())) if err != nil { return err } } fs.numTransactions++ cp.CP.AddUpdate( "transprocessed", // tag "status", // Category fmt.Sprintf("Factoid Transactions Processed: %d", fs.numTransactions), // Title "", // Message 0) // When to expire the message; 0 is never return nil }
func PrtTrans(t fct.ITransaction) { fmt.Println("Transaction") for _, input := range t.GetInputs() { fmt.Println("in ", input.GetAddress(), input.GetAmount(), fs.GetBalance(input.GetAddress())) } for _, output := range t.GetOutputs() { fmt.Println("out", output.GetAddress(), output.GetAmount(), fs.GetBalance(output.GetAddress())) } for _, ecoutput := range t.GetECOutputs() { fmt.Println("ec ", ecoutput.GetAddress(), ecoutput.GetAmount(), fs.GetECBalance(ecoutput.GetAddress())) } }
func FactoidAddFee(trans fct.ITransaction, key string, address fct.IAddress, name string) (uint64, error) { { ins, err := trans.TotalInputs() if err != nil { return 0, err } outs, err := trans.TotalOutputs() if err != nil { return 0, err } ecs, err := trans.TotalECs() if err != nil { return 0, err } if ins != outs+ecs { return 0, fmt.Errorf("Inputs and outputs don't add up") } } ok := Utility.IsValidKey(key) if !ok { return 0, fmt.Errorf("Invalid name for transaction") } fee, err := GetFee() if err != nil { return 0, err } transfee, err := trans.CalculateFee(uint64(fee)) if err != nil { return 0, err } adr, err := factoidState.GetWallet().GetAddressHash(address) if err != nil { return 0, err } for _, input := range trans.GetInputs() { if input.GetAddress().IsSameAs(adr) { amt, err := fct.ValidateAmounts(input.GetAmount(), transfee) if err != nil { return 0, err } input.SetAmount(amt) return transfee, nil } } return 0, fmt.Errorf("%s is not an input to the transaction.", key) }
// Returns an error message about what is wrong with the transaction if it is // invalid, otherwise you are good to go. func (fs *FactoidState) Validate(index int, trans fct.ITransaction) error { err := fs.currentBlock.ValidateTransaction(index, trans) if err != nil { return err } var sums = make(map[[32]byte]uint64, 10) // Look at the sum of an address's inputs for _, input := range trans.GetInputs() { // to a transaction. bal, err := fct.ValidateAmounts(sums[input.GetAddress().Fixed()], input.GetAmount()) if err != nil { return err } if bal > fs.GetBalance(input.GetAddress()) { return fmt.Errorf("Not enough funds in input addresses for the transaction") } sums[input.GetAddress().Fixed()] = bal } return nil }
// Returns an error message about what is wrong with the transaction if it is // invalid, otherwise you are good to go. func (fs *AssetState) Validate(trans fct.ITransaction) error { if err := trans.ValidateSignatures(); err != nil { return err } var sums = make(map[fct.IAddress]uint64, 10) for _, input := range trans.GetInputs() { bal, err := fct.ValidateAmounts( sums[input.GetAddress()], // Will be zero the first time around input.GetAmount()) // Get this amount, check against bounds if err != nil { return err } if bal > fs.GetBalance(input.GetAddress()) { return fmt.Errorf("Not enough funds in input addresses for the transaction") } sums[input.GetAddress()] = bal } return nil }
// Add the first transaction of a block. This transaction makes the // payout to the servers, so it has no inputs. This transaction must // be deterministic so that all servers will know and expect its output. func (b *FBlock) AddCoinbase(trans fct.ITransaction) error { b.BodyMR = nil if len(b.Transactions) != 0 { return fmt.Errorf("The coinbase transaction must be the first transaction") } if len(trans.GetInputs()) != 0 { return fmt.Errorf("The coinbase transaction cannot have any inputs") } if len(trans.GetECOutputs()) != 0 { return fmt.Errorf("The coinbase transaction cannot buy Entry Credits") } if len(trans.GetRCDs()) != 0 { return fmt.Errorf("The coinbase transaction cannot have anyRCD blocks") } if len(trans.GetSignatureBlocks()) != 0 { return fmt.Errorf("The coinbase transaction is not signed") } // TODO Add check here for the proper payouts. b.Transactions = append(b.Transactions, trans) return nil }