Skip to content

Commit

Permalink
define Address as u128
Browse files Browse the repository at this point in the history
define Identity as u256
  • Loading branch information
Centril committed Sep 5, 2024
1 parent dd65d6d commit 5a73630
Show file tree
Hide file tree
Showing 20 changed files with 201 additions and 216 deletions.
72 changes: 40 additions & 32 deletions crates/bindings-csharp/BSATN.Runtime/Builtins.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,18 @@
using System.Diagnostics;
using SpacetimeDB.BSATN;
using SpacetimeDB.Internal;
using System.Runtime.InteropServices;

namespace SpacetimeDB;

internal static class Util
{
// Same as `Convert.ToHexString`, but that method is not available in .NET Standard
// which we need to target for Unity support.
public static string ToHex<T>(T val) where T: struct =>
BitConverter.ToString(MemoryMarshal.AsBytes([val]).ToArray()).Replace("-", "");
}

public readonly partial struct Unit
{
// Custom BSATN that returns an inline empty product type that can be recognised by SpacetimeDB.
Expand Down Expand Up @@ -61,67 +70,66 @@ string wrapperPropertyName
);
}

public record Address : BytesWrapper
public readonly record struct Address
{
protected override int SIZE => 16;

public Address() { }
private readonly U128 value;

private Address(byte[] bytes)
: base(bytes) { }

public static Address? From(byte[] bytes)
{
if (bytes.All(b => b == 0))
{
return null;
}
return new(bytes);
internal Address(U128 v) => value = v;
public static Address? From(byte[] bytes) {
Debug.Assert(bytes.Length == 16);
var addr = new Address(MemoryMarshal.Read<U128>(bytes));
return addr == default ? null : addr;
}

public static Address Random()
{
var random = new Random();
var addr = new Address();
random.NextBytes(addr.bytes);
return addr;
var bytes = new byte[16];
random.NextBytes(bytes);
return Address.From(bytes) ?? default;
}

public readonly struct BSATN : IReadWrite<Address>
{
public Address Read(BinaryReader reader) => new(ReadRaw(reader));
public Address Read(BinaryReader reader) => new(new SpacetimeDB.BSATN.U128Stdb().Read(reader));

public void Write(BinaryWriter writer, Address value) => value.Write(writer);
public void Write(BinaryWriter writer, Address value)
=> new SpacetimeDB.BSATN.U128Stdb().Write(writer, value.value);

public AlgebraicType GetAlgebraicType(ITypeRegistrar registrar) =>
BytesWrapper.GetAlgebraicType(registrar, "__address_bytes");
new AlgebraicType.Product(
[new("__address__", new AlgebraicType.U128(default))]
);
}

// This must be explicitly forwarded to base, otherwise record will generate a new implementation.
public override string ToString() => base.ToString();
public override string ToString() => Util.ToHex(value);
}

public record Identity : BytesWrapper
public readonly record struct Identity
{
protected override int SIZE => 32;
private readonly U256 value;

public Identity() { }

public Identity(byte[] bytes)
: base(bytes) { }
internal Identity(U256 val) => value = val;
public Identity(byte[] bytes) {
Debug.Assert(bytes.Length == 32);
value = MemoryMarshal.Read<U256>(bytes);
}

public static Identity From(byte[] bytes) => new(bytes);

public readonly struct BSATN : IReadWrite<Identity>
{
public Identity Read(BinaryReader reader) => new(ReadRaw(reader));
public Identity Read(BinaryReader reader) => new(new SpacetimeDB.BSATN.U256().Read(reader));

public void Write(BinaryWriter writer, Identity value) => value.Write(writer);
public void Write(BinaryWriter writer, Identity value)
=> new SpacetimeDB.BSATN.U256().Write(writer, value.value);

public AlgebraicType GetAlgebraicType(ITypeRegistrar registrar) =>
BytesWrapper.GetAlgebraicType(registrar, "__identity_bytes");
new AlgebraicType.Product(
[new("__identity__", new AlgebraicType.U256(default))]
);
}

// This must be explicitly forwarded to base, otherwise record will generate a new implementation.
public override string ToString() => base.ToString();
public override string ToString() => Util.ToHex(value);
}
2 changes: 1 addition & 1 deletion crates/bindings/src/rt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -429,7 +429,7 @@ extern "C" fn __describe_module__(description: BytesSink) {
/// - `sender_3` contains bytes `[24..32]`.
///
/// The `address_{0-1}` are the pieces of a `[u8; 16]` (`u128`) representing the callers's `Address`.
/// They are encoded as follows (assuming `identity.__address_bytes: [u8; 16]`):
/// They are encoded as follows (assuming `address.__address__: u128`):
/// - `address_0` contains bytes `[0 ..8 ]`.
/// - `address_1` contains bytes `[8 ..16]`.
///
Expand Down
2 changes: 1 addition & 1 deletion crates/core/src/client/messages.rs
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ impl<U: ToProtocol<Encoded = ws::DatabaseUpdate>> ToProtocol for TransactionUpda
},
energy_quanta_used: event.energy_quanta_used,
host_execution_duration_micros: event.host_execution_duration.as_micros() as u64,
caller_address: event.caller_address.unwrap_or(Address::zero()),
caller_address: event.caller_address.unwrap_or(Address::ZERO),
};

