Files
proto/p/txs/create_chain_tx.go

96 lines
2.8 KiB
Go

// Copyright (C) 2019-2025, Lux Industries, Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package txs
import (
"context"
"errors"
"unicode"
"github.com/luxfi/constants"
"github.com/luxfi/ids"
"github.com/luxfi/runtime"
"github.com/luxfi/vm/components/verify"
)
const (
MaxNameLen = 128
MaxGenesisLen = constants.MiB
)
var (
_ UnsignedTx = (*CreateChainTx)(nil)
ErrCantValidatePrimaryNetwork = errors.New("new blockchain can't be validated by primary network")
errInvalidVMID = errors.New("invalid VM ID")
errFxIDsNotSortedAndUnique = errors.New("feature extensions IDs must be sorted and unique")
errNameTooLong = errors.New("name too long")
errGenesisTooLong = errors.New("genesis too long")
errIllegalNameCharacter = errors.New("illegal name character")
)
// CreateChainTx is an unsigned createChainTx
type CreateChainTx struct {
// Metadata, inputs and outputs
BaseTx `serialize:"true"`
// ID of the Network that validates this chain
ValidateNetworkID ids.ID `serialize:"true" json:"networkID"`
// A human readable name for the blockchain; need not be unique
BlockchainName string `serialize:"true" json:"blockchainName"`
// ID of the VM running on the new blockchain
VMID ids.ID `serialize:"true" json:"vmID"`
// IDs of the feature extensions running on the new blockchain
FxIDs []ids.ID `serialize:"true" json:"fxIDs"`
// Byte representation of genesis state of the new blockchain
GenesisData []byte `serialize:"true" json:"genesisData"`
// Authorizes this blockchain to be added to this chain
ChainAuth verify.Verifiable `serialize:"true" json:"chainAuthorization"`
}
func (tx *CreateChainTx) SyntacticVerify(rt *runtime.Runtime) error {
switch {
case tx == nil:
return ErrNilTx
case tx.SyntacticallyVerified: // already passed syntactic verification
return nil
case tx.ValidateNetworkID == constants.PrimaryNetworkID:
return ErrCantValidatePrimaryNetwork
case len(tx.BlockchainName) > MaxNameLen:
return errNameTooLong
case tx.VMID == ids.Empty:
return errInvalidVMID
case !isSortedAndUniqueByCompare(tx.FxIDs):
return errFxIDsNotSortedAndUnique
case len(tx.GenesisData) > MaxGenesisLen:
return errGenesisTooLong
}
for _, r := range tx.BlockchainName {
if r > unicode.MaxASCII || (!unicode.IsLetter(r) && !unicode.IsNumber(r) && r != ' ') {
return errIllegalNameCharacter
}
}
if err := tx.BaseTx.SyntacticVerify(rt); err != nil {
return err
}
if err := tx.ChainAuth.Verify(); err != nil {
return err
}
tx.SyntacticallyVerified = true
return nil
}
func (tx *CreateChainTx) Visit(visitor Visitor) error {
return visitor.CreateChainTx(tx)
}
// InitializeWithContext initializes the transaction with consensus context
func (tx *CreateChainTx) InitializeWithContext(ctx context.Context) error {
// Initialize any context-dependent fields here
return nil
}