github.com/MetalBlockchain/metalgo@v1.11.9/vms/platformvm/txs/create_chain_tx.go (about) 1 // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. 2 // See the file LICENSE for licensing terms. 3 4 package txs 5 6 import ( 7 "errors" 8 "unicode" 9 10 "github.com/MetalBlockchain/metalgo/ids" 11 "github.com/MetalBlockchain/metalgo/snow" 12 "github.com/MetalBlockchain/metalgo/utils" 13 "github.com/MetalBlockchain/metalgo/utils/constants" 14 "github.com/MetalBlockchain/metalgo/utils/units" 15 "github.com/MetalBlockchain/metalgo/vms/components/verify" 16 ) 17 18 const ( 19 MaxNameLen = 128 20 MaxGenesisLen = units.MiB 21 ) 22 23 var ( 24 _ UnsignedTx = (*CreateChainTx)(nil) 25 26 ErrCantValidatePrimaryNetwork = errors.New("new blockchain can't be validated by primary network") 27 28 errInvalidVMID = errors.New("invalid VM ID") 29 errFxIDsNotSortedAndUnique = errors.New("feature extensions IDs must be sorted and unique") 30 errNameTooLong = errors.New("name too long") 31 errGenesisTooLong = errors.New("genesis too long") 32 errIllegalNameCharacter = errors.New("illegal name character") 33 ) 34 35 // CreateChainTx is an unsigned createChainTx 36 type CreateChainTx struct { 37 // Metadata, inputs and outputs 38 BaseTx `serialize:"true"` 39 // ID of the Subnet that validates this blockchain 40 SubnetID ids.ID `serialize:"true" json:"subnetID"` 41 // A human readable name for the chain; need not be unique 42 ChainName string `serialize:"true" json:"chainName"` 43 // ID of the VM running on the new chain 44 VMID ids.ID `serialize:"true" json:"vmID"` 45 // IDs of the feature extensions running on the new chain 46 FxIDs []ids.ID `serialize:"true" json:"fxIDs"` 47 // Byte representation of genesis state of the new chain 48 GenesisData []byte `serialize:"true" json:"genesisData"` 49 // Authorizes this blockchain to be added to this subnet 50 SubnetAuth verify.Verifiable `serialize:"true" json:"subnetAuthorization"` 51 } 52 53 func (tx *CreateChainTx) SyntacticVerify(ctx *snow.Context) error { 54 switch { 55 case tx == nil: 56 return ErrNilTx 57 case tx.SyntacticallyVerified: // already passed syntactic verification 58 return nil 59 case tx.SubnetID == constants.PrimaryNetworkID: 60 return ErrCantValidatePrimaryNetwork 61 case len(tx.ChainName) > MaxNameLen: 62 return errNameTooLong 63 case tx.VMID == ids.Empty: 64 return errInvalidVMID 65 case !utils.IsSortedAndUnique(tx.FxIDs): 66 return errFxIDsNotSortedAndUnique 67 case len(tx.GenesisData) > MaxGenesisLen: 68 return errGenesisTooLong 69 } 70 71 for _, r := range tx.ChainName { 72 if r > unicode.MaxASCII || !(unicode.IsLetter(r) || unicode.IsNumber(r) || r == ' ') { 73 return errIllegalNameCharacter 74 } 75 } 76 77 if err := tx.BaseTx.SyntacticVerify(ctx); err != nil { 78 return err 79 } 80 if err := tx.SubnetAuth.Verify(); err != nil { 81 return err 82 } 83 84 tx.SyntacticallyVerified = true 85 return nil 86 } 87 88 func (tx *CreateChainTx) Visit(visitor Visitor) error { 89 return visitor.CreateChainTx(tx) 90 }