# 4.Canister（程序罐）和代码

我们需要注意的最重要的原则是Internet Computer主要是运行软件的分布式和去中心化平台。

为运行在Internet Computer上的应用程序编写源代码时，会将源代码编译为WebAssembly模块。 当您在Internet Computer副本上部署包含程序的WebAssembly模块时，该程序将在称为软件Canister的概念性计算单元内执行。

部署后，用户可以通过前端客户端（例如浏览器）访问您为Canister定义的入口点功能与之交互。

## Canister包含了程序和状态

软件Canister与容器相似，两者都部署为包含为应用或服务编译后的代码和依赖的软件单元。

容器化允许将应用程序与环境分离，从而实现简单而可靠的部署。 但是，Canister与容器的不同之处在于，它还存储有关当前软件状态的信息以及先前事件和用户交互的记录。

尽管容器化的应用程序可能包含有关该应用程序运行环境的状态的信息，但是Canister能够保留应用程序功能使用而导致的状态更改的记录。

## 查询和更新方法

这种由程序和状态组成的Canister的概念非常重要，因为当通过向其入口点之一发送消息来调用Canister功能时，只有两种类型的调用：非提交查询调用和提交更新调用

| 类型   | 关键点                                                                                                                                                                                                                                                                                              |
| ---- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| 查询调用 | <p>允许用户查询Canister当前状态或调用一个Canister的不改变状态的函数</p><ul><li>同步并且立即响应</li><li>可以被持有Canister且无需共识即可验证结果的任何节点调用。 在安全性和性能之间存在内在平衡，因为来自单个节点的答复可能是不可信的或不准确的。</li><li>不允许修改Canister的状态，本质上，程序使用查询调用来执行只读操作</li><li>不允许被调用Canister调用其他Canister作为容器间调用暴露的方法(这个限制是临时的，在将来Canister可以调用其他Canister暴露的方法)</li></ul> |
| 更新调用 | <p>允许用户修改Canister状态并保留更改</p><ul><li>异步</li><li>必须通过共识才能返回结果。 由于需要达成共识，因此更改容器的状态可能会花费一些时间。 因此，更新调用使用基于Actor的编程模型（状态隔离）来允许并发和异步处理。 在安全性和性能之间存在内在权衡，因为子网中三分之二的副本必须就结果达成一致。</li><li>被调用的Canister可以调用其他Canister公开的函数</li></ul>                                                                        |

作为开发人员，重要的是要认识到查询的调用与更改状态的调用之间的这种关系。 特别是，您应牢记安全性和性能之间的内在平衡。

## 如何为Internet Computer开发应用程序

对于程序员和软件开发人员而言，Internet Computer平台在提供了独特功能和机会的框架，从而简化了您设计，构建和部署应用程序的方式。 该框架的关键部分是一种新的通用编程语言Motoko。 Motoko是一种编程语言，经过专门设计，可以充分利用Internet Computer提供的独特功能，包括：

* 直接使用actor对象和类定义程序的能力。
* 使用async和await语法来像处理同步消息一样处理异步消息
* 自动支持消息序列化和反序列化。
* 无需外部数据库或存储即可使用数据结构持久性的能力。

作为一种现代的高级编程语言，Motoko提供了一些自己的关键功能，包括：

* 支持大整数运算和溢出保护。
* 一种声音类型系统，它会静态检查每个程序，以确保其可以在所有可能的输入上都没有类型错误的情况下执行。
* 支持抽象函数，用户定义类型和用户定义Actor