ws::ServerMessage::TransactionUpdate(tx_update)
Expand Down
12 changes: 6 additions & 6 deletions crates/core/src/db/datastore/locking_tx_datastore/datastore.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1044,7 +1044,7 @@ mod tests {
}

fn get_datastore() -> Result<Locking> {
Locking::bootstrap(Address::zero())
Locking::bootstrap(Address::ZERO)
}

fn col(col: u16) -> ColList {
Expand Down Expand Up @@ -1352,14 +1352,14 @@ mod tests {
ColRow { table: ST_CONSTRAINT_ID.into(), pos: 3, name: "table_id", ty: TableId::get_type() },
ColRow { table: ST_CONSTRAINT_ID.into(), pos: 4, name: "columns", ty: AlgebraicType::array(ColId::get_type()) },

ColRow { table: ST_MODULE_ID.into(), pos: 0, name: "database_address", ty: AlgebraicType::bytes() },
ColRow { table: ST_MODULE_ID.into(), pos: 1, name: "owner_identity", ty: AlgebraicType::bytes() },
ColRow { table: ST_MODULE_ID.into(), pos: 0, name: "database_address", ty: AlgebraicType::U128 },
ColRow { table: ST_MODULE_ID.into(), pos: 1, name: "owner_identity", ty: AlgebraicType::U256 },
ColRow { table: ST_MODULE_ID.into(), pos: 2, name: "program_kind", ty: AlgebraicType::U8 },
ColRow { table: ST_MODULE_ID.into(), pos: 3, name: "program_hash", ty: AlgebraicType::bytes() },
ColRow { table: ST_MODULE_ID.into(), pos: 3, name: "program_hash", ty: AlgebraicType::U256 },
ColRow { table: ST_MODULE_ID.into(), pos: 4, name: "program_bytes", ty: AlgebraicType::bytes() },

ColRow { table: ST_CLIENT_ID.into(), pos: 0, name: "identity", ty: AlgebraicType::bytes()},
ColRow { table: ST_CLIENT_ID.into(), pos: 1, name: "address", ty: AlgebraicType::bytes()},
ColRow { table: ST_CLIENT_ID.into(), pos: 0, name: "identity", ty: AlgebraicType::U256},
ColRow { table: ST_CLIENT_ID.into(), pos: 1, name: "address", ty: AlgebraicType::U128},

ColRow { table: ST_VAR_ID.into(), pos: 0, name: "name", ty: AlgebraicType::String },
ColRow { table: ST_VAR_ID.into(), pos: 1, name: "value", ty: StVarValue::type_of() },
Expand Down
29 changes: 15 additions & 14 deletions crates/core/src/db/datastore/system_tables.rs
Original file line number Diff line number Diff line change
Expand Up @@ -392,10 +392,10 @@ pub(crate) fn st_module_schema() -> TableSchema {
RawTableDefV8::new(
ST_MODULE_NAME.into(),
vec![
RawColumnDefV8::sys(StModuleFields::DatabaseAddress.name(), AlgebraicType::bytes()),
RawColumnDefV8::sys(StModuleFields::OwnerIdentity.name(), AlgebraicType::bytes()),
RawColumnDefV8::sys(StModuleFields::DatabaseAddress.name(), AlgebraicType::U128),
RawColumnDefV8::sys(StModuleFields::OwnerIdentity.name(), AlgebraicType::U256),
RawColumnDefV8::sys(StModuleFields::ProgramKind.name(), AlgebraicType::U8),
RawColumnDefV8::sys(StModuleFields::ProgramHash.name(), AlgebraicType::bytes()),
RawColumnDefV8::sys(StModuleFields::ProgramHash.name(), Hash::get_type()),
RawColumnDefV8::sys(StModuleFields::ProgramBytes.name(), AlgebraicType::bytes()),
],
)
Expand All @@ -407,16 +407,16 @@ pub(crate) fn st_module_schema() -> TableSchema {
///
// identity | address
// -----------------------------------------------------------------------------------------+--------------------------------------------------------
// (__identity_bytes = 0x7452047061ea2502003412941d85a42f89b0702588b823ab55fc4f12e9ea8363) | (__address_bytes = 0x6bdea3ab517f5857dc9b1b5fe99e1b14)
// (__identity_bytes = 0x7452047061ea2502003412941d85a42f89b0702588b823ab55fc4f12e9ea8363) | (__address__ = 0x6bdea3ab517f5857dc9b1b5fe99e1b14)
fn st_client_schema() -> TableSchema {
#[allow(deprecated)]
TableSchema::from_def(
ST_CLIENT_ID,
RawTableDefV8::new(
ST_CLIENT_NAME.into(),
vec![
RawColumnDefV8::sys(StClientFields::Identity.name(), AlgebraicType::bytes()),
RawColumnDefV8::sys(StClientFields::Address.name(), AlgebraicType::bytes()),
RawColumnDefV8::sys(StClientFields::Identity.name(), AlgebraicType::U256),
RawColumnDefV8::sys(StClientFields::Address.name(), AlgebraicType::U128),
],
)
.with_type(StTableType::System)
Expand Down Expand Up @@ -803,23 +803,24 @@ pub fn read_bytes_from_col(row: RowRef<'_>, col: impl StFields) -> Result<Box<[u

/// Read an [`Address`] directly from the column `col` in `row`.
///
/// The [`Address`] is assumed to be stored as a flat byte array.
/// The [`Address`] is assumed to be stored as an u128.
pub fn read_addr_from_col(row: RowRef<'_>, col: impl StFields) -> Result<Address, DBError> {
read_bytes_from_col(row, col).map(Address::from_slice)
let val: u128 = row.read_col(col.col_id())?;
Ok(val.into())
}

/// Read an [`Identity`] directly from the column `col` in `row`.
///
/// The [`Identity`] is assumed to be stored as a flat byte array.
pub fn read_identity_from_col(row: RowRef<'_>, col: impl StFields) -> Result<Identity, DBError> {
read_bytes_from_col(row, col).map(|bytes| Identity::from_slice(&bytes))
Ok(Identity::from_u256(row.read_col(col.col_id())?))
}

/// Read a [`Hash`] directly from the column `col` in `row`.
///
/// The [`Hash`] is assumed to be stored as a flat byte array.
pub fn read_hash_from_col(row: RowRef<'_>, col: impl StFields) -> Result<Hash, DBError> {
read_bytes_from_col(row, col).map(|bytes| Hash::from_slice(&bytes))
Ok(Hash::from_u256(row.read_col(col.col_id())?))
}

impl TryFrom<RowRef<'_>> for StModuleRow {
Expand Down Expand Up @@ -847,10 +848,10 @@ impl From<StModuleRow> for ProductValue {
}: StModuleRow,
) -> Self {
product![
database_address.as_slice().as_slice(),
owner_identity.as_bytes().as_slice(),
database_address.to_u128(),
owner_identity.to_u256(),
program_kind,
program_hash.as_slice(),
program_hash.to_u256(),
program_bytes
]
}
Expand All @@ -864,7 +865,7 @@ pub struct StClientsRow {

impl From<&StClientsRow> for ProductValue {
fn from(x: &StClientsRow) -> Self {
product![x.identity.as_bytes().as_slice(), x.address.as_slice().as_slice()]
product![x.identity.to_u256(), x.address.to_u128()]
}
}

Expand Down
4 changes: 2 additions & 2 deletions crates/core/src/host/wasmtime/wasmtime_module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -194,8 +194,8 @@ impl module_host_actor::WasmInstance for WasmtimeInstance {
set_store_fuel(store, budget.into());

// Prepare sender identity and address.
let [sender_0, sender_1, sender_2, sender_3] = bytemuck::must_cast(*op.caller_identity.as_bytes());
let [address_0, address_1] = bytemuck::must_cast(*op.caller_address.as_slice());
let [sender_0, sender_1, sender_2, sender_3] = bytemuck::must_cast(op.caller_identity.to_byte_array());
let [address_0, address_1] = bytemuck::must_cast(op.caller_address.as_byte_array());

// Prepare arguments to the reducer + the error sink & start timings.
let (args_source, errors_sink) = store.data_mut().start_reducer(op.name, op.arg_bytes);
Expand Down
23 changes: 10 additions & 13 deletions crates/core/src/sql/compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ mod tests {
use spacetimedb_lib::{Address, Identity};
use spacetimedb_primitives::{col_list, ColList, TableId};
use spacetimedb_sats::{
product, satn, AlgebraicType, AlgebraicValue, ProductType, ProductTypeElement, Typespace, ValueWithType,
product, satn, AlgebraicType, AlgebraicValue, GroundSpacetimeType as _, ProductType, Typespace, ValueWithType,
};
use spacetimedb_vm::expr::{ColumnOp, IndexJoin, IndexScan, JoinExpr, Query};
use std::convert::From;
Expand Down Expand Up @@ -397,10 +397,7 @@ mod tests {
#[test]
fn output_identity_address() -> ResultTest<()> {
let row = product![AlgebraicValue::from(Identity::__dummy())];
let kind = ProductType::new(Box::new([ProductTypeElement::new(
Identity::get_type(),
Some("i".into()),
)]));
let kind: ProductType = [("i", Identity::get_type())].into();
let ty = Typespace::EMPTY.with_type(&kind);
let out = ty
.with_values(&row)
Expand All @@ -415,17 +412,17 @@ mod tests {
// Check tuples
let kind = [
("a", AlgebraicType::String),
("b", AlgebraicType::bytes()),
("b", AlgebraicType::U256),
("o", Identity::get_type()),
("p", Address::get_type()),
]
.into();

let value = AlgebraicValue::product([
AlgebraicValue::String("a".into()),
AlgebraicValue::Bytes((*Identity::ZERO.as_bytes()).into()),
AlgebraicValue::Bytes((*Identity::ZERO.as_bytes()).into()),
AlgebraicValue::Bytes((*Address::__DUMMY.as_slice()).into()),
Identity::ZERO.to_u256().into(),
Identity::ZERO.to_u256().into(),
Address::__DUMMY.to_u128().into(),
]);

assert_eq!(
Expand All @@ -437,10 +434,10 @@ mod tests {

// Check struct
let value = product![
AlgebraicValue::String("a".into()),
AlgebraicValue::Bytes((*Identity::ZERO.as_bytes()).into()),
AlgebraicValue::product([AlgebraicValue::Bytes((*Identity::ZERO.as_bytes()).into())]),
AlgebraicValue::product([AlgebraicValue::Bytes((*Address::__DUMMY.as_slice()).into())]),
"a",
Identity::ZERO.to_u256(),
AlgebraicValue::product([Identity::ZERO.to_u256().into()]),
AlgebraicValue::product([Address::__DUMMY.to_u128().into()]),
];

let value = ValueWithType::new(ty, &value);
Expand Down
8 changes: 5 additions & 3 deletions crates/core/src/sql/type_check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,10 @@ fn resolve_type(field: &FieldExpr, ty: AlgebraicType) -> Result<Option<Algebraic
}

if let (AlgebraicType::Product(_), FieldExpr::Value(val)) = (&ty, field) {
if val.as_bytes().is_some() {
return Ok(Some(AlgebraicType::bytes()));
match val {
AlgebraicValue::U128(_) => return Ok(Some(AlgebraicType::U128)),
AlgebraicValue::U256(_) => return Ok(Some(AlgebraicType::U256)),
_ => {}
}
}
Ok(Some(ty))
Expand Down Expand Up @@ -146,7 +148,7 @@ fn check_both(op: OpQuery, lhs: &Typed, rhs: &Typed) -> Result<(), PlanError> {
fn patch_type(lhs: &FieldOp, ty_lhs: &mut Typed, ty_rhs: &Typed) -> Result<(), PlanError> {
if let FieldOp::Field(lhs_field) = lhs {
if let Some(ty) = ty_rhs.ty() {
if ty.is_sum() || ty.as_product().map_or(false, |x| x.is_special()) {
if ty.is_sum() || ty.as_product().is_some_and(|x| x.is_special()) {
ty_lhs.set_ty(resolve_type(lhs_field, ty.clone())?);
}
}
Expand Down
Loading

0 comments on commit 5a73630

Please sign in to comment.