LayerX エンジニアブログ

LayerX の エンジニアブログです。

負荷テストツール「Vegeta」でAnonifyの負荷テストをしていく話

こんにちは!LayerX Labsでエンジニアをやっているきむ(@jkcomment)です。

なぜ負荷テストを行うのか

負荷テストと言われるとシステム開発が終わったタイミングやサービスのリリース前、システムの性能低下が検知されたタイミングで行われることが多く、また、計画から手法、シナリオ策定、ツール選定など時間・金・人がかかる大変な仕事的なイメージが多いのではないでしょうか。我々が手掛けているAnonifyは、現在絶賛開発中のプロジェクトで、従来の負荷テストのような大規模でガッツリした感じではなく、Anonifyを開発していく中で①普通に予定通りの性能が出るか②現時点でのAnonifyのシステム的な限界点を知る③負荷をかけることで想定外のエラーや不具合を検知するという目的で負荷テストをやっています。言い換えると、Anonifyを成長させていくためのプロセスの一つとして負荷テストを行なっているということです。これを可能にしてくれてるのがVegetaという負荷テストツールです。あとで詳しくご紹介しますが、Vegetaはシンプルながらも強力なツールで、気軽に負荷テストを行うことができます。また、LabsではVegetaを用いてどのようにAnonifyの負荷テストをしていくかについてお話ししたいと思います。

Vegetaとは

github.com

Vegetaは、Go言語で開発された負荷テストツールです。インストールも簡単で、CLIとしても、ライブラリとしても利用できます。ちなみにVegetaという名前はドラゴンボールから来ているそうです。
Vegetaの1番の特徴としてシンプルさが挙げられます。vegeta attackコマンドで負荷をかけ、結果をvegeta reportコマンドで確認する。はい、これが全てです。笑

vegeta attackで負荷をかける

echo "GET http://localhost/" | vegeta attack -duration=5s > result.bin

テストシナリオを用いた負荷テストコマンド(-targetsの部分がテストシナリオの指定する部分)

vegeta attack -duration=1s -rate=500 -targets=targets.txt > result.bin

vegeta reportで結果を確認

vegeta report result.bin

他にも、例えばテストシナリオを作成して負荷をかけることもできますし、分散して負荷がかけられる、プロセス間で負荷がかけられるなど基本シンプルさを維持しながらも多様なユースケースに対応できるように様々な機能が備えています。また、負荷テストの結果を確認する機能も充実しており、ターミナルだけでなくブラウザで確認することもできますし、他のツールと組み合わせることでリアルタイムで負荷テストの状況を確認することもできます。

今回のシナリオの想定

github.com

Anonifyリポジトリのexampleディレクトリにあるerc20を前提に、erc20のtransferという機能を前提で進めます。 transferを実行するには下記の手順が必要です。SGX環境の構築手順はこちらをご覧ください。

tech.layerx.co.jp

  1. Anonifyからuser_counterを取得
  2. Anonifyからenclave公開鍵を取得
  3. Enclave上で実行するtransfer実行コマンド生成
  4. 3で生成したコマンドとtransfer処理の引数(recipient, amount)とenclave公開鍵を用いて暗号化し、リクエストデータ作成
  5. 4で生成したリクエストデータを送信

上記の手順について簡単に説明しますと、1のuser_counterは冪等性および順序性の保証に利用するもので、2のenclave暗号鍵はuser_counter取得時にリクエストを暗号化するための公開鍵です。 3と4はEnclave内でtransferを実行するためのデータ生成と暗号化を行います。5は生成されたリクエストデータをAnonifyに送ることでtransferを実行が完了になります。

1と2, 5は別途実行することにし、3,4をRustのコードで表現したのが下になります。

pub(crate) fn create_transfer_req<CR: RngCore + CryptoRng>(
    state_runtime_url: String,
    recipient: AccountId,
    amount: u64,
    enckey: SodiumPubKey,
    user_counter: u32,
    csprng: &mut CR,
) -> Result<()> {
    // Enclave上で実行するtransfer実行コマンド生成
    let req = json!({
        "access_policy": NoAuth::new(AccountId::from_array(DUMMY_ACCOUNT_ID)),
        "runtime_params": {
            "amount": amount,
            "recipient": recipient,
        },
        "cmd_name": "transfer",
        "counter": user_counter,
    });
    
    // 3で生成したコマンドとtransfer処理の引数(recipient, amount)とenclave公開鍵を用いて暗号化
    let ciphertext = SodiumCiphertext::encrypt(
        csprng,
        &enckey,
        &serde_json::to_vec(&req).unwrap(),
    )
    .map_err(|e| anyhow!("{:?}", e))?;
    let req = json!(ciphertext);

    let out = stdout();
    let mut out = BufWriter::new(out.lock());
    write!(
        out,
        "{}",
        base64::encode(&serde_json::to_vec(&req).unwrap())
    )
    .unwrap();

    Ok(())
}

このコードがテストシナリオになるわけですが、そのままVegetaのテストシナリオ機能を使うには工夫が必要になってくるため、生成されたリクエストデータを標準出力としてvegeta attackコマンドに渡すようにします。上記の1~5の手順をスクリプトファイルに書くと下記になります。

#!/bin/bash
set -e

# user_counter
i=0

# Anonifyからenclave公開鍵を取得
PUBKEY=$(curl http://localhost/api/v1/enclave_encryption_key -k -s -X GET -H "Content-Type: application/json" -d '')
SCRIPTS_DIR_PATH=$(cd $(dirname $0) && pwd)

while true
do
    # 上記のtransfer.rsのtransferを実行し、リクエストデータを取得(下記はコードは例です)
    REQ=$(create_transfer_req -recipient 0x1234 -amount 1000 -usercounter $i -c 1 -k "$PUBKEY")
    jq -ncM "{method: \"POST\", url: \"localhost/api/v1/state\", body: \"$REQ\", header: {\"Content-Type\": [\"application/json\"]}}" >&1
    # user_counter更新
    ((i=i+1))
done

負荷テストの時は便宜上、enclave公開鍵は1度だけ取得して使い回す、user_counterはローカルで生成した値を処理時に使用し、処理が終わったらuser_counterをインクリメントして次の処理に使うようにします。

Vegeta Attack!

vegeta attackコマンドはたくさんのオプションが用意されていますが、最低限のものとして下記のオプションを使うと無難にvegeta attackができます。

-duration: 負荷をかける時間。0の場合、無制限(例: -duration=60s)
-rate: 秒間リクエスト数(例: -rate=30)
-format: 実行結果をデコードするためのファイル形式を指定(例: -format=json)

下記のコマンドを実行することで今回のシナリオの想定のところでお話ししたシナリオ通り負荷テストが始まります(秒間700リクエストを永遠に送る)。

generate-transfer-req.sh | vegeta attack -duration=0 -rate=700 -lazy -format=json > result.bin

負荷テストが終わったら、vegeta reportコマンドで結果を確認します。

vegeta report result.bin

結果

Requests      [total, rate, throughput]  38961, 208.43, 190.88
Duration      [total, attack, wait]      3m24.103060884s, 3m6.923253452s, 17.179807432s
Latencies     [mean, 50, 95, 99, max]    1m14.405205472s, 1m14.869557049s, 2m21.081362339s, 2m26.972727327s, 2m28.454031212s
Bytes In      [total, mean]              3116983, 80.00
Bytes Out     [total, mean]              33783415, 867.11
Success       [ratio]                    100.00%
Status Codes  [code:count]               202:38961
Error Set:

最後に

今回はLabsで負荷テストを行なっている理由と、Vegetaの紹介、負荷テストを実施方法についてご紹介しました。普段から負荷テストを行なっている方にはご存知の内容ばかりだったかもしれませんが、使い始めの方だったり、これから負荷テストを検討される方にお役に立てれば幸いです。

絶賛エンジニア採用中ですので、少しでも興味のある方は一度お話をさせていただければと思います! herp.careers

複雑な開発要件を整理する際の考え方〜RDRAを参考に〜

はじめまして!LayerXのカレー担当のN_Taisho(西井)です。

私は、もともと霞ヶ関の役人として、6年ほど地方財政支援、大規模災害の被災地の復旧・復興支援、国際協定交渉等に関わってきました。現在はLayerXに所属しながら、三井物産デジタル・アセットマネジメント株式会社(以下、MDM)にてProduct Managerとしてプロダクト開発に主に携わりつつ、会社立ち上げに係る様々な業務に従事させてもらっています。

このMDMは、「眠れる「銭」を、Activateせよ。」をミッションに、「Operation × Techでどうアセマネ業務をリデザインするか」に取り組んでおりますが、その概要については以前、同じくLayerXに所属しながらMDMにコミットしている丸野が執筆した以下の記事が詳しいところなのでそちらをご一読いただければと思います。

tech.layerx.co.jp

今回は、プロダクト開発の経験がない私が、複雑な要件が絡まり合うアセマネ業務においてどのように開発要件を整理していったか、その考え方を中心に簡単に解説できればと思っています。実際に、要件を整理して開発を進める中で気づいた点・学んだ点もありますが、本文においてはその辺りも再度まとめ直した形でお伝えできればと思っています。

正直、私にとって要件定義とは、画面一覧、機能一覧、インターフェース一覧などの一覧系とその一覧に対応した機能系の大量のドキュメントという印象しかありませんでした。開発において要件定義の必要性は認識されていますが、そもそもの定義内容が明確ではないと物事を前に進めるのは難しいので、どのように進めて行こうかあれこれ思案をしていました。

参考にしたもの

経験豊富なメンバーに相談するのはもちろんのことですが、手法としてはRDRAを参考にしました。書籍としては以下のものが参考になりました。

RDRAとは

多くの解説記事等が出ているところなので詳細は譲りますが、単語としてはRelationship Driven Requirement Analysys(リレーションシップ駆動要件分析)の略称です。「網羅性」「整合性」「表現力」がキーワードとなっており、網羅性により要件定義に必要な情報の枠組みを決定し、整合性によって作業手順を決定し、表現力によって共通認識を確立していくものです。簡単に、システムの全体像を素早く把握し、整合性を保ちながらチーム全体で要件定義をしていくもの、と思っていただければと思います。

大事にしたこと

私自身、実は、当初は三井物産グループ内のアセマネ会社に出向し、アセマネ業務を学ばせていただいていたので、開発チームには後から参加する形となりました。なので、RDRAという手法を参考にしたとはいえ、これまでの開発チームのやり方であったり、はたまた個々のメンバーの特性もあるので、手法をそのまま取り入れるというより「考え方」の部分を大いに参考にしました。具体的には次のとおりです。

①全体把握と優先順位決めを最速で

RDRAは上述の通り軽く最速で要件定義を行うための手法です。一方、開発においてはいつでも時間は有限なので、素早く全体を把握した後には、枝葉の決め事は後回しにし、重要・主要なところを重点的に議論することを意識しました。

②共通のコミュニケーションツール・議論の土台とする

大前提として、経験のない自分が決め切ることはどう考えても不可能だと考えており、また、書面を作成することが目的化し、整合しない資料を量産しても時間の無駄だと考えていました。その上で、重要なことは、ドキュメントを作ることではなく、開発メンバーとのコミュニケーションのベースを作り、最優先に着手しなくてはいけないものを明らかにすることと考えました。そのため、Lucidchart、スプレッドシートなどに自分がアセマネ会社に出向して学んだ業務フローやデータの流れを可視化し、これを議論の土台にし、「議論しながらその場で作成・確認する」サイクルで進めることを意識しました。これにより、要件を決めるスピードが格段に上がったような気がします。なお、この際ドキュメントを複数作る場合において、当該ドキュメント間の整合性は強く意識しました。

今になって思えば、ふわっとしたことを形にしていく工程では、様々な要素が相互に関わり合うため、アウトプットが一度出てきても都度見直す必要があります。そのため、 早い段階で重要部分を把握・共有し、当該部分との整合性を図りながら要件定義・開発を進めることで不要な手戻りを減らすことはとても重要な気がしています。

③仮説ベースでも進めていく

アセマネ業務の経験があるメンバーのいない中での開発プロセスだったので、資料集めやヒアリングももちろん行っていました。ただ、入手した資料・情報は粒度も目的も様々だったので、それらを土台に分からないことをただ闇雲にヒアリングしても効果は薄いだろうと予想されました。なので、まずは事前に、手に入る資料や見聞きした情報から仮説を組み立て、それを元にヒアリングを行うことを意識しました。この辺りは、「動くものを作る」だとか「Demo Driven Development」というLayerXのカルチャーにも通じるところがあります。

tech.layerx.co.jp

具体的に何をしたのか?

ここまでは考え方というような、抽象論に終始してしまいましたが、お伝えできる範囲内で具体的にどのようなプロセスで、何をしてきたのかをご紹介できればと思います。

一般的にプロダクト開発は以下のプロセスで進んでいくかと思います。
①ユースケース・アクターなどの抽出
②BPMNなどのような手法を使い業務プロセスをモデリング(BPMNについても機会があれば紹介できればと思います。)
③ドメイン抽出(イベント、システムとの境界把握等)
④機能群の整理

この後、機能ごとにスケジュールを立てて、以下を実施します。
⑤画面の洗い出し
⑥データ設計(DBスキーマや状態遷移等の整理)
⑦ユースケース充当性確認
⑧アーキテクチャ設計やコードの設計議論
⑨実装

この中で、上記の考え方をもとに、①から⑤までを迅速に行い、議論の土台を構築しました。 例えば、以下のようなLucidchartの図を活用して、①から③を行い、

f:id:N_taisho:20210525200543p:plain

その上で、次のような図で④と⑤を素早く行いました。図自体は、証券会社が投資家に対して投資案件の情報を提供する機能を例としてイメージし、極端に簡素化した上で作成しております。
f:id:N_taisho:20210524231449p:plain

関連会社に出向していたこともあり、業務フローに一番精通していた自分が、業務フローからユースケースを詳細化し、プロダクトの価値の単位を大雑把に把握し、早めにチームに共有することで、 なぜこの機能が必要なのか、この機能の使われ方はこのようになる、などの議論ができたように思います。
また、機能を活用するユーザーにとって価値が提供されるものから着手すべきという考え方から、できるだけ早い段階から全体を見通しつつ、優先順位をつけて開発に移行できる単位を明確にする作業も行いました。具体的には、機能の全体図を描きつつ、機能ごとの依存関係の図示なども行い、被依存度の高い機能の優先度を上げるということをしました。「議論しながらその場で作成・確認する」というサイクルを意識することで、意思決定もチーム内で素早く実施ができたように思います。

ここで個人的に意識していたのは、
a. ビジネスロジックまで含めて精度の高い仕様を事前に整備しない
b. 情報や状態の遷移まで細かく把握していないので後回し(上記で⑥を含めてないのはここにも一因があります)
c. 荒い要件定義でよく、細かい仕様は議論・開発しながら
という点で、上述した「大事にしたこと」とも大いに関わってきます。

胸を張ってしっかりとできたと言えるとは思っていませんが、この辺りの意識も、重要なユースケースの洗い出し、全体像の合意、開発着手順の足場作りに大いに貢献するのではないかと、今では改めて感じております。

開発の面白さ

ドメイン知識・業務知識もほとんどない段階から始めたので、振り返れば、初期に作成した画面・機能は以後の検討でほとんど書き換えられ、最終的に残らないこともありました。ここには悔しさに似た気持ちもありますが、正確性に固執せず、まずは自分たちの理解する範囲で記述し、チームで議論するベースを作る、その後、自分たちの理解していること・議論の結果を足場にすることでヒアリング精度が上がったり、仮説が磨き込まれていく。この繰り返しで、正解に近づいて行ける感覚があります。初めてのことでも知識が繋がっていくこと、同じく誤解していたこと・勘違いしていたことがはっきりし正しい方向へ迎えること、これをチームで行えることに個人的には面白さを感じています。

以上ではありますが、簡単に自分が未経験でありながらプロダクト開発にあたり複雑な要件を整理する際にどのように考えてきたかを紹介してきました。

We’re hiring!!

最後になりましたが、LayerXは各職種(特にエンジニアの皆さん!)絶賛採用中です! 私のように未経験分野でも挑戦する機会やそこをバックアップしてくれる頼もしい仲間がある環境です。 少しでも興味ありましたら一度カジュアルに話を聞きに来てください!

herp.careers

Azure Confidential Computing VMでAnonifyを動かそう

こんにちは!LayerX LabsでAnonifyを開発している恩田(さいぺ)です。

前回は秘匿化モジュールAnonifyの開発について書かせていただきました。

tech.layerx.co.jp

記事中でも言及しましたが、AnonifyのバックエンドはIntel SGX®︎を採用しています。Anonifyはソースコードを公開しているので、誰でも動かすことができるのですが、Intel SGXが動作する環境でないと実行できない等、少々ハードルが高くなっています。
そこで今回はIntel SGXを動作可能なAzure Confidential Computing VMを利用して、Linux(Ubuntu)でAnonifyを動かすまでの初期セットアップ手順を紹介します。

ゴールは「AnonifyのCIで実行しているスクリプトを動作させること」です。
スクリプトの内容は、Anonify上で実装したERC201相当の送金ロジックを含む結合テストです2。実際の内容はこちらから見ることができます。

Azure Confidential Computing VMのセットアップ

Intel SGXに対応した仮想マシンを提供しているAzure Confidential Computingを利用します。仮想マシンのシリーズとしては「DCsv2」がAzure Confidential Computing VMに該当します。
残念ながらDCsv2シリーズは日本のリージョン(Japan EastとJapan West)には対応していません。対応しているリージョンはこちらから確認できるので、お好きなものを選んでいただいて大丈夫です。本記事ではEast USを選びました。

まずはAzure Marketplaceから「Azure Confidential Computing (Virtual Machine)」を検索します。

f:id:cipepser:20210523102411p:plain

「作成」を押下すると、以下の画面が出てくるので必要事項を埋めてください。認証用の公開鍵はご自身のものを使ってください。

f:id:cipepser:20210523102750p:plain

「確認および作成」を押下するとデプロイ可否の検証が始まります。少し待ち、検証に成功したあともう一度「作成」を押下するとVMが作成されます。数分待つと登録したSSH公開鍵を用いて、SSHでアクセスができます。今回の例ではssh cipe@<VM Global IP>でアクセスできます。3

VM内のセットアップ

さて、SSHができたらVMのセットアップを行います。
大きくAnonifyに関わるセットアップと、SGXに関わるセットアップがあります。

Anonify関連のセットアップ

必要な依存やバイナリをインストールします。

$ sudo apt update
$ sudo apt install apt-transport-https ca-certificates curl gnupg-agent software-properties-common
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
$ sudo apt-key fingerprint 0EBFCD88
$ sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
$ sudo apt update
$ sudo apt-get install docker-ce docker-ce-cli containerd.io

dockerを再起動します。

$ sudo systemctl daemon-reload
$ sudo systemctl restart docker
$ systemctl show --property=Environment docker

docker groupが存在するか確認します。存在しなければ作成してください。

$ cat /etc/group | grep docker
docker:x:999:

dockerグループにazureインスタンスのユーザを追加します。

$ sudo gpasswd -a <user name: 今回だとcipe> docker

更新を反映するため、ここで再度SSHし直します。 再SSH後、以下のsocketがあることを確認してください。

$ ls -l /var/run/docker.sock
srw-rw---- 1 root docker 0 May 23 04:44 /var/run/docker.sock

次にdokcer-composeをインストールします。 dockerとversion合わせる必要があるので、上述のdockerのversionに合わせてインストールしてください。

$ sudo curl -L https://github.com/docker/compose/releases/download/1.25.4/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
$ sudo mv /usr/local/bin/docker-compose /usr/bin
$ sudo chmod +x /usr/bin/docker-compose

最後にsolcをインストールします。Anonifyでは、ノード同士で状態遷移命令を共有するためのバックエンドとしてQuorumを利用しています。Solidityで記述されたスマートコントラクトをコンパイルするためインストールします。

$ sudo snap install solc

Intel SGX関連のセットアップ

IntelとMicrosoftのaptレポジトリを設定します。

$ echo 'deb [arch=amd64] https://download.01.org/intel-sgx/sgx_repo/ubuntu bionic main' | sudo tee /etc/apt/sources.list.d/intel-sgx.list
wget -qO - https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key | sudo apt-key add -
$ echo "deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-7 main" | sudo tee /etc/apt/sources.list.d/llvm-toolchain-bionic-7.list
wget -qO - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
$ echo "deb [arch=amd64] https://packages.microsoft.com/ubuntu/18.04/prod bionic main" | sudo tee /etc/apt/sources.list.d/msprod.list
wget -qO - https://packages.microsoft.com/keys/microsoft.asc | sudo apt-key add -
$ sudo apt update

Intel SGXを動作させるために必要な依存をインストールします。Intelが提供しているライブラリはこちらです。適宜必要なものをインストールいただければと思いますが、ここでは以下の依存をインストールします。

$ sudo apt -y install clang-7 libssl-dev gdb libsgx-enclave-common libsgx-enclave-common-dev libprotobuf10 libsgx-ae-qe3 libsgx-ae-qve libsgx-epid libsgx-launch libsgx-pce-logic libsgx-qe3-logic libsgx-quote-ex libsgx-uae-service libsgx-urts

インストールが終わったら、aesmd(Application Enclave Services Manager4のデーモン)を起動します。

$ LD_LIBRARY_PATH=/opt/intel/sgx-aesm-service/aesm /opt/intel/sgx-aesm-service/aesm/aesm_service

/var/run/aesmd/にsocketができていれば無事起動ができています。なおSGXへのアクセスは/dev/sgx/enclaveを介して行われます。

$ ls /dev/sgx/
enclave  provision

Anonifyではdocker-compose.ymlにdevicesファイルとして指定し、コンテナ内からenclaveにアクセスできるようにしています。

volumes:
- /var/run/aesmd:/var/run/aesmd
..
..
devices:
- "/dev/sgx/enclave"

Intelに開発者登録

前回のブログよりAnonifyが有する2つの性質「Confidentiality」「Execution Integrity」について触れました。

Intel SGXがもたらすセキュリティ・プロパティの観点では、ハードウェアレベルでの分離およびメモリ暗号化で「Confidentiality」を、Remote Attestationで「Execution Integrity」を実現します。

後者のRemote Attestationでは、Intelが運営するAttestation Service(IAS)を利用します5。Anonifyを動作させるために、SPIDSUB_KEY(APIキーのようなものです)が必要なので、IntelのAPI webポータルで開発者登録を行います。

Intel API webポータルにアクセスし、「Sign up」を押下します。

f:id:cipepser:20210523141526p:plain

各種情報を入力します。

f:id:cipepser:20210523141552p:plain

メール認証が必要なため、「Confirm email address」を押下します。

f:id:cipepser:20210523141621p:plain

メール認証が完了したらSign Inします。

f:id:cipepser:20210523141654p:plain

Sing Inした状態で、以下の「Intel® SGX Attestation Service Utilizing Enhanced Privacy ID (EPID)」の文中のリンクを押下します。

f:id:cipepser:20210523141854p:plain

今回は開発用の「Development Attestation」欄にある「Subscribe(unlikable)」を選びます。

f:id:cipepser:20210523141922p:plain

確認画面が表示されるので「Subscribe」を押下してください。

f:id:cipepser:20210523141941p:plain

SPIDPrimary key(以下、SUB_KEY)が表示されると思います。次のステップで使うのでメモしておいてください。

Anonifyを動かす

長い道のりでしたが、いよいよAnonifyを動かします。
VMに戻り、Anonifyをcloneしてください。

$ git clone https://github.com/LayerXcom/anonify.git
$ cd anonify && cp .env.sample .env

.env内にご自身のSPIDSUB_KEY を設定してください。

$ docker-compose up -d
$ docker-compose exec sgx_machine bash

最後にテスト用のスクリプトを実行します。最後までエラーが起きなければ無事成功です。

cd anonify/scripts && ./test.sh

最後に

Azure Confidential Computing VMとAnonifyのセットアップ、Intelの開発者登録の手順を紹介しました。Intel SGXは気になっているけど、なかなか動かすハードルが高いなぁと思っている方の一助になれば幸いです。Confidential Computing関連の技術は低レイヤで楽しいので、ぜひお試しいただけると嬉しいです!


  1. EIP-20で送金可能なトークンが備えるべきインタフェースが定義されています。Anonifyでは送金に限らないアプリケーションを実装可能ですが、ここではシンプルな例として挙げています。

  2. 単体テストや異常系、ツール群のビルドなども含まれており、テスト自体が膨大ですが、わかりやすい代表例として挙げました。

  3. アクセスできない場合は、Seruity GroupでSSHが許可されていない可能性があるので、適切な許可設定を行ってください。

  4. 資料によってはArchitectural Enclave Service Managerと書かれていることもある。

  5. Data Center Attestation Primitives (DCAP) と呼ばれるサードパーティが運営するAttestation Serviceも存在します

Product Engineering Managerの募集をスタートしました

こんにちは。松本(@y_matsuwitter)です。 最近はひたすら干し芋を齧っています。

昨日、新たにProduct Engineering Managerという、Engineering Managementに加えてProductも一体的に見ていくべくセットしたポジションについて募集を開始しました。 今回はこのポジションの募集に関して、将来を見越して何を狙っているのか簡単に書かせていただこうと思います。

herp.careers

Engineering Managementの重要性

様々な企業でEngineering Manager(以下EM)が募集される様になって久しいと思います。 開発組織のPeople Managementに責務を持って行動することがEMの主たる責務となります。 その延長としてのVPoEについて、以下の記事で書かせていただいています。

tech.gunosy.io

この記事から引用すると、

メンバーの採用から育成、組織形態の設計を通じて、人の生産性とその成長を最大化する。

とあります。

しかし、ここまで様々な組織や取り組みを経験する中で世の中とはPeople Managementに閉じて何かが完結するわけでもなく、結局の所良いプロダクトが生まれなければ片手落ちとなってしまいます。 そうした思いもあり、またLayerXの未来を考えた時に、EMの役割について単にPeople Managementに閉じる以上の形を明示したいということから今回の募集がスタートしました。

プロダクトやソフトウェアと組織は一体、それをデザインする

具体的にその役割とはなにか。 それは「プロダクト、ソフトウェアと組織を表裏一体のものとして設計・運営する」というものになります。

その根底には、プロダクトやソフトウェアの設計は組織構造と密接に関わっている、というコンウェイの法則的な考え方から来ています。 (コンウェイの法則やそれと関連したアーキテクチャの考え方についてはこちらを読んでいただければと。)

note.com

組織に責務を持つこととプロダクトに責務を持つことは密接な関係にあるといえます。

こうした考えを元にすると、将来に渡ってスケールするプロダクトを目指すにはスケールできる組織が一体となって設計されている必要があります。

もっと具体的に考えてみましょう。 そのプロダクトが将来成長していく際に十分なスピードを担保するためには、どのように内部のソフトウェアとその責務が分割されていき、それに対してどのようなチームが存在しているべきか考慮せねばなりません。 例えば、3年後には複数のサービスに分割しある程度マイクロサービス的な方針を取る場合、それに沿った開発チームが必要となります。

f:id:y_matsuwitter:20210520182520j:plain
組織とソフトウェアの成長

とすると、

  • 将来に向けて開発チームのリーダーをどうするか
  • 内部にはどのようなメンバーが必要か
  • チーム間はどのように連携するか
  • ソフトウェア間はどのように連携するか
  • ...etc

など様々なことを設計していくことになります。

より良いプロダクトに向けてはEMもプロダクト設計に積極的に関与し、People managementの外側にも関わりながら組織・プロダクトの双方設計が必要です。

Engineering Managementを軸足にしつつも、Product ManagerかつTechLeadである榎本(@mosa_siru)と連携しプロダクトの意思決定をしていくポジション、それがProduct Engineering Managerという名前に込められた我々の思いです。

人・組織をうまく設計しながらプロダクト開発とその意思決定過程を支えていくことが長期的に「すべての経済活動を、デジタル化する」ために求められています。

どんな方に来ていただきたいのか

PEMについては、我々もこれから在り方を明確化していこうということで、ともに学び、試しながら在り方を作っていける方を探しております。 とにかくプロダクトが好き、成長させたい、そしてその根幹、重要なものは人であると確信している方であれば楽しんでいただけるポジションです。

求めるスキル・経験については募集にも書かせていただいていますが、下記のようになっています。

  • 「チーム成果の最大化」「アウトカムの最大化」を目的とした開発チーム運営並びにそのための意思決定を行った経験
  • 一定規模(5〜10人)以上の開発チームに対する複数年以上のPM・EM等としてのマネジメント経験のある方
  • スクラムやアジャイルな開発プロセスの推進経験
  • 数年に渡るプロダクトの運用・改善経験
  • ソフトウェアエンジニアとしての業務における開発経験と知識
  • 日本語にてコミュニケーションが可能なこと / Native-like fluency in Japanese

ぜひ、一緒にソフトウェアと組織をともに設計する開発組織に挑戦してみませんか? カジュアルな面談含め、皆様からのご連絡お待ちしております。

herp.careers

新卒エンジニアから見てLayerXはどんな会社か

こんにちは、LayerX インボイスのAI-OCRを開発しています、新卒ソフトウェアエンジニアのTomoakiです。 推しのグリーンカレーのペーストはMAE PLOYのものです(KALDIとかにあります)。

さて、私ごとですが最近大学を卒業しまして、”新卒の社員”になりました。 新卒ということで入社エントリーなるものを書く機会を頂いたのですが、LayerXではすでに2年程働いているので、入社エントリーというよりは"入社経過エントリー"を書いていきたいと思います。

f:id:tomoaki25:20210520160142p:plain
内定式の様子

今回は新卒社員から見てLayerXがどんな会社かを

①事業

②人・カルチャー

の2つの観点から、よくある勘違いを交えつつ紹介していきたいと思います。

TL; DR

  • LayerXはテクノロジーを駆使する事業会社です。

  • 現在は経理向けのSaaS、アセマネ会社の立ち上げ、秘匿化技術の研究開発を行っています。

  • リスクを取って、産業のデジタル化、特に重い産業の生産性向上をテーマに、本気で日本を改革しようとしています。

  • 現在の事業にとどまらず、「すべての経済活動のデジタル化」の実現を進め、歴史に残る偉大な会社になると私は信じています。

  • 若いメンバーもたくさん在籍していて、各方面で大活躍しています。

  • 在籍期間に関わらず活躍できる環境が整備されています。

LayerXはテクノロジーを駆使する事業会社

よくある勘違い:LayerXはブロックチェーンの会社

たまにある勘違い :LayerXは大企業・事業会社の受託開発の会社

f:id:tomoaki25:20210520010611p:plain

LayerXは大きくDX事業部、MDM事業部、LayerX Labsと3つの事業部から構成されます。

DX事業部は経理向けのSaaSプロダクトである、請求書AIクラウド 「LayerX インボイス」を自社で開発・提供しています。3つの事業部の中でも最も人数が多い部署で今も絶賛拡大中です。

tech.layerx.co.jp

三井物産デジタル・アセットマネジメント株式会社(以下、MDM)は2020年4月に、三井物産54%、LayerX36%、SMBC日興証券5%、三井住友信託銀行5%の4社JVでスタートした会社です。MDM事業部にはMDMに在籍するLayerXのメンバーが所属します。

MDM事業部では「複雑なオペレーションとテクノロジーを掛け合わせて、どうアセマネ業務をリデザインするか」という問題に向き合い、ゼロからアセマネ会社の立ち上げを行っています。3つの事業部の中でも2番目に人数が多い部署です。

tech.layerx.co.jp

LayerX Labs(研究開発)は主にプライバシー保護技術の研究開発を行う事業部であり、長期的目線での事業の立ち上げを目指しています。直近では加賀市、つくば市とインターネット投票の実現などを進めています。

tech.layerx.co.jp

以上のように現在のLayerXは経理・金融・行政の領域を中心に事業を展開しています。

これらの領域はオペレーションが極めて複雑であったり、ライセンスが必要だあったり、法規制が絡んでいたりと単にSaaSなどを導入するだけで効率化が実現できるような領域ではありません。 したがって、今もアナログな作業が多く残存しています。

LayerXはそれらの領域のオペレーションをなるべくテックを活用してデザインし直し、効率化することを目指しています。 LayerXは大企業・事業会社の受託開発を行う会社ではなく、事業そのものを展開する会社です。必要に応じてはその領域のエキスパートとタッグを組むことで最速で事業の立ち上げを実現しようとしています。

また、ブロックチェーンの会社だと勘違いされることも多いですが(以前はそういう側面もありました)、LayerXは自社で経理向けのSaaS事業を展開したり、アセマネ会社をゼロから作ったり、インターネット投票など秘匿化技術の研究開発を行ったりと、産業のデジタル化をメインとする事業会社です。

会社の代表取締役である、福島さん・松本さんはじめLayerXにはto Cの領域で活躍された方が多く在籍していますが、皆次の10年はto Bの領域におけるデジタル化に闘志を燃やしています。リスクを取って、産業のデジタル化、特に重い産業の生産性向上をテーマに、本気で日本を改革しようとしています。

私はLayerXが、現在の事業にとどまらない産業のデジタル化・効率化により、ミッションである「すべての経済活動のデジタル化」の実現を進め、歴史に残る偉大な会社になると信じています(そうなるようにコミットします)。

LayerXは年齢や在籍期間に関わらず全員が活躍する会社

たまにある勘違い:LayerXはベンチャー2・3周目のシニアなメンバーがほとんどで、若手はあまり活躍してない

確かに、LayerXにはベンチャー2・3周目のシニアなメンバーが多く在籍しています。しかし、若いメンバーもたくさんいます。昨年は新卒で2名、今年も私を含めて2名新卒で入社しており、さらに大学在学中の執行役員がいてと実は20代前半のメンバーが結構います。

昨年新卒の伊藤田本さんはMDM事業部を主導していたり、執行役員の中村さんはLayerX Labsの所長として「ベンチャー企業での研究開発」というチャレンジングな取り組みをしており、私も日々刺激を受けています。

www.fastgrow.jp

financial.nikkei.com

他にもLayerX インボイスのPMを担う生田さん、営業の柱である宮崎さんなど、若い世代が事業の推進において重要な役割を担っています。

f:id:tomoaki25:20210520160926p:plain
受注の数だけ銅鑼を鳴らす宮崎氏

また、LayerXのメンバーは個人の力が高い人が多いのですが、私はそれ以上に全員のチームワークが特に素晴らしいなと思っています。 これは週次定例で毎週みっちり情報の共有を行うので全員の目線が合っていることが大きいと思います。

週次定例では会社としての戦略や方針の共有だけでなく、現在抱えている課題感や不安といったふわっとしたものまでも含まれます。目線が合うと、誰から指示されることなく求められる意思決定を実行することが可能になり、結果として個人への権限・責任の移譲が進みます。

また、経営会議や週次定例の議事録といった会社の意思決定に関わる情報はすべてメンバーに公開されているため、古株メンバーと新規メンバーの間の情報の非対称性は小さく、スムーズなオンボーディングにもつながっています。

tech.layerx.co.jp

このようにLayerXでは、情報収集などに余計な手間をかけることなく新規メンバーがすぐに持ち味を発揮できる環境が整備されており、さらに各々が裁量を持ってできる仕事がどんどん振られていくため、年齢や在籍期間に関わらず全員が活躍できる会社になっているのだなと感じます。

私もLayerX インボイスのコア機能であるAI-OCRの開発をやらせていただいておりますが、会社の透明性や周囲のサポートに日々助けられていると実感します。

最後に

今回は新卒社員から見てLayerXがどんな会社かを紹介しました。少しでも興味がありましたら、一度お話させてください。

このブログの読者から次の10年を一緒に作っていくメンバーが生まれれば嬉しく思います。

herp.careers

たとえ採用に繋がらなくとも、本記事を通じてLayerXの事業やメンバー・カルチャーについて知って頂けただけでも嬉しく思います。

ちなみに新卒の募集もあります。

herp.careers

Golandでよく使うショートカット

こんにちは、DX事業部の木戸です。

約10年前にWindows + Java + Eclipseという環境からMac + PHPという環境に変わった際に、今はどうかわかりませんがMac + EclipseがWindowsと使用感があまりにも異なっていて、開発効率が悪化したときに出会ったのがJetBrains製のPhpStormでした。Windows + Eclipseの仕様感とほぼ変わらず、うおおおってなって以来、JetBrains製品をずっと利用しています。

LayerX インボイス、ワークフロー機能ではバックエンドにGoを採用しており、今回は同社製のGolandで良く使っているショートカットについてご紹介したいと思います。よく使ってるのを上の方にしてます。
※使用しているPCがMacのため、Macのみのご紹介です。

  • コード補完
  • 変数宣言箇所、メソッド実装箇所へジャンプ
  • さっきの場所に戻る、戻った後進む
  • 呼び出し元へジャンプ
  • 呼び出し元検索
  • interfaceの実装箇所へジャンプ
  • 選択行の複製
  • 選択行の移動
  • 選択行を削除
  • 選択行をコメントアウト
  • ファイル名検索
  • 全ファイルからテキスト検索
  • 全ファイルからテキスト検索&置換
  • なんでも検索
  • リネーム
  • マルチカーソル
  • タブを閉じる
  • 警告を修正
  • コードのフォーマット
  • メソッド引数を改行
  • 選択行をメソッドに切り出す

コード補完

Ctrl + スペース
一番使うのはこれです。time.の後ろで実行すると候補がずらっと出てきたり、日付フォーマットのYYYY -> 2006なんかも補完してくれます。
f:id:lx_anago:20210517195918g:plain

変数宣言箇所、メソッド実装箇所へジャンプ

Command + ↓
Command + B
Command + マウスでクリック
過去の自分のソース含めソース解析しているときに多用してます。後述ですが、ジャンプした後の戻るショートカットの相性の良さでキーボードの場合はCommand + ↓を使うことがほとんどです。マウス操作中はマウスでクリックですね。
f:id:lx_anago:20210517204013g:plain

さっきの場所に戻る、戻った後進む

戻る:Command + Option + ←
進む:Command + Option + →
Commnd + ↓でジャンプして、Commad + ←で戻って、あれ?戻るべきじゃなかったってCommand + →でジャンプ先に戻ってって感じで使ってます。便利。
f:id:lx_anago:20210517204757g:plain

呼び出し元へジャンプ

Command + B
Command + マウスでクリック
宣言箇所へのジャンプとCommand + ↓以外は同じです。これの良いところがメソッドの引数を増やしたり減らしたりしても呼び出し元へジャンプしてくれるところなんです。メソッドの引数変えたとかリファクタした時とかによく使います。
f:id:lx_anago:20210517223319g:plain

呼び出し元検索

Control + Option + H
呼び出し元へジャンプとほとんど同じです。呼び出し元をリストアップしたいときに使います。
f:id:lx_anago:20210517225758g:plain

interfaceの実装箇所へジャンプ

Command + Option + B
Command+ ↓ or Bでメソッド実装箇所へジャンプして、interfaceかってなったときに使います。
f:id:lx_anago:20210518110358g:plain

選択行の複製

Command + D
同じような実装をメソッド単位でするときとかにもよく使います。
f:id:lx_anago:20210518112213g:plain

選択行の移動

インデントを無視した行移動:Shift + Option + ↑ or ↓
インデントを考慮した行移動:Shift + Command + ↑ or ↓
f:id:lx_anago:20210518134307g:plain

選択行を削除

Command + Delete
f:id:lx_anago:20210518134630g:plain

選択行をコメントアウト

Command + /
f:id:lx_anago:20210518134815g:plain

ファイル名検索

Command + Shift + O
f:id:lx_anago:20210518141109g:plain

全ファイルからテキスト検索

Command + Shift + F
f:id:lx_anago:20210518142044g:plain

全ファイルからテキスト検索&置換

Command + Shift + R

f:id:lx_anago:20210518142420g:plain

なんでも検索

Shift * 2回
ショートカットキー忘れたとか、ショートカット割当たってないコマンドとかを実行する時とかに使います。
f:id:lx_anago:20210518141803g:plain

リネーム

Shift + F6
変数名、メソッド名とかのリネームも可能なのと、ファイル名のリネームもできます。
f:id:lx_anago:20210518143146g:plain

マルチカーソル

Alt + マウスでクリック
何かしら一気に変更かけたいときにはこれ
f:id:lx_anago:20210518143736g:plain

タブを閉じる

Command + W
f:id:lx_anago:20210518144105g:plain

警告を修正

Option + Enter
何かしら警告が出てるときにマウスオーバーで警告理由出てくるんですが、修正候補を出すときに利用します。使用頻度はそこまで高くないです。
f:id:lx_anago:20210518140701g:plain

コードのフォーマット

Command + Option + L
Golandだとgoファイルは自動フォーマットの設定があるのであまり使いませんが、sqlファイルなどでよく使います。
f:id:lx_anago:20210518144239g:plain

メソッド引数を改行

Option + Enter
警告を修正するときと同じショートカットです。引数が多くなった時とかに便利
f:id:lx_anago:20210518145436g:plain

選択行をメソッドに切り出す

Command + Option + M
f:id:lx_anago:20210518150027g:plain

最後に

JetBrains製品をお使いの方にはご存知の内容ばかりだったかもしれませんが、使い始めの方だったり、使っている方でもこんなショートカットあったんだーってお役に立てれば幸いです。今回はショートカットのみの内容でしたが次回以降で便利な設定や使い方などもご紹介できればと思います。

絶賛エンジニア採用中ですので、少しでも興味のある方は一度お話をさせていただければと思います! herp.careers

多種多様な会計ソフトと接続するためのSaaSの作り方

こんにちは。LayerX エンジニアの花村(@naomasabit)です。

プレスリリースでも多く出していますが、請求書処理を行うLayerX インボイスは多くの会計ソフトと連携しています。他ソフトウェアと連携するという機能は複雑性を伴いますが、この記事では私が会計ソフト連携部分の開発を実施してきてぶつかった課題、と対応してきた内容をご紹介します。

多くの会計ソフトと連携しているLayerX インボイス

f:id:naomasabit:20210518114604p:plain

具体的な連携内容は

  • 会計ソフトからマスタデータの取り込み
  • そして会計ソフトへの仕訳データの取り込み

です。「仕訳」とは経済活動を一定のルールで表した概念で、例えば 5/1に銀行の普通預金から現金を10,000円引き出したら「5/1 現金 10,000 普通預金 10,000」といった形式で記述します。実際には会計ソフトによって仕訳のフォーマットは多種多様であり、環境が異なるため、ユーザーの利用ソフトに合わせて多くの連携を考える必要があります。

しかし、会計ソフト対応といっても一筋縄にはいきません。これまで多くの会計ソフトに対応する中であたった

  • 課題1. 会計ソフトが持つマスタがそれぞれ異なる
  • 課題2. 仕訳出力フォーマットの違いによる実装パターンの増加への対応
  • 課題3. チーム内における仕様理解の混乱

について、それぞれへの対応を述べていきます。

課題1: 会計ソフトが持つマスタがそれぞれ異なる

基本的に、「勘定科目」、「部門」といったマスタデータはどの会計ソフトも持っているのですが、会計ソフトによって保持するマスタが異なり、例えば「取引先」は会計ソフトごとに持っていたり持っていなかったりします。また、「補助科目」という勘定科目をより細かく分類するためにつけるグループについては、freeeでは同様の役割を「品目」や「メモタグ」等の概念で表すなど、保持マスタは千差万別です。

対応: 地道な調査による対応と、マスタの利用設定を管理する仕組みの提供による対応

これらはまず、地道な調査による会計ソフトが持つマスタ群の理解を行いました。

f:id:naomasabit:20210517112014p:plain
マスタ早見表

会計ソフトが持つマスタ群についてそれぞれ理解し、上記のような早見表にしています。(内容は伏せます)会計ソフトのドキュメントに加えて、実機の動作を確認して調査します。調査して仕様を切る人と実装者が別々だとスピードが遅くなってしまうので、実装者自身が調査してクイックに実装しています。

調査した結果を環境に反映するために、マスタの利用設定を管理する機能を用意しています。LayerX インボイス利用ユーザーの環境毎にfreee利用ユーザーではこのマスタとこのマスタを利用する、マネーフォワード利用ユーザーではこのマスタとこのマスタを利用する等、対応する会計ソフト毎に設定できる実装にしています。

課題2: 仕訳出力フォーマットの違いによる実装パターンの増加への対応

仕訳出力フォーマットも大きく異なります。会計ソフトにインポートするために、さまざまなフォーマットでの出力対応が必要です。対応する会計ソフトが増えるごとにそれぞれフォーマットが必要です。

なお、@yyoshikiがfreeeのAPIライブラリを先日公開しましたが、こちらのようにLayerX インボイスが仕訳APIも連携している会計ソフトについては別の実装になるのですが、ここでは主にCSV出力による連携を述べます。

対応1: 仕訳テンプレートを定義したjsonの追加だけで仕訳出力の対応を可能にしてスケールしやすくした

f:id:naomasabit:20210518114637p:plain

当初は会計ソフトに合わせた加工のコードを書いていたのですが、対応会計ソフトが増える毎に実装が増えていき、スケールしづらくなってきました。そこで現在は、様々な仕訳フォーマットに対応するために、仕訳出力テンプレートをjson形式で設定し、マッピング・加工して出力するようにしています。これにより、新しい会計ソフトへの対応が必要になった時も、新しくjsonを定義するだけで新しい会計ソフトの仕訳出力に対応できます。

対応2: 横展開可能な仕訳テストの標準化による品質とスピードの両立をした

f:id:naomasabit:20210519093524p:plain

定義した出力が正しいかを確認する必要があります。LayerX インボイスでは、会計ソフト横断で同一のインプットデータを用意し、それぞれの会計ソフトフォーマットに合わせたCSVが出力されるかというに期待値テストを行います。

f:id:naomasabit:20210517120546p:plain

GoではTable Driven Testを使ったテストがメジャーですが、仕訳構造のような複雑なデータはコード内に書くと可読性が下がるため、図のようにCSVで期待値を定義して、こちらを読み込むようにしています。CSVで書くことで、数十列あるような仕訳フォーマットでも期待値を作りやすくしています。

また、同一ケースを使い、仕訳を組み立てて比較する部分は共通モジュールにしているので、新しい会計ソフトが出てきても以下のような数行を書けば横展開できるようにしています。

// ほげほげ会計ソフトのテスト実装
func TestJournalsHogeHogeAccountingSoft(t *testing.T) {
  // 期待値のCSVを読み込んで共通の型にする共通関数
  expectedJournals := importExpectedJournals(ExpectedHogeHogeAccountingSoftCSV)
  var eTests = setTestDataTable(expectedJournals)
  // テストを行う関数
  testExpenseCase(t, model.HogeHogeAccountingSoft, eTests)
}

課題3: チーム内における仕様理解の混乱

いくつもの会計ソフトに対応していることで、チームメンバーの仕様理解にハードルがいくつもあります。メンバー間で知識差分があると意思決定のスピードが遅くなり、精度も悪くなりますし無駄な体力を使うことになります。

対応: 各会計ソフトの知見をPlaybookとして整備し、チーム内へ知見の共有

詳細仕様について会計ソフトを理解するためのPlaybookを作成し、共有できるようにしています。

f:id:naomasabit:20210518113340p:plain

上記はPlaybookの一部抜粋で、勘定奉行シリーズについて書いています。もっとも、Playbookだけでは理解に繋がらず、実機を触ってもらわないと理解が浅く終わってしまうため、定期的に実機を触ってもらうような取り組みを始めています。

まとめ

f:id:naomasabit:20210517123258p:plain
まとめ

多くのソフトウェアと繋がるソフトウェアは考慮事項が多く複雑になりがちです。1つ1つ課題を解きほぐして、打ち手を立てていくことでこれまで対応してきました。ユーザーに合わせた環境提供の柔軟性、仕訳出力の共通化と品質向上施策など実装に加え、チームメンバー間でドメイン知識の差分をなくすための仕組みやドキュメントなども整理しています。実装、チームへのナレッジ共有とバランス感が求められる仕事をしています。

このようなSaaSの課題を解いていきたい方、また会計についても学んでいきたい知的好奇心の強い方、ぜひ下記のリンクからご応募ください。お待ちしております。

herp.careers

最後までお読みいただきありがとうございます。

追記: 図中のGopherアイコンはTakuya Ueda(@tenntenn)さん作のものを利用させていただきました。当初作者表記が漏れていたのをご指摘いただき、修正追記いたしました。