Substrate에서 파일의 존재 증명
7319 단어 SubstrateBlockchainRust
개요
Substrate에서 파일의 존재 증명 및 개조되지 않았는지 확인할 수 있는 것을 만듭니다.
NEM의 아포스티유와 같습니다.
아포스티유에 대한 자세한 내용은 여기
Substrate란?
블록체인 프레임워크입니다. 자세한 내용은 아래를 참조하십시오.
What is Substrate | Parity Technologies |
설정
실행 환경은 mac입니다.
먼저 npm과 node가 설치되어 있어야 합니다.
다음 명령으로 Substrate가 실행할 수 있는 환경을 만듭니다.
Rust 등이 설치됩니다.
$ curl https://getsubstrate.io -sSf | bash
커피를 마시면서 기다립니다.
완료되면 Substrate 노드 템플릿을 만듭니다.
$ substrate-node-new receiptchain junki
$ cd receiptchain
receiptchain은 프로젝트 이름이고 junki는 자신의 이름을 넣을 수 있습니다.
다시 커피를 마시자.
파일 편집
runtime/src 이하에 receiptchain.rs를 작성합니다.
receiptchain.rs를 다음과 같이 편집합니다.
receiptchain.rsuse support::{decl_storage, decl_module, StorageValue, StorageMap, dispatch::Result, ensure, decl_event};
use system::ensure_signed;
use parity_codec::{Encode, Decode};
use rstd::vec::Vec;
const BYTEARRAY_LIMIT: usize = 3000000;
#[derive(Encode, Decode, Default, Clone, PartialEq)]
#[cfg_attr(feature = "std", derive(Debug))]
pub struct Receipt<AccountId, Moment> {
id: u64,
owner: AccountId,
timestamp: Moment
}
pub trait Trait: timestamp::Trait + balances::Trait {
type Event: From<Event<Self>> + Into<<Self as system::Trait>::Event>;
}
decl_event!(
pub enum Event<T> where
<T as system::Trait>::AccountId,
<T as timestamp::Trait>::Moment,
{
ReceiptCreated(AccountId, Moment),
}
);
decl_storage! {
trait Store for Module<T: Trait> as ReceiptStorage {
Receipts get(receipt): map Vec<u8> => Receipt<T::AccountId, T::Moment>;
Nonce: u64;
}
}
decl_module! {
pub struct Module<T: Trait> for enum Call where origin: T::Origin {
fn deposit_event<T>() = default;
fn create_receipt(origin, hash: Vec<u8>) -> Result {
ensure!(hash.len() <= BYTEARRAY_LIMIT, "Bytearray is too large");
let sender = ensure_signed(origin)?;
let nonce = <Nonce<T>>::get();
ensure!(!<Receipts<T>>::exists(&hash), "This receipt has already been registered");
let time = <timestamp::Module<T>>::now();
let new_receipt = Receipt {
id: nonce,
owner: sender.clone(),
timestamp: time.clone()
};
<Receipts<T>>::insert(hash, new_receipt);
<Nonce<T>>::mutate(|n| *n += 1);
Self::deposit_event(RawEvent::ReceiptCreated(sender, time));
Ok(())
}
}
}
Substrate는 String
를 지원하지 않습니다.
체인에 데이터를 얹을 때는 바이트열로 해 둡시다.
덧붙여서 여기서 사용하고 있는 형태 Vec<u8>
는 바이트열입니다.
런타임 업데이트
블록체인 프레임워크입니다. 자세한 내용은 아래를 참조하십시오.
What is Substrate | Parity Technologies |
설정
실행 환경은 mac입니다.
먼저 npm과 node가 설치되어 있어야 합니다.
다음 명령으로 Substrate가 실행할 수 있는 환경을 만듭니다.
Rust 등이 설치됩니다.
$ curl https://getsubstrate.io -sSf | bash
커피를 마시면서 기다립니다.
완료되면 Substrate 노드 템플릿을 만듭니다.
$ substrate-node-new receiptchain junki
$ cd receiptchain
receiptchain은 프로젝트 이름이고 junki는 자신의 이름을 넣을 수 있습니다.
다시 커피를 마시자.
파일 편집
runtime/src 이하에 receiptchain.rs를 작성합니다.
receiptchain.rs를 다음과 같이 편집합니다.
receiptchain.rsuse support::{decl_storage, decl_module, StorageValue, StorageMap, dispatch::Result, ensure, decl_event};
use system::ensure_signed;
use parity_codec::{Encode, Decode};
use rstd::vec::Vec;
const BYTEARRAY_LIMIT: usize = 3000000;
#[derive(Encode, Decode, Default, Clone, PartialEq)]
#[cfg_attr(feature = "std", derive(Debug))]
pub struct Receipt<AccountId, Moment> {
id: u64,
owner: AccountId,
timestamp: Moment
}
pub trait Trait: timestamp::Trait + balances::Trait {
type Event: From<Event<Self>> + Into<<Self as system::Trait>::Event>;
}
decl_event!(
pub enum Event<T> where
<T as system::Trait>::AccountId,
<T as timestamp::Trait>::Moment,
{
ReceiptCreated(AccountId, Moment),
}
);
decl_storage! {
trait Store for Module<T: Trait> as ReceiptStorage {
Receipts get(receipt): map Vec<u8> => Receipt<T::AccountId, T::Moment>;
Nonce: u64;
}
}
decl_module! {
pub struct Module<T: Trait> for enum Call where origin: T::Origin {
fn deposit_event<T>() = default;
fn create_receipt(origin, hash: Vec<u8>) -> Result {
ensure!(hash.len() <= BYTEARRAY_LIMIT, "Bytearray is too large");
let sender = ensure_signed(origin)?;
let nonce = <Nonce<T>>::get();
ensure!(!<Receipts<T>>::exists(&hash), "This receipt has already been registered");
let time = <timestamp::Module<T>>::now();
let new_receipt = Receipt {
id: nonce,
owner: sender.clone(),
timestamp: time.clone()
};
<Receipts<T>>::insert(hash, new_receipt);
<Nonce<T>>::mutate(|n| *n += 1);
Self::deposit_event(RawEvent::ReceiptCreated(sender, time));
Ok(())
}
}
}
Substrate는 String
를 지원하지 않습니다.
체인에 데이터를 얹을 때는 바이트열로 해 둡시다.
덧붙여서 여기서 사용하고 있는 형태 Vec<u8>
는 바이트열입니다.
런타임 업데이트
$ curl https://getsubstrate.io -sSf | bash
$ substrate-node-new receiptchain junki
$ cd receiptchain
runtime/src 이하에 receiptchain.rs를 작성합니다.
receiptchain.rs를 다음과 같이 편집합니다.
receiptchain.rs
use support::{decl_storage, decl_module, StorageValue, StorageMap, dispatch::Result, ensure, decl_event};
use system::ensure_signed;
use parity_codec::{Encode, Decode};
use rstd::vec::Vec;
const BYTEARRAY_LIMIT: usize = 3000000;
#[derive(Encode, Decode, Default, Clone, PartialEq)]
#[cfg_attr(feature = "std", derive(Debug))]
pub struct Receipt<AccountId, Moment> {
id: u64,
owner: AccountId,
timestamp: Moment
}
pub trait Trait: timestamp::Trait + balances::Trait {
type Event: From<Event<Self>> + Into<<Self as system::Trait>::Event>;
}
decl_event!(
pub enum Event<T> where
<T as system::Trait>::AccountId,
<T as timestamp::Trait>::Moment,
{
ReceiptCreated(AccountId, Moment),
}
);
decl_storage! {
trait Store for Module<T: Trait> as ReceiptStorage {
Receipts get(receipt): map Vec<u8> => Receipt<T::AccountId, T::Moment>;
Nonce: u64;
}
}
decl_module! {
pub struct Module<T: Trait> for enum Call where origin: T::Origin {
fn deposit_event<T>() = default;
fn create_receipt(origin, hash: Vec<u8>) -> Result {
ensure!(hash.len() <= BYTEARRAY_LIMIT, "Bytearray is too large");
let sender = ensure_signed(origin)?;
let nonce = <Nonce<T>>::get();
ensure!(!<Receipts<T>>::exists(&hash), "This receipt has already been registered");
let time = <timestamp::Module<T>>::now();
let new_receipt = Receipt {
id: nonce,
owner: sender.clone(),
timestamp: time.clone()
};
<Receipts<T>>::insert(hash, new_receipt);
<Nonce<T>>::mutate(|n| *n += 1);
Self::deposit_event(RawEvent::ReceiptCreated(sender, time));
Ok(())
}
}
}
Substrate는
String
를 지원하지 않습니다.체인에 데이터를 얹을 때는 바이트열로 해 둡시다.
덧붙여서 여기서 사용하고 있는 형태
Vec<u8>
는 바이트열입니다.런타임 업데이트
mod receiptchain;
넣기 lib.rs
...
pub type Hash = primitives::H256;
/// Index of a block number in the chain.
pub type BlockNumber = u64;
/// Index of an account's extrinsic in the chain.
pub type Nonce = u64;
mod receiptchain;
...
impl receiptchain::Trait for Runtime {
type Event = Event;
}
넣기 lib.rs
...
impl sudo::Trait for Runtime {
/// The uniquitous event type.
type Event = Event;
type Proposal = Call;
}
impl receiptchain::Trait for Runtime {
type Event = Event;
}
...
construct_runtime!
안에 module을 선언한다. lib.rs
construct_runtime!(
pub enum Runtime with Log(InternalLog: DigestItem<Hash, AuthorityId, AuthoritySignature>) where
Block = Block,
NodeBlock = opaque::Block,
UncheckedExtrinsic = UncheckedExtrinsic
{
System: system::{default, Log(ChangesTrieRoot)},
Timestamp: timestamp::{Module, Call, Storage, Config<T>, Inherent},
Consensus: consensus::{Module, Call, Storage, Config<T>, Log(AuthoritiesChange), Inherent},
Aura: aura::{Module},
Indices: indices,
Balances: balances,
Sudo: sudo,
Receiptchain: receiptchain::{Module, Call, Storage, Event<T>},
}
);
움직이다
$ ./scripts/build.sh //build wasm
$ cargo build --release //build binary
$ ./target/release/receiptchain --dev //start node
체인의 모든 데이터를 삭제하고 블록 생성을 시작하려면 다음 명령을 실행합니다.
./target/release/receiptchain purge-chain --dev
이런 식으로 블록 생성이 시작됩니다.

