aluvm / rust-aluvm Goto Github PK
View Code? Open in Web Editor NEWRust implementation of AluVM (RISC functional machine)
Home Page: https://docs.rs/aluvm
License: Apache License 2.0
Rust implementation of AluVM (RISC functional machine)
Home Page: https://docs.rs/aluvm
License: Apache License 2.0
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn ops_on_numbers() {
let num1 = Number::from(127);
assert_eq!(false, num1.is_zero())
}
}
results in:
thread 'data::arithm::tests::ops_on_numbers' panicked at 'assertion failed: `(left == right)`
left: `false`,
right: `true`', src/data/arithm.rs:513:9
because of this:
https://github.com/internet2-org/rust-aluvm/blob/3b16ef83bad1b02137261739f9d22dfc1a966d6f/src/data/number.rs#L1066
It seems that 0 will be assigned to len
when the number of bits is below 7, while 1 should be assigned.
rust-aluvm/src/data/bitwise.rs
Lines 50 to 57 in 2bde05b
Lines 128 to 133 in 97bd8e7
Secp256k1 context object is not a part of the state and must be handled accordingly
Currently libraries are referenced by full SHA256-hash (LibId). For call stack and inside the code this creates a lot of mamory requirements. Thus, a special segment with numbered library list has to be introduced that matches internal library ids with hashes only once and then uses short 16-bit identifiers.
Currently put
mnemonic is used for both putting numbers and strings to registers. However, these two commands have different macro and display implementations: number format lists the literal first, while the string version puts the string literal as the last argument. This should be fixed.
AluAsm (Alu assembler) makes it easier to use and debug AluVM (you can write assembly as files, not rust macros, and compile them + use libraries): https://github.com/pandoracore/aluasm
AluRE (Alu runtime environment) moves this further and provides runtime environment - but it is very early stage right now: https://github.com/pandoracore/AluRE
A concept of a high-level language for AluVM which may be used for smart contracts: https://github.com/rgb-org/contractum-lang
e.g. fmt
check uses nightly
while clippy
is on stable
. Since fmt
and clippy
yells at different points on stable
and nightly
, we would need to switch the compiler frequently on the local machine
With the move to use Intel-style ordering in assembly ("destination-first ordering") we got into a quite inconsistent state:
We have the following options of introducing consistency here:
I am pro second option, since a released RGB v0.10 already depends on the bytecode in AluVM, and if we use the first option, we need to fork AluVM and maintain two variants of it - one for RGB and the other one for the rest of the world.
Opinions? @6293
This will be probably best done as a PR to the upstream rustc_apfloat
#[test]
fn my_test() { let _register = CoreRegs::default(); }
fails with
thread 'isa::exec::tests::my_test' has overflowed its stack
fatal runtime error: stack overflow
https://github.com/internet2-org/rust-aluvm/blob/a7e64abd4a7058bf9f06886452147810b4a5cf6d/src/reg/core_regs.rs#L99
With Box<[LibSite; CALL_STACK_SIZE]>
, the value would be allocated to stack first, but CALL_STACK_SIZE = 1 << 16
is too big, resuting in overflow.
Use Vec<LibSite>
instead.
This github org (@Internet2-WG) was created to host projects related to better privacy and trustless decentralization in internet protocols.
AluVM and strict-encoding-related repos got to this organization since there seemed no place for them in other LNP/BP Standards Association github orgs at that time.
Now, we have a dedicated computing working group in LNP/BP Standards Association, called @Prometheus-WG. This WG seems to be a more native place for AluVM; I also plan to move all strict-encoding repositories there and repos from @pandoracore which are AluVM-related (assembly compiler, Alu runtime environment etc).
CC @zoedberg @cryptoquick @monaka @josediegorobles @6293 @UkolovaOlga - I plan to add you guys to the new org as team members; please let be know if you have arguments against the approach of migrating there. Otherwise I proceed with the moving at the end of the next week.
My env is the same as #58.
Error log:
$ cargo test --no-fail-fast
Compiling aluvm v0.6.0 (/home/monaka/rgb/rust-aluvm)
error[E0599]: no variant or associated item named `Secp256k1` found for enum `Instr` in the current scope
--> examples/asm.rs:25:16
|
25 | let code = aluasm! {
| ________________^
26 | | clr r1024[5] ;
27 | | put 5,a16[8] ;
28 | | putif 0xaf67937b5498dc,r256[1] ;
... |
92 | | ret ;
93 | | };
| |_____^ variant or associated item not found in `Instr<_>`
|
= note: this error originates in the macro `instr` (in Nightly builds, run with -Z macro-backtrace for more info)
For more information about this error, try `rustc --explain E0599`.
error: could not compile `aluvm` due to 4 previous errors
Is this issue related to #14 ?
con
splt
ins
del
rust-aluvm/src/isa/bytecode.rs
Lines 950 to 955 in eb4fcc4
Here, reg
spans across 2 bytes (last bit of first byte to third bit of second byte). write_u4
, however, does not handle such cases
rust-aluvm/src/library/cursor.rs
Line 129 in 866f9c8
Depends on upstreams:
rustc_apfloat
half
amplify_num
: https://github.com/LNP-BP/rust-amplify/issues/87#[test]
fn test_neg() {
let x = Number::from(1i8);
let y = Number::from(-1i8);
assert_eq!(x.neg(), y);
}
fails with
left: `Number { layout: Integer(IntLayout { signed: true, bytes: 1 }), bytes: "81" }`,
right: `Number { layout: Integer(IntLayout { signed: true, bytes: 1 }), bytes: "ff" }`'
Also, when the Number is unsigned, we could:
IntLayout
to signed (if it would cause overflow, change the bytes
in the layout too)IntLayout
to signed (if it caused overflow, panic)@dr-orlovsky wdyt? have a happy new year
let code = aluasm! {
put 4,a16[8];
sub 9,a16[8];
ret;
};
this would fail because
here, val
is stored as unsigned Number while Number::from(-step.as_i16())
produces signed Number, causing
thread 'main' panicked at 'assertion failed: `(left == right)`
left: `Integer(IntLayout { signed: false, bytes: 2 })`,
right: `Integer(IntLayout { signed: true, bytes: 2 })`: subtracting numbers with different layout', src/data/arithm.rs:143:9
We can fix this to something like below?
if step.as_i16() < 0 {
val.int_sub(Number::from(<convert -step to u16>), IntFlags {
signed: false,
wrap: true,
})
}
bugs on aluasm are often caused by aluvm. submitting separate PR is sometimes cumbersome because the PR on aluasm fails until the PR on aluvm has been merged
Reproduction step:
cargo test --all-features
target/debug/examples/asm
Result:
thread 'main' panicked at 'invalid number literal `2.13`: Int(ParseIntError { kind: InvalidDigit })', examples/asm.rs:25:16
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Env:
cargo version
cargo 1.61.0 (a028ae4 2022-04-29)
println!("{:?}", Number::from(-1i8));
shows
Number { layout: Integer(IntLayout { signed: false, bytes: 1 }), bytes: "ff" }
This is caused by
https://github.com/internet2-org/rust-aluvm/blob/3b16ef83bad1b02137261739f9d22dfc1a966d6f/src/data/number.rs#L1120
this macro always returning Number
with an unsigned IntLayout
.
My env is:
$ cargo --version
cargo 1.61.0 (a028ae4 2022-04-29)
$ rustc --version
rustc 1.61.0 (fe5b13d68 2022-05-18)
The log is here:
$ cargo test
{snip}
Compiling aluvm v0.6.0 (/home/monaka/rgb/rust-aluvm)
error: unused imports: `Reg8`, `RegBlockAR`
--> src/isa/exec.rs:1019:29
|
1019 | use crate::reg::{Reg16, Reg8, RegBlockAR};
| ^^^^ ^^^^^^^^^^
|
note: the lint level is defined here
--> src/lib.rs:13:34
|
13 | #![deny(dead_code, missing_docs, warnings)]
| ^^^^^^^^
= note: `#[deny(unused_imports)]` implied by `#[deny(warnings)]`
error: could not compile `aluvm` due to previous error
warning: build failed, waiting for other jobs to finish...
Assignment to large R-regs like
regs.r2048[0] = Some([0u8; 256])
panics with uncanny message thread panicked while panicking. aborting.
. This is a same bug as #40,
pub(crate) r1024: Box<[Option<[u8; 128]>; 32]>,
pub(crate) r2048: Box<[Option<[u8; 256]>; 32]>,
pub(crate) r4096: Box<[Option<[u8; 512]>; 32]>,
pub(crate) r8192: Box<[Option<[u8; 1024]>; 32]>,
too many things are on stack. R-regs should be something like
pub(crate) r1024: Confined<Vec<Option<[u8; 128]>>, 32, 32>,
pub(crate) r2048: Confined<Vec<Option<[u8; 256]>>, 32, 32>,
pub(crate) r4096: Confined<Vec<Option<[u8; 512]>>, 32, 32>,
pub(crate) r8192: Confined<Vec<Option<[u8; 1024]>>, 32, 32>,
Number::from(-1).int_add(Number::from(-2), IntFlags { signed: true, wrap: false })
returns None
, despite the fact that it is not overflowing.
Here, we calculate the addition by converting Numbers to u1024
. u1024
, however, is not capable of judging negative overflow (of course because u1024
is "unsigned")
More specifically, u1024
will assert overflow whenever a carry bit results in > 0. But in an addition of two negative numbers, -1
and -2
for example, the carry bit hits 1 and we should ignore that.
i256
, i512
, i1024
) in rust-amplify
pub fn int_add(self, rhs: Self, flags: IntFlags) -> Option<Number> {
let layout = self.layout();
assert_eq!(layout, rhs.layout(), "adding numbers with different layout");
match layout {
// Signed and unsigned integers do not differ in their addition, since we use
// two's complement system
Layout::Integer(IntLayout { .. }) => {
let (res, mut overflow) = {
match flags.signed {
true => {
let val1 = self.to_i1024_bytes();
let val2 = rhs.to_i1024_bytes();
val1.overflowing_add(val2);
},
false => {
let val1 = self.to_u1024_bytes();
let val2 = rhs.to_u1024_bytes();
val1.overflowing_add(val2);
}
}
let mut res = Number::from(res);
overflow |= !res.reshape(layout);
if !overflow || flags.wrap {
Some(res)
} else {
None
}
}
Layout::Float(_) => panic!("integer addition of float numbers"),
}
}
MSB(A) == MSB(B)
and MSB(A) != MSB(C)
pub fn int_add(self, rhs: Self, flags: IntFlags) -> Option<Number> {
let layout = self.layout();
assert_eq!(layout, rhs.layout(), "adding numbers with different layout");
match layout {
Layout::Integer(IntLayout { .. }) => {
let mut ret = Number::zero(Layout::Integer(IntLayout {
signed: flags.signed,
bytes: layout.bytes(),
}));
let mut carry = 0u8;
for i in 0..layout.bytes() {
let (res, flag) = self[i].overflowing_add(carry);
carry = flag as u8;
let (res, flag) = res.overflowing_add(rhs[i]);
carry += flag as u8;
ret[i] = res;
}
let overflow = {
if flags.signed {
let sign_byte = layout.sign_byte();
let is_self_positive = self[sign_byte] & 0x80 == 0;
let is_rhs_positive = rhs[sign_byte] & 0x80 == 0;
let is_ret_positive = ret[sign_byte] & 0x80 == 0;
(is_self_positive == is_rhs_positive) && (is_rhs_positive ^ is_ret_positive)
} else {
carry > 0
}
};
if !overflow || flags.wrap {
Some(ret)
} else {
None
}
}
Layout::Float(_) => panic!("integer addition of float numbers"),
}
}
We have to filter NaN and negative zero values for float numbers and convert them into deterministic representation of MaybeNumber::None
and positive zero
I'll send a PR soon.
$ cargo version
cargo 1.66.0 (d65d197ad 2022-11-15)
$ rustc --version
rustc 1.66.0 (69f9c33d7 2022-12-12)
cargo check
Checking aluvm v0.10.0-rc.1 (/home/monaka/diamondhands-dev/rust-aluvm)
error[E0433]: failed to resolve: use of undeclared crate or module `std`
--> src/program.rs:28:5
|
28 | use std::collections::btree_map;
| ^^^ use of undeclared crate or module `std`
error[E0433]: failed to resolve: could not find `std` in the list of imported crates
--> src/library/lib.rs:49:22
|
49 | #[derive(StrictType, StrictEncode, StrictDecode)]
| ^^^^^^^^^^^^ could not find `std` in the list of imported crates
|
= note: this error originates in the derive macro `StrictEncode` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0433]: failed to resolve: could not find `std` in the list of imported crates
--> src/library/lib.rs:311:22
|
311 | #[derive(StrictType, StrictEncode, StrictDecode)]
| ^^^^^^^^^^^^ could not find `std` in the list of imported crates
|
= note: this error originates in the derive macro `StrictEncode` (in Nightly builds, run with -Z macro-backtrace for more info)
For more information about this error, try `rustc --explain E0433`.
error: could not compile `aluvm` due to 3 previous errors
Data must be kept within a library as a separate structure limited by 2^24 in size.
I was compiling a rgb dependencies inside my project but I have this error
Compiling aluvm v0.10.6
Compiling bp-consensus v0.10.11
error[E0308]: mismatched types
--> /home/vincent/.cargo/registry/src/index.crates.io-6f17d22bba15001f/aluvm-0.10.6/src/reg/indexes.rs:425:9
|
424 | fn try_from(value: Reg32) -> Result<Self, Self::Error> {
| ------------------------- expected `Result<Reg16, OverflowError>` because of return type
425 | u4::try_from(value as u8).map(Reg16::from)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Result<Reg16, OverflowError>`, found `Result<Reg16, OverflowError<u8>>`
|
= note: expected enum `Result<_, OverflowError<usize>>`
found enum `Result<_, OverflowError<u8>>`
error[E0308]: mismatched types
--> /home/vincent/.cargo/registry/src/index.crates.io-6f17d22bba15001f/aluvm-0.10.6/src/reg/indexes.rs:528:9
|
527 | fn try_from(value: Reg32) -> Result<Self, Self::Error> {
| ------------------------- expected `Result<Reg8, OverflowError>` because of return type
528 | u3::try_from(value as u8).map(Reg8::from)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Result<Reg8, OverflowError>`, found `Result<Reg8, OverflowError<u8>>`
|
= note: expected enum `Result<_, OverflowError<usize>>`
found enum `Result<_, OverflowError<u8>>`
error[E0308]: mismatched types
--> /home/vincent/.cargo/registry/src/index.crates.io-6f17d22bba15001f/aluvm-0.10.6/src/reg/indexes.rs:620:9
|
619 | fn try_from(value: Reg32) -> Result<Self, Self::Error> {
| ------------------------- expected `Result<RegS, OverflowError>` because of return type
620 | u5::try_from(value as u8).map(RegS::from)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Result<RegS, OverflowError>`, found `Result<RegS, OverflowError<u8>>`
|
= note: expected enum `Result<_, OverflowError<usize>>`
found enum `Result<_, OverflowError<u8>>`
For more information about this error, try `rustc --explain E0308`.
error: could not compile `aluvm` (lib) due to 3 previous errors
warning: build failed, waiting for other jobs to finish..
Not sure why :/
the dependencies that I am using
# RGB and related
amplify = "=4.5.0"
base64 = "0.13.0"
bp-core = "=0.10.11"
commit_verify = "=0.10.6"
futures = "0.3"
hex = "0.4"
reqwest = { version = "0.11", default-features = false, features = ["json", "blocking"] }
rgb-contracts = { version = "=0.10.2", features = ["electrum"] }
rgb_core = { package = "rgb-core", version = "=0.10.8" }
rgb-lib = { git = "https://github.com/RGB-Tools/rgb-lib", branch = "rln_v0.10" }
rgb-std = "=0.10.9"
rgb-wallet = "=0.10.9"
serde = { version = "^1.0", features = ["derive"] }
serde_json = "^1.0"
strict_encoding = "=2.6.1"
tokio = { version = "1.36", features = ["macros", "rt-multi-thread"] }
The output from several eprint
and eprintln
instructions appears on the console while calling aluvm methods.
This is inconvenient and I think this output should be suppressed.
I propose to protect those eprint
's behind a feature flag (e.g. log
).
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn cmp_numbers() {
let num0 = Number::from(1);
let num1 = Number::from(2);
assert_eq!(num0, num1);
}
}
results in
thread 'data::arithm::tests::cmp_numbers' has overflowed its stack
fatal runtime error: stack overflow
because eq
method calls itself.
https://github.com/internet2-org/rust-aluvm/blob/3b16ef83bad1b02137261739f9d22dfc1a966d6f/src/data/arithm.rs#L28
Maybe we can compare two Numbers by converting them to corresponding integer/float types, just like cmp
method does?
This is required to ensure backwards compatibility
See examples/rgb.rs
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.