Bladeren bron

anchor-client with new()

This commit introduces an anchor-bridge-client crate with a partially
working new() call. Still needs proper handling of seeds for some of
the accounts.

Change-Id: I73bfc4b7e23c45643776ba8f13946f1f8c7c65ed
Stan Drozd 4 jaren geleden
bovenliggende
commit
e0b193b390

+ 1 - 0
.envrc

@@ -0,0 +1 @@
+eval "$(lorri direnv)"

+ 10 - 0
nix/rust.nix

@@ -0,0 +1,10 @@
+{ sources ? import ./sources.nix }:
+
+let
+  pkgs =
+  import sources.nixpkgs {overlays = [ (import sources.nixpkgs-mozilla) ]; };
+  channel = "nightly";
+  date = "2020-11-19";
+  targets = [];
+  chan = pkgs.rustChannelOfTargets channel date targets;
+in chan

+ 62 - 0
nix/sources.json

@@ -0,0 +1,62 @@
+{
+    "cargo2nix": {
+        "branch": "master",
+        "description": "Build Rust crates with Nix",
+        "homepage": "",
+        "owner": "cargo2nix",
+        "repo": "cargo2nix",
+        "rev": "c491edfb1b2721c8202afe4051ce7b44adfb668d",
+        "sha256": "0aby21f72314qfmkqcdv7wpw6cywn7isr7gsh8gz992cn2szjpg4",
+        "type": "tarball",
+        "url": "https://github.com/cargo2nix/cargo2nix/archive/c491edfb1b2721c8202afe4051ce7b44adfb668d.tar.gz",
+        "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
+    },
+    "niv": {
+        "branch": "master",
+        "description": "Easy dependency management for Nix projects",
+        "homepage": "https://github.com/nmattia/niv",
+        "owner": "nmattia",
+        "repo": "niv",
+        "rev": "af958e8057f345ee1aca714c1247ef3ba1c15f5e",
+        "sha256": "1qjavxabbrsh73yck5dcq8jggvh3r2jkbr6b5nlz5d9yrqm9255n",
+        "type": "tarball",
+        "url": "https://github.com/nmattia/niv/archive/af958e8057f345ee1aca714c1247ef3ba1c15f5e.tar.gz",
+        "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
+    },
+    "nixpkgs": {
+        "branch": "release-20.09",
+        "description": "Nix Packages collection",
+        "homepage": "",
+        "owner": "NixOS",
+        "repo": "nixpkgs",
+        "rev": "a1643da0480d7716e76c79654b2591dfacbf2931",
+        "sha256": "1bvivv5dj6qvc5kyf2f0s84s5hqh8ry0i5ly9c9qsw4s9svl9yb1",
+        "type": "tarball",
+        "url": "https://github.com/NixOS/nixpkgs/archive/a1643da0480d7716e76c79654b2591dfacbf2931.tar.gz",
+        "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
+    },
+    "nixpkgs-mozilla": {
+        "branch": "master",
+        "description": "mozilla related nixpkgs (extends nixos/nixpkgs repo)",
+        "homepage": "",
+        "owner": "mozilla",
+        "repo": "nixpkgs-mozilla",
+        "rev": "8c007b60731c07dd7a052cce508de3bb1ae849b4",
+        "sha256": "1zybp62zz0h077zm2zmqs2wcg3whg6jqaah9hcl1gv4x8af4zhs6",
+        "type": "tarball",
+        "url": "https://github.com/mozilla/nixpkgs-mozilla/archive/8c007b60731c07dd7a052cce508de3bb1ae849b4.tar.gz",
+        "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
+    },
+    "rust-overlay": {
+        "branch": "master",
+        "description": "Pure and reproducible nix overlay for binary distributed rust toolchains",
+        "homepage": "",
+        "owner": "oxalica",
+        "repo": "rust-overlay",
+        "rev": "a3873f83ed5fe58c4c6af09700d27b54aa19b986",
+        "sha256": "07hll4yalziyzd68gg518kmxs6y31bb2y3ilp1hw4lpbj1jyj4k7",
+        "type": "tarball",
+        "url": "https://github.com/oxalica/rust-overlay/archive/a3873f83ed5fe58c4c6af09700d27b54aa19b986.tar.gz",
+        "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
+    }
+}

