feat: release Dever 0.1.5 with direct workers and long transactions
This commit is contained in:
1 parent
89629c2197
commit
a900d7e8db
153 files changed
+3676
-3708
No files matched your search
@@ -20,12 +20,26 @@ pub(super) fn prepare(
|
||||
supplied: &BTreeMap<&str, &EmbeddedResource>,
|
||||
target: BuildTarget,
|
||||
) -> Result<Vec<EmbeddedResource>, String> {
|
||||
let worker = contract.ecosystem == "exec";
|
||||
let tree_kind = if worker { "workers" } else { "commands" };
|
||||
let binary_name = if worker { "worker" } else { "tool" };
|
||||
let prefix = format!(
|
||||
"commands/{}",
|
||||
"{tree_kind}/{}",
|
||||
digest(&serde_json::to_vec(&contract.sdk_manifest()).map_err(|error| error.to_string())?)
|
||||
);
|
||||
let mut tree = Tree::new(prefix.clone());
|
||||
let source = command_files(root, &contract.entry, package_files)?;
|
||||
let entry = if worker {
|
||||
let entry = supplied
|
||||
.get(contract.entry.as_str())
|
||||
.ok_or("exec Worker is missing from verified resources")?;
|
||||
if !entry.executable || entry.bytes.is_empty() {
|
||||
return Err("exec Worker entry must be a nonempty executable resource".into());
|
||||
}
|
||||
Some(entry.bytes.as_slice())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let source = command_files(root, &contract.entry, package_files, entry)?;
|
||||
let binary = &source["program/tool"];
|
||||
runtime::validate_binary(&contract.entry, binary, target.platform())?;
|
||||
let machine = match target {
|
||||
@@ -44,19 +58,17 @@ pub(super) fn prepare(
|
||||
files.extend(
|
||||
supplied
|
||||
.iter()
|
||||
.filter(|(path, _)| path.starts_with("sandbox/lib/"))
|
||||
.filter(|(path, _)| path.starts_with("process-runtime/lib/"))
|
||||
.map(|(path, entry)| ((*path).to_owned(), entry.bytes.as_slice())),
|
||||
);
|
||||
let closure = elf::Closure {
|
||||
files: &files,
|
||||
machine,
|
||||
directories: vec!["program/lib".into(), "sandbox/lib".into()],
|
||||
directories: vec!["program/lib".into(), "process-runtime/lib".into()],
|
||||
};
|
||||
for (path, bytes) in &source {
|
||||
let object = elf::object(path, bytes, machine)?;
|
||||
reject_loader_hooks(&object)?;
|
||||
// The logical program root becomes /worker in the sandbox. A path
|
||||
// escaping it could otherwise resolve a library from a file grant.
|
||||
for fields in [&object.rpaths, &object.runpaths] {
|
||||
for directory in elf::origin_directories(path, fields)? {
|
||||
if directory != "program" && !directory.starts_with("program/") {
|
||||
@@ -65,9 +77,9 @@ pub(super) fn prepare(
|
||||
}
|
||||
}
|
||||
if let Some(name) = path.strip_prefix("program/lib/") {
|
||||
if supplied.contains_key(format!("sandbox/lib/{name}").as_str()) {
|
||||
if supplied.contains_key(format!("process-runtime/lib/{name}").as_str()) {
|
||||
return Err(format!(
|
||||
"command library '{name}' overrides a signed sandbox library"
|
||||
"command library '{name}' overrides a signed process_runtime library"
|
||||
));
|
||||
}
|
||||
if object.header.e_type != header::ET_DYN
|
||||
@@ -83,38 +95,38 @@ pub(super) fn prepare(
|
||||
}
|
||||
for (path, bytes) in source {
|
||||
let name = path.strip_prefix("program/").expect("owned command tree");
|
||||
tree.add(name, bytes, name == "tool")?;
|
||||
tree.add(
|
||||
if name == "tool" { binary_name } else { name },
|
||||
bytes,
|
||||
name == "tool",
|
||||
)?;
|
||||
}
|
||||
let (executable, arguments) = if let Some(interpreter) = interpreter {
|
||||
if worker {
|
||||
tree.add(
|
||||
"contract.json",
|
||||
serde_json::to_vec(&contract.sdk_manifest()).map_err(|error| error.to_string())?,
|
||||
false,
|
||||
)?;
|
||||
}
|
||||
if let Some(interpreter) = interpreter {
|
||||
let name = interpreter
|
||||
.rsplit('/')
|
||||
.next()
|
||||
.expect("validated GNU loader");
|
||||
let loader = supplied
|
||||
.get(format!("sandbox/lib/{name}").as_str())
|
||||
.get(format!("process-runtime/lib/{name}").as_str())
|
||||
.ok_or("command requires the signed target GNU loader")?;
|
||||
runtime::validate_binary(name, &loader.bytes, target.platform())?;
|
||||
tree.add("loader", loader.bytes.clone(), true)?;
|
||||
(
|
||||
format!("{prefix}/loader"),
|
||||
vec![
|
||||
json!({"literal": "--inhibit-cache"}),
|
||||
json!({"literal": "--library-path"}),
|
||||
json!({"literal": "lib:/lib"}),
|
||||
json!({"resource": format!("{prefix}/tool")}),
|
||||
],
|
||||
)
|
||||
} else {
|
||||
(format!("{prefix}/tool"), Vec::new())
|
||||
};
|
||||
}
|
||||
let suffix = if worker { "worker" } else { "command" };
|
||||
let manifest = json!({
|
||||
"format": "dever-command-launch-v1", "ecosystem": "command",
|
||||
"entry": contract.entry, "executable": executable,
|
||||
"arguments": arguments, "working_directory": prefix,
|
||||
"format": format!("dever-{suffix}-launch-v1"), "ecosystem": contract.ecosystem,
|
||||
"entry": contract.entry, "executable": format!("{prefix}/{binary_name}"),
|
||||
"arguments": [], "working_directory": prefix,
|
||||
});
|
||||
let mut output = tree.finish();
|
||||
output.push(resource(
|
||||
format!("{}.dever-command.json", contract.entry),
|
||||
format!("{}.dever-{suffix}.json", contract.entry),
|
||||
serde_json::to_vec(&manifest).map_err(|error| error.to_string())?,
|
||||
false,
|
||||
));
|
||||
@@ -143,6 +155,7 @@ fn command_files(
|
||||
root: &Path,
|
||||
entry: &str,
|
||||
package_files: &BTreeMap<String, Vec<u8>>,
|
||||
verified: Option<&[u8]>,
|
||||
) -> Result<BTreeMap<String, Vec<u8>>, String> {
|
||||
valid_path(entry)?;
|
||||
let parent = entry
|
||||
@@ -151,7 +164,9 @@ fn command_files(
|
||||
.ok_or("command entry must belong to a domain")?;
|
||||
let library_prefix = format!("{parent}/lib/");
|
||||
let packaged = crate::packages::owns_worker(root, entry)?;
|
||||
let binary = if packaged {
|
||||
let binary = if let Some(bytes) = verified {
|
||||
bytes.to_vec()
|
||||
} else if packaged {
|
||||
package_files
|
||||
.get(entry)
|
||||
.cloned()
|
||||
|
||||
Reference in new issue
Block a user