wip: semi-broken first transition to CIDs

feat/type-attributes
Tomáš Mládek 2023-06-29 13:30:27 +02:00
parent f880a0e38c
commit ef74c8520f
3 changed files with 159 additions and 45 deletions

90
Cargo.lock generated
View File

@ -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",

View File

@ -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"

View File

@ -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(),
)),
}
}