Skip to content

Commit

Permalink
Use Dialect where possible.
Browse files Browse the repository at this point in the history
  • Loading branch information
richardkiss committed Aug 23, 2021
1 parent ca503f6 commit 738b3b0
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 98 deletions.
26 changes: 15 additions & 11 deletions src/chia_dialect_factory.rs → src/chia_dialect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,18 @@ use crate::run_program::OperatorHandler;

const QUOTE_KW: [u8; 1] = [1];
const APPLY_KW: [u8; 1] = [2];

pub fn chia_op_handler(strict: bool) -> Box<dyn OperatorHandler> {
let f_lookup: FLookup = f_lookup_for_hashmap(chia_opcode_mapping());

Box::new(OperatorHandlerWithMode { f_lookup, strict })
}

pub fn chia_dialect(strict: bool) -> Dialect {
Dialect::new(&QUOTE_KW, &APPLY_KW, chia_op_handler(strict))
}

pub struct OperatorHandlerWithMode {
f_lookup: FLookup,
strict: bool,
}

impl OperatorHandlerWithMode {
pub fn new_with_hashmap(hashmap: HashMap<String, Vec<u8>>, strict: bool) -> Self {
let f_lookup: FLookup = f_lookup_for_hashmap(hashmap);
OperatorHandlerWithMode { f_lookup, strict }
}
}

