+++ /dev/null
-package mainchain
-
-import (
- "math"
- "time"
-
- "github.com/vapor/blockchain/txbuilder"
- bytomtypes "github.com/vapor/claim/bytom/protocolbc/types"
- "github.com/vapor/consensus"
- "github.com/vapor/errors"
-)
-
-// NewBuilder return new TemplateBuilder instance
-func NewBuilder(maxTime time.Time) *TemplateBuilder {
- return &TemplateBuilder{maxTime: maxTime}
-}
-
-// TemplateBuilder is struct of building transactions
-type TemplateBuilder struct {
- base *bytomtypes.TxData
- inputs []*bytomtypes.TxInput
- outputs []*bytomtypes.TxOutput
- signingInstructions []*SigningInstruction
- minTime time.Time
- maxTime time.Time
- timeRange uint64
- referenceData []byte
- rollbacks []func()
- callbacks []func() error
-}
-
-// AddInput add inputs of transactions
-func (b *TemplateBuilder) AddInput(in *bytomtypes.TxInput, sigInstruction *SigningInstruction) error {
- if in.InputType() != bytomtypes.CoinbaseInputType && in.Amount() > math.MaxInt64 {
- return errors.WithDetailf(txbuilder.ErrBadAmount, "amount %d exceeds maximum value 2^63", in.Amount())
- }
- b.inputs = append(b.inputs, in)
- b.signingInstructions = append(b.signingInstructions, sigInstruction)
- return nil
-}
-
-// AddOutput add outputs of transactions
-func (b *TemplateBuilder) AddOutput(o *bytomtypes.TxOutput) error {
- if o.Amount > math.MaxInt64 {
- return errors.WithDetailf(txbuilder.ErrBadAmount, "amount %d exceeds maximum value 2^63", o.Amount)
- }
- b.outputs = append(b.outputs, o)
- return nil
-}
-
-// RestrictMinTime set minTime
-func (b *TemplateBuilder) RestrictMinTime(t time.Time) {
- if t.After(b.minTime) {
- b.minTime = t
- }
-}
-
-// RestrictMaxTime set maxTime
-func (b *TemplateBuilder) RestrictMaxTime(t time.Time) {
- if t.Before(b.maxTime) {
- b.maxTime = t
- }
-}
-
-// MaxTime return maxTime
-func (b *TemplateBuilder) MaxTime() time.Time {
- return b.maxTime
-}
-
-// OnRollback registers a function that can be
-// used to attempt to undo any side effects of building
-// actions. For example, it might cancel any reservations
-// reservations that were made on UTXOs in a spend action.
-// Rollback is a "best-effort" operation and not guaranteed
-// to succeed. Each action's side effects, if any, must be
-// designed with this in mind.
-func (b *TemplateBuilder) OnRollback(rollbackFn func()) {
- b.rollbacks = append(b.rollbacks, rollbackFn)
-}
-
-// OnBuild registers a function that will be run after all
-// actions have been successfully built.
-func (b *TemplateBuilder) OnBuild(buildFn func() error) {
- b.callbacks = append(b.callbacks, buildFn)
-}
-
-func (b *TemplateBuilder) rollback() {
- for _, f := range b.rollbacks {
- f()
- }
-}
-
-// Build build transactions with template
-func (b *TemplateBuilder) Build() (*Template, *bytomtypes.TxData, error) {
- // Run any building callbacks.
- for _, cb := range b.callbacks {
- err := cb()
- if err != nil {
- return nil, nil, err
- }
- }
-
- tpl := &Template{}
- tx := b.base
- if tx == nil {
- tx = &bytomtypes.TxData{
- Version: 1,
- }
- }
-
- if b.timeRange != 0 {
- tx.TimeRange = b.timeRange
- }
-
- // Add all the built outputs.
- tx.Outputs = append(tx.Outputs, b.outputs...)
-
- // Add all the built inputs and their corresponding signing instructions.
- for i, in := range b.inputs {
- instruction := b.signingInstructions[i]
- instruction.Position = uint32(len(tx.Inputs))
-
- // Empty signature arrays should be serialized as empty arrays, not null.
- if instruction.WitnessComponents == nil {
- instruction.WitnessComponents = []witnessComponent{}
- }
- tpl.SigningInstructions = append(tpl.SigningInstructions, instruction)
- tx.Inputs = append(tx.Inputs, in)
- }
-
- tpl.Transaction = bytomtypes.NewTx(*tx)
- tpl.Fee = CalculateTxFee(tpl.Transaction)
- return tpl, tx, nil
-}
-
-// CalculateTxFee calculate transaction fee
-func CalculateTxFee(tx *bytomtypes.Tx) (fee uint64) {
- totalInputBTM := uint64(0)
- totalOutputBTM := uint64(0)
-
- for _, input := range tx.Inputs {
- if input.InputType() != bytomtypes.CoinbaseInputType && input.AssetID() == *consensus.BTMAssetID {
- totalInputBTM += input.Amount()
- }
- }
-
- for _, output := range tx.Outputs {
- if *output.AssetId == *consensus.BTMAssetID {
- totalOutputBTM += output.Amount
- }
- }
-
- fee = totalInputBTM - totalOutputBTM
- return
-}