Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new operators to avoid pedersen commitments in amount validation #276

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/vm/macroasm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ macro_rules! isa_instr {
(pcvs $no:ident) => {{ RgbIsa::Contract(ContractOp::Pcvs($no)) }};
(pcas $no:ident) => {{ RgbIsa::Contract(ContractOp::Pcas($no)) }};
(pcps $no:ident) => {{ RgbIsa::Contract(ContractOp::Pcps($no)) }};
(svs $no:ident) => {{ RgbIsa::Contract(ContractOp::Svs($no)) }};
(sas $no:ident) => {{ RgbIsa::Contract(ContractOp::Sas($no)) }};
(sps $no:ident) => {{ RgbIsa::Contract(ContractOp::Sps($no)) }};
(cng $t:ident,a8[$a_idx:literal]) => {{ RgbIsa::Contract(ContractOp::CnG($t, Reg32::from(u5::with($a_idx)))) }};
(cnc $t:ident,a16[$a_idx:literal]) => {{ RgbIsa::Contract(ContractOp::CnC($t, Reg32::from(u5::with($a_idx)))) }};
(ldm $t:ident,s16[$s_idx:literal]) => {{ RgbIsa::Contract(ContractOp::LdM($t, RegS::from($s_idx))) }};
Expand Down
148 changes: 145 additions & 3 deletions src/vm/op_contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,43 @@
#[display("ldm {0},{1}")]
LdM(MetaType, RegS),

/// Verify sum of inputs and outputs are equal.
///
/// The only argument specifies owned state type for the sum operation. If
/// this state does not exist, or either inputs or outputs does not have
/// any data for the state, the verification fails.
///
/// If verification succeeds, doesn't change `st0` value; otherwise sets it
/// to `false` and stops execution.
#[display("svs {0}")]
Svs(AssignmentType),

/// Verify sum of outputs and value in `a64[0]` register are equal.
///
/// The first argument specifies owned state type for the sum operation. If
/// this state does not exist, or either inputs or outputs does not have
/// any data for the state, the verification fails.
///
/// If `a64[0]` register does not contain value, the verification fails.
///
/// If verification succeeds, doesn't change `st0` value; otherwise sets it
/// to `false` and stops execution.
#[display("sas {0}")]
Sas(/** owned state type */ AssignmentType),

/// Verify sum of inputs and value in `a64[0]` register are equal.
///
/// The first argument specifies owned state type for the sum operation. If
/// this state does not exist, or either inputs or outputs does not have
/// any data for the state, the verification fails.
///
/// If `a64[0]` register does not contain value, the verification fails.
///
/// If verification succeeds, doesn't change `st0` value; otherwise sets it
/// to `false` and stops execution.
#[display("sps {0}")]
Sps(/** owned state type */ AssignmentType),

/// Verify sum of pedersen commitments from inputs and outputs.
///
/// The only argument specifies owned state type for the sum operation. If
Expand Down Expand Up @@ -202,6 +239,8 @@
| ContractOp::LdM(_, _) => bset![],
ContractOp::Pcvs(_) => bset![],
ContractOp::Pcas(_) | ContractOp::Pcps(_) => bset![Reg::A(RegA::A64, Reg32::Reg0)],
ContractOp::Svs(_) => bset![],
ContractOp::Sas(_) | ContractOp::Sps(_) => bset![Reg::A(RegA::A64, Reg32::Reg0)],

Check warning on line 243 in src/vm/op_contract.rs

View check run for this annotation

Codecov / codecov/patch

src/vm/op_contract.rs#L242-L243

Added lines #L242 - L243 were not covered by tests
ContractOp::Fail(_, _) => bset![],
}
}
Expand All @@ -227,6 +266,9 @@
ContractOp::Pcvs(_) | ContractOp::Pcas(_) | ContractOp::Pcps(_) => {
bset![]
}
ContractOp::Svs(_) | ContractOp::Sas(_) | ContractOp::Sps(_) => {
bset![]

Check warning on line 270 in src/vm/op_contract.rs

View check run for this annotation

Codecov / codecov/patch

src/vm/op_contract.rs#L270

Added line #L270 was not covered by tests
}
ContractOp::Fail(_, _) => bset![],
}
}
Expand All @@ -243,6 +285,10 @@
| ContractOp::LdG(_, _, _)
| ContractOp::LdC(_, _, _) => 8,
ContractOp::LdM(_, _) => 6,
// TODO: what are the proper values for complexity?
ContractOp::Svs(_)
| ContractOp::Sas(_)
| ContractOp::Sps(_) => 20,

Check warning on line 291 in src/vm/op_contract.rs

View check run for this annotation

Codecov / codecov/patch

src/vm/op_contract.rs#L291

