github.com/ava-labs/avalanchego@v1.11.11/vms/example/xsvm/vm.go (about) 1 // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. 2 // See the file LICENSE for licensing terms. 3 4 package xsvm 5 6 import ( 7 "context" 8 "fmt" 9 "net/http" 10 11 "github.com/gorilla/rpc/v2" 12 "go.uber.org/zap" 13 14 "github.com/ava-labs/avalanchego/database" 15 "github.com/ava-labs/avalanchego/database/versiondb" 16 "github.com/ava-labs/avalanchego/ids" 17 "github.com/ava-labs/avalanchego/snow" 18 "github.com/ava-labs/avalanchego/snow/consensus/snowman" 19 "github.com/ava-labs/avalanchego/snow/engine/common" 20 "github.com/ava-labs/avalanchego/utils/constants" 21 "github.com/ava-labs/avalanchego/utils/json" 22 "github.com/ava-labs/avalanchego/version" 23 "github.com/ava-labs/avalanchego/vms/example/xsvm/api" 24 "github.com/ava-labs/avalanchego/vms/example/xsvm/builder" 25 "github.com/ava-labs/avalanchego/vms/example/xsvm/chain" 26 "github.com/ava-labs/avalanchego/vms/example/xsvm/execute" 27 "github.com/ava-labs/avalanchego/vms/example/xsvm/genesis" 28 "github.com/ava-labs/avalanchego/vms/example/xsvm/state" 29 30 smblock "github.com/ava-labs/avalanchego/snow/engine/snowman/block" 31 xsblock "github.com/ava-labs/avalanchego/vms/example/xsvm/block" 32 ) 33 34 var ( 35 _ smblock.ChainVM = (*VM)(nil) 36 _ smblock.BuildBlockWithContextChainVM = (*VM)(nil) 37 ) 38 39 type VM struct { 40 common.AppHandler 41 42 chainContext *snow.Context 43 db database.Database 44 genesis *genesis.Genesis 45 engineChan chan<- common.Message 46 47 chain chain.Chain 48 builder builder.Builder 49 } 50 51 func (vm *VM) Initialize( 52 _ context.Context, 53 chainContext *snow.Context, 54 db database.Database, 55 genesisBytes []byte, 56 _ []byte, 57 _ []byte, 58 engineChan chan<- common.Message, 59 _ []*common.Fx, 60 _ common.AppSender, 61 ) error { 62 vm.AppHandler = common.NewNoOpAppHandler(chainContext.Log) 63 64 chainContext.Log.Info("initializing xsvm", 65 zap.Stringer("version", Version), 66 ) 67 68 vm.chainContext = chainContext 69 vm.db = db 70 g, err := genesis.Parse(genesisBytes) 71 if err != nil { 72 return fmt.Errorf("failed to parse genesis bytes: %w", err) 73 } 74 75 vdb := versiondb.New(vm.db) 76 if err := execute.Genesis(vdb, chainContext.ChainID, g); err != nil { 77 return fmt.Errorf("failed to initialize genesis state: %w", err) 78 } 79 if err := vdb.Commit(); err != nil { 80 return err 81 } 82 83 vm.genesis = g 84 vm.engineChan = engineChan 85 86 vm.chain, err = chain.New(chainContext, vm.db) 87 if err != nil { 88 return fmt.Errorf("failed to initialize chain manager: %w", err) 89 } 90 91 vm.builder = builder.New(chainContext, engineChan, vm.chain) 92 93 chainContext.Log.Info("initialized xsvm", 94 zap.Stringer("lastAcceptedID", vm.chain.LastAccepted()), 95 ) 96 return nil 97 } 98 99 func (vm *VM) SetState(_ context.Context, state snow.State) error { 100 vm.chain.SetChainState(state) 101 return nil 102 } 103 104 func (vm *VM) Shutdown(context.Context) error { 105 if vm.chainContext == nil { 106 return nil 107 } 108 return vm.db.Close() 109 } 110 111 func (*VM) Version(context.Context) (string, error) { 112 return Version.String(), nil 113 } 114 115 func (vm *VM) CreateHandlers(context.Context) (map[string]http.Handler, error) { 116 server := rpc.NewServer() 117 server.RegisterCodec(json.NewCodec(), "application/json") 118 server.RegisterCodec(json.NewCodec(), "application/json;charset=UTF-8") 119 api := api.NewServer( 120 vm.chainContext, 121 vm.genesis, 122 vm.db, 123 vm.chain, 124 vm.builder, 125 ) 126 return map[string]http.Handler{ 127 "": server, 128 }, server.RegisterService(api, constants.XSVMName) 129 } 130 131 func (*VM) HealthCheck(context.Context) (interface{}, error) { 132 return http.StatusOK, nil 133 } 134 135 func (*VM) Connected(context.Context, ids.NodeID, *version.Application) error { 136 return nil 137 } 138 139 func (*VM) Disconnected(context.Context, ids.NodeID) error { 140 return nil 141 } 142 143 func (vm *VM) GetBlock(_ context.Context, blkID ids.ID) (snowman.Block, error) { 144 return vm.chain.GetBlock(blkID) 145 } 146 147 func (vm *VM) ParseBlock(_ context.Context, blkBytes []byte) (snowman.Block, error) { 148 blk, err := xsblock.Parse(blkBytes) 149 if err != nil { 150 return nil, err 151 } 152 return vm.chain.NewBlock(blk) 153 } 154 155 func (vm *VM) BuildBlock(ctx context.Context) (snowman.Block, error) { 156 return vm.builder.BuildBlock(ctx, nil) 157 } 158 159 func (vm *VM) SetPreference(_ context.Context, preferred ids.ID) error { 160 vm.builder.SetPreference(preferred) 161 return nil 162 } 163 164 func (vm *VM) LastAccepted(context.Context) (ids.ID, error) { 165 return vm.chain.LastAccepted(), nil 166 } 167 168 func (vm *VM) BuildBlockWithContext(ctx context.Context, blockContext *smblock.Context) (snowman.Block, error) { 169 return vm.builder.BuildBlock(ctx, blockContext) 170 } 171 172 func (vm *VM) GetBlockIDAtHeight(_ context.Context, height uint64) (ids.ID, error) { 173 return state.GetBlockIDByHeight(vm.db, height) 174 }