先までは、"愛記"についての記載で、どのようにブロックチェーンSNSに組み込んで実装していけばよいのか、概念的なところからアプローチ方法を記載していった。大まかな概念としてはひとまず終えた。次は、ブロックチェーンの概念設計といえるところまで、基本設計書に着手できるようなところまで、概念を具体化していきたい。
自動処理について
さて、初期設定ができたら、さっそく行動をしてみよう。まずは簡単な行動からやってみることだ。例えば、先にも記載した瞑想し無意識になる、ということを人にも教えたという愛の行動をしたとしよう。
・愛の行動Lv7:”瞑想し無意識になる”となる
石川太郎さんは、普段から思考を使わず、直感を大事に生きている。日々の習慣として、お昼休みに瞑想を10分程度、毎日ルーティーンワークとして行っている。この日も瞑想をしていたら、知り合いでも何でもない加賀次郎さんから声をかけられ、瞑想の仕方を教えてほしいという。瞑想の方法というのはいろんなやり方が記載はされているが、ポイントは、顕在意識をいかに働かせず、潜在意識優位な半睡眠、半覚醒状態を作れるかということだ。眠くて寝てしまってはダメだが、起きてしまってもダメだ。そのフッと顕在意識がストップしてリラックスするその瞬間の状態を維持するのであれば、形はどのような形でも良いのだ。
このようなことを伝え、繰り返し、繰り返しやることで少しずつ潜在意識優位な状態が一瞬から数秒、そして数分というように長くなっていく。その状態をいかに頭ではなく、身体で覚えるか、感覚で覚えるかにかかっている。頭で覚えているうちは再現できず、感覚で覚えられて初めて、繰り返し再現できるようになるのだという。こうして、加賀次郎さんは毎日12:00過ぎにやってきて、石川太郎さんと一緒に瞑想するようになり、石川太郎さんに感謝をすることとなった。
今回の仕訳の科目としては、愛の行動Lv7:”瞑想し無意識になる”となる。今回の事例は、石川太郎さんは、人類の代表として行動しているのであり、人類の皆が瞑想による安らぎを手に入れれば良いのにと願っての行動なのだ。よって、第8次元:人類という立場にて仕訳することになる。
・借方(発信先):第8次元_人類_石川太郎さん 、瞑想し無意識になる
→ 詳細内容を備考欄に記入。
・貸方(受信側):第8次元_人類_加賀次郎さん 、気持ちが楽になる
→ 背景等を備考欄に記入。
さて、これを自動仕訳していかねばならない。どうすればよいかということだ。問題になるのが科目と次元だ。どうやって科目と次元を選んだのか?ということだ。まず科目の方だが、愛の行動レベルの選択から入る。レベル1なのか?レベル4なのか?レベル8なのか?いったい、どれほどの影響度がある愛の行動なのだろう?と考えるのだ。レベルが上がれば上がるほど、相手への影響度が高いということになる。今回の瞑想を教えるという行為が、相手にどれほどの影響度を及ぼすのだろう?と想像しながら、しかもあまり深く考えずにレベルを選ぶのかもしれない。今回は影響力は大きいと考え、レベル7あたりの科目を眺める。すると、愛の行動Lv7:”瞑想し無意識になる”という科目があった。これが実際にふさわしい科目だろうと判断して、この科目を選択したという具合だ。
さらに次元はというと、今回の愛の行動での影響度がどの次元に影響を及ぼすのかを考える。個人なのか、会社なのか、業界なのか、国なのか、世界なのか、人類なのか。。小さく考えると加賀次郎さんという個人にだけ影響を及ぼすことかもしれないし、大きく考えると人類全体にまで影響を及ぼすことかもしれない。ここは石川太郎さんの判断で、第8次元:人類を選択したという具合だ。
このように、科目や次元は、もっとも相応しいだろうと思うものを自己判断で選択し、相手に送るのであるが、手入力であると3ステップもあり面倒くさい。そこで、どこかの工程を自動処理できないかを考える。自動処理について、今は3ステップなのが、1ステップになれば大幅な短縮となるだろう。そのためには、SNSを立ち上げ、①科目選択、②次元選択、さらに相手を特定してから③相手へのメッセージ内容を記入し、投稿という作業を何とか1つの作業で終わらせることができないか?ということだ。そのためには、生成AIと連携するのが早いのであろう。音声入力モードで、上記のようなことを網羅して話しかければ良いのかもしれない。すると、AIが自動処理してくれるということになるのだろう。
例えば、「”愛記システム”を立ち上げ、科目は、Lv7:”瞑想し無意識になる”を選択し、次元は、”8次元:人類”を選択し、内容は、”心が安らぐ”と記載し、”NFT化”して!」
と頼めば良いのかもしれない。
このNFT化された行動がQRコードやURLになってくれば、これで1ステップの作業となる。目の前に相手が居るのなら、このQRコードを相手にかざして相手が読み込んでくれるかどうかだ。目の前に相手が居ないのであれば、URLを相手に渡して相手が読み込んでくれるかどうかだ。読み込んでくれれば、NFTを受け取ったことになるような仕組みにすればよい。
NFT化について
愛の行動にはレベル1~10まであって、それぞれに科目が複数設定されている。愛記システムとは、愛貨をやりとりするブロックチェーンSNSとリンクしたDAppsである。以下は、レベル7の「瞑想し無意識になる」科目に対して、8次元の「人類」次元で「心が安らぐ」行動が行われ、その結果をNFT化する仕訳の例である。
-
科目: レベル7 - 瞑想し無意識になる
- この科目は、深い瞑想によって無意識の領域にアクセスすることを意味する。愛貨のやりとりが行われる際に、ユーザーがこの科目を選択すると、その行動がブロックチェーン上に不変的に記録される。
-
次元: 8次元 - 人類
- この次元は、ユーザーの行動が人類全体に影響を与えることを示している。ユーザーの愛の行動が8次元に関連している場合、その行動は人類全体に対してポジティブな影響をもたらすとされる。
-
内容: 心が安らぐ
- ユーザーが瞑想し無意識になる行動を通じて、心が安らぐという内容が記載される。これは愛貨のやりとりの一部としてブロックチェーン上に保存される。
-
NFT化:
- 愛の行動がNFT(非代替トークン)としてブロックチェーン上に記録され、不変的なものとなる。これにより、その特定の行動が一意であり、トークンとして他のユーザーに送信できるようになる。
この仕訳により、ユーザーが愛貨のやりとりを行う際に、その行動が具体的な科目、次元、内容に結びつき、NFTとしてブロックチェーン上に保存される仕組みが構築される。これにより、愛記システムは個々の愛の行動を詳細かつ透明に追跡し、NFTとして保存することで、独自の価値を創出する。
もっと詳細な説明を行おう。
-
スマートコントラクトのデプロイ:
-
スマートコントラクトをデプロイするには、ウォレットソフトウェアや開発フレームワークを使用する。ここではHardhatフレームワークを例に説明する。
-
プロジェクトディレクトリで、以下のようなコマンドを実行する。
Hardhatフレームワークを使用してスマートコントラクトをデプロイする例を示す。以下のスクリプトは、deploy.jsとして保存されているものとする。
// scripts/deploy.js
async function main() {
const LoveRecordNFT = await ethers.getContractFactory("LoveRecordNFT");
console.log("Deploying LoveRecordNFT...");
const loveRecordNFT = await LoveRecordNFT.deploy();
await loveRecordNFT.deployed();
console.log("LoveRecordNFT deployed to:", loveRecordNFT.address);
}
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});
このスクリプトでは、LoveRecordNFTというスマートコントラクトのファクトリーを作成し、そのファクトリーを使用して実際にスマートコントラクトをデプロイしている。デプロイ後に、デプロイされたスマートコントラクトのアドレスがコンソールに表示される。デプロイするには、以下のコマンドを実行する。
npx hardhat run scripts/deploy.js --network <network-name>
-
<network-name>にはデプロイ先のネットワーク名を指定する。例えば、ローカルネットワークならば"localhost"などである。
-
scripts/deploy.jsスクリプトは、mainnetというネットワークにデプロイする例を示している。このスクリプト内で「LoveRecordNFT」コントラクトのデプロイとアドレスの表示が行われる。
-
-
デプロイされたスマートコントラクトのアドレス取得:
- デプロイが成功すると、デプロイされた「LoveRecordNFT」コントラクトのアドレスが表示される。このアドレスを控えておく。
LoveRecordNFT deployed to: 0x123456789abcdef
ここで表示されている0x123456789abcdefの部分がデプロイされたスマートコントラクトのアドレスである。このアドレスを控えておくことで、後でスマートコントラクトにアクセスする際に使用することができる。
- デプロイが成功すると、デプロイされた「LoveRecordNFT」コントラクトのアドレスが表示される。このアドレスを控えておく。
以上で、スマートコントラクト「LoveRecordNFT」がデプロイされ、そのアドレスが取得できる。このアドレスは、NFTの発行や取引において必要になる。では、NFT化の詳細手順を以下に記載する。
-
スマートコントラクトのデプロイ:
- スマートコントラクト「LoveRecordNFT」をデプロイすると、そのコントラクトはブロックチェーン上に配置される。これは、分散型台帳における特別なプログラムであり、愛記システムの基盤となる。
- ブロックチェーン上にデプロイされたスマートコントラクトは、一意のアドレスを持ち、そのアドレスを用いて他のユーザーがアクセスできる。
use ink_lang as ink;
#[ink::contract]
mod love_record_nft {
#[cfg(not(feature = "ink-as-dependency"))]
use ink_storage::{
collections::HashMap as StorageHashMap,
lazy::Lazy,
};
// 追加: AccountIdの使用を可能にする
use ink_env::AccountId;
#[ink(storage)]
pub struct LoveRecordNFT {
records: StorageHashMap<u64, Record>, // AccountIdをキーとするレコードのマップに変更
token_id_counter: Lazy<u64>,
}
#[derive(Debug, PartialEq, Eq, scale::Encode, scale::Decode)]
pub struct Record {
subject: Vec<u8>,
dimension: Vec<u8>,
description: Vec<u8>,
is_approved: bool,
}
impl LoveRecordNFT {
#[ink(constructor)]
pub fn new() -> Self {
Self {
records: StorageHashMap::new(),
token_id_counter: Lazy::new(0),
}
}
#[ink(message)]
pub fn create_record(&mut self, subject: Vec<u8>, dimension: Vec<u8>, description: Vec<u8>) -> u64 {
let token_id = *self.token_id_counter;
let record = Record {
subject,
dimension,
description,
is_approved: false,
};
self.records.insert(token_id, record);
*self.token_id_counter += 1;
token_id
}
#[ink(message)]
pub fn approve_record(&mut self, token_id: u64) {
if let Some(record) = self.records.get_mut(&token_id) {
record.is_approved = true;
}
}
#[ink(message)]
pub fn get_record(&self, token_id: u64) -> Option<(Vec<u8>, Vec<u8>, Vec<u8>, bool)> {
if let Some(record) = self.records.get(&token_id) {
Some((
record.subject.clone(),
record.dimension.clone(),
record.description.clone(),
record.is_approved,
))
} else {
None
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[ink::test]
fn create_and_approve_record_works() {
let mut contract = LoveRecordNFT::new();
let token_id = contract.create_record(
b"subject".to_vec(),
b"dimension".to_vec(),
b"description".to_vec(),
);
assert_eq!(contract.get_record(token_id), Some((b"subject".to_vec(), b"dimension".to_vec(), b"description".to_vec(), false)));
contract.approve_record(token_id);
assert_eq!(contract.get_record(token_id), Some((b"subject".to_vec(), b"dimension".to_vec(), b"description".to_vec(), true)));
}
}
}
このスマートコントラクトでは、LoveRecordNFTというコントラクトが作成され、create_record関数で新しいNFTを作成し、approve_record関数でNFTを承認し、get_record関数でNFTの情報を取得できる。これにより、ブロックチェーン上でNFTを作成、管理、取引するための基盤が提供される。
-
NFTの発行:
- ブロックチェーンSNS上で、ユーザーが「愛の行動」を報告した際、その情報はスマートコントラクトに送信される。
- ブロックチェーン上でスマートコントラクトが実行され、指定された条件(例: レベル7の「瞑想し無意識になる」行動)が満たされると、NFTが発行される。
- NFTには、その特定の行動に関する詳細情報(レベル、次元、内容など)が含まれ、それが非代替性トークンとして取引可能である。
以下は、rustで記載された上記のスマートコントラクトを含むブロックチェーンのプログラム例である。
use std::collections::HashMap;
use std::time::{SystemTime, UNIX_EPOCH};
use sha2::{Sha256, Digest};
use rand::seq::SliceRandom;
use ink_lang as ink;
#[ink::contract]
mod love_record_nft {
#[cfg(not(feature = "ink-as-dependency"))]
use ink_storage::{
collections::HashMap as StorageHashMap,
lazy::Lazy,
};
use ink_env::AccountId;
#[derive(Debug, PartialEq, Eq, scale::Encode, scale::Decode)]
pub struct Record {
subject: Vec<u8>,
dimension: Vec<u8>,
description: Vec<u8>,
is_approved: bool,
}
#[ink(storage)]
pub struct LoveRecordNFT {
records: StorageHashMap<u64, Record>,
token_id_counter: Lazy<u64>,
}
impl LoveRecordNFT {
#[ink(constructor)]
pub fn new() -> Self {
Self {
records: StorageHashMap::new(),
token_id_counter: Lazy::new(0),
}
}
#[ink(message)]
pub fn create_record(&mut self, subject: Vec<u8>, dimension: Vec<u8>, description: Vec<u8>) -> u64 {
let token_id = *self.token_id_counter;
let record = Record {
subject,
dimension,
description,
is_approved: false,
};
self.records.insert(token_id, record);
*self.token_id_counter += 1;
token_id
}
#[ink(message)]
pub fn approve_record(&mut self, token_id: u64) {
if let Some(record) = self.records.get_mut(&token_id) {
record.is_approved = true;
}
}
#[ink(message)]
pub fn get_record(&self, token_id: u64) -> Option<(Vec<u8>, Vec<u8>, Vec<u8>, bool)> {
if let Some(record) = self.records.get(&token_id) {
Some((
record.subject.clone(),
record.dimension.clone(),
record.description.clone(),
record.is_approved,
))
} else {
None
}
}
}
}
use std::fmt;
use ink_env::AccountId;
struct Wallet {
address: AccountId,
balance: f64,
}
impl Wallet {
fn new(address: AccountId) -> Wallet {
Wallet {
address,
balance: 0.0,
}
}
fn add_balance(&mut self, amount: f64) {
self.balance += amount;
}
fn subtract_balance(&mut self, amount: f64) {
if self.balance >= amount {
self.balance -= amount;
} else {
panic!("Insufficient balance");
}
}
}
struct Transaction {
transaction_id: String,
sender: AccountId,
receiver: AccountId,
timestamp: String,
location: String,
love_action_level: i32,
amount: f64,
action_content: String,
approval_target: AccountId,
zero_knowledge_proof: Option<String>,
sender_dimension: i32,
receiver_dimension: i32,
validators: Vec<AccountId>,
}
impl Transaction {
fn new(sender: AccountId, receiver: AccountId, location: String, love_action_level: i32, action_content: String, sender_dimension: i32, receiver_dimension: i32, approver: AccountId, approver_dimension: i32) -> Transaction {
Transaction {
transaction_id: format!("{:x}", Sha256::digest(rand::thread_rng().gen::<[u8; 32]>().as_ref())),
sender,
receiver,
timestamp: format!("{:?}", SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs()),
location,
love_action_level,
amount: 0.0,
action_content,
approval_target: approver,
zero_knowledge_proof: None,
sender_dimension,
receiver_dimension,
validators: vec![],
}
}
fn generate_proof_of_place(&self) -> String {
format!("Transaction {}'s proof of place has been generated: {}", self.transaction_id, self.location)
}
fn generate_proof_of_history(&self) -> String {
format!("Transaction {}'s proof of history has been generated: {}", self.transaction_id, self.timestamp)
}
fn generate_zero_knowledge_proof(&mut self) {
let n = 499 * 547; // Replace with actual calculation
let g = 2; // Replace with actual calculation
let m = rand::thread_rng().gen_range(1, n);
let c = (g.pow(m as u32) % n) * (g.pow(n as u32) % n) % n;
self.zero_knowledge_proof = Some(format!("{},{},{}", n, g, c));
}
fn transfer_token(&self, love_currency: &str) {
println!("Token transfer: {} token transferred from {:?} to {:?} in
LoveRecordNFTコントラクトは、Record構造体を保持するストレージと、NFTのトークンIDを管理するtoken_id_counterを持っている。create_recordメソッドは新しいレコードを作成し、approve_recordメソッドはレコードを承認し、get_recordメソッドは指定されたトークンIDのレコード情報を取得する。このコントラクトは、インク言語のフレームワークを使用して実装されており、Substrate上で実行することができる。ブロックチェーン上でNFTを作成、管理、取引するための基盤として使用することができる。インク言語は、Substrate上でスマートコントラクトを実装するための専用の言語であり、Rust言語のフレームワークとして提供されている。インク言語を使用することで、Substrateの機能や特性に最適化されたスマートコントラクトを簡単に作成できる。インク言語は、Solidityなどの他のスマートコントラクト言語とは異なる構文や特性を持っているが、これはSubstrateの設計思想や機能に合わせて設計されている。
-
ブロックチェーンSNSとの連携:
- ブロックチェーンSNS上でのユーザーアクションや「愛の行動」が、スマートコントラクトによってブロックチェーン上に透明かつ不変的に記録される。
- ユーザーは、自身が行った「愛の行動」に基づくNFTを所有し、他のユーザーとこれをやりとりできるようになることで、愛の行動を受け取る相手への送信する。
- ブロックチェーンSNS上でのNFTの所有権や取引履歴は、分散型台帳により確認可能で、透明性が保たれる。
このようにして、スマートコントラクトとブロックチェーンSNSが連携し、愛記システムがDAppsとして機能する。
-
DAppsでの仕訳結果の表示:
- ブロックチェーンSNSにリンクしたDAppsは、スマートコントラクトの状態を参照して、仕訳結果をユーザーに表示できる。
- ユーザーはDAppsを通じて、自身の行動や他のユーザーの行動に関する情報を透明かつリアルタイムに確認できる。
-
仕訳結果に基づくサービス提供や評価:
- スマートコントラクトが特定の条件を満たす仕訳結果に基づいて、サービス提供や評価の処理が行われることもある。
- 例えば、一定の愛の行動がある程度のレベルに達した場合に、市町村の税減免サービスが提供されるような仕組みを構築できる。
このような仕組みを通じて、愛記システムはブロックチェーンSNS上でのユーザーの行動を透明かつ信頼性のある形で処理し、DAppsを介してユーザーに結果を表示する。これにより、分散型アプリケーションとしての愛記システムが成り立つ。
上記のDApps側のプログラムに、音声入力からの上記の情報を処理するプログラムも入れて欲しいと思うだろう。というのも、音声入力は、chatGTPの音声モードをユーザーのフロント画面に用意しておき、そこから音声で、「”愛記システム”を立ち上げ、科目は、Lv7:”瞑想し無意識になる”を選択し、次元は、”8次元:人類”を選択し、内容は、”心が安らぐ”と記載し、”NFT化”して!」という。これをNFT化して、ユーザーのフロント画面に表示して、この内容でよろしければ、相手に送信しますがよろしいですか?というポップアップ画面をだし、ユーザーがOKボタンを押すと、NFTが上記のフェデレーションモデルであるブロックチェーンに送信されて処理されるという具合に。以下は、DAppsのバックエンド側のプログラムである。
fn process_voice_input(input: &str) -> Result<(String, String, String, String), String> {
let parts: Vec<&str> = input.split(':').collect();
if parts.len() < 5 {
return Err("Invalid input format".to_string());
}
let system_name = parts[0].trim();
let subject = parts[1].trim();
let dimension = parts[3].trim();
let description = parts[4].trim();
Ok((system_name.to_string(), subject.to_string(), dimension.to_string(), description.to_string()))
}
fn create_nft_and_confirm(system_name: &str, subject: &str, dimension: &str, description: &str) -> bool {
// NFTを作成する処理
// ユーザーに確認を求める処理
let confirmation = format!(
"{}を立ち上げ、科目は、{}を選択し、次元は、{}を選択し、内容は、{}と記載し、NFT化して!\n\nこの内容でよろしければ、相手に送信しますか?",
system_name, subject, dimension, description
);
let user_confirmation = get_user_confirmation(confirmation);
user_confirmation
}
fn send_nft_to_blockchain(system_name: &str, subject: &str, dimension: &str, description: &str) {
// ブロックチェーンにNFTを送信する処理
println!("NFTをブロックチェーンに送信しました。");
}
fn get_user_confirmation(confirmation_message: String) -> bool {
// ポップアップ画面を表示してユーザーに確認を求める処理
// ユーザーがOKボタンを押したかどうかを返す
true // 仮の返り値
}
fn main() {
// 音声入力を受け取る
let voice_input = "愛記システム:Lv7:瞑想し無意識になる:8次元:人類:心が安らぐ".to_string();
// 音声入力を解析して情報を取得
match process_voice_input(&voice_input) {
Ok((system_name, subject, dimension, description)) => {
// NFTを作成し、ユーザーに確認を求める
if create_nft_and_confirm(&system_name, &subject, &dimension, &description) {
// ユーザーが承認した場合、NFTをブロックチェーンに送信
send_nft_to_blockchain(&system_name, &subject, &dimension, &description);
} else {
println!("ユーザーがNFTの送信をキャンセルしました。");
}
}
Err(err) => {
println!("音声入力の解析中にエラーが発生しました: {}", err);
}
}
}
このプログラムは、以下のような関係性を持っている:
・Voice Input Processing(音声入力の処理): process_voice_input関数は、音声入力を受け取り、特定のフォーマットで分割してシステム名、科目、次元、内容を取得する。
・NFT Creation and Confirmation(NFTの作成と確認): create_nft_and_confirm関数は、取得した情報を元にNFTを作成し、ユーザーに確認を求める。確認メッセージは特定のフォーマットで作成され、ユーザーが承認するとtrueを返す。
・Sending NFT to Blockchain(NFTをブロックチェーンに送信): send_nft_to_blockchain関数は、ユーザーがNFTの作成を承認した場合に、取得した情報を元にNFTをブロックチェーンに送信する。
・User Confirmation(ユーザーの確認): get_user_confirmation関数は、ポップアップ画面を表示してユーザーに確認を求め、ユーザーがOKボタンを押したかどうかを返す。
・Main Function(メイン関数): main関数では、音声入力を解析し、情報を取得した後、NFTの作成と送信を行うかどうかを判断する。解析中にエラーが発生した場合はエラーメッセージを表示する。
いかがであろうか、このような自動処理は、必須になってくる。いちいち手入力で仕訳科目を選択し、愛の行動レベルを選択し、とやっていては面倒くさい。自動処理で1ステップで出来るようになれば、普及もしていくだろう。