PolkadotJS-UI로 동작 확인
PolkadotJS-UI 를 엽니다.
Setting
의 remote node 를 Local Node (127.0.0.1:9944)
로 하여 Save&reload 합니다.

그런 다음 Setting
의 Developer
섹션에서 페이지가 올바르게 디코딩되도록 구조체를 설정합니다.

{
"Receipt": {
"id": "u64",
"owner": "H256",
"timestamp": "u64"
}
}
그런 다음 Extrinsics
로 이동하여 함수를 실행합니다.

Alice가 토큰을 가지고 있어야하므로 Alice에서 실행합니다.
hash: Bytes 옆의 문서 표시를 클릭하고 원하는 파일을 선택합니다.
그리고 Sign&Submit합니다.

그런 다음 Chain State
로 이동하여 receitStorage/receipt(Bytes):Receipt
를 선택합니다.
그리고 방금 선택한 파일을 다시 선택하고 + 마크를 클릭합니다.

그러면 등록한 정보가 표시됩니다.
이때 등록시에 선택한 파일과는 다른 파일을 선택했을 경우, 또는 파일의 내용이 변경되어 있던 경우는 이렇게 되돌아옵니다.

마지막으로
Substrate는 버전의 변경이 많기 때문에 위의 코드가 움직이지 않는 경우가 있으므로 주의해 주십시오.
Reference
이 문제에 관하여(Substrate에서 파일의 존재 증명), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/YuasaJunki/items/21295a8992bc4688a21a
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
$ ./scripts/build.sh //build wasm
$ cargo build --release //build binary
$ ./target/release/receiptchain --dev //start node
./target/release/receiptchain purge-chain --dev
PolkadotJS-UI 를 엽니다.
Setting
의 remote node 를 Local Node (127.0.0.1:9944)
로 하여 Save&reload 합니다.
그런 다음
Setting
의 Developer
섹션에서 페이지가 올바르게 디코딩되도록 구조체를 설정합니다.
{
"Receipt": {
"id": "u64",
"owner": "H256",
"timestamp": "u64"
}
}
그런 다음
Extrinsics
로 이동하여 함수를 실행합니다.
Alice가 토큰을 가지고 있어야하므로 Alice에서 실행합니다.
hash: Bytes 옆의 문서 표시를 클릭하고 원하는 파일을 선택합니다.
그리고 Sign&Submit합니다.

그런 다음
Chain State
로 이동하여 receitStorage/receipt(Bytes):Receipt
를 선택합니다.그리고 방금 선택한 파일을 다시 선택하고 + 마크를 클릭합니다.

그러면 등록한 정보가 표시됩니다.
이때 등록시에 선택한 파일과는 다른 파일을 선택했을 경우, 또는 파일의 내용이 변경되어 있던 경우는 이렇게 되돌아옵니다.

마지막으로
Substrate는 버전의 변경이 많기 때문에 위의 코드가 움직이지 않는 경우가 있으므로 주의해 주십시오.
Reference
이 문제에 관하여(Substrate에서 파일의 존재 증명), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/YuasaJunki/items/21295a8992bc4688a21a
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
Reference
이 문제에 관하여(Substrate에서 파일의 존재 증명), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/YuasaJunki/items/21295a8992bc4688a21a텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)