Added line #L291 was not covered by tests
ContractOp::Pcvs(_) => 1024,
ContractOp::Pcas(_) | ContractOp::Pcps(_) => 512,
ContractOp::Fail(_, _) => u64::MAX,
Expand Down Expand Up @@ -286,6 +332,38 @@
}
}};
}
macro_rules! load_revealed_inputs {
($state_type:ident) => {{
let Some(prev_state) = context.op_info.prev_state.get($state_type) else {
fail!()
};
match prev_state {
TypedAssigns::Fungible(state) => state
.iter()
.map(Assign::as_revealed_state)
// TODO: properly fail if we can't read revealed state
.map(|s| s.unwrap().value.as_u64())

Check warning on line 345 in src/vm/op_contract.rs

View check run for this annotation

Codecov / codecov/patch

src/vm/op_contract.rs#L345

Added line #L345 was not covered by tests
.collect::<Vec<_>>(),
_ => fail!(),
}
}};
}
macro_rules! load_revealed_outputs {
($state_type:ident) => {{
let Some(new_state) = context.op_info.owned_state.get(*$state_type) else {
fail!()
};
match new_state {
TypedAssigns::Fungible(state) => state
.iter()
.map(Assign::as_revealed_state)
// TODO: properly fail if we can't read revealed state
.map(|s| s.unwrap().value.as_u64())

Check warning on line 361 in src/vm/op_contract.rs

View check run for this annotation

Codecov / codecov/patch

src/vm/op_contract.rs#L361

Added line #L361 was not covered by tests
.collect::<Vec<_>>(),
_ => fail!(),
}
}};
}

match self {
ContractOp::CnP(state_type, reg) => {
Expand Down Expand Up @@ -473,6 +551,59 @@
fail!()
}
}
ContractOp::Svs(state_type) => {
let Some(input_amt) = load_revealed_inputs!(state_type)
.iter()
.try_fold(0u64, |acc, &x| acc.checked_add(x))

Check warning on line 557 in src/vm/op_contract.rs

View check run for this annotation

Codecov / codecov/patch

src/vm/op_contract.rs#L554-L557

Added lines #L554 - L557 were not covered by tests
else {
fail!()

Check warning on line 559 in src/vm/op_contract.rs

View check run for this annotation

Codecov / codecov/patch

src/vm/op_contract.rs#L559

Added line #L559 was not covered by tests
};
let Some(output_amt) = load_revealed_outputs!(state_type)
.iter()
.try_fold(0u64, |acc, &x| acc.checked_add(x))

Check warning on line 563 in src/vm/op_contract.rs

View check run for this annotation

Codecov / codecov/patch

src/vm/op_contract.rs#L561-L563

Added lines #L561 - L563 were not covered by tests
else {
fail!()

Check warning on line 565 in src/vm/op_contract.rs

View check run for this annotation

Codecov / codecov/patch

src/vm/op_contract.rs#L565

Added line #L565 was not covered by tests
};
if input_amt != output_amt {
fail!()
}

Check warning on line 569 in src/vm/op_contract.rs

View check run for this annotation

Codecov / codecov/patch

src/vm/op_contract.rs#L567-L569

Added lines #L567 - L569 were not covered by tests
}

ContractOp::Sas(owned_state) => {
let Some(sum) = *regs.get_n(RegA::A64, Reg32::Reg0) else {
fail!()

Check warning on line 574 in src/vm/op_contract.rs

View check run for this annotation

Codecov / codecov/patch

src/vm/op_contract.rs#L572-L574

Added lines #L572 - L574 were not covered by tests
};
let sum = u64::from(sum);

Check warning on line 576 in src/vm/op_contract.rs

View check run for this annotation

Codecov / codecov/patch

src/vm/op_contract.rs#L576

Added line #L576 was not covered by tests

let Some(output_amt) = load_revealed_outputs!(owned_state)
.iter()
.try_fold(0u64, |acc, &x| acc.checked_add(x))

Check warning on line 580 in src/vm/op_contract.rs

View check run for this annotation

Codecov / codecov/patch

src/vm/op_contract.rs#L578-L580

Added lines #L578 - L580 were not covered by tests
else {
fail!()

Check warning on line 582 in src/vm/op_contract.rs

View check run for this annotation

Codecov / codecov/patch

src/vm/op_contract.rs#L582

Added line #L582 was not covered by tests
};

if sum != output_amt {
fail!()
}

Check warning on line 587 in src/vm/op_contract.rs

View check run for this annotation

Codecov / codecov/patch

src/vm/op_contract.rs#L585-L587

Added lines #L585 - L587 were not covered by tests
}

