diff --git a/include/ircd/m/vm.h b/include/ircd/m/vm.h index dde0665da..9852de799 100644 --- a/include/ircd/m/vm.h +++ b/include/ircd/m/vm.h @@ -219,6 +219,10 @@ struct ircd::m::vm::opts /// TODO: Y bool head_must_exist {false}; + /// Whether to automatically fetch and evaluate the auth chain for the + /// event; effective when there is no state for this room on the server. + bool fetch_auth_chain {true}; + /// Evaluators can set this value to optimize the creation of the database /// transaction where the event will be stored. This value should be set /// to the amount of space the event consumes; the JSON-serialized size is diff --git a/modules/s_fetch.cc b/modules/s_fetch.cc index 5cac6985f..50a48ca62 100644 --- a/modules/s_fetch.cc +++ b/modules/s_fetch.cc @@ -59,19 +59,31 @@ ircd::m::fetch::hook_handler(const event &event, if(type == "m.room.create") return; + const m::event::id &event_id + { + at<"event_id"_>(event) + }; + const m::room::id &room_id { at<"room_id"_>(event) }; - if(opts.head_must_exist || opts.history) - if(!exists(room_id)) + if(!exists(room_id)) + { + if((opts.head_must_exist || opts.history) && !opts.fetch_auth_chain) throw vm::error { vm::fault::STATE, "Missing state for room %s", string_view{room_id} }; + m::room room{room_id}; + room.event_id = event_id; + const m::room::auth auth{room}; + auth.chain_eval(auth, event_id.host()); + } + const event::prev prev { *eval.event_ @@ -117,6 +129,7 @@ ircd::m::room::auth::chain_eval(const auth &auth, m::vm::opts opts; opts.non_conform.set(m::event::conforms::MISSING_PREV_STATE); opts.infolog_accept = true; + opts.prev_check_exists = false; opts.warnlog |= m::vm::fault::STATE; opts.warnlog &= ~m::vm::fault::EXISTS; opts.errorlog &= ~m::vm::fault::STATE;