pangea-sdk 6.2.0b1__py3-none-any.whl → 6.3.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pangea/__init__.py +9 -1
- pangea/asyncio/__init__.py +1 -0
- pangea/asyncio/file_uploader.py +4 -2
- pangea/asyncio/request.py +70 -169
- pangea/asyncio/services/__init__.py +2 -1
- pangea/asyncio/services/ai_guard.py +9 -12
- pangea/asyncio/services/audit.py +13 -307
- pangea/asyncio/services/authn.py +40 -32
- pangea/asyncio/services/authz.py +51 -17
- pangea/asyncio/services/base.py +4 -0
- pangea/asyncio/services/file_scan.py +8 -2
- pangea/asyncio/services/intel.py +26 -28
- pangea/asyncio/services/redact.py +11 -268
- pangea/asyncio/services/sanitize.py +5 -1
- pangea/asyncio/services/share.py +5 -1
- pangea/asyncio/services/vault.py +71 -55
- pangea/audit_logger.py +3 -1
- pangea/deep_verify.py +13 -13
- pangea/deprecated.py +1 -1
- pangea/dump_audit.py +2 -3
- pangea/exceptions.py +8 -5
- pangea/file_uploader.py +4 -0
- pangea/request.py +80 -200
- pangea/response.py +21 -18
- pangea/services/__init__.py +2 -1
- pangea/services/ai_guard.py +35 -24
- pangea/services/audit/audit.py +17 -314
- pangea/services/audit/models.py +69 -307
- pangea/services/audit/signing.py +1 -1
- pangea/services/audit/util.py +10 -10
- pangea/services/authn/authn.py +39 -31
- pangea/services/authn/models.py +183 -148
- pangea/services/authz.py +108 -60
- pangea/services/base.py +7 -4
- pangea/services/embargo.py +6 -0
- pangea/services/file_scan.py +8 -2
- pangea/services/intel.py +36 -19
- pangea/services/redact.py +14 -476
- pangea/services/sanitize.py +5 -1
- pangea/services/share/share.py +13 -7
- pangea/services/vault/models/asymmetric.py +4 -0
- pangea/services/vault/models/common.py +15 -12
- pangea/services/vault/models/keys.py +4 -9
- pangea/services/vault/models/secret.py +3 -8
- pangea/services/vault/models/symmetric.py +4 -0
- pangea/services/vault/vault.py +69 -59
- pangea/tools.py +13 -9
- pangea/utils.py +3 -5
- pangea/verify_audit.py +23 -27
- {pangea_sdk-6.2.0b1.dist-info → pangea_sdk-6.3.0.dist-info}/METADATA +36 -17
- pangea_sdk-6.3.0.dist-info/RECORD +60 -0
- {pangea_sdk-6.2.0b1.dist-info → pangea_sdk-6.3.0.dist-info}/WHEEL +1 -1
- pangea/asyncio/services/management.py +0 -576
- pangea/services/management.py +0 -720
- pangea_sdk-6.2.0b1.dist-info/RECORD +0 -62
pangea/services/audit/models.py
CHANGED
@@ -1,5 +1,9 @@
|
|
1
1
|
# Copyright 2022 Pangea Cyber Corporation
|
2
2
|
# Author: Pangea Cyber Corporation
|
3
|
+
|
4
|
+
# TODO: Modernize.
|
5
|
+
# ruff: noqa: UP006, UP035
|
6
|
+
|
3
7
|
from __future__ import annotations
|
4
8
|
|
5
9
|
import datetime
|
@@ -7,7 +11,7 @@ import enum
|
|
7
11
|
from typing import Any, Dict, List, Optional, Sequence, Union
|
8
12
|
|
9
13
|
from pydantic import Field
|
10
|
-
from typing_extensions import Annotated
|
14
|
+
from typing_extensions import Annotated
|
11
15
|
|
12
16
|
from pangea.response import APIRequestModel, APIResponseModel, PangeaDateTime, PangeaResponseResult
|
13
17
|
|
@@ -116,20 +120,25 @@ class Event(Dict[str, Any]):
|
|
116
120
|
|
117
121
|
|
118
122
|
class EventEnvelope(APIResponseModel):
|
119
|
-
|
120
|
-
Contain extra information about an event.
|
123
|
+
event: Optional[dict[str, Any]] = None
|
121
124
|
|
122
|
-
|
123
|
-
|
124
|
-
signature
|
125
|
-
|
126
|
-
|
125
|
+
signature: Optional[str] = None
|
126
|
+
"""
|
127
|
+
This is the signature of the hash of the canonicalized event that can be
|
128
|
+
verified with the public key provided in the public_key field. Signatures
|
129
|
+
cannot be used with the redaction feature turned on. If redaction is
|
130
|
+
required, the user needs to perform redaction before computing the signature
|
131
|
+
that is to be sent with the message. The SDK facilitates this for users.
|
127
132
|
"""
|
128
133
|
|
129
|
-
event: Dict[str, Any]
|
130
|
-
signature: Optional[str] = None
|
131
134
|
public_key: Optional[str] = None
|
132
|
-
|
135
|
+
"""
|
136
|
+
The base64-encoded ed25519 public key used for the signature, if one is
|
137
|
+
provided
|
138
|
+
"""
|
139
|
+
|
140
|
+
received_at: Optional[PangeaDateTime] = None
|
141
|
+
"""A Pangea provided timestamp of when the event was received."""
|
133
142
|
|
134
143
|
|
135
144
|
class LogRequest(APIRequestModel):
|
@@ -180,21 +189,28 @@ class LogBulkRequest(APIRequestModel):
|
|
180
189
|
|
181
190
|
|
182
191
|
class LogResult(PangeaResponseResult):
|
192
|
+
envelope: Optional[EventEnvelope] = None
|
183
193
|
"""
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
hash -- Event envelope hash.
|
188
|
-
unpublished_root -- The current unpublished root.
|
189
|
-
membership_proof -- A proof for verifying the unpublished root.
|
190
|
-
consistency_proof -- If prev_root was present in the request, this proof verifies that the new unpublished root is a continuation of the prev_root
|
194
|
+
The sealed envelope containing the event that was logged. Includes event
|
195
|
+
metadata such as optional client-side signature details and server-added
|
196
|
+
timestamps.
|
191
197
|
"""
|
192
198
|
|
193
|
-
|
194
|
-
hash
|
199
|
+
hash: Annotated[Optional[str], Field(max_length=64, min_length=64)] = None
|
200
|
+
"""The hash of the event data."""
|
201
|
+
|
195
202
|
unpublished_root: Optional[str] = None
|
203
|
+
"""The current unpublished root."""
|
204
|
+
|
196
205
|
membership_proof: Optional[str] = None
|
206
|
+
"""A proof for verifying that the buffer_root contains the received event"""
|
207
|
+
|
197
208
|
consistency_proof: Optional[List[str]] = None
|
209
|
+
"""
|
210
|
+
If prev_buffer_root was present in the request, this proof verifies that the
|
211
|
+
new unpublished root is a continuation of prev_unpublished_root
|
212
|
+
"""
|
213
|
+
|
198
214
|
consistency_verification: EventVerification = EventVerification.NONE
|
199
215
|
membership_verification: EventVerification = EventVerification.NONE
|
200
216
|
signature_verification: EventVerification = EventVerification.NONE
|
@@ -357,29 +373,47 @@ class RootResult(PangeaResponseResult):
|
|
357
373
|
|
358
374
|
|
359
375
|
class SearchEvent(APIResponseModel):
|
376
|
+
envelope: EventEnvelope
|
377
|
+
|
378
|
+
membership_proof: Optional[str] = None
|
379
|
+
"""A cryptographic proof that the record has been persisted in the log"""
|
380
|
+
|
381
|
+
hash: Annotated[Optional[str], Field(max_length=64, min_length=64)] = None
|
382
|
+
"""The record's hash"""
|
383
|
+
|
384
|
+
published: Optional[bool] = None
|
385
|
+
"""
|
386
|
+
If true, a root has been published after this event. If false, there is no
|
387
|
+
published root for this event
|
360
388
|
"""
|
361
|
-
Event information received after a search request
|
362
389
|
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
membership_proof -- A cryptographic proof that the record has been persisted in the log.
|
368
|
-
consistency_verification -- Consistency verification calculated if required.
|
369
|
-
membership_verification -- Membership verification calculated if required.
|
370
|
-
signature_verification -- Signature verification calculated if required.
|
371
|
-
fpe_context -- The context data needed to decrypt secure audit events that have been redacted with format preserving encryption.
|
390
|
+
imported: Optional[bool] = None
|
391
|
+
"""
|
392
|
+
If true, the even was imported manually and not logged by the standard
|
393
|
+
procedure. Some features such as tamper proofing may not be available
|
372
394
|
"""
|
373
395
|
|
374
|
-
envelope: EventEnvelope
|
375
|
-
hash: str
|
376
|
-
membership_proof: Optional[str] = None
|
377
|
-
published: Optional[bool] = None
|
378
396
|
leaf_index: Optional[int] = None
|
397
|
+
"""
|
398
|
+
The index of the leaf of the Merkle Tree where this record was inserted or
|
399
|
+
null if published=false
|
400
|
+
"""
|
401
|
+
|
402
|
+
valid_signature: Optional[bool] = None
|
403
|
+
"""
|
404
|
+
Result of the verification of the Vault signature, if the event was signed
|
405
|
+
and the parameter `verify_signature` is `true`
|
406
|
+
"""
|
407
|
+
|
408
|
+
fpe_context: Optional[str] = None
|
409
|
+
"""
|
410
|
+
The context data needed to decrypt secure audit events that have been
|
411
|
+
redacted with format preserving encryption.
|
412
|
+
"""
|
413
|
+
|
379
414
|
consistency_verification: EventVerification = EventVerification.NONE
|
380
415
|
membership_verification: EventVerification = EventVerification.NONE
|
381
416
|
signature_verification: EventVerification = EventVerification.NONE
|
382
|
-
fpe_context: Optional[str] = None
|
383
417
|
|
384
418
|
|
385
419
|
class SearchResultOutput(PangeaResponseResult):
|
@@ -498,275 +532,3 @@ class ExportRequest(APIRequestModel):
|
|
498
532
|
Whether or not to include the root hash of the tree and the membership proof
|
499
533
|
for each record.
|
500
534
|
"""
|
501
|
-
|
502
|
-
|
503
|
-
class AuditSchemaField(APIResponseModel):
|
504
|
-
"""A description of a field in an audit log."""
|
505
|
-
|
506
|
-
id: str
|
507
|
-
"""Prefix name / identity for the field."""
|
508
|
-
|
509
|
-
type: Literal["boolean", "datetime", "integer", "string", "string-unindexed", "text"]
|
510
|
-
"""The data type for the field."""
|
511
|
-
|
512
|
-
description: Optional[str] = None
|
513
|
-
"""Human display description of the field."""
|
514
|
-
|
515
|
-
name: Optional[str] = None
|
516
|
-
"""Human display name/title of the field."""
|
517
|
-
|
518
|
-
redact: Optional[bool] = None
|
519
|
-
"""If true, redaction is performed against this field (if configured.) Only valid for string type."""
|
520
|
-
|
521
|
-
required: Optional[bool] = None
|
522
|
-
"""If true, this field is required to exist in all logged events."""
|
523
|
-
|
524
|
-
size: Optional[int] = None
|
525
|
-
"""The maximum size of the field. Only valid for strings, which limits number of UTF-8 characters."""
|
526
|
-
|
527
|
-
ui_default_visible: Optional[bool] = None
|
528
|
-
"""If true, this field is visible by default in audit UIs."""
|
529
|
-
|
530
|
-
|
531
|
-
class AuditSchema(APIResponseModel):
|
532
|
-
"""A description of acceptable fields for an audit log."""
|
533
|
-
|
534
|
-
client_signable: Optional[bool] = None
|
535
|
-
"""If true, records contain fields to support client/vault signing."""
|
536
|
-
|
537
|
-
save_malformed: Optional[str] = None
|
538
|
-
"""Save (or reject) malformed AuditEvents."""
|
539
|
-
|
540
|
-
tamper_proofing: Optional[bool] = None
|
541
|
-
"""If true, records contain fields to support tamper-proofing."""
|
542
|
-
|
543
|
-
fields: Optional[List[AuditSchemaField]] = None
|
544
|
-
"""List of field definitions."""
|
545
|
-
|
546
|
-
|
547
|
-
class ForwardingConfiguration(APIResponseModel):
|
548
|
-
"""Configuration for forwarding audit logs to external systems."""
|
549
|
-
|
550
|
-
type: str
|
551
|
-
"""Type of forwarding configuration."""
|
552
|
-
|
553
|
-
forwarding_enabled: Optional[bool] = False
|
554
|
-
"""Whether forwarding is enabled."""
|
555
|
-
|
556
|
-
event_url: Optional[str] = None
|
557
|
-
"""URL where events will be written to. Must use HTTPS."""
|
558
|
-
|
559
|
-
ack_url: Optional[str] = None
|
560
|
-
"""If indexer acknowledgement is required, this must be provided along with a 'channel_id'."""
|
561
|
-
|
562
|
-
channel_id: Optional[str] = None
|
563
|
-
"""An optional splunk channel included in each request if indexer acknowledgement is required."""
|
564
|
-
|
565
|
-
public_cert: Optional[str] = None
|
566
|
-
"""Public certificate if a self signed TLS cert is being used."""
|
567
|
-
|
568
|
-
index: Optional[str] = None
|
569
|
-
"""Optional splunk index passed in the record bodies."""
|
570
|
-
|
571
|
-
vault_config_id: Optional[str] = None
|
572
|
-
"""The vault config used to store the HEC token."""
|
573
|
-
|
574
|
-
vault_secret_id: Optional[str] = None
|
575
|
-
"""The secret ID where the HEC token is stored in vault."""
|
576
|
-
|
577
|
-
|
578
|
-
class ServiceConfigV1(PangeaResponseResult):
|
579
|
-
"""Configuration options available for audit service"""
|
580
|
-
|
581
|
-
id: Optional[str] = None
|
582
|
-
"""The config ID"""
|
583
|
-
|
584
|
-
version: Literal[1] = 1
|
585
|
-
|
586
|
-
created_at: Optional[str] = None
|
587
|
-
"""The DB timestamp when this config was created. Ignored when submitted."""
|
588
|
-
|
589
|
-
updated_at: Optional[str] = None
|
590
|
-
"""The DB timestamp when this config was last updated at"""
|
591
|
-
|
592
|
-
name: Optional[str] = None
|
593
|
-
"""Configuration name"""
|
594
|
-
|
595
|
-
retention: Optional[str] = None
|
596
|
-
"""Retention window to store audit logs."""
|
597
|
-
|
598
|
-
cold_query_result_retention: Optional[str] = None
|
599
|
-
"""Retention window for cold query result / state information."""
|
600
|
-
|
601
|
-
hot_storage: Optional[str] = None
|
602
|
-
"""Retention window to keep audit logs in hot storage."""
|
603
|
-
|
604
|
-
query_result_retention: Optional[str] = None
|
605
|
-
"""Length of time to preserve server-side query result caching."""
|
606
|
-
|
607
|
-
redact_service_config_id: Optional[str] = None
|
608
|
-
"""A redact service config that will be used to redact PII from logs."""
|
609
|
-
|
610
|
-
redaction_fields: Optional[List[str]] = None
|
611
|
-
"""Fields to perform redaction against."""
|
612
|
-
|
613
|
-
vault_service_config_id: Optional[str] = None
|
614
|
-
"""A vault service config that will be used to sign logs."""
|
615
|
-
|
616
|
-
vault_key_id: Optional[str] = None
|
617
|
-
"""ID of the Vault key used for signing. If missing, use a default Audit key"""
|
618
|
-
|
619
|
-
vault_sign: Optional[bool] = None
|
620
|
-
"""Enable/disable event signing"""
|
621
|
-
|
622
|
-
|
623
|
-
class ServiceConfigV2(PangeaResponseResult):
|
624
|
-
"""Configuration options available for audit service"""
|
625
|
-
|
626
|
-
audit_schema: AuditSchema = Field(alias="schema")
|
627
|
-
"""Audit log field configuration. Only settable at create time."""
|
628
|
-
|
629
|
-
version: Literal[2] = 2
|
630
|
-
|
631
|
-
cold_query_result_retention: Optional[str] = None
|
632
|
-
"""Retention window for cold query result / state information."""
|
633
|
-
|
634
|
-
created_at: Optional[str] = None
|
635
|
-
"""The DB timestamp when this config was created. Ignored when submitted."""
|
636
|
-
|
637
|
-
hot_storage: Optional[str] = None
|
638
|
-
"""Retention window to keep audit logs in hot storage."""
|
639
|
-
|
640
|
-
id: Optional[str] = None
|
641
|
-
"""The config ID"""
|
642
|
-
|
643
|
-
name: Optional[str] = None
|
644
|
-
"""Configuration name"""
|
645
|
-
|
646
|
-
query_result_retention: Optional[str] = None
|
647
|
-
"""Length of time to preserve server-side query result caching."""
|
648
|
-
|
649
|
-
redact_service_config_id: Optional[str] = None
|
650
|
-
"""A redact service config that will be used to redact PII from logs."""
|
651
|
-
|
652
|
-
retention: Optional[str] = None
|
653
|
-
"""Retention window to store audit logs."""
|
654
|
-
|
655
|
-
updated_at: Optional[str] = None
|
656
|
-
"""The DB timestamp when this config was last updated at"""
|
657
|
-
|
658
|
-
vault_key_id: Optional[str] = None
|
659
|
-
"""ID of the Vault key used for signing. If missing, use a default Audit key"""
|
660
|
-
|
661
|
-
vault_service_config_id: Optional[str] = None
|
662
|
-
"""A vault service config that will be used to sign logs."""
|
663
|
-
|
664
|
-
vault_sign: Optional[bool] = None
|
665
|
-
"""Enable/disable event signing"""
|
666
|
-
|
667
|
-
forwarding_configuration: Optional[ForwardingConfiguration] = None
|
668
|
-
"""Configuration for forwarding audit logs to external systems."""
|
669
|
-
|
670
|
-
|
671
|
-
class ServiceConfigV3(PangeaResponseResult):
|
672
|
-
"""Configuration options available for audit service"""
|
673
|
-
|
674
|
-
audit_schema: AuditSchema = Field(alias="schema")
|
675
|
-
"""Audit log field configuration. Only settable at create time."""
|
676
|
-
|
677
|
-
version: Literal[3] = 3
|
678
|
-
"""Version of the service config."""
|
679
|
-
|
680
|
-
cold_storage: Optional[str] = None
|
681
|
-
"""Retention window for logs in cold storage. Deleted afterwards."""
|
682
|
-
|
683
|
-
created_at: Optional[str] = None
|
684
|
-
"""The DB timestamp when this config was created. Ignored when submitted."""
|
685
|
-
|
686
|
-
forwarding_configuration: Optional[ForwardingConfiguration] = None
|
687
|
-
"""Configuration for forwarding audit logs to external systems."""
|
688
|
-
|
689
|
-
hot_storage: Optional[str] = None
|
690
|
-
"""Retention window for logs in hot storage. Migrated to warm, cold, or deleted afterwards."""
|
691
|
-
|
692
|
-
id: Optional[str] = None
|
693
|
-
"""The config ID"""
|
694
|
-
|
695
|
-
name: Optional[str] = None
|
696
|
-
"""Configuration name"""
|
697
|
-
|
698
|
-
redact_service_config_id: Optional[str] = None
|
699
|
-
"""A redact service config that will be used to redact PII from logs."""
|
700
|
-
|
701
|
-
updated_at: Optional[str] = None
|
702
|
-
"""The DB timestamp when this config was last updated at"""
|
703
|
-
|
704
|
-
vault_key_id: Optional[str] = None
|
705
|
-
"""ID of the Vault key used for signing. If missing, use a default Audit key"""
|
706
|
-
|
707
|
-
vault_service_config_id: Optional[str] = None
|
708
|
-
"""A vault service config that will be used to sign logs."""
|
709
|
-
|
710
|
-
vault_sign: Optional[bool] = None
|
711
|
-
"""Enable/disable event signing"""
|
712
|
-
|
713
|
-
warm_storage: Optional[str] = None
|
714
|
-
"""Retention window for logs in warm storage. Migrated to cold or deleted afterwards."""
|
715
|
-
|
716
|
-
|
717
|
-
ServiceConfig = Annotated[
|
718
|
-
Union[ServiceConfigV1, ServiceConfigV2, ServiceConfigV3],
|
719
|
-
Field(discriminator="version"),
|
720
|
-
]
|
721
|
-
"""Configuration options available for audit service"""
|
722
|
-
|
723
|
-
|
724
|
-
class ServiceConfigFilter(APIRequestModel):
|
725
|
-
id: Optional[str] = None
|
726
|
-
"""Only records where id equals this value."""
|
727
|
-
|
728
|
-
id__contains: Optional[Sequence[str]] = None
|
729
|
-
"""Only records where id includes each substring."""
|
730
|
-
|
731
|
-
id__in: Optional[Sequence[str]] = None
|
732
|
-
"""Only records where id equals one of the provided substrings."""
|
733
|
-
|
734
|
-
created_at: Optional[str] = None
|
735
|
-
"""Only records where created_at equals this value."""
|
736
|
-
|
737
|
-
created_at__gt: Optional[str] = None
|
738
|
-
"""Only records where created_at is greater than this value."""
|
739
|
-
|
740
|
-
created_at__gte: Optional[str] = None
|
741
|
-
"""Only records where created_at is greater than or equal to this value."""
|
742
|
-
|
743
|
-
created_at__lt: Optional[str] = None
|
744
|
-
"""Only records where created_at is less than this value."""
|
745
|
-
|
746
|
-
created_at__lte: Optional[str] = None
|
747
|
-
"""Only records where created_at is less than or equal to this value."""
|
748
|
-
|
749
|
-
updated_at: Optional[str] = None
|
750
|
-
"""Only records where updated_at equals this value."""
|
751
|
-
|
752
|
-
updated_at__gt: Optional[str] = None
|
753
|
-
"""Only records where updated_at is greater than this value."""
|
754
|
-
|
755
|
-
updated_at__gte: Optional[str] = None
|
756
|
-
"""Only records where updated_at is greater than or equal to this value."""
|
757
|
-
|
758
|
-
updated_at__lt: Optional[str] = None
|
759
|
-
"""Only records where updated_at is less than this value."""
|
760
|
-
|
761
|
-
updated_at__lte: Optional[str] = None
|
762
|
-
"""Only records where updated_at is less than or equal to this value."""
|
763
|
-
|
764
|
-
|
765
|
-
class ServiceConfigListResult(PangeaResponseResult):
|
766
|
-
count: int
|
767
|
-
"""The total number of service configs matched by the list request."""
|
768
|
-
|
769
|
-
last: str
|
770
|
-
"""Used to fetch the next page of the current listing when provided in a repeated request's last parameter."""
|
771
|
-
|
772
|
-
items: Sequence[ServiceConfig]
|
pangea/services/audit/signing.py
CHANGED
@@ -81,7 +81,7 @@ class Signer:
|
|
81
81
|
with open(self.private_key_file, "rb") as file:
|
82
82
|
file_bytes = file.read()
|
83
83
|
except FileNotFoundError:
|
84
|
-
raise Exception(f"Error: Failed opening private key file {self.private_key_file}")
|
84
|
+
raise Exception(f"Error: Failed opening private key file {self.private_key_file}") from None
|
85
85
|
|
86
86
|
privkey = self._decode_private_key(file_bytes)
|
87
87
|
for cls, signer in signers.items():
|
pangea/services/audit/util.py
CHANGED
@@ -1,5 +1,11 @@
|
|
1
1
|
# Copyright 2022 Pangea Cyber Corporation
|
2
2
|
# Author: Pangea Cyber Corporation
|
3
|
+
|
4
|
+
# TODO: Modernize.
|
5
|
+
# ruff: noqa: UP006, UP035
|
6
|
+
|
7
|
+
from __future__ import annotations
|
8
|
+
|
3
9
|
import base64
|
4
10
|
import json
|
5
11
|
import logging
|
@@ -155,9 +161,9 @@ def verify_membership_proof(node_hash: Hash, root_hash: Hash, proof: MembershipP
|
|
155
161
|
def normalize_log(data: dict) -> dict:
|
156
162
|
ans = {}
|
157
163
|
for key in data:
|
158
|
-
if
|
164
|
+
if isinstance(data[key], datetime):
|
159
165
|
ans[key] = format_datetime(data[key])
|
160
|
-
elif
|
166
|
+
elif isinstance(data[key], dict):
|
161
167
|
ans[key] = normalize_log(data[key]) # type: ignore[assignment]
|
162
168
|
else:
|
163
169
|
ans[key] = data[key]
|
@@ -223,9 +229,7 @@ def get_arweave_published_roots(tree_name: str, tree_sizes: Collection[int]) ->
|
|
223
229
|
}
|
224
230
|
}
|
225
231
|
}
|
226
|
-
""".replace(
|
227
|
-
"{tree_sizes}", ", ".join(f'"{tree_size}"' for tree_size in tree_sizes)
|
228
|
-
).replace(
|
232
|
+
""".replace("{tree_sizes}", ", ".join(f'"{tree_size}"' for tree_size in tree_sizes)).replace(
|
229
233
|
"{tree_name}", tree_name
|
230
234
|
)
|
231
235
|
|
@@ -273,8 +277,4 @@ def verify_consistency_proof(new_root: Hash, prev_root: Hash, proof: Consistency
|
|
273
277
|
return False
|
274
278
|
|
275
279
|
logger.debug("Verifying the proofs for the new root")
|
276
|
-
for item in proof
|
277
|
-
if not verify_membership_proof(item.node_hash, new_root, item.proof):
|
278
|
-
return False
|
279
|
-
|
280
|
-
return True
|
280
|
+
return all(verify_membership_proof(item.node_hash, new_root, item.proof) for item in proof)
|