// 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 interfaces.ITransaction) error { 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 := factoid.ValidateAmounts(sums[input.GetAddress().Fixed()], input.GetAmount()) if err != nil { return err } if int64(bal) > fs.State.GetF(true, input.GetAddress().Fixed()) { return fmt.Errorf("%s", "Not enough funds in input addresses for the transaction") } sums[input.GetAddress().Fixed()] = bal } return nil }
// Assumes validation has already been done. func (fs *FactoidState) UpdateTransaction(rt bool, trans interfaces.ITransaction) error { for _, input := range trans.GetInputs() { adr := input.GetAddress().Fixed() oldv := fs.State.GetF(rt, adr) fs.State.PutF(rt, adr, oldv-int64(input.GetAmount())) } for _, output := range trans.GetOutputs() { adr := output.GetAddress().Fixed() oldv := fs.State.GetF(rt, adr) fs.State.PutF(rt, adr, oldv+int64(output.GetAmount())) } for _, ecOut := range trans.GetECOutputs() { ecbal := int64(ecOut.GetAmount()) / int64(fs.State.FactoshisPerEC) fs.State.PutE(rt, ecOut.GetAddress().Fixed(), fs.State.GetE(rt, ecOut.GetAddress().Fixed())+ecbal) } fs.State.NumTransactions++ 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 interfaces.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 }
func (w *SCWallet) SignInputs(trans interfaces.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.(*RCD_1) if ok { pub := rcd1.GetPublicKey() wex, err := w.db.Get([]byte(constants.W_ADDRESS_PUB_KEY), pub, new(WalletEntry)) if err != nil { return false, err } we := wex.(*WalletEntry) if we != nil { var pri [constants.SIGNATURE_LENGTH]byte copy(pri[:], we.private[0]) bsig := ed25519.Sign(&pri, data) sig := new(FactoidSignature) sig.SetSignature(bsig[:]) sigblk := new(SignatureBlock) sigblk.AddSignature(sig) trans.SetSignatureBlock(i, sigblk) numSigs += 1 } } } return numSigs == len(inputs), nil }