ContractOp::Sps(owned_state) => {
let Some(sum) = *regs.get_n(RegA::A64, Reg32::Reg0) else {
fail!()

Check warning on line 592 in src/vm/op_contract.rs

View check run for this annotation

Codecov / codecov/patch

src/vm/op_contract.rs#L590-L592

Added lines #L590 - L592 were not covered by tests
};
let sum = u64::from(sum);

Check warning on line 594 in src/vm/op_contract.rs

View check run for this annotation

Codecov / codecov/patch

src/vm/op_contract.rs#L594

Added line #L594 was not covered by tests

let Some(input_amt) = load_revealed_inputs!(owned_state)
.iter()
.try_fold(0u64, |acc, &x| acc.checked_add(x))

Check warning on line 598 in src/vm/op_contract.rs

View check run for this annotation

Codecov / codecov/patch

src/vm/op_contract.rs#L596-L598

Added lines #L596 - L598 were not covered by tests
else {
fail!()

Check warning on line 600 in src/vm/op_contract.rs

View check run for this annotation

Codecov / codecov/patch

src/vm/op_contract.rs#L600

Added line #L600 was not covered by tests
};

if sum != input_amt {
fail!()
}

Check warning on line 605 in src/vm/op_contract.rs

View check run for this annotation

Codecov / codecov/patch

src/vm/op_contract.rs#L603-L605

Added lines #L603 - L605 were not covered by tests
}
// All other future unsupported operations, which must set `st0` to `false`.
_ => fail!(),
}
Expand Down Expand Up @@ -501,6 +632,10 @@
ContractOp::Pcas(_) => INSTR_PCAS,
ContractOp::Pcps(_) => INSTR_PCPS,

ContractOp::Svs(_) => INSTR_SVS,
ContractOp::Sas(_) => INSTR_SAS,
ContractOp::Sps(_) => INSTR_SPS,

Check warning on line 637 in src/vm/op_contract.rs

View check run for this annotation

Codecov / codecov/patch

src/vm/op_contract.rs#L635-L637

Added lines #L635 - L637 were not covered by tests

ContractOp::Fail(other, _) => *other,
}
}
Expand Down Expand Up @@ -559,9 +694,12 @@
writer.write_u4(u4::ZERO)?;
}

ContractOp::Pcvs(state_type) => writer.write_u16(*state_type)?,
ContractOp::Pcas(owned_type) => writer.write_u16(*owned_type)?,
ContractOp::Pcps(owned_type) => writer.write_u16(*owned_type)?,
ContractOp::Pcvs(state_type)
| ContractOp::Svs(state_type) => writer.write_u16(*state_type)?,
ContractOp::Pcas(owned_type)
| ContractOp::Sas(owned_type) => writer.write_u16(*owned_type)?,
ContractOp::Pcps(owned_type)
| ContractOp::Sps(owned_type) => writer.write_u16(*owned_type)?,

Check warning on line 702 in src/vm/op_contract.rs

View check run for this annotation

Codecov / codecov/patch

src/vm/op_contract.rs#L697-L702

Added lines #L697 - L702 were not covered by tests

ContractOp::Fail(_, _) => {}
}
Expand Down Expand Up @@ -630,6 +768,10 @@
INSTR_PCAS => Self::Pcas(reader.read_u16()?.into()),
INSTR_PCPS => Self::Pcps(reader.read_u16()?.into()),

INSTR_SVS => Self::Svs(reader.read_u16()?.into()),
INSTR_SAS => Self::Sas(reader.read_u16()?.into()),
INSTR_SPS => Self::Sps(reader.read_u16()?.into()),

Check warning on line 773 in src/vm/op_contract.rs

View check run for this annotation

Codecov / codecov/patch

src/vm/op_contract.rs#L771-L773

Added lines #L771 - L773 were not covered by tests

x => Self::Fail(x, PhantomData),
})
}
Expand Down
5 changes: 4 additions & 1 deletion src/vm/opcodes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,11 @@ pub const INSTR_PCVS: u8 = 0b11_010_000;
pub const INSTR_PCAS: u8 = 0b11_010_001;
pub const INSTR_PCPS: u8 = 0b11_010_010;
// Reserved 0b11_010_011
pub const INSTR_SVS: u8 = 0b11_010_100;
pub const INSTR_SAS: u8 = 0b11_010_101;
pub const INSTR_SPS: u8 = 0b11_010_110;
pub const INSTR_CONTRACT_FROM: u8 = 0b11_000_000;
pub const INSTR_CONTRACT_TO: u8 = 0b11_010_011;
pub const INSTR_CONTRACT_TO: u8 = 0b11_011_011;

// TIMECHAIN:
pub const INSTR_TIMECHAIN_FROM: u8 = 0b11_011_100;
Expand Down
Loading