bitcoin scriptの前提知識

OP_RETURNはトランザクションの際にデータを乗っけるイメージで想像はしやすかったのですが、bitcoin scriptとなるとさらに敷居が高くなります。
データを乗っけるというと初心者の頃はコイン1枚にデータが乗ると思いがちです。そのためブロックチェーンは想定を覆す設定が多く難しいイメージを持たれていますね。

で、もう黎明期真っただ中な訳です。そこらにいる人に聞いても分からないし、興味もある人もほぼいない訳です。
そうしたらもう権威に直接「初歩的ですいません(汗」と、聞くしかない。

聞いて返せることと言ったら理解して広めて使う事ですよね。それしかギブられてもテイクできない。

と、言うわけでまずは

  • bitcoin scriptってのがある。
  • それはLocking Scriptに埋め込まれる。
  • それにたいしてUnlocking Scriptのtxを送る。

これで一連のbitcoin scriptを試すというのが行える。
ただこれを簡単に試すライブラリみたいのはまだない。構築真っ最中。

余裕であった。moneybutton SDK

この技術者のための技術提供が今の時期です。開発スピードは速い。
まぁなもんで今普及活動するっていうのはかなり熱狂的なオタクと言えます。

そろそろエンジニアが湧きたつフェーズが来るわけです。

私はライブラリを待つことにしました。言葉でもう少しビットコインスクリプトの流れの例を書くと。

  • 5 + 5と同じ値になるか判定するLocking Scriptを作ります。
  • これに対して、"9"とか"10"とかUnlocking Scriptを乗せてtxを送ります。
  • この解がもし正なら取引が成立し、負なら取引は成立しません。

どうでしょう。

P2PKH Pay-to-Public-Key-HashってのがBCHとかLTCでも同じ概念がありまして、
はじめ毛嫌いしていたのですが、これが基礎になりまして、送金スクリプトになります。

P2SHと検索するとその解説やサンプルスクリプトなどがでてきます。
どれもいい記事ですが、ここが分かりやすいかも。

zoom-blc.com

ここまで読んだうえで、使いやすいライブラリが誕生するのを待ち、
他のスクリプトを解析したりOP_RETURNで遊ぶ日々を送ります。

sCrypt(エス・クリプト)の使い道(前座)

まず情報をまとめると以下

slack: //scryptworkspace.slack.com
sCrypt IDE: //scrypt.studio/

datapayでOPCODEをチェーンに埋め込む
//github.com/moneybutton/bsv/blob/master/lib/opcode.js#L78

ビットコインスクリプトで使用されるオペコード
//wiki.bitcoinsv.io/index.php/Opcodes_used_in_Bitcoin_Script

ちょっと話題になったtx
//whatsonchain.com/tx/723c903d83cdce9f32246a451652f4b4f469ef78d630bf0f22770cb16bbc187b

この様に、やってる人はやっています。
前座なので情報を集めただけです。

sCrypt(エス・クリプト)は難解なビットコインスクリプトを簡単なプログラムで記述してコンバートしてくれるサービス?です。
将来的にはビジネス展開するロードマップがあるとのこと。
で、例えばこのコード。

contract DemoSum {
  int x;
  int y;

  constructor(int x, int y) {
      this.x = x;
      this.y = y;
  }

  function sum(int a, int b) returns (int) {
      return a + b;
  }

  public function unlock(int z) {
      require(z == this.sum(this.x, this.y));
  }
}

なんとなーく読めますよね。デモの足し算判定クラス。
x + yがzとイコールならtrueです。
これをコンバートするとこちら

OP_1 OP_6 OP_0 OP_0 OP_3 OP_PICK OP_2 OP_ROLL OP_DROP OP_1 OP_ROLL OP_2 OP_PICK OP_1 OP_ROLL OP_DROP OP_4 OP_PICK OP_2 OP_PICK OP_2 OP_PICK OP_1 OP_PICK OP_1 OP_PICK OP_ADD OP_NIP OP_NIP OP_NUMEQUAL OP_VERIFY OP_TRUE OP_NIP OP_NIP OP_NIP OP_NIP OP_NIP

HAHAHA.
これをいきなり記述するのは人間の平凡な頭脳では不可能ですよね。
なんとなーく読めるようになる職人もでてくるかもしれないけど。

ということで前座でしたが必要そうだなぁと実感すればOK

OP_PUSHDATA4にhello worldとぶち込む(ぶち込めず)

色々読んでるけど、
要は一連でどうやるのよ?
応用の先に例えば飛躍してどんなことができるのよ?
が、全く分からない。

で、まずは実施してできそうであり、実施したらどうなるか見れそうなものをやっていく。

こちらのツイート

datapayでもOPCODE扱えるようです。
前回のmoneybuttonのソースをコピって、ぶち込むところだけ改修して実施してみます。

<script>
document.addEventListener("DOMContentLoaded", function(e) {
	databutton.build({
		data: [{op: 78}, "test text data."],
		button: {
			$el: "#button",
			onPayment: function(msg) {
				console.log(msg)
				document.querySelector("a#tx").innerHTML = "View on B (" + msg.txid + ")"
				document.querySelector("a#tx").setAttribute("href", "https://b.bitdb.network#" + msg.txid)
				console.log("https://whatsonchain.com/tx/" + msg.txid);
			},
			onError: function(err) { console.log(err) }
		}
	})
})
</script>

確認

{
  "v": 3,
  "q": {
    "find": {
      "tx.h": "tx..."
    }
  }
}

OP_RETURNはerrorだけどデコードするとテストテキストがでました。
しかし「genesis.bitdb.network/query」では取得できず。bico.mediaは取れた。
これだと取得に難アリになってしまうな。一応bico.mediaから参照すればいけるのでいいかな...
趣味レベルでしか使えないけど、本格的になるようなら相談すればいい話だな。

と、思ったけどどうもマニュアル見ると見れそうなんだよな。
docs.bitdb.network

もしかしてOP_RETURNがerrorなのが問題かも?あdatapayではなくてdatabuttonが対応してないかも?
と、いうことでサーバjsで試してみることに...

うーん、芳しくない。OP_PUSHDATA4+OP_RETURNとOP_PUSHDATA4のみでやったけど微妙におかしい
出来る言うから簡単なテストかと思ったけど、やって良かった。今のところ微妙。

私のやりたいことと課題山積み。

datapay用opcode一覧
github.com

もしかすると、106にそれを入れられるだけで、78に直接いれることはできないのかも??
ではどうやってbitcoinscriptを投入するのでしょうか。

  • 追記.

因みにこのOP_PUSHDATA系に短いテキストを埋め込むのは現在は?少なくともできないようです。
PUSHDATAは容量の増加に応じて利用される枠のためです。

Script.prototype._addBuffer = function (buf, prepend) {
  var opcodenum
  var len = buf.length
  if (len >= 0 && len < Opcode.OP_PUSHDATA1) {
    opcodenum = len
  } else if (len < Math.pow(2, 8)) {
    opcodenum = Opcode.OP_PUSHDATA1
  } else if (len < Math.pow(2, 16)) {
    opcodenum = Opcode.OP_PUSHDATA2
  } else if (len < Math.pow(2, 32)) {
    opcodenum = Opcode.OP_PUSHDATA4
  } else {
    throw new Error('You can\'t push that much data')
  }
  this._insertAtPosition({
    buf: buf,
    len: len,
    opcodenum: opcodenum
  }, prepend)
  return this
}

また、datapayなどはmoneybuttonのjsライブラリを簡易に実行しやすくするインタフェースなので、深く知る必要がある場合はそっちのソースを解析せよとの事でした。
github.com

自分(サービス)への利益をいただきつつ、当事者にブロックチェーンを使わせる

変なタイトルですが、無償ではなくて、有償でブロックチェーンサービスを使用していただきつつ、こちらとしてはカスタマーへウォレット管理はしませんよという形態をとる方法。

カスタマーはブロックチェーンに登録する際にかかる費用に手数料としてこちらにお布施をくれる。お布施というかサービスを繋ぐ場の手数料ですかね。

前回の続きで、簡単にオプション追加で行える。

document.addEventListener("DOMContentLoaded", function(e) {
	databutton.build({
		data: ["0x6d0c", "テストなので短いテキスト"],
		button: {
			$el: "#button",
			$pay: {
				to: [{
					address: "支払うアドレス",
					value: サトシ
				}]
			},
			onPayment: function(msg) {
				console.log(msg)
				document.querySelector("a#tx").innerHTML = "View on B (" + msg.txid + ")"
				document.querySelector("a#tx").setAttribute("href", "https://b.bitdb.network#" + msg.txid)
			},
			onError: function(err) { console.log(err) }
		}
	})
})

これで、OP_RETURNに登録しつつ、payも行う。OP_RETURNは自身のmoneybuttonアドレスへ自分に向かって行う。なので2通信。といってもあっという間に行われる。

当たり前のこと言うけど重いファイルはネットワーク上にあげる分待つ。それはネットと同じ。これで皆さんは顧客のウォレットを管理せず感知せずにサービスを提供し、利益を得られる。難点としてはfiatでできない事ですね。今後気軽に法貨トークンを交換できたとしても、いちいち交換しないといけない。suica, paypayやlinepayにいちいち入金しないといけないのと同じ。これは電子マネーみな敷居として苦労している。

ちなみにfeebを0.4にしようとよこしまなテストをしたがきっちり0.5sat取られた。

github.com
github.com

次の課題はこれだと暗号化できない。jsで暗号化、復号化できると幸い。それとtxをちゃんとこちらのサーバで出来れば受け取りたい。ajaxだと不確実なのが恐い。実際は登録の仕方で、こちらでブロックチェーンを参照すれば取れそうだが、これも確実ではない。例えばイタズラで似たようなデータ形式を登録されたりとか...まぁメリットないけどビジネス化が進めばないこともないよね。
jsの暗号復号はふつうにopensslの形式である模様。
techacademy.jp
こちらのサーバで用意したキーを入れたりできれば良さそう。まだちゃんと読んでないけど。

意味のある暗号化されたデータをブロックチェーンにいれてみた。

1bytes 0.5satoshiになったんですが、ビットコインの値段が上がってしまって恩恵がない...
でも各ツール系は0.5がデフォのfeeになるようにアップデートされてきました。
さらにトランザクションあたり1GBになったそうなのです。そこまでの容量のものを上げるには価格もしくはfeeがまだ高すぎる。

そもそも制限意識したことなかったが、制限に到達した場合はOP_PUSHDATA4とか?分散とかで乗り切っていたらしい。
それもジェネシスでもどりんこしたので、基本的にはもう制限は意識しなくてよくなった。

ということでdatapayも0.0.18を使っていたが0.0.22にアップデート。
ついでにdatabuttonなるものがあるらしいのでいれた。しかしこれが転機となる。

nodeモジュールのアップデートとかではエラーでてうまく行かなくて、検索したらnode_modules自体作り直せみたいにあって、
ちょっとnpm?のモジュール周りいまだに弱いよね。簡単に壊れる。書き込めないよというエラーだった。自分が壊しただけかもしれんけど...。
検索すると特定のディレクトリにインスコするパターンとグローバルにパスを通す場合があるらしく、
そっちでやっとくといいらしい?

mkdir ~/.npm-global
npm config set prefix '~/.npm-global'
touch ~/.profile
export PATH=~/.npm-global/bin:$PATH
source ~/.profile

これ系の記事はいろいろある。これを実行してからインスコしなおすとここがデフォのディレクトリになる。

ls -al /*****/.npm-global/lib/node_modules/

この配下にインスコされた最新がね。package.jsonはどうなったんや...よくわからん。

  • datapayについては今回は、暗号化したもので大きいデータをアップするテスト
  • databuttonはとりあえずサンプルとして設置テストをしてみる

多分、datapay+databuttonで必要なsatoshiをブラウザ上でpay出来ると予想。
そうすると前回みたいに目算と実際に支払うsatoshiが違うなんてことも起きない?とりあえずやってみる。

https://api.bitindex.network/api/v2/addrs/balance?address=アドレス

これいままで使ってきたけど無料ではなくなったみたい。
システムに組み込むなら支払うべきだが、こちらはまだテストの前のテストレベルほかのサービスを使う。

https://whatsonchain.com/address/アドレス

こんな感じ。whatsonchainはアドレスもtxもなんでもフリーワードで検索できる。

https://blockchair.com/bitcoin-sv/address/アドレス

これもあり。こちらはさらにいろいろなブロックチェーンの検索が出来る。こりゃすごい。

MatterCloudさんいままでありがとう。

話を戻してdatabuttonの設置テストは、githubにdemoがあるので、そのhtmlをブラウザで開けばもう完成。
github.com

ただ、アドレスが誰かのが入っているので、別に誰宛でもいいけど迷惑かけてはあれなんでdatapayの時同様にmemo.cashの0x6d02にしておく。
支払いは、サーバで作成したシークレットキーやアドレス、そのアドレスにビットコインは不要。なぜならdatabuttonはmoneybuttonとの連携だから、払うのはmoneybuttonのアカウントだ。

とりえあず小さい画像でやってみよう。価格高騰でこれでも貧乏性との闘いだ。以前のdatapayで上げた画像をdemohtmlであげてみようとしたところ。

おや?(画像参照)
f:id:online106:20200213202117p:plain

7086satoshi !??
0.00007086 BSV だよね...やっぱ7000satoshi...

しかし約2.9円。そうか前回たしか14211satoshiだったからだいたい半分か。すごい!けど価格が上がったから、前回より日本円は掛かってる、ウゼェ(笑)
無事上がりました。楽すぎる。これはサンプルなので暗号化せずにあがった。しかしこれだけなら楽だな。

と、いうことでdatapay+databuttonの検証は終わり今回は"binary"なのでこの仕組みで暗号復号で上げられる方法を試さないといけない。
最近のウォレット系はアドレスを都度生成するので残高がどうとかが簡単にバレない。素晴らしい。しかし今の内からコツコツ勉強しないと、5年後とか何が何だか分からなくなりそう。
キーレスやパス紛失時の復旧など、今後はより安全なものに変わっていく。中身は知らなくてもいい、そういうもんだと思えば。テレビ、冷蔵庫、エアコン、電子レンジと同じ仕組みは知らなくても便利に動くという事実だけでいい。

最後に大きな花火、大きいファイルを暗号化してアップしてみる。暗号化はいろいろあるのでそこは簡略化して暗号化済みの文字列をあげるとする。ただし大きなデータだ。
3M程度のファイル暗号化したら5Mくらいになる。...なんとかならんかこれ...ってことでいくつかのファイルで試算。

5,202,840 bytes
2,601,420 satoshi
0.02601420 bsv
約1000円

1,637,120 bytes
818,560‬satoshi
0.00818560 bsv
約320円

366,592 bytes
183,296‬satoshi
0.00183296 bsv
約70円

1000円...現実的じゃねーぞ。てか3MBはデカすぎる。これはファイルが悪い。そして暗号化で倍近くなるのがキツイ。しかし復号化ひつようだしな。
nakasendoSDKとhandcashSDK試してみるか...それも次回への伸びしろということで、今回は約70円の暗号化したファイルをアップしてみるテスツ。

今回は面倒なので、datapay+databuttonのサンプルで上げてしまう。ファイルではないバージョンのサンプルも概要に記載されている。それがこれ

databutton.build({
  data: ["0x6d02", "hello world"],
  button: { $el: "#button" }
})

"hello world"を暗号化文字列にする。
これだとtx見れないので、サンプルhtmlのbutton.onPaymentは付ける。

よし...やって見よう...。ちなみに"hello world"だと0.00000111BSV / 0.04円ですね。
一番安い暗号化ファイル。70円を実装した結果...moneybuttonは想定したsatoshiでした。

刻んでみたところ1秒もたたないくらいでコミットした模様でtxが表示された。
しかしトランザクションブラウジングしようとしたところそんなもんはないと出た。
これもしかして容量が上がるとすぐに出ない奴かな?とりあえず10分待つか...

10分待ってようやく出た。ちょっと焦った。もしやjs壊れてたんじゃとか。まぁそれならエラーでとまるけどね。

で、今回は取得をAPIに頼る。前回は仮で文字列コピペで終わらせたが今回はちゃんとチェーンから引っ張ってそれを描画してみるテスツです。
前回のクエリ例を参考にさきほどのトランザクションを取得
https://genesis.bitdb.network/q/************

{
  "v": 3,
  "q": {
    "find": {
      "tx.h": "トランザクション"
    }
  },
  "r": {
    "f": "[.[] | .out[0] | {res: .ls3} ]"
  }
}

無事取れた。URLはヘッダーにkeyを入れる必要がある。暗号復号の方法は暗号なので一応伏せておく。
これでjsonで暗号化された文字列がまま取得できたので、無事復号化。これにより元のデータを取得できた!

今回の件で、
■パブリックブロックチェーンに暗号化したデータをアップし、クラックでもされん限り安全にデータをアップで来た。
この暗号復号も他にも困難にする方法はある。例えば分割する。そして関係なさそうに偽装する。関係ないものと混ぜるなど。
まぁそこまでしなくてもクラックされたら困るデータでもないんだけど、一応プライバシーの観点ね。
■登録さえしてしまえば、今後永遠に無料でデータを取得できるストレージができた。ひ孫にもワシのtxじゃと伝承できる。
■データが大きいと10分待つ必要があった。本来は待つんだけど、早めに閲覧できることができるので、その恩恵がないと不便。
■ウォレット(デバイス)からマイナーへデータを送れるが、仲介する自分は素通りするので法律に触れない代わりに自分に全くメリットがない。

など分かったことや悩む点が出てきた。あとは優秀なSDKがないか旅をしなくてはならない。

insta360 go 操作

電源オン/オフ 初期化

・アクションボタンを長押しするとGOが起動します。その際に2回振動します。
・アクションボタンを3秒間長押しすると電源が切れます。
・アクションボタンを20秒間長押しすると強制終了します。

※GOをスタンバイモードで30秒間放置すると自動的に電源が落ちます。

基本機能

・クイックキャプチャ
設定により秒数は変えられますが、30秒間の撮影を行います。
電源オフの状態でアクションボタンを1度押下します。
録画終了後、振動します。

・ハイパーラプス
電源オンの状態で素早く2回アクションボタンを押下します。
30分間の撮影を行います。撮影中は白色で早く点滅し、終了すると振動し電源が落ちます。

・スローモーション
電源オンの状態で素早く3回アクションボタンを押下します。
15秒間の撮影を行います。撮影中は白色で遅く点滅し、終了すると振動し電源が落ちます。

https://www.insta360.com/support/supportdetail?name=go
https://www.insta360.com/download/insta360-go
https://www.insta360.com/support/supportcourse?post_id=11139

BitDB query マニュアル

datapayのこれまで使ったクエリーまとめ。

特定のトランザクションデータを取得する

{
  "v": 3,
  "q": {
    "find": {
      "tx.h": "トランザクション"
    }
  }
}

特定のアドレスのデータを取得する

{
  "v": 3,
  "q": {
    "find": {
      "in.e.a": "アドレス"
    }
  }
}

特定のアドレスで文字列検索する(AND検索)
検索対象の文字列.半角スペースで区切るとorで検索を行う。Not検索はワードの前に"-"をつける。(例:A not B -> A -B) また、A B Cという単語を検索する場合には "\"A B C \""とダブルクオーテーションを使用する。

{
  "v": 3,
  "q": {
    "find": {
      "in.e.a": "アドレス",
      "$text": { "$search": "\"aaa bbb ccc\"" }
    },
    "limit": 5
  }
}

特定のカラム?で検索する

{
  "v": 3,
  "q": {
    "find": {
      "in.e.a": "アドレス",
      "out.s4": { "$regex": "^正規表現", "$options": "i" }
    },
    "limit": 5
  }
}

オプションとかはmongodb参照
$regex — MongoDB Manual


5件表示の2ページ目を取得する

{
  "v": 3,
  "q": {
    "find": {
      "in.e.a": "アドレス"
    },
    "limit": 5,
    "skip": 5
  }
}

最新のトランザクションでソートする

{
  "v": 3,
  "q": {
    "find": {
      "in.e.a": "アドレス"
    },
    "limit": 5,
    "sort": {
      "blk": -1
    }
  }
}

取得データをjqで整形する

{
  "v": 3,
  "q": {
    "find": {
      "in.e.a": "アドレス"
    }
  },
  "r": {
    "f": "[.[] | .out[0] | { sample: .lb3} ]"
  }
}