有关Motoko编程语言更多详细信息，包括语法约定和受支持的功能，请参阅[《 Motoko编程语言》](https://sdk.dfinity.org/docs/language-guide/motoko.html)。

下图提供了作为Internet Computer生态系统一部分的开发环境的简化drill-down视图。

![](https://210739325-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ma3V1sgF0nYMJqZDzw8%2Fsync%2F76db0c61b52c00545011ba2a830f691b74bfd638.png?generation=1621426228303657\&alt=media)

## Canister, Actor和生成的代码

用motoko语言编写程序时最重要的原则是，Motoko使用基于Actor的编程模型

Actor是一种特殊的对象，它以隔离状态处理消息，从而使消息可以远程和异步地进行处理。 Internet Computer平台的许多关键功能都依赖于这种类型的安全有效的异步消息处理。

通常，每个软件Canister都包含一个Actor对象的已编译代码。 每个Canister还包括一些其他信息，例如界面描述或前端资源。 您可以创建包含多个Canister的项目，但是每个Canister只能包含一个Actor。

## 为什么代码被编译为WebAssembly

当编译Motoko代码时，结果是WebAssembly模块。 WebAssembly是一种可移植的抽象低级计算机指令格式，可在大多数现代计算机硬件上执行。 它在互联网上运行的程序得到广泛支持，并且天然适合于部署哪计划在Internet Computer平台上运行的应用程序。

使用Motoko，开发人员可以编译为可移植WebAssembly，同时仍可以发布为简单的高级语言应用程序。

Motoko语言提供了其他高级现代语言所共有的许多特性，例如类型安全和模式匹配。 此外，Motoko提供了内置的支持，以使用actor定义消息传递服务的方式特别适合Internet Computer平台，并且无论您是新手还是经验丰富的程序员，都可以轻松了解。

本指南介绍了Motoko编程语言基本特性，更多详细信息请参见[Motoko编程语言](https://sdk.dfinity.org/docs/developers-guide/language-guide/motoko.html)

## 身份和认证

用户调用容器操作与容器间操作之间的主要区别之一是，容器在\[IC]上具有明确注册的身份。

IC上没有存储用户身份的中央注册表。 每个用户通过一个或多个公私钥对与访问的Canister相关联。 用户的私钥用于签名消息，消息与公钥一起发送到Canister。 \[IC]对用户进行身份验证，然后将委托人传递给Canister以授权其操作。

较高层级上，用户首次在与Internet Computer进行交互时会生成一个未签名的密钥对，并从公用密钥中获取其用户信息。使用已由用户代理安全存储的私钥（或多个私钥）对返回的用户进行身份验证。可以访问多个Canister的用户可以管理用于与每个Canister关联的身份验证的密钥和设备。

单个用户可以具有多个公私钥对，以从不同的设备（例如在不同的计算机，移动电话或平板电脑上运行的浏览器）访问Canister，但是这些派生的密钥都映射到主身份。

## 资源消耗和Cycles

通常，所有Canister都会以以下形式消耗资源：CPU执行，路由消息带宽和持久数据内存。 Canister维护帐户的Cycles余额，以支付其应用程序消耗的通信，计算和存储成本。

Cycles反映实际的操作成本，包括物理硬件，机架空间，能源，存储设备和带宽，以使程序执行的成本保持不变或随着操作效率的降低而降低。

* 程序必须能够支付完整执行费用（全部或全部不付），但与单位Cycles相关的成本将使高效的程序具有成本效益。
* 通过设置Canister可以消耗多少个Cycle的限制，该平台可以防止恶意代码消耗资源。

运营成本的相对稳定性使得更容易预测处理例如一百万条消息所需的Cycle。

执行程序可用的Cycles保存在钱包Canister中。对于本地开发环境，钱包Canister自动创建和分发Cycles，但是如果发布到运在外部节点和子网上的Internet Computer网络上，您必须提供一个分发了钱包Canister身份的账户。

注：当部署Canister到本地或Internet Computer测试网络，程序执行会消耗Cycle，但没有与这些相关的资金。但是，在计算要执行的操作时，执行程序可能会导致“out of cycles”异常，因为这些操作将超过预定义的阈值。 如果在测试中看到此异常，则可以通过设置命令行选项来临时配置更高的Cycles限制。

## 想了解更多？

如果要查找有关Canister的更多信息，请查看以下相关资源：

* [介绍Canister-智能合约的演化（视频）](https://www.youtube.com/watch?v=LKpGuBOXxtQ)
* [什么是Dfinity Canister SDK？（视频）](https://www.youtube.com/watch?v=60uHQfoA8Dk)
* [部署你的第一个应用（视频）](https://www.youtube.com/watch?v=yqIoiyuGYNA)
