Solana(索拉纳)公链了解

Solana(索拉纳)公链

一、背景

随着加密货币市场热度不断攀升,以太坊的用户也不断增加,随之而来的就是高额的Gas费用以及拥堵的网络,这迫使用户不得不去寻找新的公链

公链领域存在着“不可能三角”,即去中心化、安全性和可扩展性三者不可兼得。其中,各大公链都会首要保证去中心化和安全性,于是可扩展性便成为许多新兴公链钻研的目标。

Solana是在这个背景下产生的。它给自己的定位是世界上最快的高性能公链,它的可扩展性可以达到网络级别,理论上标准千兆网络下TPS 最高可达 71 万。

公链领域的“不可能三角”问题TPS对比图如下:

 

 

 

TPSTransactions Per Second(每秒传输的事物处理个数),即服务器每秒处理的事务数。TPS包括一条消息入和一条消息出,加上一次用户数据库访问。(业务TPS = CAPS × 每个呼叫平均TPS)

TPS是软件测试结果的测量单位。一个事务是指一个客户机向服务器发送请求然后服务器做出反应的过程。客户机在发送请求时开始计时,收到服务器响应后结束计时,以此来计算使用的时间和完成的事务个数。

一般的,评价系统性能均以每秒钟完成的技术交易的数量来衡量。系统整体处理能力取决于处理能力最低模块的TPS值。

 

二、基本概念

Solana 创立于2017年,总部位于瑞士日内瓦,三位主要创始人Anatoly Yakovenko、Greg Fitzgerald和Stephen Akridge,都曾就职于高通公司。这么一支技术团队致力于将Solana打造为:一条根据摩尔定律(摩尔定律是由英特尔(Intel)创始人之一戈登·摩尔(Gordon Moore)提出来的。其内容为:当价格不变时,集成电路上可容纳的元器件的数目,约每隔18-24个月便会增加一倍,性能也将提升一倍) 扩容、为大规模应用提供高性能和低费用的公链。

下面是Solana的大事件:

 

  

之前DeFi的盛行让以太坊交易慢、gas贵Solana团队在DeFi爆发的前夜,预见性地推出了以太坊桥——虫洞(Wormhole)协议,实现了Solana和以太坊上资产的跨链转移,这为以太坊上大量的DeFi项目提供了一个新的选项。在Layer 2扩容方案完善落地之前,Solana为各平台、项目提供了一条无需重写合约即可低成本快速迁移的公链。

当以太坊的问题暴露在所有人面前的时候,Solana的提前布局为他们带来了很多优质项目的迁移和大量活跃用户。

(一)Solana的优势

Solana利用工作历史证明 PoH、基站拜占庭容错(Tower BFT)、涡轮机(区块传播协议)、海湾流(无内存交易转发协议)、海平面(并行智能合约)、管道(验证交易)、云散(水平扩展账户数据库)以及档案(分布式账本存储)八大突破性技术构建出了一个超高性能的区块链。

现在相较与其他公链:费用低、可拓展性好、有自己的虫洞协议来跨链互通。

(二)ETH公链的不同点

1.账户模型

作为一个开发者,最先要了解的就是账户模型

(1)以太坊账户模型

大家都知道以太坊账户模型是分两种,一种是主网币,一种是合约币,主网币里面的的account 就有一个balance字断,用来记录用户的ETH 的数量,如果某个地址拥有其他的token ,是在合约里面给这个地址存了个mapping,用来记录这个用户token 的数量。因此用户拥有的ERC20 token其实记账是记录在合约里面,以太坊合约具有存储功能,是因为合约用一个世纪状态永远存储在区块里面。

(2)Solana账户模型

solana 的账户模型不一样的地方在于,solana 账户除了可以存储本币sol以外,还增加了一个data字段

这个data字段具体可以参https://github.com/jstarry/solana-wiki/blob/main/content/zh-cn/docs/Account%20Model/_index.md

先看一下账户的字段

详细描述一下

lamports :这个就是和以太坊的balance一样,描述这个账号有多少个SOL 可以使用

ownerowner这个字段保证了用户对账户的决定拥有权利,如果某一个地址是某一个account的owner,那么那个地址就可以对这个account资产进行转移。所以solana的合约token其实就是solana程序会帮忙生成一个account,然后把owner赋予给你。

