mirror of
https://github.com/luxfi/node.git
synced 2026-10-30 15:24:05 +00:00
The chain restated `lux-rs/node`'s `src/vm.rs` in a `host.rs` of its own and minted a 32-byte `Id` newtype beside the one the finality rule already uses. Both are gone. `host` is now `pub use lux_node::vm`, so `impl host::Vm for Xvm` implements the trait the node actually holds its chains behind. A restatement compiles against a shape the node never sees, and keeps compiling on the day the node changes a method. `Id` is `lux_consensus::finality::Id` — the same `[u8; 32]` the P-Chain port already names, so a node can hold both in one chain map. The operations that were methods on the newtype are free functions in `ids`, and `is_empty` is one of them deliberately: an array derefs to a slice, whose own `is_empty` answers about the length and would be a silently wrong answer to "is this the empty id". The wire is untouched: the twelve Go-generated golden vectors and the execution-root KAT pass unchanged.
444 lines
31 KiB
Rust
444 lines
31 KiB
Rust
// SPDX-License-Identifier: BSD-3-Clause-Eco
|
|
// Copyright (C) 2019-2026, Lux Industries Inc. All rights reserved.
|
|
|
|
//! Byte-for-byte against Go.
|
|
//!
|
|
//! Every other test in this crate asks whether the chain agrees with itself: a
|
|
//! round trip proves the reader can undo the writer, and nothing more. These
|
|
//! ask the only question that matters between two implementations — whether the
|
|
//! bytes are the SAME bytes.
|
|
//!
|
|
//! Each vector below was printed by the Go X-chain (`luxfi/node/vms/xvm` at
|
|
//! `github.com/luxfi/zap v1.2.7`, `github.com/luxfi/utxo v0.5.10`) from the
|
|
//! structure named in the test, and pasted here unchanged. A transaction's id
|
|
//! is the SHA-256 of its signed bytes, so if these ever diverge the two chains
|
|
//! are not the same chain — a transaction one node accepted would have a
|
|
//! different name on the other.
|
|
//!
|
|
//! HOW TO REGENERATE. Build the same structures against the Go packages and
|
|
//! print `hex.EncodeToString` of: `txs.UnsignedBytes(t)`, `tx.Bytes()`,
|
|
//! `tx.ID()`, each fx primitive's `Bytes()`, and `utxo.WireBytes()`.
|
|
|
|
use lux_xvm::fx::secp256k1::{Credential, MintOutput, TransferInput, TransferOutput};
|
|
use lux_xvm::fx::{FxIn, Input, Owners, State};
|
|
use lux_xvm::ids::{self, ShortId};
|
|
use lux_xvm::txs::{BaseTx, Tx, Unsigned};
|
|
use lux_xvm::utxo::{Asset, BaseTxFields, TransferableInput, TransferableOutput, Utxo, UtxoId};
|
|
|
|
fn hex(b: &[u8]) -> String {
|
|
b.iter().map(|x| format!("{x:02x}")).collect()
|
|
}
|
|
|
|
/// The transaction the Go vectors were printed from: network 10, chain 5, one
|
|
/// output of 12345 to one address, one input of 12346 spending output 7 of
|
|
/// transaction 2, and a four-byte memo.
|
|
fn the_transaction() -> Tx {
|
|
Tx::new(Unsigned::Base(BaseTx {
|
|
base: BaseTxFields {
|
|
network_id: 10,
|
|
blockchain_id: ids::prefixed(&[5]),
|
|
outs: vec![TransferableOutput {
|
|
asset: Asset {
|
|
id: ids::prefixed(&[1]),
|
|
},
|
|
out: State::Transfer(TransferOutput {
|
|
amt: 12345,
|
|
owners: Owners {
|
|
locktime: 0,
|
|
threshold: 1,
|
|
addrs: vec![ShortId::prefixed_bytes(&[0xAA, 0xBB])],
|
|
},
|
|
}),
|
|
}],
|
|
ins: vec![TransferableInput {
|
|
utxo_id: UtxoId::new(ids::prefixed(&[2]), 7),
|
|
asset: Asset {
|
|
id: ids::prefixed(&[1]),
|
|
},
|
|
input: FxIn::Transfer(TransferInput {
|
|
amt: 12346,
|
|
input: Input {
|
|
sig_indices: vec![0, 2],
|
|
},
|
|
}),
|
|
}],
|
|
memo: b"memo".to_vec(),
|
|
},
|
|
}))
|
|
}
|
|
|
|
/// What every signature in this chain is computed over.
|
|
const GO_BASETX_UNSIGNED: &str = "5a41500002000000100000006e0100000100000000000000080000004e01000000125a41500002000000080100004c0100000100000000000000000000000000000000000000000000000000000000000000080000004600000001015a415000020000002800000044000000aabb000000000000000000000000000000000000000000003930000000000000000000000000000001000000d4ffffff0100000000000200000000000000000000000000000000000000000000000000000000000000070000000100000000000000000000000000000000000000000000000000000000000000080000002a00000001025a41500002000000180000002800000000000000020000003a30000000000000f0ffffff02000000000018ffffff0000000080ffffff000000000a000000000000000500000000000000000000000000000000000000000000000000000000000000c8ffffff01000000c8ffffff0100000008000000040000006d656d6f";
|
|
|
|
/// The signed envelope with no credentials attached — the unsigned body plus an
|
|
/// empty credential run.
|
|
const GO_BASETX_SIGNED_NOCREDS: &str = "000e5a415000020000001000000092010000140000006e0100000000000000000000000000005a41500002000000100000006e0100000100000000000000080000004e01000000125a41500002000000080100004c0100000100000000000000000000000000000000000000000000000000000000000000080000004600000001015a415000020000002800000044000000aabb000000000000000000000000000000000000000000003930000000000000000000000000000001000000d4ffffff0100000000000200000000000000000000000000000000000000000000000000000000000000070000000100000000000000000000000000000000000000000000000000000000000000080000002a00000001025a41500002000000180000002800000000000000020000003a30000000000000f0ffffff02000000000018ffffff0000000080ffffff000000000a000000000000000500000000000000000000000000000000000000000000000000000000000000c8ffffff01000000c8ffffff0100000008000000040000006d656d6f";
|
|
|
|
/// The id Go gives that transaction.
|
|
const GO_BASETX_ID: &str = "76feb0c9414e3a4ecff34210c9a4aaadbde9274c90deacd2b1bcbdd8f14c0731";
|
|
|
|
#[test]
|
|
fn the_unsigned_bytes_are_the_bytes_go_signs() {
|
|
let tx = the_transaction();
|
|
assert_eq!(hex(tx.unsigned_bytes()), GO_BASETX_UNSIGNED);
|
|
}
|
|
|
|
#[test]
|
|
fn the_signed_envelope_is_the_envelope_go_puts_on_the_wire() {
|
|
let tx = the_transaction();
|
|
assert_eq!(hex(tx.bytes()), GO_BASETX_SIGNED_NOCREDS);
|
|
}
|
|
|
|
#[test]
|
|
fn a_transaction_has_the_same_name_in_both_languages() {
|
|
// The id is the hash of the signed bytes, so this follows from the vector
|
|
// above — and it is asserted separately because it is the thing that would
|
|
// actually break: two nodes calling one transaction by two names.
|
|
let tx = the_transaction();
|
|
assert_eq!(hex(&tx.id()), GO_BASETX_ID);
|
|
}
|
|
|
|
#[test]
|
|
fn a_transaction_go_encoded_reads_back_here_as_the_same_transaction() {
|
|
let raw: Vec<u8> = (0..GO_BASETX_SIGNED_NOCREDS.len())
|
|
.step_by(2)
|
|
.map(|i| u8::from_str_radix(&GO_BASETX_SIGNED_NOCREDS[i..i + 2], 16).unwrap())
|
|
.collect();
|
|
let parsed = Tx::parse(&raw).unwrap();
|
|
assert_eq!(hex(&parsed.id()), GO_BASETX_ID);
|
|
let base = parsed.unsigned.base();
|
|
assert_eq!(base.network_id, 10);
|
|
assert_eq!(base.blockchain_id, ids::prefixed(&[5]));
|
|
assert_eq!(base.memo, b"memo");
|
|
assert_eq!(base.outs.len(), 1);
|
|
assert_eq!(base.outs[0].out.amount(), 12345);
|
|
assert_eq!(base.ins.len(), 1);
|
|
assert_eq!(base.ins[0].utxo_id.output_index, 7);
|
|
// And re-encoding it gives back the very bytes it came from.
|
|
assert_eq!(hex(parsed.bytes()), GO_BASETX_SIGNED_NOCREDS);
|
|
}
|
|
|
|
#[test]
|
|
fn every_fx_primitive_envelope_is_the_envelope_go_writes() {
|
|
let out = TransferOutput {
|
|
amt: 7,
|
|
owners: Owners {
|
|
locktime: 3,
|
|
threshold: 1,
|
|
addrs: vec![ShortId::prefixed_bytes(&[9])],
|
|
},
|
|
};
|
|
assert_eq!(
|
|
hex(&out.bytes()),
|
|
"01015a4150000200000028000000440000000900000000000000000000000000000000000000000000000700000000000000030000000000000001000000d4ffffff01000000"
|
|
);
|
|
|
|
let in_ = TransferInput {
|
|
amt: 7,
|
|
input: Input {
|
|
sig_indices: vec![1],
|
|
},
|
|
};
|
|
assert_eq!(
|
|
hex(&in_.bytes()),
|
|
"01025a41500002000000180000002800000001000000000000000700000000000000f0ffffff01000000"
|
|
);
|
|
|
|
let mut sig = [0u8; 65];
|
|
sig[0] = 1;
|
|
sig[1] = 2;
|
|
sig[2] = 3;
|
|
let cred = Credential { sigs: vec![sig] };
|
|
assert_eq!(
|
|
hex(&cred.bytes()),
|
|
"01065a41500002000000580000006c00000001020300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b4ffffff410000000000000000000000"
|
|
);
|
|
|
|
let mint = MintOutput {
|
|
owners: Owners {
|
|
locktime: 0,
|
|
threshold: 1,
|
|
addrs: vec![ShortId::prefixed_bytes(&[9])],
|
|
},
|
|
};
|
|
assert_eq!(
|
|
hex(&mint.bytes()),
|
|
"01035a41500002000000280000003c000000090000000000000000000000000000000000000000000000000000000000000001000000dcffffff01000000"
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn an_unspent_output_crosses_between_chains_as_the_bytes_go_writes() {
|
|
let utxo = Utxo {
|
|
utxo_id: UtxoId::new(ids::prefixed(&[3]), 1),
|
|
asset: Asset {
|
|
id: ids::prefixed(&[1]),
|
|
},
|
|
out: State::Transfer(TransferOutput {
|
|
amt: 7,
|
|
owners: Owners {
|
|
locktime: 3,
|
|
threshold: 1,
|
|
addrs: vec![ShortId::prefixed_bytes(&[9])],
|
|
},
|
|
}),
|
|
};
|
|
assert_eq!(
|
|
hex(&utxo.wire_bytes()),
|
|
"000a5a4150000200000010000000a20000000300000000000000000000000000000000000000000000000000000000000000010000000100000000000000000000000000000000000000000000000000000000000000080000004600000001015a4150000200000028000000440000000900000000000000000000000000000000000000000000000700000000000000030000000000000001000000d4ffffff01000000"
|
|
);
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// The other four transactions, a block, and every fx primitive envelope.
|
|
// Same generator, same structures — see the module comment.
|
|
// ---------------------------------------------------------------------------
|
|
|
|
use lux_xvm::block::Block;
|
|
use lux_xvm::fx::{nft, property, Op};
|
|
use lux_xvm::txs::{CreateAssetTx, ExportTx, ImportTx, InitialState, Operation, OperationTx};
|
|
|
|
/// The envelope every one of the four shares.
|
|
fn base_fields() -> BaseTxFields {
|
|
BaseTxFields {
|
|
network_id: 10,
|
|
blockchain_id: ids::prefixed(&[5]),
|
|
outs: vec![TransferableOutput {
|
|
asset: Asset {
|
|
id: ids::prefixed(&[1]),
|
|
},
|
|
out: State::Transfer(TransferOutput {
|
|
amt: 12345,
|
|
owners: Owners::new(1, vec![ShortId::prefixed_bytes(&[0xAA, 0xBB])]),
|
|
}),
|
|
}],
|
|
ins: vec![TransferableInput {
|
|
utxo_id: UtxoId::new(ids::prefixed(&[2]), 7),
|
|
asset: Asset {
|
|
id: ids::prefixed(&[1]),
|
|
},
|
|
input: FxIn::Transfer(TransferInput {
|
|
amt: 12346,
|
|
input: Input {
|
|
sig_indices: vec![0, 2],
|
|
},
|
|
}),
|
|
}],
|
|
memo: b"memo".to_vec(),
|
|
}
|
|
}
|
|
|
|
fn owner9() -> Owners {
|
|
Owners::new(1, vec![ShortId::prefixed_bytes(&[9])])
|
|
}
|
|
|
|
/// Assert one transaction's three vectors at once: what is signed, what goes on
|
|
/// the wire, and what it is called.
|
|
fn check(u: Unsigned, unsigned: &str, signed: &str, id: &str) {
|
|
let tx = Tx::new(u);
|
|
assert_eq!(hex(tx.unsigned_bytes()), unsigned, "unsigned bytes");
|
|
assert_eq!(hex(tx.bytes()), signed, "signed bytes");
|
|
assert_eq!(hex(&tx.id()), id, "id");
|
|
// And what Go wrote reads back here as the same transaction.
|
|
let raw: Vec<u8> = (0..signed.len())
|
|
.step_by(2)
|
|
.map(|i| u8::from_str_radix(&signed[i..i + 2], 16).unwrap())
|
|
.collect();
|
|
let parsed = Tx::parse(&raw).unwrap();
|
|
assert_eq!(hex(parsed.bytes()), signed);
|
|
assert_eq!(parsed.unsigned, tx.unsigned);
|
|
}
|
|
|
|
#[test]
|
|
fn a_create_asset_is_the_bytes_go_writes() {
|
|
check(
|
|
Unsigned::CreateAsset(CreateAssetTx {
|
|
base: base_fields(),
|
|
name: "Test Asset".into(),
|
|
symbol: "TST".into(),
|
|
denomination: 8,
|
|
states: vec![InitialState {
|
|
fx_index: 0,
|
|
outs: vec![State::Mint(MintOutput { owners: owner9() })],
|
|
}],
|
|
}),
|
|
"5a4150000200000018000000110200006a0000000000000002000000000000002c0000004e010000720100000a000000740100000300000008000000d4ffffff01000000630100006a00000000125a41500002000000080100004c0100000100000000000000000000000000000000000000000000000000000000000000080000004600000001015a415000020000002800000044000000aabb000000000000000000000000000000000000000000003930000000000000000000000000000001000000d4ffffff0100000000000200000000000000000000000000000000000000000000000000000000000000070000000100000000000000000000000000000000000000000000000000000000000000080000002a00000001025a41500002000000180000002800000000000000020000003a30000000000000f0ffffff02000000000018ffffff0000000080ffffff000000000a000000000000000500000000000000000000000000000000000000000000000000000000000000c8ffffff01000000c8ffffff0100000008000000040000006d656d6f546573742041737365745453545a41500002000000180000006a0000003e0000000000000000000000f4ffffff01000000080000003e00000001035a41500002000000280000003c000000090000000000000000000000000000000000000000000000000000000000000001000000dcffffff01000000",
|
|
"000e5a41500002000000100000003502000014000000110200000000000000000000000000005a4150000200000018000000110200006a0000000000000002000000000000002c0000004e010000720100000a000000740100000300000008000000d4ffffff01000000630100006a00000000125a41500002000000080100004c0100000100000000000000000000000000000000000000000000000000000000000000080000004600000001015a415000020000002800000044000000aabb000000000000000000000000000000000000000000003930000000000000000000000000000001000000d4ffffff0100000000000200000000000000000000000000000000000000000000000000000000000000070000000100000000000000000000000000000000000000000000000000000000000000080000002a00000001025a41500002000000180000002800000000000000020000003a30000000000000f0ffffff02000000000018ffffff0000000080ffffff000000000a000000000000000500000000000000000000000000000000000000000000000000000000000000c8ffffff01000000c8ffffff0100000008000000040000006d656d6f546573742041737365745453545a41500002000000180000006a0000003e0000000000000000000000f4ffffff01000000080000003e00000001035a41500002000000280000003c000000090000000000000000000000000000000000000000000000000000000000000001000000dcffffff01000000",
|
|
"cd718316970d18f0b30826bf7b215f2b7d4a9f0cf90384252bd74ee841396f72",
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn an_operation_transaction_is_the_bytes_go_writes() {
|
|
check(
|
|
Unsigned::Operation(OperationTx {
|
|
base: base_fields(),
|
|
ops: vec![Operation {
|
|
asset: Asset { id: ids::prefixed(&[1]) },
|
|
utxo_ids: vec![UtxoId::new(ids::prefixed(&[4]), 2)],
|
|
op: Op::PropertyBurn(property::BurnOperation {
|
|
input: Input { sig_indices: vec![0] },
|
|
}),
|
|
}],
|
|
}),
|
|
"5a4150000200000018000000100200008a000000000000000300000000000000180000004e010000e8ffffff01000000560100008a00000000125a41500002000000080100004c0100000100000000000000000000000000000000000000000000000000000000000000080000004600000001015a415000020000002800000044000000aabb000000000000000000000000000000000000000000003930000000000000000000000000000001000000d4ffffff0100000000000200000000000000000000000000000000000000000000000000000000000000070000000100000000000000000000000000000000000000000000000000000000000000080000002a00000001025a41500002000000180000002800000000000000020000003a30000000000000f0ffffff02000000000018ffffff0000000080ffffff000000000a000000000000000500000000000000000000000000000000000000000000000000000000000000c8ffffff01000000c8ffffff0100000008000000040000006d656d6f5a41500002000000380000008a000000040000000000000000000000000000000000000000000000000000000000000002000000000000000100000000000000000000000000000000000000000000000000000000000000b8ffffff01000000080000002200000009165a4150000200000018000000200000000000000000000000f8ffffff01000000",
|
|
"000e5a41500002000000100000003402000014000000100200000000000000000000000000005a4150000200000018000000100200008a000000000000000300000000000000180000004e010000e8ffffff01000000560100008a00000000125a41500002000000080100004c0100000100000000000000000000000000000000000000000000000000000000000000080000004600000001015a415000020000002800000044000000aabb000000000000000000000000000000000000000000003930000000000000000000000000000001000000d4ffffff0100000000000200000000000000000000000000000000000000000000000000000000000000070000000100000000000000000000000000000000000000000000000000000000000000080000002a00000001025a41500002000000180000002800000000000000020000003a30000000000000f0ffffff02000000000018ffffff0000000080ffffff000000000a000000000000000500000000000000000000000000000000000000000000000000000000000000c8ffffff01000000c8ffffff0100000008000000040000006d656d6f5a41500002000000380000008a000000040000000000000000000000000000000000000000000000000000000000000002000000000000000100000000000000000000000000000000000000000000000000000000000000b8ffffff01000000080000002200000009165a4150000200000018000000200000000000000000000000f8ffffff01000000",
|
|
"76c21c1c719205e4bdf2a83b8a3975c464d231406f36b647c92589c810baef0e",
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn an_import_is_the_bytes_go_writes() {
|
|
check(
|
|
Unsigned::Import(ImportTx {
|
|
base: base_fields(),
|
|
source_chain: ids::prefixed(&[6]),
|
|
imported_ins: vec![TransferableInput {
|
|
utxo_id: UtxoId::new(ids::prefixed(&[8]), 3),
|
|
asset: Asset { id: ids::prefixed(&[1]) },
|
|
input: FxIn::Transfer(TransferInput {
|
|
amt: 50,
|
|
input: Input { sig_indices: vec![0] },
|
|
}),
|
|
}],
|
|
}),
|
|
"5a4150000200000090000000160200000800000000000000000000000000000000000000000000000000000000000000030000000100000000000000000000000000000000000000000000000000000000000000080000002a00000001025a41500002000000180000002800000000000000000000003200000000000000f0ffffff01000000000088ffffff000000000400000000000000300000004e0100000600000000000000000000000000000000000000000000000000000000000000c8ffffff0100000000125a41500002000000080100004c0100000100000000000000000000000000000000000000000000000000000000000000080000004600000001015a415000020000002800000044000000aabb000000000000000000000000000000000000000000003930000000000000000000000000000001000000d4ffffff0100000000000200000000000000000000000000000000000000000000000000000000000000070000000100000000000000000000000000000000000000000000000000000000000000080000002a00000001025a41500002000000180000002800000000000000020000003a30000000000000f0ffffff02000000000018ffffff0000000080ffffff000000000a000000000000000500000000000000000000000000000000000000000000000000000000000000c8ffffff01000000c8ffffff0100000008000000040000006d656d6f",
|
|
"000e5a41500002000000100000003a02000014000000160200000000000000000000000000005a4150000200000090000000160200000800000000000000000000000000000000000000000000000000000000000000030000000100000000000000000000000000000000000000000000000000000000000000080000002a00000001025a41500002000000180000002800000000000000000000003200000000000000f0ffffff01000000000088ffffff000000000400000000000000300000004e0100000600000000000000000000000000000000000000000000000000000000000000c8ffffff0100000000125a41500002000000080100004c0100000100000000000000000000000000000000000000000000000000000000000000080000004600000001015a415000020000002800000044000000aabb000000000000000000000000000000000000000000003930000000000000000000000000000001000000d4ffffff0100000000000200000000000000000000000000000000000000000000000000000000000000070000000100000000000000000000000000000000000000000000000000000000000000080000002a00000001025a41500002000000180000002800000000000000020000003a30000000000000f0ffffff02000000000018ffffff0000000080ffffff000000000a000000000000000500000000000000000000000000000000000000000000000000000000000000c8ffffff01000000c8ffffff0100000008000000040000006d656d6f",
|
|
"4c29b16ccaef5d364db2a414ea9f0a87febea057f0b5c67973d3fe418b623350",
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn an_export_is_the_bytes_go_writes() {
|
|
check(
|
|
Unsigned::Export(ExportTx {
|
|
base: base_fields(),
|
|
destination_chain: ids::prefixed(&[6]),
|
|
exported_outs: vec![TransferableOutput {
|
|
asset: Asset { id: ids::prefixed(&[1]) },
|
|
out: State::Transfer(TransferOutput { amt: 50, owners: owner9() }),
|
|
}],
|
|
}),
|
|
"5a41500002000000880000000e0200000100000000000000000000000000000000000000000000000000000000000000080000004600000001015a4150000200000028000000440000000900000000000000000000000000000000000000000000003200000000000000000000000000000001000000d4ffffff01000000000090ffffff000000000500000000000000300000004e0100000600000000000000000000000000000000000000000000000000000000000000c8ffffff0100000000125a41500002000000080100004c0100000100000000000000000000000000000000000000000000000000000000000000080000004600000001015a415000020000002800000044000000aabb000000000000000000000000000000000000000000003930000000000000000000000000000001000000d4ffffff0100000000000200000000000000000000000000000000000000000000000000000000000000070000000100000000000000000000000000000000000000000000000000000000000000080000002a00000001025a41500002000000180000002800000000000000020000003a30000000000000f0ffffff02000000000018ffffff0000000080ffffff000000000a000000000000000500000000000000000000000000000000000000000000000000000000000000c8ffffff01000000c8ffffff0100000008000000040000006d656d6f",
|
|
"000e5a415000020000001000000032020000140000000e0200000000000000000000000000005a41500002000000880000000e0200000100000000000000000000000000000000000000000000000000000000000000080000004600000001015a4150000200000028000000440000000900000000000000000000000000000000000000000000003200000000000000000000000000000001000000d4ffffff01000000000090ffffff000000000500000000000000300000004e0100000600000000000000000000000000000000000000000000000000000000000000c8ffffff0100000000125a41500002000000080100004c0100000100000000000000000000000000000000000000000000000000000000000000080000004600000001015a415000020000002800000044000000aabb000000000000000000000000000000000000000000003930000000000000000000000000000001000000d4ffffff0100000000000200000000000000000000000000000000000000000000000000000000000000070000000100000000000000000000000000000000000000000000000000000000000000080000002a00000001025a41500002000000180000002800000000000000020000003a30000000000000f0ffffff02000000000018ffffff0000000080ffffff000000000a000000000000000500000000000000000000000000000000000000000000000000000000000000c8ffffff01000000c8ffffff0100000008000000040000006d656d6f",
|
|
"9002973879e88f10407576114f6ad69db07013fc297d3c1149f35efbfb49c8bd",
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn a_block_is_the_bytes_go_writes_and_has_the_name_go_gives_it() {
|
|
let tx = Tx::new(Unsigned::Export(ExportTx {
|
|
base: base_fields(),
|
|
destination_chain: ids::prefixed(&[6]),
|
|
exported_outs: vec![TransferableOutput {
|
|
asset: Asset {
|
|
id: ids::prefixed(&[1]),
|
|
},
|
|
out: State::Transfer(TransferOutput {
|
|
amt: 50,
|
|
owners: owner9(),
|
|
}),
|
|
}],
|
|
}));
|
|
let blk = Block::new(
|
|
ids::prefixed(&[0xB1]),
|
|
42,
|
|
123_456,
|
|
ids::prefixed(&[0xAA]),
|
|
vec![tx],
|
|
)
|
|
.unwrap();
|
|
assert_eq!(hex(blk.bytes()), "5a4150000200000018000000ac0200003402000000000000b1000000000000000000000000000000000000000000000000000000000000002a0000000000000040e2010000000000aa00000000000000000000000000000000000000000000000000000000000000a8ffffff010000000800000034020000000e5a415000020000001000000032020000140000000e0200000000000000000000000000005a41500002000000880000000e0200000100000000000000000000000000000000000000000000000000000000000000080000004600000001015a4150000200000028000000440000000900000000000000000000000000000000000000000000003200000000000000000000000000000001000000d4ffffff01000000000090ffffff000000000500000000000000300000004e0100000600000000000000000000000000000000000000000000000000000000000000c8ffffff0100000000125a41500002000000080100004c0100000100000000000000000000000000000000000000000000000000000000000000080000004600000001015a415000020000002800000044000000aabb000000000000000000000000000000000000000000003930000000000000000000000000000001000000d4ffffff0100000000000200000000000000000000000000000000000000000000000000000000000000070000000100000000000000000000000000000000000000000000000000000000000000080000002a00000001025a41500002000000180000002800000000000000020000003a30000000000000f0ffffff02000000000018ffffff0000000080ffffff000000000a000000000000000500000000000000000000000000000000000000000000000000000000000000c8ffffff01000000c8ffffff0100000008000000040000006d656d6f");
|
|
assert_eq!(
|
|
hex(&blk.id()),
|
|
"ddae8ce1976a006d7f45117f1cc0acacbc7f2232a85bc6d3545ad8c5dd07223b"
|
|
);
|
|
|
|
// And Go's own block bytes parse back here to the same block.
|
|
let raw: Vec<u8> = (0.."5a4150000200000018000000ac0200003402000000000000b1000000000000000000000000000000000000000000000000000000000000002a0000000000000040e2010000000000aa00000000000000000000000000000000000000000000000000000000000000a8ffffff010000000800000034020000000e5a415000020000001000000032020000140000000e0200000000000000000000000000005a41500002000000880000000e0200000100000000000000000000000000000000000000000000000000000000000000080000004600000001015a4150000200000028000000440000000900000000000000000000000000000000000000000000003200000000000000000000000000000001000000d4ffffff01000000000090ffffff000000000500000000000000300000004e0100000600000000000000000000000000000000000000000000000000000000000000c8ffffff0100000000125a41500002000000080100004c0100000100000000000000000000000000000000000000000000000000000000000000080000004600000001015a415000020000002800000044000000aabb000000000000000000000000000000000000000000003930000000000000000000000000000001000000d4ffffff0100000000000200000000000000000000000000000000000000000000000000000000000000070000000100000000000000000000000000000000000000000000000000000000000000080000002a00000001025a41500002000000180000002800000000000000020000003a30000000000000f0ffffff02000000000018ffffff0000000080ffffff000000000a000000000000000500000000000000000000000000000000000000000000000000000000000000c8ffffff01000000c8ffffff0100000008000000040000006d656d6f".len())
|
|
.step_by(2)
|
|
.map(|i| u8::from_str_radix(&"5a4150000200000018000000ac0200003402000000000000b1000000000000000000000000000000000000000000000000000000000000002a0000000000000040e2010000000000aa00000000000000000000000000000000000000000000000000000000000000a8ffffff010000000800000034020000000e5a415000020000001000000032020000140000000e0200000000000000000000000000005a41500002000000880000000e0200000100000000000000000000000000000000000000000000000000000000000000080000004600000001015a4150000200000028000000440000000900000000000000000000000000000000000000000000003200000000000000000000000000000001000000d4ffffff01000000000090ffffff000000000500000000000000300000004e0100000600000000000000000000000000000000000000000000000000000000000000c8ffffff0100000000125a41500002000000080100004c0100000100000000000000000000000000000000000000000000000000000000000000080000004600000001015a415000020000002800000044000000aabb000000000000000000000000000000000000000000003930000000000000000000000000000001000000d4ffffff0100000000000200000000000000000000000000000000000000000000000000000000000000070000000100000000000000000000000000000000000000000000000000000000000000080000002a00000001025a41500002000000180000002800000000000000020000003a30000000000000f0ffffff02000000000018ffffff0000000080ffffff000000000a000000000000000500000000000000000000000000000000000000000000000000000000000000c8ffffff01000000c8ffffff0100000008000000040000006d656d6f"[i..i + 2], 16).unwrap())
|
|
.collect();
|
|
let parsed = Block::parse(&raw).unwrap();
|
|
assert_eq!(parsed, blk);
|
|
}
|
|
|
|
#[test]
|
|
fn every_nft_and_property_envelope_is_the_envelope_go_writes() {
|
|
assert_eq!(
|
|
hex(&nft::MintOutput { group_id: 3, owners: owner9() }.bytes()),
|
|
"08105a41500002000000280000004000000009000000000000000000000000000000000000000000000003000000000000000000000001000000d8ffffff01000000"
|
|
);
|
|
let nto = nft::TransferOutput {
|
|
group_id: 3,
|
|
payload: vec![0xde, 0xad],
|
|
owners: owner9(),
|
|
};
|
|
assert_eq!(hex(&nto.bytes()), "08115a41500002000000280000004a00000009000000000000000000000000000000000000000000000003000000000000000000000001000000d8ffffff010000000800000002000000dead");
|
|
assert_eq!(
|
|
hex(&nft::MintOperation {
|
|
mint_input: Input { sig_indices: vec![0] },
|
|
group_id: 3,
|
|
payload: vec![0xde, 0xad],
|
|
outputs: vec![owner9()],
|
|
}
|
|
.bytes()),
|
|
"08135a41500002000000180000007c0000000000000000000000f8ffffff01000000030000001800000002000000010000000e0000003e00000000000000dead00095a41500002000000280000003c000000090000000000000000000000000000000000000000000000000000000000000001000000dcffffff01000000"
|
|
);
|
|
assert_eq!(
|
|
hex(&nft::TransferOperation {
|
|
input: Input { sig_indices: vec![0] },
|
|
output: nto,
|
|
}
|
|
.bytes()),
|
|
"08145a4150000200000018000000740000000000000000000000f8ffffff01000000080000004c00000008115a41500002000000280000004a00000009000000000000000000000000000000000000000000000003000000000000000000000001000000d8ffffff010000000800000002000000dead"
|
|
);
|
|
|
|
let pmo = property::MintOutput { owners: owner9() };
|
|
let poo = property::OwnedOutput { owners: owner9() };
|
|
assert_eq!(hex(&pmo.bytes()), "09035a41500002000000280000003c000000090000000000000000000000000000000000000000000000000000000000000001000000dcffffff01000000");
|
|
assert_eq!(hex(&poo.bytes()), "09155a41500002000000280000003c000000090000000000000000000000000000000000000000000000000000000000000001000000dcffffff01000000");
|
|
assert_eq!(
|
|
hex(&property::MintOperation {
|
|
mint_input: Input { sig_indices: vec![0] },
|
|
mint_output: pmo,
|
|
owned_output: poo,
|
|
}
|
|
.bytes()),
|
|
"09055a4150000200000018000000ac0000000000000000000000f8ffffff01000000100000003e000000460000003e00000009035a41500002000000280000003c000000090000000000000000000000000000000000000000000000000000000000000001000000dcffffff0100000009155a41500002000000280000003c000000090000000000000000000000000000000000000000000000000000000000000001000000dcffffff01000000"
|
|
);
|
|
assert_eq!(
|
|
hex(&property::BurnOperation {
|
|
input: Input {
|
|
sig_indices: vec![0]
|
|
}
|
|
}
|
|
.bytes()),
|
|
"09165a4150000200000018000000200000000000000000000000f8ffffff01000000"
|
|
);
|
|
assert_eq!(
|
|
hex(&lux_xvm::fx::secp256k1::MintOperation {
|
|
mint_input: Input { sig_indices: vec![0] },
|
|
mint_output: MintOutput { owners: owner9() },
|
|
transfer_output: TransferOutput { amt: 7, owners: owner9() },
|
|
}
|
|
.bytes()),
|
|
"01055a4150000200000018000000b40000000000000000000000f8ffffff01000000100000003e000000460000004600000001035a41500002000000280000003c000000090000000000000000000000000000000000000000000000000000000000000001000000dcffffff0100000001015a4150000200000028000000440000000900000000000000000000000000000000000000000000000700000000000000000000000000000001000000d4ffffff01000000"
|
|
);
|
|
|
|
// A credential's family byte is the whole difference between the three.
|
|
let mut sig = [0u8; 65];
|
|
sig[0] = 1;
|
|
sig[1] = 2;
|
|
sig[2] = 3;
|
|
let cred = Credential { sigs: vec![sig] };
|
|
assert_eq!(
|
|
hex(&cred.bytes_for(lux_xvm::wire::TypeKind::Nft)),
|
|
"08065a41500002000000580000006c00000001020300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b4ffffff410000000000000000000000"
|
|
);
|
|
assert_eq!(
|
|
hex(&cred.bytes_for(lux_xvm::wire::TypeKind::Property)),
|
|
"09065a41500002000000580000006c00000001020300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b4ffffff410000000000000000000000"
|
|
);
|
|
}
|