Documentation ¶
Index ¶
- Constants
- func GetVstorageKeeper(t *testing.T, k Keeper) vstorage.Keeper
- func NewMsgServerImpl(keeper Keeper) types.MsgServer
- func NewQuerier(keeper Keeper, legacyQuerierCdc *codec.LegacyAmino) sdk.Querier
- func WaitUntilSwingStoreExportDone() error
- func WaitUntilSwingStoreExportStarted() error
- func WriteSwingStoreExportToDirectory(provider SwingStoreExportProvider, exportDir string) (err error)
- type ExtensionSnapshotter
- func (snapshotter *ExtensionSnapshotter) InitiateSnapshot(height int64) error
- func (snapshotter *ExtensionSnapshotter) OnExportRetrieved(provider SwingStoreExportProvider) error
- func (snapshotter *ExtensionSnapshotter) OnExportStarted(blockHeight uint64, retrieveExport func() error) error
- func (snapshotter *ExtensionSnapshotter) RestoreExtension(blockHeight uint64, format uint32, ...) error
- func (snapshotter *ExtensionSnapshotter) SnapshotExtension(blockHeight uint64, payloadWriter snapshots.ExtensionPayloadWriter) error
- func (snapshotter *ExtensionSnapshotter) SnapshotFormat() uint32
- func (snapshotter *ExtensionSnapshotter) SnapshotName() string
- func (snapshotter *ExtensionSnapshotter) SupportedFormats() []uint32
- type Keeper
- func (k Keeper) BlockingSend(ctx sdk.Context, action vm.Action) (string, error)
- func (k Keeper) ChargeBeans(ctx sdk.Context, beansPerUnit map[string]sdkmath.Uint, addr sdk.AccAddress, ...) error
- func (k Keeper) ChargeForProvisioning(ctx sdk.Context, submitter, addr sdk.AccAddress, powerFlags []string) error
- func (k Keeper) ChargeForSmartWallet(ctx sdk.Context, beansPerUnit map[string]sdkmath.Uint, addr sdk.AccAddress) error
- func (k Keeper) CoreEvalProposal(ctx sdk.Context, p *types.CoreEvalProposal) error
- func (k Keeper) GetBeansOwing(ctx sdk.Context, addr sdk.AccAddress) sdkmath.Uint
- func (k Keeper) GetBeansPerUnit(ctx sdk.Context) map[string]sdkmath.Uint
- func (k Keeper) GetEgress(ctx sdk.Context, addr sdk.AccAddress) types.Egress
- func (k Keeper) GetMailbox(ctx sdk.Context, peer string) string
- func (k Keeper) GetParams(ctx sdk.Context) (params types.Params)
- func (k Keeper) GetSmartWalletState(ctx sdk.Context, addr sdk.AccAddress) types.SmartWalletState
- func (k Keeper) GetState(ctx sdk.Context) types.State
- func (k Keeper) GetStoreName() string
- func (k Keeper) GetSwingStore(ctx sdk.Context) sdk.KVStore
- func (k Keeper) InboundQueueLength(ctx sdk.Context) (int32, error)
- func (k Keeper) IsHighPriorityAddress(ctx sdk.Context, addr sdk.AccAddress) (bool, error)
- func (k Keeper) Logger(ctx sdk.Context) log.Logger
- func (k Keeper) PathToEncodedKey(path string) []byte
- func (k Keeper) PushAction(ctx sdk.Context, action vm.Action) error
- func (k Keeper) PushHighPriorityAction(ctx sdk.Context, action vm.Action) error
- func (k Keeper) SetBeansOwing(ctx sdk.Context, addr sdk.AccAddress, beans sdkmath.Uint)
- func (k Keeper) SetEgress(ctx sdk.Context, egress *types.Egress) error
- func (k Keeper) SetMailbox(ctx sdk.Context, peer string, mailbox string)
- func (k Keeper) SetParams(ctx sdk.Context, params types.Params)
- func (k Keeper) SetState(ctx sdk.Context, state types.State)
- func (k Keeper) UpdateQueueAllowed(ctx sdk.Context) error
- type Migrator
- type Querier
- func (k Querier) Egress(c context.Context, req *types.QueryEgressRequest) (*types.QueryEgressResponse, error)
- func (k Querier) Mailbox(c context.Context, req *types.QueryMailboxRequest) (*types.QueryMailboxResponse, error)
- func (k Querier) Params(c context.Context, req *types.QueryParamsRequest) (*types.QueryParamsResponse, error)
- type SwingStoreExportEventHandler
- type SwingStoreExportOptions
- type SwingStoreExportProvider
- type SwingStoreExportsHandler
- type SwingStoreRestoreOptions
Constants ¶
const ( StoragePathActionQueue = "actionQueue" StoragePathHighPriorityQueue = "highPriorityQueue" StoragePathHighPrioritySenders = "highPrioritySenders" StoragePathBeansOwing = "beansOwing" StoragePathEgress = "egress" StoragePathMailbox = "mailbox" StoragePathCustom = "published" StoragePathBundles = "bundles" StoragePathSwingStore = "swingStore" )
Top-level paths for chain storage should remain synchronized with packages/internal/src/chain-storage-paths.js
const ( QueryEgress = "egress" QueryMailbox = "mailbox" LegacyQueryStorage = "storage" LegacyQueryKeys = "keys" )
query endpoints supported by the swingset Querier
const ( // SwingStoreArtifactModeNone means that no artifacts are part of the // export / import. SwingStoreArtifactModeNone = "none" // SwingStoreArtifactModeOperational represents the minimal set of artifacts // needed to operate a node. SwingStoreArtifactModeOperational = "operational" // SwingStoreArtifactModeReplay represents the set of artifacts needed to // replay the current incarnation of every vat. SwingStoreArtifactModeReplay = "replay" // SwingStoreArtifactModeArchival represents the set of all artifacts // providing all available historical state. SwingStoreArtifactModeArchival = "archival" // SwingStoreArtifactModeDebug represents the maximal set of artifacts // available in the JS swing-store, including any kept around for debugging // purposes only (like previous XS heap snapshots) SwingStoreArtifactModeDebug = "debug" )
const ( // SwingStoreExportDataModeSkip indicates "export data" should be excluded from // an export. ArtifactMode cannot be "none" in this case. SwingStoreExportDataModeSkip = "skip" // SwingStoreExportDataModeRepairMetadata indicates the "export data" should be // used to repair the metadata of an existing swing-store for an import // operation. ArtifactMode must be "none" in this case. SwingStoreExportDataModeRepairMetadata = "repair-metadata" // SwingStoreExportDataModeAll indicates "export data" should be part of the // export or import. For import, ArtifactMode cannot be "none". SwingStoreExportDataModeAll = "all" )
const ExportManifestFilename = "export-manifest.json"
ExportManifestFilename is the manifest filename which must be synchronized with the JS export/import tooling See packages/cosmic-swingset/src/export-kernel-db.js and packages/cosmic-swingset/src/import-kernel-db.js
const SnapshotFormat = 1
SnapshotFormat 1 defines all extension payloads to be SwingStoreArtifact proto messages
const UntrustedExportDataArtifactName = "UNTRUSTED-EXPORT-DATA"
UntrustedExportDataArtifactName is a special artifact name that the provider and consumer of an export can use to indicate the presence of a synthetic artifact containing untrusted "export data". This artifact must not end up in the list of artifacts imported by the JS import tooling (which would fail).
const ( // WalletStoragePathSegment matches the value of WALLET_STORAGE_PATH_SEGMENT // packages/vats/src/core/startWalletFactory.js WalletStoragePathSegment = "wallet" )
Variables ¶
This section is empty.
Functions ¶
func GetVstorageKeeper ¶
GetVstorageKeeper returns the vstorage keeper from the swingset keeper for testing purposes.
func NewMsgServerImpl ¶
NewMsgServerImpl returns an implementation of the bank MsgServer interface for the provided Keeper.
func NewQuerier ¶
func NewQuerier(keeper Keeper, legacyQuerierCdc *codec.LegacyAmino) sdk.Querier
NewQuerier is the module level router for state queries
func WaitUntilSwingStoreExportDone ¶
func WaitUntilSwingStoreExportDone() error
WaitUntilSwingStoreExportDone synchronizes with the completion of an export operation in progress, if any. Only a single swing-store operation may execute at a time. Calling InitiateExport or RestoreExport will fail if a swing-store operation is already in progress. Furthermore, a component may need to know once an export it initiated has completed. Once this method call returns, the goroutine is guaranteed to have terminated, and the SwingStoreExportEventHandler provided to InitiateExport to no longer be in use.
Reports any error that may have occurred from InitiateExport. If no export operation is in progress (InitiateExport hasn't been called or already completed), or if we previously checked if an export had completed, returns immediately.
Must be called by the main goroutine
func WaitUntilSwingStoreExportStarted ¶
func WaitUntilSwingStoreExportStarted() error
WaitUntilSwingStoreExportStarted synchronizes with an export operation in progress, if any. The JS swing-store export must have started before a new block is committed to ensure the content of the export is the one expected. The app must call this method before sending a commit action to the JS controller.
Waits for a just initiated export operation to have started in its goroutine. If no operation is in progress (InitiateExport hasn't been called or already completed), or if we previously checked if the operation had started, returns immediately.
Must be called by the main goroutine
func WriteSwingStoreExportToDirectory ¶
func WriteSwingStoreExportToDirectory(provider SwingStoreExportProvider, exportDir string) (err error)
WriteSwingStoreExportToDirectory consumes a provider and saves a swing-store export to disk in the provided directory. It creates files for each artifact deriving a filename from the artifact name, and stores any "export data" in a jsonl-like file, before saving the export manifest linking these together. The export manifest filename and overall export format is common with the JS swing-store import/export logic.
Types ¶
type ExtensionSnapshotter ¶
type ExtensionSnapshotter struct {
// contains filtered or unexported fields
}
ExtensionSnapshotter is the cosmos state-sync extension snapshotter for the x/swingset module. It handles the SwingSet state that is not part of the Cosmos DB. Currently that state is solely composed of the SwingStore artifacts, as a copy of the SwingStore "export data" is streamed into the cosmos DB during execution. When performing a snapshot, the extension leverages the SwingStoreExportsHandler to retrieve the needed SwingStore artifacts. When restoring a snapshot, the extension combines the artifacts from the state-sync snapshot with the SwingStore "export data" from the already restored cosmos DB, to produce a full SwingStore export that can be imported to create a new JS swing-store DB.
Since swing-store is not able to open its DB at historical commit points, the export operation must start before new changes are committed, aka before Swingset is instructed to commit the next block. For that reason the cosmos snapshot operation is currently mediated by the SwingStoreExportsHandler, which helps with the synchronization needed to generate consistent exports, while allowing SwingSet activity to proceed for the next block. This relies on the application calling WaitUntilSwingStoreExportStarted before instructing SwingSet to commit a new block.
func NewExtensionSnapshotter ¶
func NewExtensionSnapshotter( app *baseapp.BaseApp, swingStoreExportsHandler *SwingStoreExportsHandler, getSwingStoreExportDataShadowCopyReader func(height int64) agoric.KVEntryReader, ) *ExtensionSnapshotter
NewExtensionSnapshotter creates a new swingset ExtensionSnapshotter
func (*ExtensionSnapshotter) InitiateSnapshot ¶
func (snapshotter *ExtensionSnapshotter) InitiateSnapshot(height int64) error
InitiateSnapshot initiates a snapshot for the given block height. If a snapshot is already in progress, or if no snapshot manager is configured, this will fail.
The snapshot operation is performed in a goroutine. Use WaitUntilSwingStoreExportStarted to synchronize commit boundaries.
func (*ExtensionSnapshotter) OnExportRetrieved ¶
func (snapshotter *ExtensionSnapshotter) OnExportRetrieved(provider SwingStoreExportProvider) error
OnExportRetrieved handles the SwingStore export retrieved by the SwingStoreExportsHandler and writes it out to the SnapshotExtension's payloadWriter. This operation is invoked by the SwingStoreExportsHandler in the snapshot manager goroutine synchronized with SwingStoreExportsHandler's own goroutine.
Implements SwingStoreExportEventHandler
func (*ExtensionSnapshotter) OnExportStarted ¶
func (snapshotter *ExtensionSnapshotter) OnExportStarted(blockHeight uint64, retrieveExport func() error) error
OnExportStarted performs the actual cosmos state-sync app snapshot. The cosmos implementation will ultimately call SnapshotExtension, which can retrieve and process the SwingStore artifacts. This method is invoked by the SwingStoreExportsHandler in a goroutine started by InitiateExport, only if no other SwingStore export operation is already in progress.
Implements SwingStoreExportEventHandler
func (*ExtensionSnapshotter) RestoreExtension ¶
func (snapshotter *ExtensionSnapshotter) RestoreExtension(blockHeight uint64, format uint32, payloadReader snapshots.ExtensionPayloadReader) error
RestoreExtension restores an extension state snapshot, the payload reader returns io.EOF when it reaches the extension boundaries. Implements ExtensionSnapshotter
func (*ExtensionSnapshotter) SnapshotExtension ¶
func (snapshotter *ExtensionSnapshotter) SnapshotExtension(blockHeight uint64, payloadWriter snapshots.ExtensionPayloadWriter) error
SnapshotExtension is the method invoked by cosmos to write extension payloads into the underlying protobuf stream of the state-sync snapshot. This method is invoked by the cosmos snapshot manager in a goroutine it started during the call to OnExportStarted. However the snapshot manager fully synchronizes its goroutine with the goroutine started by the SwingStoreSnapshotter, making it safe to invoke callbacks of the SwingStoreSnapshotter. SnapshotExtension actually delegates writing extension payloads to OnExportRetrieved.
Implements ExtensionSnapshotter
func (*ExtensionSnapshotter) SnapshotFormat ¶
func (snapshotter *ExtensionSnapshotter) SnapshotFormat() uint32
SnapshotFormat returns the extension specific format used to encode the extension payloads when creating a snapshot. It's independent of the format used for the overall state-sync snapshot. Implements ExtensionSnapshotter
func (*ExtensionSnapshotter) SnapshotName ¶
func (snapshotter *ExtensionSnapshotter) SnapshotName() string
SnapshotName returns the name of the snapshotter, it should be unique in the manager. Implements ExtensionSnapshotter
func (*ExtensionSnapshotter) SupportedFormats ¶
func (snapshotter *ExtensionSnapshotter) SupportedFormats() []uint32
SupportedFormats returns a list of extension specific payload formats it can restore from. Implements ExtensionSnapshotter
type Keeper ¶
type Keeper struct {
// contains filtered or unexported fields
}
Keeper maintains the link to data vstorage and exposes getter/setter methods for the various parts of the state machine
func NewKeeper ¶
func NewKeeper( cdc codec.Codec, key storetypes.StoreKey, paramSpace paramtypes.Subspace, accountKeeper types.AccountKeeper, bankKeeper bankkeeper.Keeper, vstorageKeeper vstoragekeeper.Keeper, feeCollectorName string, callToController func(ctx sdk.Context, str string) (string, error), ) Keeper
NewKeeper creates a new IBC transfer Keeper instance
func (Keeper) BlockingSend ¶
BlockingSend sends a message to the controller and blocks the Golang process until the response. It is orthogonal to PushAction, and should only be used by SwingSet to perform block lifecycle events (BEGIN_BLOCK, END_BLOCK, COMMIT_BLOCK).
func (Keeper) ChargeBeans ¶
func (k Keeper) ChargeBeans( ctx sdk.Context, beansPerUnit map[string]sdkmath.Uint, addr sdk.AccAddress, beans sdkmath.Uint, ) error
ChargeBeans charges the given address the given number of beans. It divides the beans into the number to debit immediately vs. the number to store in the beansOwing.
func (Keeper) ChargeForProvisioning ¶
func (Keeper) ChargeForSmartWallet ¶
func (k Keeper) ChargeForSmartWallet( ctx sdk.Context, beansPerUnit map[string]sdkmath.Uint, addr sdk.AccAddress, ) error
ChargeForSmartWallet charges the fee for provisioning a smart wallet.
func (Keeper) CoreEvalProposal ¶
CoreEvalProposal tells SwingSet to evaluate the given JS code.
func (Keeper) GetBeansOwing ¶
GetBeansOwing returns the number of beans that the given address owes to the FeeAccount but has not yet paid.
func (Keeper) GetBeansPerUnit ¶
GetBeansPerUnit returns a map taken from the current SwingSet parameters from a unit (key) string to an unsigned integer amount of beans.
func (Keeper) GetMailbox ¶
GetMailbox gets the entire mailbox struct for a peer
func (Keeper) GetSmartWalletState ¶
func (k Keeper) GetSmartWalletState(ctx sdk.Context, addr sdk.AccAddress) types.SmartWalletState
GetSmartWalletState returns the provision state of the smart wallet for the account address
func (Keeper) GetStoreName ¶
func (Keeper) InboundQueueLength ¶
func (Keeper) IsHighPriorityAddress ¶
func (Keeper) PathToEncodedKey ¶
func (Keeper) PushAction ¶
PushAction appends an action to the controller's actionQueue.
func (Keeper) PushHighPriorityAction ¶
PushAction appends an action to the controller's highPriorityQueue.
func (Keeper) SetBeansOwing ¶
SetBeansOwing sets the number of beans that the given address owes to the feeCollector but has not yet paid.
func (Keeper) SetEgress ¶
SetEgress sets the egress struct for a peer, and ensures its account exists
func (Keeper) SetMailbox ¶
SetMailbox sets the entire mailbox struct for a peer
type Migrator ¶
type Migrator struct {
// contains filtered or unexported fields
}
Migrator handles in-place store migrations.
func NewMigrator ¶
NewMigrator returns a new migrator based on the keeper.
func (Migrator) Migrate1to2 ¶
Migrate1to2 migrates from version 1 to 2.
type Querier ¶
type Querier struct {
Keeper
}
Querier is used as Keeper will have duplicate methods if used directly, and gRPC names take precedence over keeper
func (Querier) Egress ¶
func (k Querier) Egress(c context.Context, req *types.QueryEgressRequest) (*types.QueryEgressResponse, error)
func (Querier) Mailbox ¶
func (k Querier) Mailbox(c context.Context, req *types.QueryMailboxRequest) (*types.QueryMailboxResponse, error)
func (Querier) Params ¶
func (k Querier) Params(c context.Context, req *types.QueryParamsRequest) (*types.QueryParamsResponse, error)
type SwingStoreExportEventHandler ¶
type SwingStoreExportEventHandler interface { // OnExportStarted is called by InitiateExport in a goroutine after the // swing-store export has successfully started. // This is where the component performing the export must initiate its own // off main goroutine work, which results in retrieving and processing the // swing-store export. // // Must call the retrieveExport function before returning, which will in turn // synchronously invoke OnExportRetrieved once the swing-store export is ready. OnExportStarted(blockHeight uint64, retrieveExport func() error) error // OnExportRetrieved is called when the swing-store export has been retrieved, // during the retrieveExport invocation. // The provider is not a return value to retrieveExport in order to // report errors in components that are unable to propagate errors back to the // OnExportStarted result, like cosmos state-sync ExtensionSnapshotter. // The implementation must synchronously consume the provider, which becomes // invalid after the method returns. OnExportRetrieved(provider SwingStoreExportProvider) error }
SwingStoreExportEventHandler is used to handle events that occur while generating a swing-store export. It is provided to SwingStoreExportsHandler.InitiateExport.
type SwingStoreExportOptions ¶
type SwingStoreExportOptions struct { // ArtifactMode controls the set of artifacts that should be included in the // swing-store export. Any SwingStoreArtifactMode* const value can be used // (None, Operational, Replay, Archival, Debug). // See packages/cosmic-swingset/src/export-kernel-db.js initiateSwingStoreExport ArtifactMode string `json:"artifactMode,omitempty"` // ExportDataMode selects whether to include "export data" in the swing-store // export or not. Use the value SwingStoreExportDataModeSkip or // SwingStoreExportDataModeAll. If "skip", the reader returned by // SwingStoreExportProvider's GetExportDataReader will be nil. ExportDataMode string `json:"exportDataMode,omitempty"` }
SwingStoreExportOptions are configurable options provided to the JS swing-store export
type SwingStoreExportProvider ¶
type SwingStoreExportProvider struct { // BlockHeight is the block height of the SwingStore export. BlockHeight uint64 // GetExportDataReader returns a KVEntryReader for the "export data" of the // SwingStore export, or nil if the "export data" is not part of this export. GetExportDataReader func() (agoric.KVEntryReader, error) // ReadNextArtifact is a function to return the next unread artifact in the SwingStore export. // It errors with io.EOF upon reaching the end of the list of available artifacts. ReadNextArtifact func() (types.SwingStoreArtifact, error) }
SwingStoreExportProvider gives access to a SwingStore "export data" and the related artifacts. A JS swing-store export is composed of optional "export data" (a set of key/value pairs), and opaque artifacts (a name and data as bytes) that complement the "export data". The abstraction is similar to the JS side swing-store export abstraction, but without the ability to list artifacts or random access them.
A swing-store export for creating a state-sync snapshot will not contain any "export data" since this information is reflected every block into the verified cosmos DB. On state-sync snapshot restore, the swingset ExtensionSnapshotter will synthesize a provider for this module with "export data" sourced from the restored cosmos DB, and artifacts from the extension's payloads. When importing, the JS swing-store will verify that the artifacts match hashes contained in the trusted "export data".
func OpenSwingStoreExportDirectory ¶
func OpenSwingStoreExportDirectory(exportDir string) (SwingStoreExportProvider, error)
OpenSwingStoreExportDirectory creates an export provider from a swing-store export saved on disk in the provided directory. It expects the export manifest to be present in that directory. The provider's function will read the export's data and artifacts from disk on demand. Each artifact is using a dedicated file, and the export data is read from a jsonl-like file, if any. The export manifest filename and overall export format is common with the JS swing-store import/export logic.
type SwingStoreExportsHandler ¶
type SwingStoreExportsHandler struct {
// contains filtered or unexported fields
}
SwingStoreExportsHandler exclusively manages the communication with the JS side related to swing-store exports, ensuring insensitivity to sub-block timing, and enforcing concurrency requirements. The caller of this submodule must arrange block level commit synchronization, to ensure the results are deterministic.
Some blockingSend calls performed by this submodule are non-deterministic. This submodule will send messages to JS from goroutines at unpredictable times, but this is safe because when handling the messages, the JS side does not perform operations affecting consensus and ignores state changes since committing the previous block. Some other blockingSend calls however do change the JS swing-store and must happen before the Swingset controller on the JS side was inited, in which case the mustNotBeInited parameter will be set to true.
func NewSwingStoreExportsHandler ¶
func NewSwingStoreExportsHandler(logger log.Logger, blockingSend func(action vm.Jsonable, mustNotBeInited bool) (string, error)) *SwingStoreExportsHandler
NewSwingStoreExportsHandler creates a SwingStoreExportsHandler
func (SwingStoreExportsHandler) InitiateExport ¶
func (exportsHandler SwingStoreExportsHandler) InitiateExport(blockHeight uint64, eventHandler SwingStoreExportEventHandler, exportOptions SwingStoreExportOptions) error
InitiateExport synchronously verifies that there is not already an export or import operation in progress and initiates a new export in a goroutine, via a dedicated SWING_STORE_EXPORT blockingSend action independent of other block related blockingSends, calling the given eventHandler when a related blockingSend completes. If the eventHandler doesn't retrieve the export, then it sends another blockingSend action to discard it.
eventHandler is invoked solely from the spawned goroutine. The "started" and "done" events can be used for synchronization with an active operation taking place in the goroutine, by calling respectively the WaitUntilSwingStoreExportStarted and WaitUntilSwingStoreExportDone methods from the goroutine that initiated the export.
Must be called by the main goroutine
func (SwingStoreExportsHandler) RestoreExport ¶
func (exportsHandler SwingStoreExportsHandler) RestoreExport(provider SwingStoreExportProvider, restoreOptions SwingStoreRestoreOptions) error
RestoreExport restores the JS swing-store using previously exported data and artifacts.
Must be called by the main goroutine
type SwingStoreRestoreOptions ¶
type SwingStoreRestoreOptions struct { // ArtifactMode controls the set of artifacts that should be restored in // swing-store. Any SwingStoreArtifactMode* const value can be used // (None, Operational, Replay, Archival, Debug). // See packages/cosmic-swingset/src/import-kernel-db.js performStateSyncImport ArtifactMode string `json:"artifactMode,omitempty"` // ExportDataMode selects the purpose of the restore, to recreate a // swing-store (SwingStoreExportDataModeAll), or just to import missing // metadata (SwingStoreExportDataModeRepairMetadata). // If RepairMetadata, ArtifactMode should be SwingStoreArtifactModeNone. // If All, ArtifactMode must be at least SwingStoreArtifactModeOperational. ExportDataMode string `json:"exportDataMode,omitempty"` }
SwingStoreRestoreOptions are configurable options provided to the JS swing-store import