ブロックチェーンエンジニアになって、さびを使っている仕事を得る方法


ブロックチェーンエンジニアになって仕事を得ることは容易ではない.私はあなたにブロックチェーンを学び、仕事を得るために必要な式を与える.
必要条件
  • ノードをインストールします.JSバージョンV 17 .8.0
  • 錆安定・夜間設置
  • ソラナCLIをインストールhttps://docs.solana.com/cli/install-solana-cli-tools )
  • Intellijをインストールしましょう
  • ソースコードのダウンロード
    このポストでは、ソラナブロックチェーン上で分散eBayアプリを構築します.クローン私のrepoを開始するhttps://github.com/evergreen-trading-systems/universe ランgit submodule update --init universe-ui universe-jsインuniverse-js パッケージをインストールします.JSON
    ニューレポ
    新しいGit Repoを別のディレクトリに初期化します.
    ブロック連鎖導入
    BlockChainはコードを実行する仮想マシンです.コンピュータがプログラムを実行するように、ソラナはスマート契約を実行します.私たちはスマート契約から作らecommerce dappを構築します.
    始まり
    新しいGitレポランでcargo initこの新しいさびプロジェクトコピーで
    [package]
    name = "hello"
    version = "0.1.0"
    edition = "2021"
    
    [lib]
    crate-type = ["cdylib", "lib"]
    
    [features]
    no-entrypoint = []
    
    [dependencies]
    borsh = {version= "0.9.1",features = ["const-generics"] }
    borsh-derive = "0.9.1"
    solana-program = {version="1.9.5"}
    spl-token = {version = "3.2.0", features = ["no-entrypoint"]}
    thiserror = "1.0.30"
    solana-sdk = {version="1.9.5",optional=true}
    solana-client = {version="1.9.5",optional=true}
    
    を置き換えるCargo.toml コンテンツ.削除src/main.rs 追加src/lib.rs . 今すぐ実行cargo build インストールする.
    計画
    スマート契約は単なる機能であり、引数でそれらを呼び出します.当社のeコマースのアプリは大きな機能になるだけです.あなたのスマート契約が多くのアプリで使用することができれば、それはプロトコルと呼ぶ方が良いです.当社のeコマースプロトコルは、ユーザーがログイン、購入、販売を許可する必要があります.
    杭の証明
    証拠の証拠は、単に保険を意味します.我々のプロトコルは、より多くのセキュリティのために杭の証明を使用します.
    ラスト・シング
    誰かが論争を起こすならば、我々は人々にそれを解決する必要があります.それをする唯一の方法は、それをするためにそれらを支払うことです.私達はすべての取引販売のパーセンテージで支払うことができる.また、彼らは紛争を正しく解決することを確認する必要があります.我々は非常に高度なテクニックを使用しますScheduling Point それを保証する.
    コード
    コードへの最初のものはログイン機能です.ここでlogin関数がどの引数をとるべきかを考える必要があります.
  • ユーザー名
  • パスワード
  • Javaでは、共通の機能をグループ化するためにクラスを使用します.enums.rs インsrc . 以下を加えてください
    #[cfg(feature = "personal-program")]
    #[derive(BorshSerialize, BorshDeserialize, Debug)]
    pub enum PersonalAccountInstruction {
        CreatePersonalAccount {
            personal_account_name: [u8; 32],
            seed: Vec<Vec<u8>>,
            seed_id: u8,
        },
    }
    
    personal_account_name はユーザ名です.seed and seed_id パスワードです.
    集団契約
    我々は、1プロジェクトで多くのスマート契約を構築している.コンパイルするとき、サイズが大きくなるので、同時にコンパイルしないでください.のような属性を使用します#[cfg(feature = "personal-program")] 錆を伝えるには、このコードはpersonal-program グループ.追加personal-program=[][features] あなたのCargo.toml .

    引数型を作成しましたCreatePersonalAccount ログイン機能のために.今、私たちは考える必要があります、この機能はデータを保存するでしょう、そして、どんなタイプがそうであるでしょう.我々の場合では、それは3つのフィールド
  • ユーザー名
  • ID
  • 初期化初期化
  • ファイルを作成するstructs.rs を追加し、
    #[derive(BorshSerialize, BorshDeserialize, Debug)]
    pub struct PersonalAccount {
        /// username
        pub name: [u8; 32],
        /// id
        pub owner: [u8; 32],
        /// is initialised
        pub is_initialized: bool,
    }
    
    毎回ファイルを作成する
    毎回ファイルを作成します.lib.rs それを知る必要がある.これまでに2つのファイルを作成し、それらを追加しますlib.rs そう
    mod enums;
    mod structs;
    
    use enums::*;
    use structs::*;
    
    さび属性
    属性は、このように見えるものです
    #[derive(BorshSerialize, BorshDeserialize, Debug)]
    
    我々はいくつかを追加しましたが、彼らは完全ではありません.いくつかderive 属性をインポートする必要があります.追加use borsh::{BorshDeserialize, BorshSerialize}; 使用するすべてのファイルの先頭にborsh 属性.色はIDEで変更されます.今すぐ実行cargo build そして、すべてはコンパイルしなければなりません.あなたが最初のコミットとプッシュとしてこれを保存することができます.
    パート1の終わり
    スマート契約関数
    スマート契約は引数を持つ関数です.ファイルを作成するfns.rs . ソラナでは、スマート契約は常に3つの引数を取ります.ログインスマート契約を作成しましょう
    #[cfg(feature = "personal-program")]
    pub fn personal_account_instructions(
        program_id: &solana_program::pubkey::Pubkey, // Public key of the account the hello world program was loaded into
        accounts: &[solana_program::account_info::AccountInfo], // The account to say hello to
        instruction_data: &[u8],
    ) -> ProgramResult {
        let instruction: PersonalAccountInstruction =
            PersonalAccountInstruction::try_from_slice(instruction_data)?;
        match instruction {
            PersonalAccountInstruction::CreatePersonalAccount {
                personal_account_name,
                seed,
                seed_id,
            } => create_personal_account(program_id, accounts, personal_account_name, seed_id, seed),
        }
    }
    
    このスマートコントラクトの最後の引数は、PersonalAccountInstruction enum
    コードを貼り付ける場合は、IDEに赤エラーが表示されます.不足している依存関係をインポートするには、IDEを使用できます.
    これまでの契約では、最後の引数をデコードし、型と一致して別の関数を呼び出します.
    公式スマート契約
    我々personal_account_instructions 機能はまだスマート契約ではない.以下を加えるlib.rs
    #[cfg(feature = "personal-program")]
    solana_program::entrypoint!(personal_account_instructions);
    
    それはあなたの関数をソラナで外部から呼び出すようになります.
    関数
    我々は、スマート契約機能を呼び出すentrypoint 関数.我々のタイプPersonalAccountInstruction enumは関数に相当する.現時点では、参照create_personal_account , 存在しない関数.以下を加えるfns.rs
    #[cfg(feature = "personal-program")]
    fn create_personal_account(
        program_id: &solana_program::pubkey::Pubkey,
        accounts: &[solana_program::account_info::AccountInfo],
        personal_account_name: [u8; 32],
        seed_id: u8,
        seed: Vec<Vec<u8>>,
    ) -> ProgramResult {
        accounts.assert_account_len(3)?;
    
        let account_iter = &mut accounts.iter();
    
        let caller = next_account_info(account_iter)?;
        caller.assert_is_signer()?;
    
        let pda = next_account_info(account_iter)?;
        pda.assert_owner(&[&solana_program::system_program::id()])?;
    
        let system_program_account = next_account_info(account_iter)?;
    
        let mut pda_seeds = seed.iter().map(|x| x.as_slice()).collect::<Vec<_>>();
        let seed_id_buffer = &[seed_id];
        pda_seeds.push(seed_id_buffer);
    
        invoke_signed(
            &solana_program::system_instruction::create_account(
                caller.key,
                pda.key,
                PERSONAL_ACCOUNT_COST,
                personal_account_state_buffer().len() as u64,
                program_id,
            ),
            &[caller.clone(), pda.clone(), system_program_account.clone()],
            &[pda_seeds.as_slice()],
        )?;
    
        let mut state: PersonalAccount = PersonalAccount::try_from_slice(&pda.data.borrow())?;
        state.assert_is_uninitialised()?;
    
        state.is_initialized = true;
        state.owner = caller.key.to_bytes();
        state.name = personal_account_name;
        msg!("{:?}", String::from_utf8(state.name.to_vec()).unwrap());
        let un = state.try_to_vec()?;
        let _ = &mut pda.try_borrow_mut_data()?.copy_from_slice(un.as_slice());
        Ok(())
    }
    
    
    主張
    スマート契約を書くとき、ハッキングを避けることができるように、多くの条件を主張する必要があります.
    ソラナでaccounts 引数は、関数が必要とするすべてのアカウントを表します.この場合3
  • 発信口座
  • 新個人口座
  • システムアカウント(常に必要)
  • コード複製を避けるために再利用可能なアサーションを作成しましょう.クリエイトimpls.rs and traits.rs .
    3つの基本的なアサーションを作成します
  • accounts 長さ
  • アカウントオーナー
  • アカウント発信
  • 状態の初期化
  • 以下を加えるtraits.rs
    pub trait AccountsAssertion {
        fn assert_account_len(
            &self,
            len: usize,
        ) -> ProgramResult;
    }
    pub trait SignerAssertion {
        fn assert_is_signer(&self) -> ProgramResult;
    }
    pub trait OwnerAssertion {
        fn assert_owner(
            &self,
            keys: &[&solana_program::pubkey::Pubkey],
        ) -> ProgramResult;
    }
    pub trait InitialisationAssertion {
        fn assert_is_initialised(&self) -> ProgramResult;
        fn assert_is_uninitialised(&self) -> ProgramResult;
    }
    
    あなたの主張を実装する
    以下を加えるimpls.rs
    #[cfg(feature = "personal-program")]
    impl IsInitialized for PersonalAccount {
        fn is_initialized(&self) -> bool {
            self.is_initialized
        }
    }
    impl OwnerAssertion for AccountInfo<'_> {
        fn assert_owner(
            &self,
            keys: &[&solana_program::pubkey::Pubkey],
        ) -> ProgramResult {
            if keys.contains(&self.owner) {
                Ok(())
            } else {
                Err(ProgramError::IllegalOwner)
            }
        }
    }
    impl AccountsAssertion for &[solana_program::account_info::AccountInfo<'_>] {
        fn assert_account_len(
            &self,
            len: usize,
        ) -> ProgramResult {
            if self.len() == len {
                Ok(())
            } else {
                Err(ProgramError::NotEnoughAccountKeys)
            }
        }
    }
    impl SignerAssertion for AccountInfo<'_> {
        fn assert_is_signer(&self) -> ProgramResult {
            if self.is_signer {
                Ok(())
            } else {
                Err(ProgramError::MissingRequiredSignature)
            }
        }
    }
    impl<T> InitialisationAssertion for T
    where
        T: IsInitialized,
    {
        fn assert_is_initialised(&self) -> ProgramResult {
            if self.is_initialized() {
                Ok(())
            } else {
                Err(ProgramError::UninitializedAccount)
            }
        }
    
        fn assert_is_uninitialised(&self) -> ProgramResult {
            if !self.is_initialized() {
                Ok(())
            } else {
                Err(ProgramError::AccountAlreadyInitialized)
            }
        }
    }
    
    traits 入力と出力が何であるかを言う.impls が論理です.
    機能解剖学
  • アサーション後accounts 長さ、各アカウントを繰り返します.
  • 我々は、最初のアカウントは、呼び出し元、トランザクションに署名した人を主張する.
  • 私たちは、第2の口座がシステムアカウントによって所有されると主張します.すべての新しいアカウントは、システムアカウントが所有しています.
  • 我々は完全なパスワードを再作成pda_seeds だから、新しいアカウントの名前でトランザクションを許可することができます
  • 私たちは、新しいアカウントによって作成されたユーザーをアサート
  • ユーザーの状態を設定し、保存する
  • 状態バッファ
    状態を保存するためのアカウントを作成するときには、どのくらいの空き容量を知る必要があります.各フィールドのサイズを合計して計算します.For PersonalAccount
  • name - 32バイト
  • オーナー- 32バイト
  • 初期化- 1バイト
  • それは合計65バイト
    これを自動的に行う関数を作成します.以下を加えるfns.rs
    #[cfg(feature = "personal-program")]
    pub fn personal_account_state_buffer() -> Vec<u8> {
        PersonalAccount {
            name: Default::default(),
            owner: Default::default(),
            is_initialized: false,
        }
        .try_to_vec()
        .unwrap()
    }
    
    コンスト
    静的変数のconstsが必要です.クリエイトconsts.rs を追加し、
    pub const PERSONAL_ACCOUNT_COST: u64 = ZERO_POINT_ZERO_ONE_SOL;
    /// 0.01 SOL covers upto 1400 bytes
    pub const ZERO_POINT_ZERO_ONE_SOL: u64 = 10_000_000;
    
    アカウントを作成するトランザクションと取引コストソラナのお金です.お金はアカウントのサイズによって異なり、0.01ソルはここで私たちを65バイトが1400バイト未満であることをカバーします.
    スマート契約
    あなたがちょうど私がこれまでに書いたすべてをコピーするならば、これはあなたのためにコンパイルされません.
    インポート依存関係を持つすべてのエラーを修正するためにIDEを使用します.
    今、すべてがうまく使用してコンパイルする必要がありますcargo build --features personal-program時間を節約するサブコマンドを作成します.クリエイト.cargo/config.toml 追加
    [alias]     # command aliases
    personal-so = "build-bpf --bpf-out-dir sol/personal --features personal-program"
    
    今すぐ実行cargo personal-so . これはスマート契約を構築し、保存するsol/personal/hello.soあなたはソラナの錆を使用してスマート契約を構築.
    パート2の終わり
    スマート契約
    既にソラナCLIがインストールされているはずです.
    ランsolana config set --url localhost and solana-keygen new ローカルのブロックチェーンを初期化する.
    ランsolana-test-validator ブロックを開始して実行するにはsolana logs ログを表示するseperate端末で.
    ランsolana program deploy sol/personal/hello.so コントラクトを展開するには
    あなたはソラナスマート契約を展開しました.
    あなたはuniverse-ui アプリケーションのブロックと対話する.あなたが書いたコードを理解するために時間がかかるし、なぜそれが動作します.物事を変える、何が起こるか見なさい.
    仕事
    あなたが仕事に応募する前に、あなた自身のスマート契約を構築することは快適です.試してみて、Web 3にいくつかのweb 2アプリを変換する(Web 3はバックエンドとしてブロックチェーンを使用するだけのアプリです).いくつかのフロントエンドと共有ソースコードGitHubで構築したもののようなビルドアプリ.あなたがそうしないならば、あなたは仕事を得ません- 10のプロジェクトはよいです.
    あなた自身を良いCVウェブサイトを構築してください.CVだけはゴミです.あなたの個人的なウェブサイトを構築するためにここにいくつかの良いテーマを買いに行くhttps://themeforest.net/ .
    あなたのCVが短くて簡単であることを確認してください.多くの単語を使用しないでください、あなたのウェブサイトへのリンクを含める.つのスキルに集中しないでください、各スキルを等しくフォーカスを与える.
    最後に、プロジェクトの1つまたは2つを展開し、ビューへのリンクを持つ必要があります.ゴミアプリ“こんにちは世界”または“TODOリスト”を構築しないでください.
    天使の仕事を探す.CoとLinkedIn常に、誰かに直接連絡して、リクルーターを通しないでくださいメールを見つけるようにしてください.Blockchainジョブボードを使用しますhttps://jobs.solana.com/jobs .
    また、Hackathonsに参加しようとしてください.https://devpost.com/ .
    ステップ3?
    私に時間があるならば、私は分散したeBayを構築する際にこのチュートリアルを続けます.