Solanaの学習
リソース
これわかりやすい
やること
Solana全然わからんのに片っ端からわかりやすそうなのをやっていく
メモ
CLIでwalletの使い方やFT&NFTの発行の仕方をdevnetで説明してくれる。Wallet,Account,Tokenの関係がわかりやすい。
1) Walletの作成
solana-keygen new --outfile ~/.config/solana/my-keypair.json
Phantomに~/.config/solana/my-keypair.jsonの中身をImport private keyに入力すると連携できる。
2) configの設定
solana config set --url https://api.devnet.solana.com --keypair ~/.config/solana/my-keypair.json
3) token作成
spl-token create-token
address: 5FoKaw3YzoTHQaQUMZiixPmkBbpmtPxwuHwP2UkrvpSY
4) account作成
spl-token create-account 5FoKaw3YzoTHQaQUMZiixPmkBbpmtPxwuHwP2UkrvpSY
5) mint
spl-token mint 5FoKaw3YzoTHQaQUMZiixPmkBbpmtPxwuHwP2UkrvpSY 100
6) tokenの固定
spl-token authorize 5FoKaw3YzoTHQaQUMZiixPmkBbpmtPxwuHwP2UkrvpSY mint --disable
中身
Program(contract)とClientのやりとりが実装されてる
ClientからsayHelloされるとProgramのAccountのdataがカウントアップされる
Client(TypeScript)とProgram(Rust)の間のやりとりで使われるデータがどうエンコード・デコードされるかあたりが見所。
EthereumだとSolidityがjson形式のabiを吐いて、それを使いクラアント側から呼び出す感じだったが、それがSolanaのSmart Contractだとどうなるのかを考えながら読むと良さそう
ownerはuserではなくcontrollerに近い。 == program_id
バイナリデータのシリアライズ/デシリアライズを行う
バイナリ <-> 型の変換を行なっている
greeting_account.serialize(&mut &mut account.data.borrow_mut()[..])?;は何をやっとる?
borrow_mutとは?
RC<T>とRefCell<T>とBox<T>の整理
RC<T>は値への参照の数をカウントする型。同じデータに複数の所有者を持たせてくれる。
UseCase: ヒープにプログラムの複数箇所で読む何らかのデータを確保したいけれど コンパイル時にはどの部分が最後にデータを使用し終わるか決定できない時に使用される。
RefCell<T>は実行時に精査されるBox<T>みたいなやつ。不変参照でもRefCell<T>の値を可変にできるのが強い。
Box<T>はコンパイル時に不変借用も可変借用も精査される。いかなる時も(以下の両方ではなく、)1つの可変参照かいくつもの不変参照のどちらかが可能になる。参照は常に有効。<- RefCel<T>と違うところ
borrow_mutはRefCell<T>から可変参照を取得するためのメソッド
つまり、「account.data(Rc<RefCell<mut [u8]>>)にborrow_mutを呼び出して可変参照で[u8]を取り出し、[..]で中身を全て展開し、それらのデータをserializeでエンコードしてる」という意味
Solanaの実装あんまり関係なかった。ソースコードは見応えあるけど。Anchorを使ってるっぽいプロジェクトだった。
generative NFTのメタデータと画像を生成するツール
SolanaでNFT Projectを立ち上げるのを支援するツール
Candy Machineを使うと画像&metadataのアップロードと更新、NFTのmintまでできる
Storeのテンプレートを使うとNFTのmintやviewページも簡単に作れる
This is because Solana programs do not store data, data is stored in accounts
In Solana, we also have to pay rent for the storage cost of keeping the account alive. However, an account can be made entirely exempt from rent collection by depositing at least 2 years worth of rent.
KeyPairの保存への課題に対しての解決策としてPDA(Program Derived Address)
全てのProgramは状態を持たないステートレスな存在。よって状態は全てAccountにあり、Programには参照で渡される。
AccountはSystem Programによって作成/登録される。
Accountへのread&creditは誰でもできる、writeはowner accountのみができる。
Accountはkeypairを持つ。public keyはunique addressになる。
ではprivate keyは誰が持ってるのか->誰も持っていない!?
PDAはAccountがProgramから操作できるようにするためのアドレス(ed25519由来でないaddress)。
PDAを使うとProgramはaddressをprivate key無しで署名できる
署名: 平文が改竄されてないことを証明するもの
PDAは署名されたaddressのprivate keyを外部のユーザーが生成できないことも保証する
どうやって
findProgramDerivedAddress(programId, seeds, seedBump)をed25519の楕円曲線暗号に一致しないaddress(=public key)が見つかるまで回す。よってprivate keyに関連しないaddressが生成できる。private keyが存在しない = 外部のユーザーがPDAのための正確な署名を生成することもできない。
これで完全に理解できる。神。日本語解説。ありがた杉内。
こいつ(PDA)は要は、Walletみたいな感じでトランザクションの署名(改竄されないようにする)をやってくれる役割のやつだった。ProgramがAccount1からAccount2へ送金みたいなことをしたい時にどうしても署名が必要になる。トランザクションの署名には通常Keypairが必要。だがしかしWallletのPublic&PrivateKeyみたいなKeypairをProgramでは保持できない(したくない)。代わりにそのトランザクションに署名してくれるやつが必要になる。その時に使われるのがPDAである。PDAはprogram_idとseedから作成される。PDAの中身はただのPublic keyみたいなAddressである。Public key **みたいな** Address とは何かというと、正確にはPDAは楕円曲線暗号のed25519(通常のKeypairを生成する方法)とは異なるやり方で生成されているということ。楕円曲線暗号とは異なるということはつまりPDAにはPrivateKeyが存在しないということになる。これの何が嬉しいかというとPrivateKeyが存在しないので翻って言えば外部のユーザーには正確な署名を生成できないということになる。またKeypairをどこかに保存しておく必要もなくなる。ランタイムだけがどのProgramがinstructionを実行するのか知っておりprogram_idとseedからPDAを再生成できる(=これで安全に署名が可能になる)。こうして安全にProgramがAccountとAccountの間のやりとり=CPI(Cross-Program Invocations)が行えるようになるわけだ。
SolanaのJavascript SDKの使い方を実際の動かないコードを動くように修正しながら学んでいけるサイト
GUIで実際に動きが確認できるしweb3.jsのドキュメントを読んでコードを変更していくのでスッと頭に入ってくる感じがある