Executable这个表示用户的状态是不是可执行的状态。在solana的账户体系里面的data字断是表示存储,或者可执行。可执行的data是帐户数据专门用于不可变字节代码该字节代码用于处理交易。

data:这个和executable 描述相似

rent_epoch:这个比较有意思,就是solana的合约和solidity合约不一样的地方,solana的合约部署是要按大小定期收费的,目前是费用是2天一收,应该是0.01SOL 1K的大小。如果没有费用solana系统就会清除这些账号。

2.solana 合约和solidity合约的区别

solana的合约其实就是一段程序,这个程序没有存储功能,程序编译好以后,是一个BPF字节码,这个和solidity 编译后是一段二进制码是一样的。 solidity是通过合约地址找到合约存在得状态数,然后再通过input参数,拿到需要执行得方法和参数,再执行对于得合约方法。solana 这个部分是一样得,solana 发布到连上得合约有一个programID,这个programID也是一个Hash256,类似solidity合约地址一样,solana 合约得方法通过一个枚举来定义,也就是,方法分别是0-1-2-3-4,参数就是解析data,那么solana 合约最难得就是要解析这个data,因为这个data是用户自己定义和排序的,solana不提供标准的map,struct,这些数据结构存储, 都是以文本得形式存储在各个account里面得data里面,所以solana合约最困难得就是要对data进行编码,解析再解码,你可以想象一下一个token合约,solidity 最多两个map,一个是balance,一个是allowance,就够了,但是solana不一样,他没有存储,他需要为每一个人创建一个临时得account,然后解析出来,给他们做tranfer或者approve操作。还要有一堆的安全性判断。最重要得是你要得存储进行排版,解析。

 

(三)Solana的合约

由于账户模型的不一样,那么刚开始理解solana的合约就很困难,基于Solana开发需要知道的几个问题

1、solana 合约开发环境

2、solana 合约开发语言

3、solana 合约部署

4、solana 合约逻辑

5、solana 合约前端后端交互

1.solana 合约框架

先整理清楚solana 合约是怎么运行的。

 

2.合约具体分析

通过学习token 合约来整体理解Solana这里不讲helloworld,因为token 合约结构更完善

token 合约路径:[solana Token]

token 合约目录结构

–cli

–js

---- cli

---- client

--------token.js

–program

----src

------entrypoint.rs // 这个整个程序的入口,也就是solana节点会把交易里面的参数都传入到这个接口

------error.rs // 错误信息

------instruction.rs // 这个才是序列化/反序列化的/结构体的定义问题

------lib.rs //这个是rust 用来串联本目录或者其他目录文件用的

------native_mint.rs // 这个是mint 方法

------processor.rs //这个是token 的所有方法调用的地方,所有方法实现的地方,进入到这些方法,需要传入的参数包括(函数,参数 都要解析出来)

------state.rs // 这个是状态

 

这里类比使用go 语言版本的solidity来理解Solana智能合约,首先要明白它是需要运行在主网代码上,所以有几个要点:

1、哪个程序

2、哪个函数

3、实现什么功能

4、结果在哪里

(1)token tranfer 方法来对上面问题进行解答

1、哪个程序

前面介绍了solana 的智能合约的指向是一个programID,programID 就和solidity合约的合约地址是一个意思,所以发送交易的时候要指定programID。

 

2、哪个函数

我们的合约可能有很多方法,那么我一笔交易,指定了programID,我还需要指定是哪个函数,以及对应的参数,所以再processor方法里面,我们看到一个match 用来分发函数,里面的第一个就是获取用户输入的调用的哪个方法。

代码示例pub fn process(program_id: &Pubkey, accounts: &[AccountInfo], input: &[u8]) -> ProgramResult {undefined

let instruction = TokenInstruction::unpack(input)?;

 

也可以通过看token.js方法里面的交易组装函数createTransferCheckedInstruction),就有一个instruction :12这样一个赋值,所以这个12就是对应的函数,那么这个定义一般要怎么定义?

dataLayout.encode(
{

undefined
instruction: 12, // TransferChecked instruction
amount: new u64(amount).toBuffer(),
decimals,
},
data,
);

