make TCS compiler GIR control validation and lowering
This commit is contained in:
parent
14ffe45caa
commit
6e89b82d88
5 changed files with 271 additions and 17 deletions
|
|
@ -142,3 +142,24 @@ fn compiler_gir_tampering_and_negative_program_fail_closed() {
|
||||||
.expect_err("unregistered operation must still fail through compiler GIR");
|
.expect_err("unregistered operation must still fail through compiler GIR");
|
||||||
assert_eq!(error.code, "TCS-E2101");
|
assert_eq!(error.code, "TCS-E2101");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn tcs_compiler_source_controls_operation_policy_and_gir_lowering() {
|
||||||
|
let compiler_source = compiler_source()
|
||||||
|
.replace(
|
||||||
|
"registered_operations = [\"CORE.ECHO\"]",
|
||||||
|
"registered_operations = [\"ABSORB\"]",
|
||||||
|
)
|
||||||
|
.replace("to = \"exact_target\"", "to = \"policy_selected_target\"");
|
||||||
|
let compiler = tcs_stage0::bootstrap_compiler(&compiler_source).expect("policy compiler GIR");
|
||||||
|
|
||||||
|
let absorb_program = example().replace("CORE.ECHO", "ABSORB");
|
||||||
|
let gir = tcs_stage0::compile_with_compiler_gir(&compiler, &absorb_program)
|
||||||
|
.expect("TCS source policy permits ABSORB at compile time");
|
||||||
|
assert!(gir.get("policy_selected_target").is_some());
|
||||||
|
assert!(gir.get("exact_target").is_none());
|
||||||
|
|
||||||
|
let error = tcs_stage0::compile_with_compiler_gir(&compiler, &example())
|
||||||
|
.expect_err("TCS source policy rejects operation removed from its registry");
|
||||||
|
assert_eq!(error.code, "TCS-E2101");
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
"compiled_from": {
|
"compiled_from": {
|
||||||
"compiler_id": "TCS-STAGE0-IGNITION-0001",
|
"compiler_id": "TCS-STAGE0-IGNITION-0001",
|
||||||
"compiler_state": "FOREIGN_HOST_BOOTSTRAP_SEED_NOT_SELF_HOSTED",
|
"compiler_state": "FOREIGN_HOST_BOOTSTRAP_SEED_NOT_SELF_HOSTED",
|
||||||
"source_sha256": "d375adb7a715c93320c14f3e38a3fa10bc764493d62cfa671e5dfd2d4d3b049f"
|
"source_sha256": "49259d15c57f3a725a7507ae746c372cebf9b3fc58dba580f7c41456d2344f73"
|
||||||
},
|
},
|
||||||
"compiler_definition": {
|
"compiler_definition": {
|
||||||
"canonicalization": {
|
"canonicalization": {
|
||||||
|
|
@ -116,6 +116,26 @@
|
||||||
"from": "all",
|
"from": "all",
|
||||||
"to": "unresolved_natural_language",
|
"to": "unresolved_natural_language",
|
||||||
"transform": "MUST_BE_FALSE"
|
"transform": "MUST_BE_FALSE"
|
||||||
|
},
|
||||||
|
"G013": {
|
||||||
|
"from": "inputs",
|
||||||
|
"to": "inputs",
|
||||||
|
"transform": "COPY_RESOLVED_VALUES"
|
||||||
|
},
|
||||||
|
"G014": {
|
||||||
|
"from": "outputs",
|
||||||
|
"to": "outputs",
|
||||||
|
"transform": "COPY_RESOLVED_VALUES"
|
||||||
|
},
|
||||||
|
"G015": {
|
||||||
|
"from": "conditions",
|
||||||
|
"to": "conditions",
|
||||||
|
"transform": "COPY_RESOLVED_CONDITIONS"
|
||||||
|
},
|
||||||
|
"G016": {
|
||||||
|
"from": "failure",
|
||||||
|
"to": "failure_plan",
|
||||||
|
"transform": "COPY_EXPLICIT_FAILURE_SEMANTICS"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"output_contract": {
|
"output_contract": {
|
||||||
|
|
@ -237,7 +257,27 @@
|
||||||
"V010": {
|
"V010": {
|
||||||
"error": "TCS-E4001",
|
"error": "TCS-E4001",
|
||||||
"rule": "RELATION_AND_EMOTION_DO_NOT_GRANT_AUTHORITY"
|
"rule": "RELATION_AND_EMOTION_DO_NOT_GRANT_AUTHORITY"
|
||||||
}
|
},
|
||||||
|
"registered_operations": [
|
||||||
|
"CORE.ECHO"
|
||||||
|
],
|
||||||
|
"required_sections": [
|
||||||
|
"header",
|
||||||
|
"source",
|
||||||
|
"subject",
|
||||||
|
"target",
|
||||||
|
"inputs",
|
||||||
|
"outputs",
|
||||||
|
"conditions",
|
||||||
|
"actions",
|
||||||
|
"authority",
|
||||||
|
"resources",
|
||||||
|
"failure",
|
||||||
|
"stop",
|
||||||
|
"cleanup",
|
||||||
|
"rollback",
|
||||||
|
"receipt"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"self_host": {
|
"self_host": {
|
||||||
"compiler_A_compiles_stage1_to": "compiler-B.gir",
|
"compiler_A_compiles_stage1_to": "compiler-B.gir",
|
||||||
|
|
@ -329,7 +369,7 @@
|
||||||
"execution_abi": "TCS-COMPILER-GIR-EXEC/1",
|
"execution_abi": "TCS-COMPILER-GIR-EXEC/1",
|
||||||
"identity": {
|
"identity": {
|
||||||
"compiler_id": "TCS-COMPILER-STAGE1-0001",
|
"compiler_id": "TCS-COMPILER-STAGE1-0001",
|
||||||
"definition_sha256": "c2bf0e4e93f9952daf661628aa7b17891718c53b9fbb5e77636f5f40812ff9f6",
|
"definition_sha256": "3e27046ef79f33c1f60705d6774773265df30e2299c390673ae9b8029c8235b2",
|
||||||
"language_version": "0.1"
|
"language_version": "0.1"
|
||||||
},
|
},
|
||||||
"native_self_hosted": false,
|
"native_self_hosted": false,
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
"compiled_from": {
|
"compiled_from": {
|
||||||
"compiler_id": "TCS-COMPILER-STAGE1-0001",
|
"compiler_id": "TCS-COMPILER-STAGE1-0001",
|
||||||
"compiler_state": "TCS_COMPILER_GIR_EXECUTED",
|
"compiler_state": "TCS_COMPILER_GIR_EXECUTED",
|
||||||
"source_sha256": "d375adb7a715c93320c14f3e38a3fa10bc764493d62cfa671e5dfd2d4d3b049f"
|
"source_sha256": "49259d15c57f3a725a7507ae746c372cebf9b3fc58dba580f7c41456d2344f73"
|
||||||
},
|
},
|
||||||
"compiler_definition": {
|
"compiler_definition": {
|
||||||
"canonicalization": {
|
"canonicalization": {
|
||||||
|
|
@ -116,6 +116,26 @@
|
||||||
"from": "all",
|
"from": "all",
|
||||||
"to": "unresolved_natural_language",
|
"to": "unresolved_natural_language",
|
||||||
"transform": "MUST_BE_FALSE"
|
"transform": "MUST_BE_FALSE"
|
||||||
|
},
|
||||||
|
"G013": {
|
||||||
|
"from": "inputs",
|
||||||
|
"to": "inputs",
|
||||||
|
"transform": "COPY_RESOLVED_VALUES"
|
||||||
|
},
|
||||||
|
"G014": {
|
||||||
|
"from": "outputs",
|
||||||
|
"to": "outputs",
|
||||||
|
"transform": "COPY_RESOLVED_VALUES"
|
||||||
|
},
|
||||||
|
"G015": {
|
||||||
|
"from": "conditions",
|
||||||
|
"to": "conditions",
|
||||||
|
"transform": "COPY_RESOLVED_CONDITIONS"
|
||||||
|
},
|
||||||
|
"G016": {
|
||||||
|
"from": "failure",
|
||||||
|
"to": "failure_plan",
|
||||||
|
"transform": "COPY_EXPLICIT_FAILURE_SEMANTICS"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"output_contract": {
|
"output_contract": {
|
||||||
|
|
@ -237,7 +257,27 @@
|
||||||
"V010": {
|
"V010": {
|
||||||
"error": "TCS-E4001",
|
"error": "TCS-E4001",
|
||||||
"rule": "RELATION_AND_EMOTION_DO_NOT_GRANT_AUTHORITY"
|
"rule": "RELATION_AND_EMOTION_DO_NOT_GRANT_AUTHORITY"
|
||||||
}
|
},
|
||||||
|
"registered_operations": [
|
||||||
|
"CORE.ECHO"
|
||||||
|
],
|
||||||
|
"required_sections": [
|
||||||
|
"header",
|
||||||
|
"source",
|
||||||
|
"subject",
|
||||||
|
"target",
|
||||||
|
"inputs",
|
||||||
|
"outputs",
|
||||||
|
"conditions",
|
||||||
|
"actions",
|
||||||
|
"authority",
|
||||||
|
"resources",
|
||||||
|
"failure",
|
||||||
|
"stop",
|
||||||
|
"cleanup",
|
||||||
|
"rollback",
|
||||||
|
"receipt"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"self_host": {
|
"self_host": {
|
||||||
"compiler_A_compiles_stage1_to": "compiler-B.gir",
|
"compiler_A_compiles_stage1_to": "compiler-B.gir",
|
||||||
|
|
@ -329,7 +369,7 @@
|
||||||
"execution_abi": "TCS-COMPILER-GIR-EXEC/1",
|
"execution_abi": "TCS-COMPILER-GIR-EXEC/1",
|
||||||
"identity": {
|
"identity": {
|
||||||
"compiler_id": "TCS-COMPILER-STAGE1-0001",
|
"compiler_id": "TCS-COMPILER-STAGE1-0001",
|
||||||
"definition_sha256": "c2bf0e4e93f9952daf661628aa7b17891718c53b9fbb5e77636f5f40812ff9f6",
|
"definition_sha256": "3e27046ef79f33c1f60705d6774773265df30e2299c390673ae9b8029c8235b2",
|
||||||
"language_version": "0.1"
|
"language_version": "0.1"
|
||||||
},
|
},
|
||||||
"native_self_hosted": true,
|
"native_self_hosted": true,
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,8 @@ COMPILER TCS-COMPILER-STAGE1-0001 {
|
||||||
floating_point = "FORBIDDEN_V0_1";
|
floating_point = "FORBIDDEN_V0_1";
|
||||||
}
|
}
|
||||||
program_validation {
|
program_validation {
|
||||||
|
required_sections = ["header", "source", "subject", "target", "inputs", "outputs", "conditions", "actions", "authority", "resources", "failure", "stop", "cleanup", "rollback", "receipt"];
|
||||||
|
registered_operations = ["CORE.ECHO"];
|
||||||
V001 { rule = "EXACT_REQUIRED_SECTIONS"; standard = "TCS-FIELD-STANDARD-0001"; error_missing = "TCS-E1004"; error_unknown = "TCS-E1003"; }
|
V001 { rule = "EXACT_REQUIRED_SECTIONS"; standard = "TCS-FIELD-STANDARD-0001"; error_missing = "TCS-E1004"; error_unknown = "TCS-E1003"; }
|
||||||
V002 { rule = "CLOSED_FIELDS_PER_SECTION"; error = "TCS-E1003"; }
|
V002 { rule = "CLOSED_FIELDS_PER_SECTION"; error = "TCS-E1003"; }
|
||||||
V003 { rule = "ALL_INPUT_OUTPUT_AND_ACTION_REFS_RESOLVE"; error = "TCS-E2002"; }
|
V003 { rule = "ALL_INPUT_OUTPUT_AND_ACTION_REFS_RESOLVE"; error = "TCS-E2002"; }
|
||||||
|
|
@ -69,6 +71,10 @@ COMPILER TCS-COMPILER-STAGE1-0001 {
|
||||||
G010 { from = "rollback"; to = "rollback_plan"; transform = "COPY_ACTIONS_AND_VERIFICATION"; }
|
G010 { from = "rollback"; to = "rollback_plan"; transform = "COPY_ACTIONS_AND_VERIFICATION"; }
|
||||||
G011 { from = "receipt"; to = "receipt_plan"; transform = "BIND_MACHINE_AND_HUMAN_OUTPUTS"; }
|
G011 { from = "receipt"; to = "receipt_plan"; transform = "BIND_MACHINE_AND_HUMAN_OUTPUTS"; }
|
||||||
G012 { from = "all"; to = "unresolved_natural_language"; transform = "MUST_BE_FALSE"; }
|
G012 { from = "all"; to = "unresolved_natural_language"; transform = "MUST_BE_FALSE"; }
|
||||||
|
G013 { from = "inputs"; to = "inputs"; transform = "COPY_RESOLVED_VALUES"; }
|
||||||
|
G014 { from = "outputs"; to = "outputs"; transform = "COPY_RESOLVED_VALUES"; }
|
||||||
|
G015 { from = "conditions"; to = "conditions"; transform = "COPY_RESOLVED_CONDITIONS"; }
|
||||||
|
G016 { from = "failure"; to = "failure_plan"; transform = "COPY_EXPLICIT_FAILURE_SEMANTICS"; }
|
||||||
}
|
}
|
||||||
canonicalization {
|
canonicalization {
|
||||||
object_keys = "UTF8_BYTE_ORDER";
|
object_keys = "UTF8_BYTE_ORDER";
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ use serde::{Deserialize, Serialize};
|
||||||
use serde_json::{json, Value as JsonValue};
|
use serde_json::{json, Value as JsonValue};
|
||||||
use sha2::{Digest, Sha256};
|
use sha2::{Digest, Sha256};
|
||||||
use std::{
|
use std::{
|
||||||
collections::BTreeMap,
|
collections::{BTreeMap, BTreeSet},
|
||||||
fs,
|
fs,
|
||||||
path::{Component, Path, PathBuf},
|
path::{Component, Path, PathBuf},
|
||||||
};
|
};
|
||||||
|
|
@ -608,13 +608,26 @@ pub fn validate_program(document: &TcsDocument) -> Result<(), TcsError> {
|
||||||
"Stage-0 executable subset accepts PROGRAM only",
|
"Stage-0 executable subset accepts PROGRAM only",
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
for section in PROGRAM_SECTIONS {
|
let sections = PROGRAM_SECTIONS
|
||||||
|
.iter()
|
||||||
|
.map(|value| (*value).to_owned())
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
let operations = BTreeSet::from(["CORE.ECHO".to_owned()]);
|
||||||
|
validate_program_contract(document, §ions, &operations)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn validate_program_contract(
|
||||||
|
document: &TcsDocument,
|
||||||
|
sections: &[String],
|
||||||
|
registered_operations: &BTreeSet<String>,
|
||||||
|
) -> Result<(), TcsError> {
|
||||||
|
for section in sections {
|
||||||
document.body.get(section).ok_or_else(|| {
|
document.body.get(section).ok_or_else(|| {
|
||||||
TcsError::new("TCS-E1004", format!("required section {section} missing"))
|
TcsError::new("TCS-E1004", format!("required section {section} missing"))
|
||||||
})?;
|
})?;
|
||||||
}
|
}
|
||||||
for section in document.body.keys() {
|
for section in document.body.keys() {
|
||||||
if !PROGRAM_SECTIONS.contains(§ion.as_str()) {
|
if !sections.contains(section) {
|
||||||
return Err(TcsError::new(
|
return Err(TcsError::new(
|
||||||
"TCS-E1003",
|
"TCS-E1003",
|
||||||
format!("unknown PROGRAM section {section}"),
|
format!("unknown PROGRAM section {section}"),
|
||||||
|
|
@ -647,7 +660,7 @@ pub fn validate_program(document: &TcsDocument) -> Result<(), TcsError> {
|
||||||
for (action_id, action) in actions {
|
for (action_id, action) in actions {
|
||||||
let action = action.object(action_id)?;
|
let action = action.object(action_id)?;
|
||||||
let operation = required_text(action, "operation")?;
|
let operation = required_text(action, "operation")?;
|
||||||
if operation != "CORE.ECHO" {
|
if !registered_operations.contains(operation) {
|
||||||
return Err(TcsError::new(
|
return Err(TcsError::new(
|
||||||
"TCS-E2101",
|
"TCS-E2101",
|
||||||
format!("unregistered TCS operation {operation}"),
|
format!("unregistered TCS operation {operation}"),
|
||||||
|
|
@ -665,6 +678,99 @@ pub fn validate_program(document: &TcsDocument) -> Result<(), TcsError> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct CompilerPolicy {
|
||||||
|
required_sections: Vec<String>,
|
||||||
|
registered_operations: BTreeSet<String>,
|
||||||
|
lowerings: BTreeMap<String, String>,
|
||||||
|
output_schema: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn compiler_policy(compiler: &JsonValue) -> Result<CompilerPolicy, TcsError> {
|
||||||
|
fn text_array(value: &JsonValue, pointer: &str) -> Result<Vec<String>, TcsError> {
|
||||||
|
value
|
||||||
|
.pointer(pointer)
|
||||||
|
.and_then(JsonValue::as_array)
|
||||||
|
.ok_or_else(|| TcsError::new("TCS-E3002", format!("missing array {pointer}")))?
|
||||||
|
.iter()
|
||||||
|
.map(|item| {
|
||||||
|
item.as_str().map(str::to_owned).ok_or_else(|| {
|
||||||
|
TcsError::new("TCS-E3002", format!("non-text item in {pointer}"))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
let required_sections = text_array(
|
||||||
|
compiler,
|
||||||
|
"/compiler_definition/program_validation/required_sections",
|
||||||
|
)?;
|
||||||
|
let registered_operations = text_array(
|
||||||
|
compiler,
|
||||||
|
"/compiler_definition/program_validation/registered_operations",
|
||||||
|
)?
|
||||||
|
.into_iter()
|
||||||
|
.collect::<BTreeSet<_>>();
|
||||||
|
if required_sections.is_empty() || registered_operations.is_empty() {
|
||||||
|
return Err(TcsError::new(
|
||||||
|
"TCS-E3002",
|
||||||
|
"compiler policy must not be empty",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
let lowering_rules = compiler
|
||||||
|
.pointer("/compiler_definition/lowering_to_gir")
|
||||||
|
.and_then(JsonValue::as_object)
|
||||||
|
.ok_or_else(|| TcsError::new("TCS-E3002", "lowering rules missing"))?;
|
||||||
|
let mut lowerings = BTreeMap::new();
|
||||||
|
for rule in lowering_rules.values() {
|
||||||
|
let Some(from) = rule.get("from").and_then(JsonValue::as_str) else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
let to = rule
|
||||||
|
.get("to")
|
||||||
|
.and_then(JsonValue::as_str)
|
||||||
|
.ok_or_else(|| TcsError::new("TCS-E3002", "lowering target missing"))?;
|
||||||
|
if document_section(from) && lowerings.insert(from.to_owned(), to.to_owned()).is_some() {
|
||||||
|
return Err(TcsError::new("TCS-E3002", "duplicate lowering source"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let required_lowerings = [
|
||||||
|
"subject",
|
||||||
|
"target",
|
||||||
|
"inputs",
|
||||||
|
"outputs",
|
||||||
|
"conditions",
|
||||||
|
"actions",
|
||||||
|
"authority",
|
||||||
|
"resources",
|
||||||
|
"failure",
|
||||||
|
"stop",
|
||||||
|
"cleanup",
|
||||||
|
"rollback",
|
||||||
|
"receipt",
|
||||||
|
];
|
||||||
|
if required_lowerings
|
||||||
|
.iter()
|
||||||
|
.any(|field| !lowerings.contains_key(*field))
|
||||||
|
{
|
||||||
|
return Err(TcsError::new(
|
||||||
|
"TCS-E3002",
|
||||||
|
"compiler lowering map is incomplete",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
Ok(CompilerPolicy {
|
||||||
|
required_sections,
|
||||||
|
registered_operations,
|
||||||
|
lowerings,
|
||||||
|
output_schema: json_text(compiler, "/compiler_definition/output_contract/schema")?
|
||||||
|
.to_owned(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn document_section(value: &str) -> bool {
|
||||||
|
!matches!(value, "header" | "source" | "all")
|
||||||
|
}
|
||||||
|
|
||||||
fn validate_exact_sections(document: &TcsDocument, expected: &[&str]) -> Result<(), TcsError> {
|
fn validate_exact_sections(document: &TcsDocument, expected: &[&str]) -> Result<(), TcsError> {
|
||||||
for section in expected {
|
for section in expected {
|
||||||
document.body.get(*section).ok_or_else(|| {
|
document.body.get(*section).ok_or_else(|| {
|
||||||
|
|
@ -759,6 +865,7 @@ pub fn sha256_hex(bytes: impl AsRef<[u8]>) -> String {
|
||||||
format!("{:x}", Sha256::digest(bytes.as_ref()))
|
format!("{:x}", Sha256::digest(bytes.as_ref()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "bootstrap")]
|
||||||
fn lower_program(
|
fn lower_program(
|
||||||
document: &TcsDocument,
|
document: &TcsDocument,
|
||||||
source_sha256: &str,
|
source_sha256: &str,
|
||||||
|
|
@ -798,6 +905,44 @@ fn lower_program(
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn lower_program_with_policy(
|
||||||
|
document: &TcsDocument,
|
||||||
|
source_sha256: &str,
|
||||||
|
compiler_id: &str,
|
||||||
|
policy: &CompilerPolicy,
|
||||||
|
) -> Result<JsonValue, TcsError> {
|
||||||
|
let mut gir = json!({
|
||||||
|
"schema": policy.output_schema,
|
||||||
|
"identity": {
|
||||||
|
"gir_id": format!("GIR-{}", document.declaration_id),
|
||||||
|
"program_id": document.declaration_id,
|
||||||
|
"language_version": document.language_version,
|
||||||
|
},
|
||||||
|
"compiled_from": {
|
||||||
|
"source_sha256": source_sha256,
|
||||||
|
"compiler_id": compiler_id,
|
||||||
|
"compiler_state": "TCS_COMPILER_GIR_EXECUTED",
|
||||||
|
},
|
||||||
|
"unresolved_natural_language": false,
|
||||||
|
"native_self_hosted": true,
|
||||||
|
});
|
||||||
|
let object = gir
|
||||||
|
.as_object_mut()
|
||||||
|
.ok_or_else(|| TcsError::new("TCS-E8001", "GIR root must be object"))?;
|
||||||
|
for (from, to) in &policy.lowerings {
|
||||||
|
let value = document
|
||||||
|
.body
|
||||||
|
.get(from)
|
||||||
|
.ok_or_else(|| TcsError::new("TCS-E3002", format!("lowering source {from} missing")))?;
|
||||||
|
object.insert(
|
||||||
|
to.clone(),
|
||||||
|
serde_json::to_value(value)
|
||||||
|
.map_err(|error| TcsError::new("TCS-E8001", error.to_string()))?,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Ok(gir)
|
||||||
|
}
|
||||||
|
|
||||||
fn compiler_definition_sha256(document: &TcsDocument) -> Result<String, TcsError> {
|
fn compiler_definition_sha256(document: &TcsDocument) -> Result<String, TcsError> {
|
||||||
let definition = serde_json::to_vec(&document.body)
|
let definition = serde_json::to_vec(&document.body)
|
||||||
.map_err(|error| TcsError::new("TCS-E8001", error.to_string()))?;
|
.map_err(|error| TcsError::new("TCS-E8001", error.to_string()))?;
|
||||||
|
|
@ -922,18 +1067,20 @@ pub fn compile_with_compiler_gir(
|
||||||
source: &str,
|
source: &str,
|
||||||
) -> Result<JsonValue, TcsError> {
|
) -> Result<JsonValue, TcsError> {
|
||||||
let (compiler_id, _) = verify_compiler_gir(compiler)?;
|
let (compiler_id, _) = verify_compiler_gir(compiler)?;
|
||||||
|
let policy = compiler_policy(compiler)?;
|
||||||
let document = parse(source)?;
|
let document = parse(source)?;
|
||||||
let source_sha256 = sha256_hex(source.as_bytes());
|
let source_sha256 = sha256_hex(source.as_bytes());
|
||||||
match document.declaration_kind.as_str() {
|
match document.declaration_kind.as_str() {
|
||||||
"PROGRAM" => {
|
"PROGRAM" => {
|
||||||
validate_program(&document)?;
|
if document.language_version != "0.1" {
|
||||||
lower_program(
|
return Err(TcsError::new("TCS-E2102", "unsupported TCS version"));
|
||||||
|
}
|
||||||
|
validate_program_contract(
|
||||||
&document,
|
&document,
|
||||||
&source_sha256,
|
&policy.required_sections,
|
||||||
compiler_id,
|
&policy.registered_operations,
|
||||||
"TCS_COMPILER_GIR_EXECUTED",
|
)?;
|
||||||
true,
|
lower_program_with_policy(&document, &source_sha256, compiler_id, &policy)
|
||||||
)
|
|
||||||
}
|
}
|
||||||
"COMPILER" => {
|
"COMPILER" => {
|
||||||
validate_compiler(&document)?;
|
validate_compiler(&document)?;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue