// Only add valid transactions to the current func (fs *FactoidState) AddTransaction(index int, trans interfaces.ITransaction) error { if err := fs.Validate(index, trans); err != nil { return err } if err := fs.ValidateTransactionAge(trans); err != nil { return err } if err := fs.UpdateTransaction(true, trans); err != nil { return err } if err := fs.CurrentBlock.AddTransaction(trans); err != nil { if err != nil { return err } // We assume validity has been done elsewhere. We are maintaining the "seen" state of // all transactions here. fs.State.Replay.IsTSValid(constants.INTERNAL_REPLAY|constants.NETWORK_REPLAY, trans.GetSigHash(), trans.GetTimestamp()) fs.State.Replay.IsTSValid(constants.NETWORK_REPLAY|constants.NETWORK_REPLAY, trans.GetSigHash(), trans.GetTimestamp()) for index, eo := range trans.GetECOutputs() { pl := fs.State.ProcessLists.Get(fs.DBHeight) incBal := entryCreditBlock.NewIncreaseBalance() v := eo.GetAddress().Fixed() incBal.ECPubKey = (*primitives.ByteSlice32)(&v) incBal.NumEC = eo.GetAmount() / fs.GetCurrentBlock().GetExchRate() incBal.TXID = trans.GetSigHash() incBal.Index = uint64(index) entries := pl.EntryCreditBlock.GetEntries() i := 0 // Find the end of the last IncreaseBalance in this minute for i < len(entries) { if _, ok := entries[i].(*entryCreditBlock.IncreaseBalance); ok { break } i++ } entries = append(entries, nil) copy(entries[i+1:], entries[i:]) entries[i] = incBal pl.EntryCreditBlock.GetBody().SetEntries(entries) } } 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 }