+ 174 - 0
nix/sources.nix

@@ -0,0 +1,174 @@
+# This file has been generated by Niv.
+
+let
+
+  #
+  # The fetchers. fetch_<type> fetches specs of type <type>.
+  #
+
+  fetch_file = pkgs: name: spec:
+    let
+      name' = sanitizeName name + "-src";
+    in
+      if spec.builtin or true then
+        builtins_fetchurl { inherit (spec) url sha256; name = name'; }
+      else
+        pkgs.fetchurl { inherit (spec) url sha256; name = name'; };
+
+  fetch_tarball = pkgs: name: spec:
+    let
+      name' = sanitizeName name + "-src";
+    in
+      if spec.builtin or true then
+        builtins_fetchTarball { name = name'; inherit (spec) url sha256; }
+      else
+        pkgs.fetchzip { name = name'; inherit (spec) url sha256; };
+
+  fetch_git = name: spec:
+    let
+      ref =
+        if spec ? ref then spec.ref else
+          if spec ? branch then "refs/heads/${spec.branch}" else
+            if spec ? tag then "refs/tags/${spec.tag}" else
+              abort "In git source '${name}': Please specify `ref`, `tag` or `branch`!";
+    in
+      builtins.fetchGit { url = spec.repo; inherit (spec) rev; inherit ref; };
+
+  fetch_local = spec: spec.path;
+
+  fetch_builtin-tarball = name: throw
+    ''[${name}] The niv type "builtin-tarball" is deprecated. You should instead use `builtin = true`.
+        $ niv modify ${name} -a type=tarball -a builtin=true'';
+
+  fetch_builtin-url = name: throw
+    ''[${name}] The niv type "builtin-url" will soon be deprecated. You should instead use `builtin = true`.
+        $ niv modify ${name} -a type=file -a builtin=true'';
+
+  #
+  # Various helpers
+  #
+
+  # https://github.com/NixOS/nixpkgs/pull/83241/files#diff-c6f540a4f3bfa4b0e8b6bafd4cd54e8bR695
+  sanitizeName = name:
+    (
+      concatMapStrings (s: if builtins.isList s then "-" else s)
+        (
+          builtins.split "[^[:alnum:]+._?=-]+"
+            ((x: builtins.elemAt (builtins.match "\\.*(.*)" x) 0) name)
+        )
+    );
+
+  # The set of packages used when specs are fetched using non-builtins.
+  mkPkgs = sources: system:
+    let
+      sourcesNixpkgs =
+        import (builtins_fetchTarball { inherit (sources.nixpkgs) url sha256; }) { inherit system; };
+      hasNixpkgsPath = builtins.any (x: x.prefix == "nixpkgs") builtins.nixPath;
+      hasThisAsNixpkgsPath = <nixpkgs> == ./.;
+    in
+      if builtins.hasAttr "nixpkgs" sources
+      then sourcesNixpkgs
+      else if hasNixpkgsPath && ! hasThisAsNixpkgsPath then
+        import <nixpkgs> {}
+      else
+        abort
+          ''
+            Please specify either <nixpkgs> (through -I or NIX_PATH=nixpkgs=...) or
+            add a package called "nixpkgs" to your sources.json.
+          '';
+
+  # The actual fetching function.
+  fetch = pkgs: name: spec:
+
+    if ! builtins.hasAttr "type" spec then
+      abort "ERROR: niv spec ${name} does not have a 'type' attribute"
+    else if spec.type == "file" then fetch_file pkgs name spec
+    else if spec.type == "tarball" then fetch_tarball pkgs name spec
+    else if spec.type == "git" then fetch_git name spec
+    else if spec.type == "local" then fetch_local spec
+    else if spec.type == "builtin-tarball" then fetch_builtin-tarball name
+    else if spec.type == "builtin-url" then fetch_builtin-url name
+    else
+      abort "ERROR: niv spec ${name} has unknown type ${builtins.toJSON spec.type}";
+
+  # If the environment variable NIV_OVERRIDE_${name} is set, then use
+  # the path directly as opposed to the fetched source.
+  replace = name: drv:
+    let
+      saneName = stringAsChars (c: if isNull (builtins.match "[a-zA-Z0-9]" c) then "_" else c) name;
+      ersatz = builtins.getEnv "NIV_OVERRIDE_${saneName}";
+    in
+      if ersatz == "" then drv else
+        # this turns the string into an actual Nix path (for both absolute and
+        # relative paths)
+        if builtins.substring 0 1 ersatz == "/" then /. + ersatz else /. + builtins.getEnv "PWD" + "/${ersatz}";
+
+  # Ports of functions for older nix versions
+
+  # a Nix version of mapAttrs if the built-in doesn't exist
+  mapAttrs = builtins.mapAttrs or (
+    f: set: with builtins;
+    listToAttrs (map (attr: { name = attr; value = f attr set.${attr}; }) (attrNames set))
+  );
+
+  # https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/lists.nix#L295
+  range = first: last: if first > last then [] else builtins.genList (n: first + n) (last - first + 1);
+
+  # https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/strings.nix#L257
+  stringToCharacters = s: map (p: builtins.substring p 1 s) (range 0 (builtins.stringLength s - 1));
+
+  # https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/strings.nix#L269
+  stringAsChars = f: s: concatStrings (map f (stringToCharacters s));
+  concatMapStrings = f: list: concatStrings (map f list);
+  concatStrings = builtins.concatStringsSep "";
+
+  # https://github.com/NixOS/nixpkgs/blob/8a9f58a375c401b96da862d969f66429def1d118/lib/attrsets.nix#L331
+  optionalAttrs = cond: as: if cond then as else {};
+
+  # fetchTarball version that is compatible between all the versions of Nix
+  builtins_fetchTarball = { url, name ? null, sha256 }@attrs:
+    let
+      inherit (builtins) lessThan nixVersion fetchTarball;
+    in
+      if lessThan nixVersion "1.12" then
+        fetchTarball ({ inherit url; } // (optionalAttrs (!isNull name) { inherit name; }))
+      else
+        fetchTarball attrs;
+
+  # fetchurl version that is compatible between all the versions of Nix
+  builtins_fetchurl = { url, name ? null, sha256 }@attrs:
+    let
+      inherit (builtins) lessThan nixVersion fetchurl;
+    in
+      if lessThan nixVersion "1.12" then
+        fetchurl ({ inherit url; } // (optionalAttrs (!isNull name) { inherit name; }))
+      else
+        fetchurl attrs;
+
+  # Create the final "sources" from the config
+  mkSources = config:
+    mapAttrs (
+      name: spec:
+        if builtins.hasAttr "outPath" spec
+        then abort
+          "The values in sources.json should not have an 'outPath' attribute"
+        else
+          spec // { outPath = replace name (fetch config.pkgs name spec); }
+    ) config.sources;
+
+  # The "config" used by the fetchers
+  mkConfig =
+    { sourcesFile ? if builtins.pathExists ./sources.json then ./sources.json else null
+    , sources ? if isNull sourcesFile then {} else builtins.fromJSON (builtins.readFile sourcesFile)
+    , system ? builtins.currentSystem
+    , pkgs ? mkPkgs sources system
+    }: rec {
+      # The sources, i.e. the attribute set of spec name to spec
+      inherit sources;
+
+      # The "pkgs" (evaluated nixpkgs) to use for e.g. non-builtin fetchers
+      inherit pkgs;
+    };
+
+in
+mkSources (mkConfig {}) // { __functor = _: settings: mkSources (mkConfig settings); }

+ 17 - 0
nix/xargo.nix

@@ -0,0 +1,17 @@
+{ rust ? import ./rust.nix }: (
+  self: super: {
+    xargo = self.rustPlatform.buildRustPackage rec {
+      pname = "xargo";
+      src = self.fetchFromGitHub {
+        owner = "japaric";
+        repo = pname;
+      };
+      cargoSha256 = "unset";
+      meta = with self.lib; {
+        description = "The rust cross-compilation tool";
+        homepage = "https://github.com/japaric/xargo";
+        maintainers = maintainers.tailhook;
+      };
+    };
+  }
+)

+ 100 - 0
shell.nix

@@ -0,0 +1,100 @@
+{ sources ? import nix/sources.nix # Please specify inputs obtained from `sources` as separate params like below
+, cargo2nix ? sources.cargo2nix
+, nixpkgs ? sources.nixpkgs
+, rust-olay ? import sources.rust-overlay
+}:
+let
+  tilt-olay = self: super: {
+    tilt184 = self.tilt.overrideAttrs (
+      oldAttrs: {
+        version = "0.18.4";
+        src = self.fetchFromGitHub {
+          owner = "tilt-dev";
+          repo = oldAttrs.pname;
+          rev = "v0.18.4";
+          sha256 = "sha256-xqBgbsrVSAOqtfHbEF07i6XIdiBXMYoR7H4Kc4xK7x0=";
+        };
+        buildFlagsArray = [ "-ldflags=-X main.version=0.18.4" ];
+      }
+    );
+  };
+  scripts-olay = self: super: {
+    whcluster = self.writeShellScriptBin "whcluster" ''
+      set -e
+      default_minikube_args="--cpus=10 --memory=10gb --disk-size=200gb"
+      export MINIKUBE_ARGS=''${MINIKUBE_ARGS:-$default_minikube_args}
+      ${self.minikube}/bin/minikube start $MINIKUBE_ARGS
+      ${self.minikube}/bin/minikube ssh 'echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p'
+      ${self.whkube}/bin/whkube
+    '';
+    whkube = self.writeShellScriptBin "whkube" ''${self.kubectl}/bin/kubectl config set-context --current --namespace=wormhole'';
+    whtilt = self.writeShellScriptBin "whtilt" ''
+      echo "Starting Tilt with ''${1:=5} guardians"
+      ${self.tilt184}/bin/tilt up --update-mode exec -- --num=$1
+    '';
+    whinotify = self.writeShellScriptBin "whinotify" ''
+      ${self.minikube}/bin/minikube ssh 'echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p'
+    '';
+    # stan-work config
+    whsw = self.writeShellScriptBin "whsw" ''
+      ${pkgs.mutagen}/bin/mutagen sync terminate whsw-sync || true
+      ${pkgs.mutagen}/bin/mutagen sync create -n whsw-sync . stan-work:~/wormhole
+      ${pkgs.mutagen}/bin/mutagen sync flush whsw-sync
+      export MINIKUBE_ARGS='--cpus=30 --memory=110g --disk-size=1000gb'
+      ssh stan-work \
+        ". ~/.zprofile && \
+            cd wormhole && \
+            nix-shell --command ' MINIKUBE_ARGS=\"$MINIKUBE_ARGS\" whcluster && \
+            killall tilt || true'"
+      ssh -L 10350:127.0.0.1:10350 stan-work \
+        "cd wormhole && \
+            source ~/.zprofile && \
+            nix-shell shell.nix --command 'whtilt $WH_GUARDIAN_COUNT'"
+    '';
+  };
+  cargo2nix-olay = import "${cargo2nix}/overlay";
+  pkgs = import nixpkgs {
+    overlays = [
+      # cargo2nix-olay
+      rust-olay
+      tilt-olay
+      scripts-olay
+    ];
+  };
+  cargo2nix-drv = import cargo2nix {
+    inherit nixpkgs;
+  };
+in
+pkgs.mkShell {
+  nativeBuildInputs = (
+    with pkgs; [
+      go
+      gopls
+      hidapi
+      libudev
+      openssl
+      pkgconfig
+      protobuf
+      whcluster
+      whinotify
+      whkube
+      whtilt
+      whsw
+      # (
+      #   rust-bin.stable."1.51.0".default.override {
+      #     extensions = [
+      #       "rust-src"
+      #       "rust-analysis"
+      #     ];
+      #   }
+      # )
+      # Provided on Fedora:
+      kubectl
+      minikube
+      tilt184
+      # xargo
+    ]
+  );
+  DOCKER_BUILDKIT = 1;
+  PROTOC = "${pkgs.protobuf}/bin/protoc";
+}

File diff suppressed because it is too large
+ 3528 - 416
solana/anchor-bridge/Cargo.lock


+ 2 - 1
solana/anchor-bridge/Cargo.toml

@@ -1,4 +1,5 @@
 [workspace]
 members = [
-    "programs/*"
+    "programs/*",
+    "client"
 ]

+ 13 - 0
solana/anchor-bridge/client/Cargo.toml

@@ -0,0 +1,13 @@
+[package]
+name = "anchor-bridge-client"
+version = "0.1.0"
+authors = ["Stan Drozd <stan@nexantic.com>"]
+edition = "2018"
+
+[dependencies]
+anchor-client = {git = "https://github.com/drozdziak1/anchor", branch = "anchor-debug-feature", features = ["anchor-debug"]}
+anyhow = "1.0.40"
+anchor-bridge = {path = "../programs/anchor-bridge", features = ["no-idl", "no-entrypoint", "anchor-debug"]}
+clap = "3.0.0-beta.2"
+rand = "0.7.3"
+shellexpand = "2.1.0"

+ 96 - 0
solana/anchor-bridge/client/src/main.rs

@@ -0,0 +1,96 @@
+use anchor_bridge::{
+    accounts::Initialize,
+    instruction::state::New,
+    BridgeConfig,
+    InitializeData,
+    MAX_LEN_GUARDIAN_KEYS,
+};
+use anchor_client::{
+    solana_sdk::{
+        account_info::AccountInfo,
+        commitment_config::CommitmentConfig,
+        instruction::AccountMeta,
+        pubkey::Pubkey,
+        signature::{read_keypair_file, Keypair, Signer},
+        system_instruction,
+        system_program,
+        sysvar,
+    },
+    Client,
+    Cluster,
+    EventContext,
+};
+use anyhow::Result;
+use clap::Clap;
+use rand::rngs::OsRng;
+
+use std::time::Duration;
+
+#[derive(Clap)]
+pub struct Opts {
+    #[clap(long)]
+    bridge_address: Pubkey,
+}
+
+fn main() -> Result<()> {
+    let opts = Opts::parse();
+
+    // Wallet and cluster params.
+    let payer = read_keypair_file(&*shellexpand::tilde("~/.config/solana/id.json"))
+        .expect("Example requires a keypair file");
+    let url = Cluster::Custom(
+        "http://localhost:8899".to_owned(),
+        "ws://localhost:8900".to_owned(),
+    );
+
+    let client = Client::new_with_options(url, payer, CommitmentConfig::processed());
+
+    initialize_bridge(&client, opts.bridge_address)?;
+    Ok(())
+}
+
+fn initialize_bridge(client: &Client, bridge_address: Pubkey) -> Result<()> {
+    let program = client.program(bridge_address);
+
+    let guardian_set_key = Keypair::generate(&mut OsRng);
+    let state_key = Keypair::generate(&mut OsRng);
+
+    program
+        .state_request()
+        .instruction(system_instruction::create_account(
+            &program.payer(),
+            &guardian_set_key.pubkey(),
+            program.rpc().get_minimum_balance_for_rent_exemption(500)?,
+            500,
+            &program.id(),
+        ))
+        .instruction(system_instruction::create_account(
+            &program.payer(),
+            &state_key.pubkey(),
+            program.rpc().get_minimum_balance_for_rent_exemption(500)?,
+            500,
+            &program.id(),
+        ))
+        .signer(&guardian_set_key)
+        // .signer(&state_key)
+        .accounts(Initialize {
+            payer: program.payer(),
+            guardian_set: guardian_set_key.pubkey(),
+            state: state_key.pubkey(),
+            system_program: system_program::id(),
+            clock: sysvar::clock::id(),
+            rent: sysvar::rent::id(),
+        })
+        .new(New {
+            data: InitializeData {
+                len_guardians: 0,
+                initial_guardian_keys: [[0u8; 20]; MAX_LEN_GUARDIAN_KEYS],
+                config: BridgeConfig {
+                    guardian_set_expiration_time: 0u32,
+                },
+            },
+        })
+        .send()?;
+
+    Ok(())
+}

+ 3 - 1
solana/anchor-bridge/programs/anchor-bridge/Cargo.toml

@@ -12,9 +12,11 @@ name = "anchor_bridge"
 no-entrypoint = []
 no-idl = []
 cpi = ["no-entrypoint"]
+# default = ["anchor-debug"]
 default = []
+anchor-debug = ["anchor-lang/anchor-debug"]
 
 [dependencies]
-anchor-lang = "0.4.4"
+anchor-lang = {git = "https://github.com/drozdziak1/anchor", branch = "anchor-debug-feature"}
 byteorder = "1.4.3"
 sha3 = "0.9.1"

+ 18 - 24
solana/anchor-bridge/programs/anchor-bridge/src/lib.rs

@@ -3,7 +3,9 @@ use anchor_lang::{prelude::*, solana_program};
 mod api;
 mod types;
 
-use types::{Index, BridgeConfig, Chain};
+use types::{Chain, Index};
+
+pub use types::BridgeConfig;
 
 // Without this, Anchor's derivation macros break. It requires names with no path components at all
 // otherwise it errors.
@@ -34,10 +36,9 @@ pub struct VerifySigsData {
     pub initial_creation: bool,
 }
 
-
 #[derive(Accounts)]
 pub struct Initialize<'info> {
-    /// Account used to pay for auxillary instructions.
+    // /// Account used to pay for auxillary instructions.
     #[account(signer)]
     pub payer: AccountInfo<'info>,
 
@@ -112,15 +113,9 @@ pub mod anchor_bridge {
         pub config: types::BridgeConfig,
     }
 
-    /// Trick Anchor into generating Initialize client structs. Anchor generates a Pubkey only
-    /// version of every Context struct, but only if a function or method with a self parameter
-    /// uses it. Bridge::new does not get picked up.
-    pub fn __trick_anchor_initialize(ctx: Context<Initialize>) -> Result<()> {
-        Ok(())
-    }
-
     impl Bridge {
         pub fn new(ctx: Context<Initialize>, data: InitializeData) -> Result<Self> {
+            msg!("Yeah boiiiiiii");
             api::initialize(
                 ctx,
                 data.len_guardians,
@@ -129,34 +124,33 @@ pub mod anchor_bridge {
             )
         }
 
-        pub fn publish_message(&mut self, ctx: Context<PublishMessage>, data: PublishMessageData, nonce: u8) -> Result<()> {
+        pub fn publish_message(
+            &mut self,
+            ctx: Context<PublishMessage>,
+            data: PublishMessageData,
+            nonce: u8,
+        ) -> Result<()> {
             // Sysvar trait not implemented for Instructions by sdk, so manual check required.  See
             // the VerifySig struct for more info.
             if *ctx.accounts.instructions.key != solana_program::sysvar::instructions::id() {
                 return Err(ErrorCode::InvalidSysVar.into());
             }
 
-            api::publish_message(
-                self,
-                ctx,
-                nonce,
-            )
+            api::publish_message(self, ctx, nonce)
         }
 
-        pub fn verify_signatures(&mut self, ctx: Context<VerifySig>, data: VerifySigsData) -> Result<()> {
+        pub fn verify_signatures(
+            &mut self,
+            ctx: Context<VerifySig>,
+            data: VerifySigsData,
+        ) -> Result<()> {
             // Sysvar trait not implemented for Instructions by sdk, so manual check required.  See
             // the VerifySig struct for more info.
             if *ctx.accounts.instruction_sysvar.key != solana_program::sysvar::instructions::id() {
                 return Err(ErrorCode::InvalidSysVar.into());
             }
 
-            api::verify_signatures(
-                self,
-                ctx,
-                data.hash,
-                data.signers,
-                data.initial_creation,
-            )
+            api::verify_signatures(self, ctx, data.hash, data.signers, data.initial_creation)
         }
     }
 }

Some files were not shown because too many files changed in this diff