IPFS - merkle-link
IPFS IPLD - merkle-link
merkle-link 는 두 객체를 연결하는 방법입니다. 대상 객체와 원본 객체는 암호화 된 해시의 내용을 사용하여 주소 지정됩니다. 동시에 대상 객체의 해시도 소스 객체에 포함됩니다. merkle-link 를 통한 콘텐츠 주소 지정은 다음을 수행 할 수 있습니다.
- 암호화 무결성 검사: Resolver 된 링크의 값은 해시로 테스트 할 수 있습니다. 이렇게하면 해시를 통해 링크되지 않은 데이터를 다른 사용자에게 줄 수 없기 때문에 git 또는 bittorrent 와 같이 광범위하고 안전한 신뢰할 수없는 데이터 교환이 가능합니다.
- 변경 불가능한 데이터 구조: merkle 링크가 있는 데이터 구조는 변경 될 수 없으며 분산 시스템의 중요한 속성입니다. 이는 분산 변수 상태 (예 : CRDT) 및 장기 아카이브를 의미하는 버전 제어에 유용합니다.
merkle-link 는 다음 IPLD 객체 모델로 표현됩니다: “link value” 포함/매핑, 예:
링크는 json 에서 “link object” 로 표현 될 수 있습니다.
{
"/" : "/ipfs/QmUmg7BZC1YP1ca66rRtWKxpXp77WgVHrnv263JtDuvs2k"
}
// "/"는 링크 키입니다.
// "/ipfs/QmUmg7BZC1YP1ca66rRtWKxpXp77WgVHrnv263JtDuvs2k" 링크 값입니다.
foo/baz 에 링크가 있는 객체:
{
"foo": {
"bar": "/ipfs/QmUmg7BZC1YP1ca66rRtWKxp77WgVHrnv263JtDuvs2k", // 링크가 아닙니다.
"baz": {"/": "/ipfs/QmUmg7BZC11ca66rRtWKxpXp77WgVHrnv263JtDuvs2k"} // 링크
}
}
다음 구조에서는 files/cat.jpg 에 또 다른 가상 “link object” 가 있으며 실제 링크는 files/cat.jpg/link 에 있습니다.
{
"files": {
"cat.jpg": { // 링크 된 속성은 다른 객체에 포함됩니다.
"link": {
"/": "/ipfs/QmUmg7BZC1YP1ca66rRtWKxpXp77WgVHrnv263JtDuvs2k"}, // 링크
"mode": 0755,
"owner": "jbenet"
}
}
}
링크가 수정되어 링크 경로가 유효하지 않으면 맵 자체가 오브젝트로 바뀝니다.
이 링크는 멀티 허브 일 수 있습니다. 즉, 링크는 /ipfs 레벨 또는 객체의 절대 경로에 있다고 가정합니다. 그러나 현재 /ipfs 계층 경로만 사용할 수 있습니다.
응용 프로그램이 / 를 사용하여 다른 내용을 나타내야 할 경우 응용 프로그램 자체에서 해상도가 충돌하지 않도록해야 합니다.
IPFS - ipld
IPFS Application 계층 - IPLD
많은 대중적인 시스템 (git, bittorrent, ipfs, tahoe-lafs, sfsro) 이 merkle-tree 와 해시 링크 관련된 데이터 구조를 사용합니다. IPLD (Inter Planetary Linked Data) 는 다음과 같은 개념을 정의합니다:
- merkle-links: merkle-graph 의 핵심 단위
- merkle-dag: merkle-links 의 지도
- merkle-paths: 유닉스 스타일 경로는 merkle-dag 를 쉽게 탐색 할 수 있음
- IPLD Data Model: merkle-dag 를 표현하기위한 유연한 JSON 기반 데이터 모델
- IPLD Serialized Formats: JSON, CBOR, CSON, YAML, Protobuf, XML, RDF 등과 같이 IPLD 객체가 사용할 수 있는 형식의 목록
- IPLD 신뢰형식: 데이터에 대해 동일한 해석 논리를 보장하는 시퀀스 형식에 대한 명확한 설명으로 merkle-link 및 기타 암호화 응용 프로그램에 중요
요약하면: IPLD 는 merkle-link 가 통과 할 수있는 JSON 파일 객체입니다.
IPLD 의 구성 요소는 다음 그림과 같이 구성됩니다. CID, IPLD 트리, IPLD Resolver.
IPFS - multistream
IPFS Multiformats - multistream
multistream 은 multicodec 을 사용하여 자가 기술 함수를 구현합니다. 다음은 자바 스크립트를 기반으로 한 예제입니다. 첫째, 내부에 json 객체인 새로운 버퍼 객체를 작성한 다음 protobuf 접두어를 지정하여 multistream 을 구성하고 네트워크를 통해 전송할 수 있도록 합니다. 구문 분석에서 먼저 코덱 접두어를 취한 다음 접두사를 제거하여 특정 데이터 컨텐츠를 가져올 수 있습니다.
// encode some json
const buf = new Buffer(JSON.stringify({ hello: 'world' }))
const prefixedBuf = multistream.addPrefix('json', str) // prepends multicodec ('json')
console.log(prefixedBuf)
// <Buffer 06 2f 6a 73 6f 6e 2f 7b 22 68 65 6c 6c 6f 22 3a 22 77 6f 72 6c 64 22 7d>
const.log(prefixedBuf.toString('hex'))
// 062f6a736f6e2f7b2268656c6c6f223a22776f726c64227d
// let's get the Codec and then get the data back
const codec = multicodec.getCodec(prefixedBuf)
console.log(codec)
// json
console.log(multistream.rmPrefix(prefixedBuf).toString())
// "{ \"hello\": \"world\" }
결과 출력:
hex: 062f6a736f6e2f7b2268656c6c6f223a22776f726c64227d
ascii: /json\n"{\"hello\":\"world\"}"
1. 멀티 스트림 소스 코드 분석
소스 경로: src\github.com\multiformats\go-multistream\multistream.go
go-multistream 설치
get github.com/multiformats/go-multistream
멀티플렉서를 사용하여 사용자가 다른 “프로토콜”을 처리 할 수 있는 핸들러를 추가 할 수 있습니다:
package main
import (
"fmt"
"io"
"io/ioutil"
"net"
ms "github.com/multiformats/go-multistream"
)
// 사용되지 않는 프로토콜에 대한 다른 핸들러를 작성하기 위해 멀티플렉서를 작성
// "/cats" 및 "/docs" 두 가지 프로토콜을 만듭니다.
func main() {
mux := ms.NewMultistreamMuxer()
mux.AddHandler("/cats", func(proto string, rwc io.ReadWriteCloser) error {
fmt.Fprintln(rwc, proto, ": HELLO I LIKE CATS")
return rwc.Close()
})
mux.AddHandler("/dogs", func(proto string, rwc io.ReadWriteCloser) error {
fmt.Fprintln(rwc, proto, ": HELLO I LIKE DOGS")
return rwc.Close()
})
list, err := net.Listen("tcp", ":8765")
if err != nil {
panic(err)
}
go func() {
for {
con, err := list.Accept()
if err != nil {
panic(err)
}
go mux.Handle(con)
}
}()
// 테스트 시작
conn, err := net.Dial("tcp", ":8765")
if err != nil {
panic(err)
}
// /cats 프로토콜
mstream := ms.NewMSSelect(conn, "/cats")
cats, err := ioutil.ReadAll(mstream)
if err != nil {
panic(err)
}
fmt.Printf("%s", cats)
mstream.Close()
conn, err = net.Dial("tcp", ":8765")
if err != nil {
panic(err)
}
defer conn.Close()
// /dogs 프로토콜
err = ms.SelectProtoOrFail("/dogs", conn)
if err != nil {
panic(err)
}
dogs, err := ioutil.ReadAll(conn)
if err != nil {
panic(err)
}
fmt.Printf("%s", dogs)
conn.Close()
}
확인 테스트는 아래와 같이 수행합니다.
$ go run multistream.go
/cats :HELLO I LIKE CATS
/dogs :HELLO I LIKE DOGS
IPFS - multicodec
IPFS Multiformats - multicodec
multicodec 은 자가 기술 형식을 포함하는 자가 기술 코덱입니다. multicodec 식별자는 varint 입니다. 실제로 base58 btc 인코딩의 경우 z, protobuf 의 경우 0x50 등과 같이 데이터 내용의 형식을 결정하기 위한 1-2 바이트가 있는 테이블입니다.
이는 https://github.com/multiformats/multicodec/blob/master/table.csv 에서 볼 수 있습니다.
multicodec 으로 식별되는 많은 양의 데이터는 다음과 같습니다.
<multicodec><encoded-data>
# 생략할 수 있음:
<mc><data>
또 다른 유용한 시나리오는 multicodec 을 키 액세스의 일부로 사용하는 것입니다. 예를 들면 다음과 같습니다.
# suppose we have a value and a key to retrieve it
"<key>" -> <value>
# we can use multicodec with the key to know what codec the value is in
"<mc><key>" -> <value>
multicodec 은 multihash 및 multiaddr 과 잘 작동하며 여러 코드를 사용하여 이 값 앞에 접두어를 붙이면 자신이 무엇인지 알 수 있습니다.
IPFS - multibase
IPFS Multiformats - multibase
multibase 는 데이터를 다른 형식으로 인코딩하는 데 편리한 인코딩 형식을 나타냅니다. 예를 들어 2 진수, 8 진수, 10 진수, 16 진수 및 base58btc, base64 인코딩으로 생각할 수 있습니다.
지원되는 인코딩 형식은 다음과 같습니다.
Multibase Table v1.0.0-RC (semver)
encoding codes name
identity 0x00 8-bit binary (encoder and decoder keeps data unmodified)
base1 1 unary tends to be 11111
base2 0 binary has 1 and 0
base8 7 highest char in octal
base10 9 highest char in decimal
base16 F, f highest char in hex
base32 B, b rfc4648 - no padding - highest letter
base32pad C, c rfc4648 - with padding
base32hex V, v rfc4648 - no padding - highest char
base32hexpad T, t rfc4648 - with padding
base32z h z-base-32 - used by Tahoe-LAFS - highest letter
base58flickr Z highest char
base58btc z highest char
base64 m rfc4648 - no padding
base64pad M rfc4648 - with padding - MIME encoding
base64url u rfc4648 - no padding
base64urlpad U rfc4648 - with padding
1. multibase 형식
<varint-base-encoding-code><base-encoded-data>
- varint-base-encoding-code: 인코딩 형식 (위의 내용 참조)
- base-encoded-data: 데이터
예:
4D756C74696261736520697320617765736F6D6521205C6F2F # base16 (hex)
JV2WY5DJMJQXGZJANFZSAYLXMVZW63LFEEQFY3ZP # base32
YAjKoNbau5KiqmHPmSxYCvn66dA1vLmwbt # base58
TXVsdGliYXNlIGlzIGF3ZXNvbWUhIFxvLw== # base64
F4D756C74696261736520697320617765736F6D6521205C6F2F # base16 F
BJV2WY5DJMJQXGZJANFZSAYLXMVZW63LFEEQFY3ZP # base32 B
zYAjKoNbau5KiqmHPmSxYCvn66dA1vLmwbt # base58 z
MTXVsdGliYXNlIGlzIGF3ZXNvbWUhIFxvLw== # base64 M
시작되는 알파벳은 다음과 같습니다: F, B, z, M
2. multibase 설치
Golang 을 사용하여 multibase 를 사용합니다.
multibase 설치는 다음을 사용합니다.
go get github.com/multiformats/go-multibase
multiaddr 패키지는 패키지 gx 에 의존하기 때문에 multiaddr 을 사용하려면 다음이 필요합니다.
go get -u github.com/whyrusleeping/gx
go get -u github.com/whyrusleeping/gx-go
cd <your-project-repository>
gx init
gx import github.com/multiformats/go-multibase
gx install --global
gx-go --rewrite
3. multibase 설치 및 사용
원본 경로: src\github.com\multiformats\go-multibase\multibase.go
기본 인코딩 테이블:
// specified in standard are left out
var Encodings = map[string]Encoding{
"identity": 0x00,
"base16": 'f',
"base16upper": 'F',
"base32": 'b',
"base32upper": 'B',
"base32pad": 'c',
"base32padupper": 'C',
"base32hex": 'v',
"base32hexupper": 'V',
"base32hexpad": 't',
"base32hexpadupper": 'T',
"base58flickr": 'Z',
"base58btc": 'z',
"base64": 'm',
"base64url": 'u',
"base64pad": 'M',
"base64urlpad": 'U',
}
코드:
// Encode encodes a given byte slice with the selected encoding and returns a
// multibase string (<encoding><base-encoded-string>). It will return
// an error if the selected base is not known.
func Encode(base Encoding, data []byte) (string, error)
설치 확인 테스트는 아래와 같이 수행합니다.
// Decode takes a multibase string and decodes into a bytes buffer.
// It will return an error if the selected base is not known.
func Decode(data string) (Encoding, []byte, error)