impl OperatorHandler for OperatorHandlerWithMode {
fn op(
&self,
Expand Down Expand Up @@ -88,3 +84,11 @@ pub fn chia_opcode_mapping() -> HashMap<String, Vec<u8>> {
}
h
}

pub fn chia_op_handler(strict: bool) -> OperatorHandlerWithMode {
OperatorHandlerWithMode::new_with_hashmap(chia_opcode_mapping(), strict)
}

pub fn chia_dialect(strict: bool) -> Dialect {
Dialect::new(&QUOTE_KW, &APPLY_KW, Box::new(chia_op_handler(strict)))
}
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
pub mod allocator;
pub mod chia_dialect_factory;
pub mod chia_dialect;
pub mod core_ops;
pub mod cost;
pub mod dialect;
Expand Down
28 changes: 13 additions & 15 deletions src/py/run_generator.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
use crate::allocator::{Allocator, NodePtr};
use crate::chia_dialect::OperatorHandlerWithMode;
use crate::cost::Cost;
use crate::dialect::Dialect;
use crate::gen::conditions::{parse_spends, Condition, SpendConditionSummary};
use crate::gen::opcodes::{
ConditionOpcode, AGG_SIG_ME, AGG_SIG_UNSAFE, ASSERT_HEIGHT_ABSOLUTE, ASSERT_HEIGHT_RELATIVE,
ASSERT_SECONDS_ABSOLUTE, ASSERT_SECONDS_RELATIVE, CREATE_COIN, RESERVE_FEE,
};
use crate::gen::validation_error::{ErrorCode, ValidationErr};
use crate::int_to_bytes::u64_to_bytes;
use crate::py::run_program::OperatorHandlerWithMode;
use crate::reduction::{EvalErr, Reduction};
use crate::run_program::{run_program, STRICT_MODE};
use crate::run_program::STRICT_MODE;
use crate::serialize::node_from_bytes;

use crate::f_table::f_lookup_for_hashmap;
use crate::py::lazy_node::LazyNode;

use std::collections::HashMap;
Expand Down Expand Up @@ -215,24 +215,22 @@ pub fn run_generator(
flags: u32,
) -> PyResult<(Option<ErrorCode>, Vec<PySpendConditionSummary>, Cost)> {
let mut allocator = Allocator::new();
let f_lookup = f_lookup_for_hashmap(opcode_lookup_by_name);
let strict: bool = (flags & STRICT_MODE) != 0;
let f = OperatorHandlerWithMode::new(f_lookup, strict);
let program = node_from_bytes(&mut allocator, program)?;
let args = node_from_bytes(&mut allocator, args)?;
let dialect = Dialect::new(
&[quote_kw],
&[apply_kw],
Box::new(OperatorHandlerWithMode::new_with_hashmap(
opcode_lookup_by_name,
strict,
)),
);

let r = py.allow_threads(
|| -> Result<(Option<ErrorCode>, Cost, Vec<SpendConditionSummary>), EvalErr> {
let Reduction(cost, node) = run_program(
&mut allocator,
program,
args,
&[quote_kw],
&[apply_kw],
max_cost,
&f,
None,
)?;
let Reduction(cost, node) =
dialect.run_program(&mut allocator, program, args, max_cost)?;
// we pass in what's left of max_cost here, to fail early in case the
// cost of a condition brings us over the cost limit
match parse_spends(&allocator, node, max_cost - cost, flags) {
Expand Down
92 changes: 22 additions & 70 deletions src/py/run_program.rs
Original file line number Diff line number Diff line change
@@ -1,56 +1,18 @@
use std::collections::HashMap;
use std::rc::Rc;

use crate::allocator::{Allocator, NodePtr};
use crate::allocator::Allocator;
use crate::chia_dialect::OperatorHandlerWithMode;
use crate::cost::Cost;
use crate::err_utils::err;
use crate::f_table::{f_lookup_for_hashmap, FLookup};
use crate::more_ops::op_unknown;
use crate::dialect::Dialect;
use crate::node::Node;
use crate::py::lazy_node::LazyNode;
use crate::reduction::Response;
use crate::run_program::{run_program, OperatorHandler, STRICT_MODE};
use crate::run_program::STRICT_MODE;
use crate::serialize::{node_from_bytes, node_to_bytes, serialized_length_from_bytes};

use pyo3::prelude::*;
use pyo3::types::{PyBytes, PyDict};

pub struct OperatorHandlerWithMode {
f_lookup: FLookup,
strict: bool,
}

impl OperatorHandlerWithMode {
pub fn new(l: FLookup, strict: bool) -> OperatorHandlerWithMode {
OperatorHandlerWithMode {
f_lookup: l,
strict,
}
}
}

impl OperatorHandler for OperatorHandlerWithMode {
fn op(
&self,
allocator: &mut Allocator,
o: NodePtr,
argument_list: NodePtr,
max_cost: Cost,
) -> Response {
let b = &allocator.atom(o);
if b.len() == 1 {
if let Some(f) = self.f_lookup[b[0] as usize] {
return f(allocator, argument_list, max_cost);
}
}
if self.strict {
err(o, "unimplemented operator")
} else {
op_unknown(allocator, o, argument_list, max_cost)
}
}
}

#[pyfunction]
pub fn serialize_and_run_program(
py: Python,
Expand Down Expand Up @@ -125,24 +87,19 @@ pub fn deserialize_and_run_program(
flags: u32,
) -> PyResult<(Cost, Py<PyBytes>)> {
let mut allocator = Allocator::new();
let f_lookup = f_lookup_for_hashmap(opcode_lookup_by_name);
let strict: bool = (flags & STRICT_MODE) != 0;
let f = OperatorHandlerWithMode { f_lookup, strict };
let dialect = Dialect::new(
&[quote_kw],
&[apply_kw],
Box::new(OperatorHandlerWithMode::new_with_hashmap(
opcode_lookup_by_name,
strict,
)),
);
let program = node_from_bytes(&mut allocator, program)?;
let args = node_from_bytes(&mut allocator, args)?;

let r = py.allow_threads(|| {
run_program(
&mut allocator,
program,
args,
&[quote_kw],
&[apply_kw],
max_cost,
&f,
None,
)
});
let r = py.allow_threads(|| dialect.run_program(&mut allocator, program, args, max_cost));
match r {
Ok(reduction) => {
let node_as_blob = node_to_bytes(&Node::new(&allocator, reduction.1))?;
Expand Down Expand Up @@ -192,24 +149,19 @@ pub fn deserialize_and_run_program2(
flags: u32,
) -> PyResult<(Cost, LazyNode)> {
let mut allocator = Allocator::new();
let f_lookup = f_lookup_for_hashmap(opcode_lookup_by_name);
let strict: bool = (flags & STRICT_MODE) != 0;
let f = OperatorHandlerWithMode { f_lookup, strict };
let program = node_from_bytes(&mut allocator, program)?;
let args = node_from_bytes(&mut allocator, args)?;
let dialect = Dialect::new(
&[quote_kw],
&[apply_kw],
Box::new(OperatorHandlerWithMode::new_with_hashmap(
opcode_lookup_by_name,
strict,
)),
);

let r = py.allow_threads(|| {
run_program(
&mut allocator,
program,
args,
&[quote_kw],
&[apply_kw],
max_cost,
&f,
None,
)
});
let r = py.allow_threads(|| dialect.run_program(&mut allocator, program, args, max_cost));
match r {
Ok(reduction) => {
let val = LazyNode::new(Rc::new(allocator), reduction.1);
Expand Down
2 changes: 1 addition & 1 deletion src/run_program.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const TRAVERSE_BASE_COST: Cost = 40;
const TRAVERSE_COST_PER_ZERO_BYTE: Cost = 4;
const TRAVERSE_COST_PER_BIT: Cost = 4;

pub trait OperatorHandler {
pub trait OperatorHandler: Sync {
fn op(&self, allocator: &mut Allocator, op: NodePtr, args: NodePtr, max_cost: Cost)
-> Response;
}
Expand Down

0 comments on commit 738b3b0

Please sign in to comment.