github.com/hyperledger/burrow@v0.34.5-0.20220512172541-77f09336001d/execution/contexts/bond_context.go (about)

     1  package contexts
     2  
     3  import (
     4  	"fmt"
     5  	"math/big"
     6  
     7  	"github.com/hyperledger/burrow/acm/acmstate"
     8  	"github.com/hyperledger/burrow/acm/validator"
     9  	"github.com/hyperledger/burrow/crypto"
    10  	"github.com/hyperledger/burrow/execution/exec"
    11  	"github.com/hyperledger/burrow/logging"
    12  	"github.com/hyperledger/burrow/txs/payload"
    13  )
    14  
    15  type BondContext struct {
    16  	State        acmstate.ReaderWriter
    17  	ValidatorSet validator.ReaderWriter
    18  	Logger       *logging.Logger
    19  	tx           *payload.BondTx
    20  }
    21  
    22  // Execute a BondTx to add or remove a new validator
    23  func (ctx *BondContext) Execute(txe *exec.TxExecution, p payload.Payload) error {
    24  	var ok bool
    25  	ctx.tx, ok = p.(*payload.BondTx)
    26  	if !ok {
    27  		return fmt.Errorf("payload must be BondTx, but is: %v", txe.Envelope.Tx.Payload)
    28  	}
    29  
    30  	// the account initiating the bond
    31  	power := new(big.Int).SetUint64(ctx.tx.Input.GetAmount())
    32  	account, err := ctx.State.GetAccount(ctx.tx.Input.Address)
    33  	if err != nil {
    34  		return err
    35  	}
    36  
    37  	ct := account.PublicKey.GetCurveType()
    38  	if ct == crypto.CurveTypeSecp256k1 {
    39  		return fmt.Errorf("secp256k1 not supported")
    40  	}
    41  
    42  	// can the account bond?
    43  	if !hasBondPermission(ctx.State, account, ctx.Logger) {
    44  		return fmt.Errorf("account '%s' lacks bond permission", account.Address)
    45  	}
    46  
    47  	// check account has enough to bond
    48  	amount := ctx.tx.Input.GetAmount()
    49  	if amount == 0 {
    50  		return fmt.Errorf("nothing to bond")
    51  	} else if account.Balance < amount {
    52  		return fmt.Errorf("insufficient funds, account %s only has balance %v and "+
    53  			"we are deducting %v", account.Address, account.Balance, amount)
    54  	}
    55  
    56  	// we're good to go
    57  	err = account.SubtractFromBalance(amount)
    58  	if err != nil {
    59  		return err
    60  	}
    61  
    62  	// assume public key is know as we update account from signatures
    63  	err = validator.AddPower(ctx.ValidatorSet, account.PublicKey, power)
    64  	if err != nil {
    65  		return err
    66  	}
    67  
    68  	return ctx.State.UpdateAccount(account)
    69  }