instruction.rs文件,里面有定一个enum,里面定义了每个函数的instruction,也就是说,前端需要知道有哪些函数,这个就和ABI一样,但是更简单。复杂的事数据的处理,我们看看12是哪个函数:上面表示使用TransferChecked 这个函数。

TransferChecked {undefined

/// The amount of tokens to transfer.

amount: u64,

/// Expected number of base 10 digits to the right of the decimal place.

decimals: u8,

}

 

3、这个函数做什么事情

pub fn process(program_id: &Pubkey, accounts: &[AccountInfo], input: &[u8]) -> ProgramResult 这个函数里面找到12 这个instruction对应的TransferChecked 然后去分发进入的是这个 【process_transfer】

TokenInstruction::TransferChecked {

amount, decimals } => {undefined

msg!(“Instruction: TransferChecked”);

Self::process_transfer(program_id, accounts, amount, Some(decimals))

}

通过学习可以知道process_transfer这个函数做了什么事情
1、账户状态的准备检查
2、账户转账处理
3、账户信息打包(pack 函数)

 

4、怎么存储

由于整个rust 都是用指针对内存文件进行读写操作,所有在pack 结束后就进行了存储。

(2)solana 合约交易

对于前端而言,和solidity有什么区别?
solidity前端只需要使用ABI 对input data 进行bytecode 就可以了,然后进行组装交易,发送签名交易。就可以完成合约的调用,使用的是web3j的库。

那么solana 的前端调用合约交易如何组装呢?

统一交易的参数:

static createTransferInstruction(

programId: PublicKey,

source: PublicKey,

destination: PublicKey,

owner: PublicKey,

multiSigners: Array,

amount: number | u64,

 

输出参数的定义

const dataLayout = BufferLayout.struct([
BufferLayout.u8(‘instruction’),
Layout.uint64(‘amount’),
]);

 

调用合约函数的绑定

const data = Buffer.alloc(dataLayout.span);

dataLayout.encode(

{undefined

instruction: 3, // Transfer instruction

amount: new u64(amount).toBuffer(),

},

data,

);

 

from /to 压缩到keys 里面

let keys = [

{pubkey: source, isSigner: false, isWritable: true},

{pubkey: destination, isSigner: false, isWritable: true},

];

if (multiSigners.length === 0) {undefined

keys.push({undefined

pubkey: owner,

isSigner: true,

isWritable: false,

});

} else {undefined

keys.push({pubkey: owner, isSigner: false, isWritable: false});

multiSigners.forEach(signer =>

keys.push({undefined

pubkey: signer.publicKey,

isSigner: true,

isWritable: false,

}),

);

}

 

组装好的交易返回出去

return new TransactionInstruction({undefined
keys,
programId: programId,
data,

});

总的来说 交易发送也是对交易的组装,对input的组装,和solidity 几乎一样

3.solana 合约开发语言

solana 目前支持 rustC++ C 对合约进行开发,官方建议跟网上建议都是推荐学习Rust,因为整个链都是rust的开发的。整个接口或者其他的框架也大部分是rust,这样可利用的开发工具就会更多。

初步学习,学习完helloworld以后看 token的代码合约还有web3j调用。

示例学习链接如下:

helloworld 链接[solana Helloworld]

token 合约代码链接[solana Token]

三、环境搭建

两种环境搭建方式:有现有的docker镜像,可以直接pull镜像部署;或者通过拉源码本地搭建节点。

(一)solana 的安装

solana公链环境搭建可以参考官方文档如下:

1.环境安装

[Install the Solana Tool Suite]
[Using Solana CLI]

2.anhore安装

anhore 是一个开发工具,类似solidity 的 truffle 和 hardhat

[anhore 官方介绍]

3.本地节点搭建

依据该链接:https://solongwallet.medium.com/solana%E6%99%BA%E8%83%BD%E5%90%88%E7%BA%A6%E5%BC%80%E5%8F%91-%E6%90%AD%E5%BB%BA%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83-9723b858937e

四、基于搭建环境的开发和部署

待完善

五、示例

时间问题,待本地完善后补充

 

posted @ 2021-12-07 19:41  SoyWang  阅读(3731)  评论(0编辑  收藏  举报