wip: semi-broken first transition to CIDs
parent
f880a0e38c
commit
ef74c8520f
|
@ -418,6 +418,18 @@ version = "1.0.70"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7de8ce5e0f9f8d88245311066a578d72b7af3e7088f32783804676302df237e4"
|
||||
|
||||
[[package]]
|
||||
name = "arrayref"
|
||||
version = "0.3.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545"
|
||||
|
||||
[[package]]
|
||||
name = "arrayvec"
|
||||
version = "0.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711"
|
||||
|
||||
[[package]]
|
||||
name = "askama_escape"
|
||||
version = "0.10.3"
|
||||
|
@ -460,6 +472,41 @@ version = "2.2.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "24a6904aef64d73cf10ab17ebace7befb918b82164785cb89907993be7f83813"
|
||||
|
||||
[[package]]
|
||||
name = "blake2b_simd"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3c2f0dc9a68c6317d884f97cc36cf5a3d20ba14ce404227df55e1af708ab04bc"
|
||||
dependencies = [
|
||||
"arrayref",
|
||||
"arrayvec",
|
||||
"constant_time_eq",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "blake2s_simd"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6637f448b9e61dfadbdcbae9a885fadee1f3eaffb1f8d3c1965d3ade8bdfd44f"
|
||||
dependencies = [
|
||||
"arrayref",
|
||||
"arrayvec",
|
||||
"constant_time_eq",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "blake3"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "729b71f35bd3fa1a4c86b85d32c8b9069ea7fe14f7a53cfabb65f62d4265b888"
|
||||
dependencies = [
|
||||
"arrayref",
|
||||
"arrayvec",
|
||||
"cc",
|
||||
"cfg-if 1.0.0",
|
||||
"constant_time_eq",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
version = "0.10.4"
|
||||
|
@ -578,6 +625,19 @@ dependencies = [
|
|||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cid"
|
||||
version = "0.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fd94671561e36e4e7de75f753f577edafb0e7c05d6e4547229fdf7938fbcd2c3"
|
||||
dependencies = [
|
||||
"core2",
|
||||
"multibase",
|
||||
"multihash",
|
||||
"serde",
|
||||
"unsigned-varint",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.2.4"
|
||||
|
@ -668,6 +728,12 @@ dependencies = [
|
|||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "constant_time_eq"
|
||||
version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "21a53c0a4d288377e7415b53dcfc3c04da5cdc2cc95c8d5ac178b58f0b861ad6"
|
||||
|
||||
[[package]]
|
||||
name = "convert_case"
|
||||
version = "0.4.0"
|
||||
|
@ -1553,6 +1619,15 @@ dependencies = [
|
|||
"mutate_once",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "keccak"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f6d5ed8676d904364de097082f4e7d240b571b67989ced0240f08b7f966f940"
|
||||
dependencies = [
|
||||
"cpufeatures",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "language-tags"
|
||||
version = "0.3.2"
|
||||
|
@ -1859,10 +1934,14 @@ version = "0.18.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cfd8a792c1694c6da4f68db0a9d707c72bd260994da179e6030a5dcee00bb815"
|
||||
dependencies = [
|
||||
"blake2b_simd",
|
||||
"blake2s_simd",
|
||||
"blake3",
|
||||
"core2",
|
||||
"digest",
|
||||
"multihash-derive",
|
||||
"sha2",
|
||||
"sha3",
|
||||
"unsigned-varint",
|
||||
]
|
||||
|
||||
|
@ -2688,6 +2767,16 @@ dependencies = [
|
|||
"digest",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha3"
|
||||
version = "0.10.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60"
|
||||
dependencies = [
|
||||
"digest",
|
||||
"keccak",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "shadow-rs"
|
||||
version = "0.17.1"
|
||||
|
@ -3205,6 +3294,7 @@ name = "upend-base"
|
|||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"cid",
|
||||
"diesel",
|
||||
"lazy_static",
|
||||
"lexpr",
|
||||
|
|
|
@ -22,6 +22,7 @@ chrono = { version = "0.4", features = ["serde"] }
|
|||
serde = { version = "1.0", features = ["derive"] }
|
||||
lexpr = "0.2.6"
|
||||
|
||||
cid = { version = "0.10.1", features = ["serde"] }
|
||||
multibase = "0.9"
|
||||
multihash = { version = "*", default-features = false, features = [
|
||||
"alloc",
|
||||
|
@ -36,5 +37,6 @@ nonempty = "0.6.0"
|
|||
|
||||
wasm-bindgen = { version = "0.2", optional = true }
|
||||
|
||||
|
||||
[build-dependencies]
|
||||
shadow-rs = "0.17"
|
||||
|
|
|
@ -2,6 +2,7 @@ use crate::error::{AddressComponentsDecodeError, UpEndError};
|
|||
use crate::hash::{b58_decode, b58_encode, AsDigest, AsDigestError, Digest};
|
||||
use serde::de::Visitor;
|
||||
use serde::{de, ser, Deserialize, Deserializer, Serialize, Serializer};
|
||||
use std::convert::TryFrom;
|
||||
use std::fmt;
|
||||
use std::hash::Hash;
|
||||
use std::str::FromStr;
|
||||
|
@ -26,67 +27,88 @@ pub struct AddressComponents {
|
|||
pub c: Option<String>,
|
||||
}
|
||||
|
||||
// multihash SHA2-256
|
||||
/// multihash SHA2-256 code
|
||||
const SHA2_256: u64 = 0x12;
|
||||
// multihash identity
|
||||
/// multihash identity code
|
||||
const IDENTITY: u64 = 0x00;
|
||||
|
||||
// multicodec RAW code
|
||||
const RAW: u64 = 0x55;
|
||||
|
||||
/// multicodec UpEnd UUID code (reserved area)
|
||||
const UP_UUID: u64 = 0x300001;
|
||||
|
||||
/// multicodec UpEnd Attribute code (reserved area)
|
||||
const UP_ATTRIBUTE: u64 = 0x300000;
|
||||
|
||||
/// multicodec URL code (technically `http`)
|
||||
const UP_URL: u64 = 0x01e0;
|
||||
|
||||
pub type LargeCid = cid::CidGeneric<256>;
|
||||
pub type LargeMultihash = multihash::MultihashGeneric<256>;
|
||||
|
||||
impl Address {
|
||||
pub fn encode(&self) -> Result<Vec<u8>, UpEndError> {
|
||||
let hash = match self {
|
||||
Self::Hash(hash) => {
|
||||
LargeMultihash::wrap(SHA2_256, &hash.0).map_err(UpEndError::from_any)?
|
||||
}
|
||||
Self::Uuid(uuid) => {
|
||||
LargeMultihash::wrap(IDENTITY, &[vec![b'U'], uuid.as_bytes().to_vec()].concat())
|
||||
.map_err(UpEndError::from_any)?
|
||||
}
|
||||
Self::Attribute(attribute) => {
|
||||
LargeMultihash::wrap(IDENTITY, &[&[b'A'], attribute.as_bytes()].concat())
|
||||
.map_err(UpEndError::from_any)?
|
||||
}
|
||||
Self::Url(url) => {
|
||||
LargeMultihash::wrap(IDENTITY, &[&[b'X'], url.to_string().as_bytes()].concat())
|
||||
.map_err(UpEndError::from_any)?
|
||||
}
|
||||
let (codec, hash) = match self {
|
||||
Self::Hash(hash) => (
|
||||
RAW,
|
||||
LargeMultihash::wrap(SHA2_256, &hash.0).map_err(UpEndError::from_any)?, // TODO: BROKEN
|
||||
),
|
||||
Self::Uuid(uuid) => (
|
||||
UP_UUID,
|
||||
LargeMultihash::wrap(IDENTITY, uuid.as_bytes()).map_err(UpEndError::from_any)?,
|
||||
),
|
||||
Self::Attribute(attribute) => (
|
||||
UP_ATTRIBUTE,
|
||||
LargeMultihash::wrap(IDENTITY, attribute.as_bytes())
|
||||
.map_err(UpEndError::from_any)?,
|
||||
),
|
||||
Self::Url(url) => (
|
||||
UP_URL,
|
||||
LargeMultihash::wrap(IDENTITY, url.to_string().as_bytes())
|
||||
.map_err(UpEndError::from_any)?,
|
||||
),
|
||||
};
|
||||
|
||||
Ok(hash.to_bytes())
|
||||
let cid = LargeCid::new_v1(codec, hash);
|
||||
|
||||
Ok(cid.to_bytes())
|
||||
}
|
||||
|
||||
pub fn decode(buffer: &[u8]) -> Result<Self, UpEndError> {
|
||||
let multihash = LargeMultihash::from_bytes(buffer).map_err(|err| {
|
||||
let cid = LargeCid::try_from(buffer).map_err(|err| {
|
||||
UpEndError::AddressParseError(format!("Error decoding address: {}", err))
|
||||
})?;
|
||||
|
||||
match multihash.code() {
|
||||
SHA2_256 => Ok(Self::Hash(Digest(multihash.digest().to_vec()))),
|
||||
IDENTITY => {
|
||||
let digest = multihash.digest().to_owned();
|
||||
let digest_content: Vec<u8> = digest.clone().into_iter().skip(1).collect();
|
||||
match digest[0] {
|
||||
b'U' => Ok(Self::Uuid(
|
||||
uuid::Uuid::from_slice(digest_content.as_slice())
|
||||
.map_err(UpEndError::from_any)?,
|
||||
)),
|
||||
b'A' => Ok(Self::Attribute(
|
||||
String::from_utf8(digest_content).map_err(UpEndError::from_any)?,
|
||||
)),
|
||||
b'X' => Ok(Self::Url(
|
||||
Url::parse(
|
||||
&String::from_utf8(digest_content).map_err(UpEndError::from_any)?,
|
||||
)
|
||||
.map_err(|e| UpEndError::AddressParseError(e.to_string()))?,
|
||||
)),
|
||||
_ => Err(UpEndError::AddressParseError(
|
||||
"Error decoding address: Unknown identity marker.".to_string(),
|
||||
)),
|
||||
}
|
||||
}
|
||||
if cid.codec() == RAW {
|
||||
return Ok(Address::Hash(Digest(cid.hash().digest().into()))); // TODO: BROKEN
|
||||
}
|
||||
|
||||
let hash = cid.hash();
|
||||
|
||||
if hash.code() != IDENTITY {
|
||||
return Err(UpEndError::AddressParseError(format!(
|
||||
"Unexpected multihash code \"{}\" for codec \"{}\"",
|
||||
hash.code(),
|
||||
cid.codec()
|
||||
)));
|
||||
}
|
||||
|
||||
let digest = cid.hash().digest().to_vec();
|
||||
|
||||
match cid.codec() {
|
||||
UP_UUID => Ok(Address::Uuid(
|
||||
Uuid::from_slice(digest.as_slice()).map_err(UpEndError::from_any)?,
|
||||
)),
|
||||
UP_ATTRIBUTE => Ok(Address::Attribute(
|
||||
String::from_utf8(digest).map_err(UpEndError::from_any)?,
|
||||
)),
|
||||
UP_URL => Ok(Address::Url(
|
||||
Url::parse(&String::from_utf8(digest).map_err(UpEndError::from_any)?)
|
||||
.map_err(UpEndError::from_any)?,
|
||||
)),
|
||||
_ => Err(UpEndError::AddressParseError(
|
||||
"Error decoding address: Unknown hash function type.".to_string(),
|
||||
"Error decoding address: Unknown codec.".to_string(),
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue