Skip to main content

sawtooth_sabre/
handler.rs

1// Copyright 2018 Cargill Incorporated
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Provides a Sawtooth Transaction Handler for executing Sabre transactions.
16
17use crypto::digest::Digest;
18use crypto::sha2::Sha512;
19use sabre_sdk::protocol::state::{
20    ContractBuilder, ContractRegistry, ContractRegistryBuilder, NamespaceRegistry,
21    NamespaceRegistryBuilder, PermissionBuilder, VersionBuilder,
22};
23use sawtooth_sdk::messages::processor::TpProcessRequest;
24use sawtooth_sdk::processor::handler::ApplyError;
25use sawtooth_sdk::processor::handler::TransactionContext;
26use sawtooth_sdk::processor::handler::TransactionHandler;
27
28use crate::admin::AdminPermission;
29use crate::payload::SabreRequestPayload;
30use crate::state::SabreState;
31use crate::wasm_executor::wasm_module::WasmModule;
32use sabre_sdk::protocol::payload::{
33    Action, CreateContractAction, CreateContractRegistryAction, CreateNamespaceRegistryAction,
34    CreateNamespaceRegistryPermissionAction, DeleteContractAction, DeleteContractRegistryAction,
35    DeleteNamespaceRegistryAction, DeleteNamespaceRegistryPermissionAction, ExecuteContractAction,
36    UpdateContractRegistryOwnersAction, UpdateNamespaceRegistryOwnersAction,
37};
38use sabre_sdk::protocol::SABRE_PROTOCOL_VERSION;
39
40/// The namespace registry prefix for global state (00ec00)
41const NAMESPACE_REGISTRY_PREFIX: &str = "00ec00";
42
43/// The contract registry prefix for global state (00ec01)
44const CONTRACT_REGISTRY_PREFIX: &str = "00ec01";
45
46/// The contract prefix for global state (00ec02)
47const CONTRACT_PREFIX: &str = "00ec02";
48
49/// Handles Sabre Transactions
50///
51/// This handler implements the Sawtooth TransactionHandler trait, in order to execute Sabre
52/// transaction payloads.  These payloads include on-chain smart contracts executed in a
53/// WebAssembly virtual machine.
54///
55/// WebAssembly (Wasm) is a stack-based virtual machine newly implemented in major browsers. It is
56/// well-suited for the purposes of smart contract execution due to its sandboxed design, growing
57/// popularity, and tool support.
58pub struct SabreTransactionHandler {
59    family_name: String,
60    family_versions: Vec<String>,
61    namespaces: Vec<String>,
62    admin_permissions: Box<dyn AdminPermission>,
63}
64
65impl SabreTransactionHandler {
66    /// Constructs a new SabreTransactionHandler
67    pub fn new(admin_permissions: Box<dyn AdminPermission>) -> SabreTransactionHandler {
68        SabreTransactionHandler {
69            family_name: "sabre".into(),
70            family_versions: vec!["0.5".into(), "0.6".into(), SABRE_PROTOCOL_VERSION.into()],
71            namespaces: vec![
72                NAMESPACE_REGISTRY_PREFIX.into(),
73                CONTRACT_REGISTRY_PREFIX.into(),
74                CONTRACT_PREFIX.into(),
75            ],
76            admin_permissions,
77        }
78    }
79}
80
81impl TransactionHandler for SabreTransactionHandler {
82    fn family_name(&self) -> String {
83        self.family_name.clone()
84    }
85
86    fn family_versions(&self) -> Vec<String> {
87        self.family_versions.clone()
88    }
89
90    fn namespaces(&self) -> Vec<String> {
91        self.namespaces.clone()
92    }
93
94    fn apply(
95        &self,
96        request: &TpProcessRequest,
97        context: &mut dyn TransactionContext,
98    ) -> Result<(), ApplyError> {
99        let payload = SabreRequestPayload::new(request.get_payload());
100
101        let payload = match payload {
102            Err(e) => return Err(e),
103            Ok(payload) => payload,
104        };
105        let payload = match payload {
106            Some(x) => x,
107            None => {
108                return Err(ApplyError::InvalidTransaction(String::from(
109                    "Request must contain a payload",
110                )));
111            }
112        };
113
114        let signer = request.get_header().get_signer_public_key();
115        let mut state = SabreState::new(context);
116
117        info!(
118            "{} {:?} {:?}",
119            payload.get_action(),
120            request.get_header().get_inputs(),
121            request.get_header().get_outputs()
122        );
123
124        match payload.get_action() {
125            Action::CreateContract(create_contract_payload) => {
126                create_contract(create_contract_payload, signer, &mut state)
127            }
128            Action::DeleteContract(delete_contract_payload) => {
129                delete_contract(delete_contract_payload, signer, &mut state)
130            }
131            Action::ExecuteContract(execute_contract_payload) => execute_contract(
132                execute_contract_payload,
133                signer,
134                request.get_signature(),
135                &mut state,
136            ),
137            Action::CreateContractRegistry(create_contract_registry_payload) => {
138                create_contract_registry(
139                    create_contract_registry_payload,
140                    signer,
141                    &mut state,
142                    &*self.admin_permissions,
143                )
144            }
145            Action::DeleteContractRegistry(delete_contract_registry_payload) => {
146                delete_contract_registry(
147                    delete_contract_registry_payload,
148                    signer,
149                    &mut state,
150                    &*self.admin_permissions,
151                )
152            }
153            Action::UpdateContractRegistryOwners(update_contract_registry_owners_payload) => {
154                update_contract_registry_owners(
155                    update_contract_registry_owners_payload,
156                    signer,
157                    &mut state,
158                    &*self.admin_permissions,
159                )
160            }
161            Action::CreateNamespaceRegistry(create_namespace_registry_payload) => {
162                create_namespace_registry(
163                    create_namespace_registry_payload,
164                    signer,
165                    &mut state,
166                    &*self.admin_permissions,
167                )
168            }
169            Action::DeleteNamespaceRegistry(delete_namespace_registry_payload) => {
170                delete_namespace_registry(
171                    delete_namespace_registry_payload,
172                    signer,
173                    &mut state,
174                    &*self.admin_permissions,
175                )
176            }
177            Action::UpdateNamespaceRegistryOwners(update_namespace_registry_owners_payload) => {
178                update_namespace_registry_owners(
179                    update_namespace_registry_owners_payload,
180                    signer,
181                    &mut state,
182                    &*self.admin_permissions,
183                )
184            }
185            Action::CreateNamespaceRegistryPermission(
186                create_namespace_registry_permission_payload,
187            ) => create_namespace_registry_permission(
188                create_namespace_registry_permission_payload,
189                signer,
190                &mut state,
191                &*self.admin_permissions,
192            ),
193            Action::DeleteNamespaceRegistryPermission(
194                delete_namespace_registry_permission_payload,
195            ) => delete_namespace_registry_permission(
196                delete_namespace_registry_permission_payload,
197                signer,
198                &mut state,
199                &*self.admin_permissions,
200            ),
201        }
202    }
203}
204
205fn create_contract(
206    payload: CreateContractAction,
207    signer: &str,
208    state: &mut SabreState,
209) -> Result<(), ApplyError> {
210    let name = payload.name();
211    let version = payload.version();
212    match state.get_contract(name, version) {
213        Ok(None) => (),
214        Ok(Some(_)) => {
215            return Err(ApplyError::InvalidTransaction(format!(
216                "Contract already exists: {}, {}",
217                name, version,
218            )));
219        }
220        Err(err) => {
221            return Err(ApplyError::InvalidTransaction(format!(
222                "Unable to check state: {}",
223                err,
224            )));
225        }
226    };
227
228    // update or create the contract registry for the contract
229    let contract_registry = match state.get_contract_registry(name) {
230        Ok(None) => {
231            return Err(ApplyError::InvalidTransaction(format!(
232                "The Contract Registry does not exist: {}",
233                name,
234            )));
235        }
236        Ok(Some(contract_registry)) => contract_registry,
237        Err(err) => {
238            return Err(ApplyError::InvalidTransaction(format!(
239                "Unable to check state: {}",
240                err,
241            )));
242        }
243    };
244
245    if !contract_registry.owners().contains(&signer.into()) {
246        return Err(ApplyError::InvalidTransaction(format!(
247            "Only owners can submit new versions of contracts: {}",
248            signer,
249        )));
250    }
251
252    let contract = ContractBuilder::new()
253        .with_name(name.into())
254        .with_version(version.into())
255        .with_inputs(payload.inputs().to_vec())
256        .with_outputs(payload.outputs().to_vec())
257        .with_creator(signer.into())
258        .with_contract(payload.contract().to_vec())
259        .build()
260        .map_err(|_| ApplyError::InvalidTransaction(String::from("Cannot build contract")))?;
261
262    state.set_contract(name, version, contract)?;
263
264    let mut sha = Sha512::new();
265    sha.input(payload.contract());
266
267    let contract_registry_version = VersionBuilder::new()
268        .with_version(version.into())
269        .with_contract_sha512(sha.result_str())
270        .with_creator(signer.into())
271        .build()
272        .map_err(|_| {
273            ApplyError::InvalidTransaction(String::from("Cannot build contract version"))
274        })?;
275
276    let mut versions = contract_registry.versions().to_vec();
277    versions.push(contract_registry_version);
278
279    let contract_registry = contract_registry
280        .into_builder()
281        .with_versions(versions)
282        .build()
283        .map_err(|_| {
284            ApplyError::InvalidTransaction(String::from("Cannot build contract registry"))
285        })?;
286
287    state.set_contract_registry(name, contract_registry)
288}
289
290fn delete_contract(
291    payload: DeleteContractAction,
292    signer: &str,
293    state: &mut SabreState,
294) -> Result<(), ApplyError> {
295    let name = payload.name();
296    let version = payload.version();
297
298    match state.get_contract(name, version) {
299        Ok(Some(_)) => (),
300        Ok(_) => {
301            return Err(ApplyError::InvalidTransaction(format!(
302                "Contract does not exist: {}, {}",
303                name, version,
304            )));
305        }
306        Err(err) => {
307            return Err(ApplyError::InvalidTransaction(format!(
308                "Unable to check state: {}",
309                err,
310            )));
311        }
312    };
313
314    // update the contract registry for the contract
315    let contract_registry = match state.get_contract_registry(name) {
316        Ok(None) => {
317            return Err(ApplyError::InvalidTransaction(format!(
318                "Contract Registry does not exist {}",
319                name,
320            )));
321        }
322        Ok(Some(contract_registry)) => contract_registry,
323        Err(err) => {
324            return Err(ApplyError::InvalidTransaction(format!(
325                "Unable to check state: {}",
326                err,
327            )));
328        }
329    };
330
331    if !(contract_registry.owners().contains(&signer.into())) {
332        return Err(ApplyError::InvalidTransaction(format!(
333            "Signer is not an owner of this contract: {}",
334            signer,
335        )));
336    }
337    let mut versions = contract_registry.versions().to_vec();
338    for (index, contract_registry_version) in versions.iter().enumerate() {
339        if contract_registry_version.version() == version {
340            versions.remove(index);
341            break;
342        }
343    }
344
345    let contract_registry = contract_registry
346        .into_builder()
347        .with_versions(versions)
348        .build()
349        .map_err(|_| {
350            ApplyError::InvalidTransaction(String::from("Cannot build contract registry"))
351        })?;
352
353    state.set_contract_registry(name, contract_registry)?;
354    state.delete_contract(name, version)
355}
356
357fn execute_contract(
358    payload: ExecuteContractAction,
359    signer: &str,
360    signature: &str,
361    state: &mut SabreState,
362) -> Result<(), ApplyError> {
363    let name = payload.name();
364    let version = payload.version();
365
366    let contract = match state.get_contract(name, version) {
367        Ok(Some(contract)) => contract,
368        Ok(None) => {
369            return Err(ApplyError::InvalidTransaction(format!(
370                "Contract does not exist: {}, {}",
371                name, version,
372            )));
373        }
374        Err(err) => {
375            return Err(ApplyError::InvalidTransaction(format!(
376                "Unable to check state: {}",
377                err,
378            )));
379        }
380    };
381
382    for input in payload.inputs() {
383        let namespace = match input.get(..6) {
384            Some(namespace) => namespace,
385            None => {
386                return Err(ApplyError::InvalidTransaction(format!(
387                    "Input must have at least 6 characters: {}",
388                    input,
389                )));
390            }
391        };
392        let registries = match state.get_namespace_registries(namespace) {
393            Ok(Some(registries)) => registries,
394            Ok(None) => {
395                return Err(ApplyError::InvalidTransaction(format!(
396                    "Namespace Registry does not exist: {}",
397                    namespace,
398                )));
399            }
400            Err(err) => {
401                return Err(ApplyError::InvalidTransaction(format!(
402                    "Unable to check state: {}",
403                    err,
404                )));
405            }
406        };
407
408        let mut namespace_registry = None;
409        for registry in registries.registries() {
410            if input.starts_with(registry.namespace()) {
411                namespace_registry = Some(registry)
412            }
413        }
414
415        let mut permissioned = false;
416        match namespace_registry {
417            Some(registry) => {
418                for permission in registry.permissions() {
419                    if name == permission.contract_name() && permission.read() {
420                        permissioned = true;
421                        break;
422                    }
423                }
424                if !permissioned {
425                    return Err(ApplyError::InvalidTransaction(format!(
426                        "Contract does not have permission to read from state : {} {}",
427                        name, input
428                    )));
429                }
430            }
431            None => {
432                return Err(ApplyError::InvalidTransaction(format!(
433                    "No namespace registry exists for namespace: {} input: {}",
434                    namespace, input
435                )));
436            }
437        }
438    }
439
440    for output in payload.outputs() {
441        let namespace = match output.get(..6) {
442            Some(namespace) => namespace,
443            None => {
444                return Err(ApplyError::InvalidTransaction(format!(
445                    "Output must have at least 6 characters: {}",
446                    output,
447                )));
448            }
449        };
450        let registries = match state.get_namespace_registries(namespace) {
451            Ok(Some(registries)) => registries,
452            Ok(None) => {
453                return Err(ApplyError::InvalidTransaction(format!(
454                    "Namespace Registry does not exist: {}",
455                    namespace,
456                )));
457            }
458            Err(err) => {
459                return Err(ApplyError::InvalidTransaction(format!(
460                    "Unable to check state: {}",
461                    err,
462                )));
463            }
464        };
465
466        let mut namespace_registry = None;
467        for registry in registries.registries() {
468            if output.starts_with(registry.namespace()) {
469                namespace_registry = Some(registry)
470            }
471        }
472        let mut permissioned = false;
473        match namespace_registry {
474            Some(registry) => {
475                for permission in registry.permissions() {
476                    if name == permission.contract_name() && permission.write() {
477                        permissioned = true;
478                        break;
479                    }
480                }
481                if !permissioned {
482                    return Err(ApplyError::InvalidTransaction(format!(
483                        "Contract does not have permission to write to state: {}, {}",
484                        name, output
485                    )));
486                }
487            }
488            None => {
489                return Err(ApplyError::InvalidTransaction(format!(
490                    "No namespace registry exists for namespace: {} output: {}",
491                    namespace, output
492                )));
493            }
494        }
495    }
496
497    let mut module = WasmModule::new(contract.contract(), state.context())
498        .expect("Failed to create can_add module");
499
500    let result = module
501        .entrypoint(payload.payload().to_vec(), signer.into(), signature.into())
502        .map_err(|e| ApplyError::InvalidTransaction(format!("{:?}", e)))?;
503
504    match result {
505        None => Err(ApplyError::InvalidTransaction(format!(
506            "Wasm contract did not return a result: {}, {}",
507            name, version,
508        ))),
509        Some(1) => Ok(()),
510        Some(-3) => Err(ApplyError::InvalidTransaction(format!(
511            "Wasm contract returned invalid transaction: {}, {}",
512            name, version,
513        ))),
514        Some(num) => Err(ApplyError::InternalError(format!(
515            "Wasm contract returned internal error: {}",
516            num
517        ))),
518    }
519}
520
521fn create_contract_registry(
522    payload: CreateContractRegistryAction,
523    signer: &str,
524    state: &mut SabreState,
525    admin_permissions: &dyn AdminPermission,
526) -> Result<(), ApplyError> {
527    let name = payload.name();
528
529    match state.get_contract_registry(name) {
530        Ok(None) => (),
531        Ok(Some(_)) => {
532            return Err(ApplyError::InvalidTransaction(format!(
533                "Contract Registry already exists: {}",
534                name,
535            )));
536        }
537        Err(err) => {
538            return Err(ApplyError::InvalidTransaction(format!(
539                "Unable to check state: {}",
540                err,
541            )));
542        }
543    };
544
545    if !admin_permissions.is_admin(signer, state)? {
546        return Err(ApplyError::InvalidTransaction(format!(
547            "Only admins can create a contract registry: {}",
548            signer,
549        )));
550    }
551
552    let contract_registry = ContractRegistryBuilder::new()
553        .with_name(name.into())
554        .with_owners(payload.owners().to_vec())
555        .build()
556        .map_err(|_| {
557            ApplyError::InvalidTransaction(String::from("Cannot build contract registry"))
558        })?;
559
560    state.set_contract_registry(name, contract_registry)
561}
562
563fn delete_contract_registry(
564    payload: DeleteContractRegistryAction,
565    signer: &str,
566    state: &mut SabreState,
567    admin_permissions: &dyn AdminPermission,
568) -> Result<(), ApplyError> {
569    let name = payload.name();
570    let contract_registry = match state.get_contract_registry(name) {
571        Ok(None) => {
572            return Err(ApplyError::InvalidTransaction(format!(
573                "Contract Registry does not exist: {}",
574                name,
575            )));
576        }
577        Ok(Some(contract_registry)) => contract_registry,
578        Err(err) => {
579            return Err(ApplyError::InvalidTransaction(format!(
580                "Unable to check state: {}",
581                err,
582            )));
583        }
584    };
585
586    if !contract_registry.versions().is_empty() {
587        return Err(ApplyError::InvalidTransaction(format!(
588            "Contract Registry can only be deleted if there are no versions: {}",
589            name,
590        )));
591    }
592
593    // Check if signer is an owner or an admin
594    can_update_contract_registry(contract_registry, signer, state, admin_permissions)?;
595
596    state.delete_contract_registry(name)
597}
598
599fn update_contract_registry_owners(
600    payload: UpdateContractRegistryOwnersAction,
601    signer: &str,
602    state: &mut SabreState,
603    admin_permissions: &dyn AdminPermission,
604) -> Result<(), ApplyError> {
605    let name = payload.name();
606    let contract_registry = match state.get_contract_registry(name) {
607        Ok(None) => {
608            return Err(ApplyError::InvalidTransaction(format!(
609                "Contract Registry does not exist: {}",
610                name,
611            )));
612        }
613        Ok(Some(contract_registry)) => contract_registry,
614        Err(err) => {
615            return Err(ApplyError::InvalidTransaction(format!(
616                "Unable to check state: {}",
617                err,
618            )));
619        }
620    };
621
622    // Check if signer is an owner or an admin
623    can_update_contract_registry(contract_registry.clone(), signer, state, admin_permissions)?;
624
625    let contract_registry = contract_registry
626        .into_builder()
627        .with_owners(payload.owners().to_vec())
628        .build()
629        .map_err(|_| {
630            ApplyError::InvalidTransaction(String::from("Cannot build contract registry"))
631        })?;
632
633    state.set_contract_registry(name, contract_registry)
634}
635
636fn create_namespace_registry(
637    payload: CreateNamespaceRegistryAction,
638    signer: &str,
639    state: &mut SabreState,
640    admin_permissions: &dyn AdminPermission,
641) -> Result<(), ApplyError> {
642    let namespace = payload.namespace();
643
644    if namespace.len() < 6 {
645        return Err(ApplyError::InvalidTransaction(format!(
646            "Namespace must be at least 6 characters: {}",
647            namespace,
648        )));
649    }
650
651    match state.get_namespace_registry(namespace) {
652        Ok(None) => (),
653        Ok(Some(_)) => {
654            return Err(ApplyError::InvalidTransaction(format!(
655                "Namespace Registry already exists: {}",
656                namespace,
657            )));
658        }
659        Err(err) => {
660            return Err(ApplyError::InvalidTransaction(format!(
661                "Unable to check state: {}",
662                err,
663            )));
664        }
665    }
666
667    if !admin_permissions.is_admin(signer, state)? {
668        return Err(ApplyError::InvalidTransaction(format!(
669            "Only admins can create a namespace registry: {}",
670            signer,
671        )));
672    }
673
674    let namespace_registry = NamespaceRegistryBuilder::new()
675        .with_namespace(namespace.into())
676        .with_owners(payload.owners().to_vec())
677        .build()
678        .map_err(|_| {
679            ApplyError::InvalidTransaction(String::from("Cannot build namespace registry"))
680        })?;
681
682    state.set_namespace_registry(namespace, namespace_registry)
683}
684
685fn delete_namespace_registry(
686    payload: DeleteNamespaceRegistryAction,
687    signer: &str,
688    state: &mut SabreState,
689    admin_permissions: &dyn AdminPermission,
690) -> Result<(), ApplyError> {
691    let namespace = payload.namespace();
692
693    let namespace_registry = match state.get_namespace_registry(namespace) {
694        Ok(None) => {
695            return Err(ApplyError::InvalidTransaction(format!(
696                "Namespace Registry does not exist: {}",
697                namespace,
698            )));
699        }
700        Ok(Some(namespace_registry)) => namespace_registry,
701        Err(err) => {
702            return Err(ApplyError::InvalidTransaction(format!(
703                "Unable to check state: {}",
704                err,
705            )));
706        }
707    };
708    can_update_namespace_registry(namespace_registry.clone(), signer, state, admin_permissions)?;
709
710    if !namespace_registry.permissions().is_empty() {
711        return Err(ApplyError::InvalidTransaction(format!(
712            "Namespace Registry can only be deleted if there are no permissions: {}",
713            namespace,
714        )));
715    }
716    state.delete_namespace_registry(namespace)
717}
718
719fn update_namespace_registry_owners(
720    payload: UpdateNamespaceRegistryOwnersAction,
721    signer: &str,
722    state: &mut SabreState,
723    admin_permissions: &dyn AdminPermission,
724) -> Result<(), ApplyError> {
725    let namespace = payload.namespace();
726
727    let namespace_registry = match state.get_namespace_registry(namespace) {
728        Ok(None) => {
729            return Err(ApplyError::InvalidTransaction(format!(
730                "Namespace Registry does not exist: {}",
731                namespace,
732            )));
733        }
734        Ok(Some(namespace_registry)) => namespace_registry,
735        Err(err) => {
736            return Err(ApplyError::InvalidTransaction(format!(
737                "Unable to check state: {}",
738                err,
739            )));
740        }
741    };
742
743    // Check if signer is an owner or an admin
744    can_update_namespace_registry(namespace_registry.clone(), signer, state, admin_permissions)?;
745    let namespace_registry = namespace_registry
746        .into_builder()
747        .with_owners(payload.owners().to_vec())
748        .build()
749        .map_err(|_| {
750            ApplyError::InvalidTransaction(String::from("Cannot build namespace registry"))
751        })?;
752
753    state.set_namespace_registry(namespace, namespace_registry)
754}
755
756fn create_namespace_registry_permission(
757    payload: CreateNamespaceRegistryPermissionAction,
758    signer: &str,
759    state: &mut SabreState,
760    admin_permissions: &dyn AdminPermission,
761) -> Result<(), ApplyError> {
762    let namespace = payload.namespace();
763    let contract_name = payload.contract_name();
764    let namespace_registry = match state.get_namespace_registry(namespace) {
765        Ok(None) => {
766            return Err(ApplyError::InvalidTransaction(format!(
767                "Namespace Registry does not exist: {}",
768                namespace,
769            )));
770        }
771        Ok(Some(namespace_registry)) => namespace_registry,
772        Err(err) => {
773            return Err(ApplyError::InvalidTransaction(format!(
774                "Unable to check state: {}",
775                err,
776            )));
777        }
778    };
779    // Check if signer is an owner or an admin
780    can_update_namespace_registry(namespace_registry.clone(), signer, state, admin_permissions)?;
781
782    let new_permission = PermissionBuilder::new()
783        .with_contract_name(contract_name.into())
784        .with_read(payload.read())
785        .with_write(payload.write())
786        .build()
787        .map_err(|_| {
788            ApplyError::InvalidTransaction(String::from(
789                "Cannot build namespace registry permission",
790            ))
791        })?;
792
793    // remove old permission for contract if one exists and replace with the new permission
794    let mut permissions = namespace_registry.permissions().to_vec();
795    let mut index = None;
796    for (count, permission) in permissions.iter().enumerate() {
797        if permission.contract_name() == contract_name {
798            index = Some(count);
799            break;
800        }
801    }
802
803    if let Some(x) = index {
804        permissions.remove(x);
805    }
806
807    permissions.push(new_permission);
808
809    let namespace_registry = namespace_registry
810        .into_builder()
811        .with_permissions(permissions)
812        .build()
813        .map_err(|_| {
814            ApplyError::InvalidTransaction(String::from("Cannot build namespace registry"))
815        })?;
816
817    state.set_namespace_registry(namespace, namespace_registry)
818}
819
820fn delete_namespace_registry_permission(
821    payload: DeleteNamespaceRegistryPermissionAction,
822    signer: &str,
823    state: &mut SabreState,
824    admin_permissions: &dyn AdminPermission,
825) -> Result<(), ApplyError> {
826    let namespace = payload.namespace();
827    let contract_name = payload.contract_name();
828
829    let namespace_registry = match state.get_namespace_registry(namespace) {
830        Ok(None) => {
831            return Err(ApplyError::InvalidTransaction(format!(
832                "Namespace Registry does not exist: {}",
833                namespace,
834            )));
835        }
836        Ok(Some(namespace_registry)) => namespace_registry,
837        Err(err) => {
838            return Err(ApplyError::InvalidTransaction(format!(
839                "Unable to check state: {}",
840                err,
841            )));
842        }
843    };
844    // Check if signer is an owner or an admin
845    can_update_namespace_registry(namespace_registry.clone(), signer, state, admin_permissions)?;
846
847    // remove old permission for contract
848    let mut permissions = namespace_registry.permissions().to_vec();
849    let mut index = None;
850    for (count, permission) in permissions.iter().enumerate() {
851        if permission.contract_name() == contract_name {
852            index = Some(count);
853            break;
854        }
855    }
856
857    match index {
858        Some(x) => {
859            permissions.remove(x);
860        }
861        None => {
862            return Err(ApplyError::InvalidTransaction(format!(
863                "Namespace Registry does not have a permission for : {}",
864                contract_name,
865            )));
866        }
867    };
868
869    let namespace_registry = namespace_registry
870        .into_builder()
871        .with_permissions(permissions)
872        .build()
873        .map_err(|_| {
874            ApplyError::InvalidTransaction(String::from("Cannot build namespace registry"))
875        })?;
876    state.set_namespace_registry(namespace, namespace_registry)
877}
878
879// helper function to check if the signer is allowed to update a namespace_registry
880fn can_update_namespace_registry(
881    namespace_registry: NamespaceRegistry,
882    signer: &str,
883    state: &mut SabreState,
884    admin_permissions: &dyn AdminPermission,
885) -> Result<(), ApplyError> {
886    if !namespace_registry.owners().contains(&signer.into()) {
887        match admin_permissions.is_admin(signer, state) {
888            Ok(true) => (),
889            Ok(false) => {
890                return Err(ApplyError::InvalidTransaction(format!(
891                    "Only owners or admins can update or delete a namespace registry: {}",
892                    signer,
893                )));
894            }
895            Err(err) => {
896                return Err(err);
897            }
898        };
899    }
900    Ok(())
901}
902
903// helper function to check if the signer is allowed to update a contract_registry
904fn can_update_contract_registry(
905    contract_registry: ContractRegistry,
906    signer: &str,
907    state: &mut SabreState,
908    admin_permissions: &dyn AdminPermission,
909) -> Result<(), ApplyError> {
910    if !contract_registry.owners().contains(&signer.into()) {
911        match admin_permissions.is_admin(signer, state) {
912            Ok(true) => (),
913            Ok(false) => {
914                return Err(ApplyError::InvalidTransaction(format!(
915                    "Only owners or admins can update or delete a contract registry: {}",
916                    signer,
917                )));
918            }
919            Err(err) => {
920                return Err(err);
921            }
922        };
923    }
924    Ok(())
925}