vbase 1.0.0__tar.gz → 2.0.0__tar.gz
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.
- vbase-2.0.0/CHANGELOG.md +30 -0
- {vbase-1.0.0 → vbase-2.0.0}/MANIFEST.in +1 -0
- {vbase-1.0.0/vbase.egg-info → vbase-2.0.0}/PKG-INFO +18 -20
- {vbase-1.0.0 → vbase-2.0.0}/README.md +8 -9
- {vbase-1.0.0 → vbase-2.0.0}/pyproject.toml +1 -1
- vbase-2.0.0/requirements.in +8 -0
- {vbase-1.0.0 → vbase-2.0.0}/setup.py +0 -1
- {vbase-1.0.0 → vbase-2.0.0}/vbase/__init__.py +1 -3
- {vbase-1.0.0 → vbase-2.0.0}/vbase/_version.py +1 -1
- {vbase-1.0.0 → vbase-2.0.0}/vbase/core/aggregate_indexing_service.py +1 -1
- {vbase-1.0.0 → vbase-2.0.0}/vbase/core/commitment_service.py +13 -0
- {vbase-1.0.0 → vbase-2.0.0}/vbase/core/failover_indexing_service.py +1 -1
- {vbase-1.0.0 → vbase-2.0.0}/vbase/core/set_matching/__init__.py +1 -3
- {vbase-1.0.0 → vbase-2.0.0}/vbase/core/set_matching/base_set_matching_service.py +1 -1
- {vbase-1.0.0 → vbase-2.0.0}/vbase/core/set_matching/chain_set_matching_service.py +3 -2
- {vbase-1.0.0 → vbase-2.0.0}/vbase/core/set_matching/fuzzy_set_matching_service.py +9 -7
- {vbase-1.0.0 → vbase-2.0.0}/vbase/core/set_matching/head_based_set_matching_service.py +10 -7
- {vbase-1.0.0 → vbase-2.0.0}/vbase/core/set_matching/types.py +4 -0
- {vbase-1.0.0 → vbase-2.0.0}/vbase/core/sql_indexing_service.py +1 -1
- {vbase-1.0.0 → vbase-2.0.0}/vbase/core/vbase_client.py +13 -0
- {vbase-1.0.0 → vbase-2.0.0}/vbase/core/web3_commitment_service.py +33 -8
- {vbase-1.0.0 → vbase-2.0.0/vbase.egg-info}/PKG-INFO +18 -20
- {vbase-1.0.0 → vbase-2.0.0}/vbase.egg-info/SOURCES.txt +1 -0
- vbase-2.0.0/vbase.egg-info/requires.txt +8 -0
- vbase-1.0.0/requirements.in +0 -9
- vbase-1.0.0/vbase.egg-info/requires.txt +0 -9
- {vbase-1.0.0 → vbase-2.0.0}/LICENSE.txt +0 -0
- {vbase-1.0.0 → vbase-2.0.0}/NOTICE.txt +0 -0
- {vbase-1.0.0 → vbase-2.0.0}/setup.cfg +0 -0
- {vbase-1.0.0 → vbase-2.0.0}/vbase/core/__init__.py +0 -0
- {vbase-1.0.0 → vbase-2.0.0}/vbase/core/abi/CommitmentService.json +0 -0
- {vbase-1.0.0 → vbase-2.0.0}/vbase/core/abi/CommitmentServiceTest.json +0 -0
- {vbase-1.0.0 → vbase-2.0.0}/vbase/core/commitment_service_test.py +0 -0
- {vbase-1.0.0 → vbase-2.0.0}/vbase/core/forwarder_commitment_service.py +0 -0
- {vbase-1.0.0 → vbase-2.0.0}/vbase/core/forwarder_commitment_service_test.py +0 -0
- {vbase-1.0.0 → vbase-2.0.0}/vbase/core/indexing_service.py +0 -0
- {vbase-1.0.0 → vbase-2.0.0}/vbase/core/models.py +0 -0
- {vbase-1.0.0 → vbase-2.0.0}/vbase/core/vbase_client_test.py +0 -0
- {vbase-1.0.0 → vbase-2.0.0}/vbase/core/vbase_dataset.py +0 -0
- {vbase-1.0.0 → vbase-2.0.0}/vbase/core/vbase_dataset_async.py +0 -0
- {vbase-1.0.0 → vbase-2.0.0}/vbase/core/vbase_object.py +0 -0
- {vbase-1.0.0 → vbase-2.0.0}/vbase/core/web3_http_commitment_service.py +0 -0
- {vbase-1.0.0 → vbase-2.0.0}/vbase/core/web3_http_commitment_service_test.py +0 -0
- {vbase-1.0.0 → vbase-2.0.0}/vbase/utils/__init__.py +0 -0
- {vbase-1.0.0 → vbase-2.0.0}/vbase/utils/crypto_utils.py +0 -0
- {vbase-1.0.0 → vbase-2.0.0}/vbase/utils/error_utils.py +0 -0
- {vbase-1.0.0 → vbase-2.0.0}/vbase/utils/log.py +0 -0
- {vbase-1.0.0 → vbase-2.0.0}/vbase.egg-info/dependency_links.txt +0 -0
- {vbase-1.0.0 → vbase-2.0.0}/vbase.egg-info/top_level.txt +0 -0
vbase-2.0.0/CHANGELOG.md
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes are documented here, following
|
|
4
|
+
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
5
|
+
Versions follow [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
|
+
|
|
7
|
+
Earlier releases were not tracked in this file; see the
|
|
8
|
+
[commit history](https://github.com/validityBase/vbase-py/commits/main/)
|
|
9
|
+
for prior changes.
|
|
10
|
+
|
|
11
|
+
## [Unreleased]
|
|
12
|
+
|
|
13
|
+
## [2.0.0] - 2026-10-28
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
|
|
17
|
+
- Require Python 3.11 or later. Drop support for Python 3.8 through 3.10 (#84).
|
|
18
|
+
- Accept Web3 versions greater than or equal to 7.15 and less than 9 (#106).
|
|
19
|
+
- Set upper bounds for runtime dependencies (#63, #106).
|
|
20
|
+
- Remove the unused `imageio` runtime dependency (#110).
|
|
21
|
+
|
|
22
|
+
### Fixed
|
|
23
|
+
|
|
24
|
+
- Use a matching `AddSet` receipt event to confirm a new set commitment.
|
|
25
|
+
Check the event's user and set CID. This avoids a false `add_set` failure
|
|
26
|
+
when an RPC backend returns stale state (#86).
|
|
27
|
+
- Retry the state check if a successful `add_set` transaction has no `AddSet`
|
|
28
|
+
receipt event. Fail if the set commitment cannot be confirmed after the
|
|
29
|
+
configured retries. Commitment confirmation does not guarantee immediate
|
|
30
|
+
visibility through an indexing service (#86).
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: vbase
|
|
3
|
-
Version:
|
|
3
|
+
Version: 2.0.0
|
|
4
4
|
Summary: vBase Python Software Development Kit (SDK)
|
|
5
5
|
Author-email: vBase <tech@vbase.com>
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -10,32 +10,31 @@ Project-URL: Issues, https://github.com/validityBase/vbase-py/issues
|
|
|
10
10
|
Keywords: vbase,blockchain,provenance,web3,sdk
|
|
11
11
|
Classifier: Operating System :: OS Independent
|
|
12
12
|
Classifier: Programming Language :: Python :: 3
|
|
13
|
-
Requires-Python: >=3.
|
|
13
|
+
Requires-Python: >=3.11
|
|
14
14
|
Description-Content-Type: text/markdown
|
|
15
15
|
License-File: LICENSE.txt
|
|
16
16
|
License-File: NOTICE.txt
|
|
17
|
-
Requires-Dist: hexbytes
|
|
18
|
-
Requires-Dist: numpy
|
|
19
|
-
Requires-Dist: pandas
|
|
20
|
-
Requires-Dist: python-dotenv
|
|
21
|
-
Requires-Dist: requests
|
|
22
|
-
Requires-Dist: web3
|
|
23
|
-
Requires-Dist: sqlmodel
|
|
24
|
-
Requires-Dist:
|
|
25
|
-
Requires-Dist: retry>=0.9.2
|
|
17
|
+
Requires-Dist: hexbytes<3,>=1.2.0
|
|
18
|
+
Requires-Dist: numpy<3,>=1.24.0
|
|
19
|
+
Requires-Dist: pandas<4,>=2.0.0
|
|
20
|
+
Requires-Dist: python-dotenv<2,>=1.0.0
|
|
21
|
+
Requires-Dist: requests<3,>=2.31.0
|
|
22
|
+
Requires-Dist: web3<9,>=7.15.0
|
|
23
|
+
Requires-Dist: sqlmodel<0.1,>=0.0.24
|
|
24
|
+
Requires-Dist: retry<1,>=0.9.2
|
|
26
25
|
Dynamic: license-file
|
|
27
26
|
|
|
28
27
|
# vbase-py
|
|
29
28
|
|
|
30
29
|
vBase Python Software Development Kit (SDK)
|
|
31
30
|
|
|
32
|
-
- Python 3.
|
|
31
|
+
- Python 3.11+ support
|
|
33
32
|
|
|
34
33
|
---
|
|
35
34
|
|
|
36
35
|
## License
|
|
37
36
|
|
|
38
|
-
This project is licensed under the Apache 2.0 License - see the [LICENSE.txt](LICENSE.txt) file for details.
|
|
37
|
+
This project is licensed under the Apache 2.0 License - see the [LICENSE.txt](https://github.com/validityBase/vbase-py/blob/main/LICENSE.txt) file for details.
|
|
39
38
|
|
|
40
39
|
## Introduction
|
|
41
40
|
|
|
@@ -62,18 +61,17 @@ Install the package from PyPI:
|
|
|
62
61
|
pip install vbase
|
|
63
62
|
```
|
|
64
63
|
|
|
65
|
-
See the [local installation](https://docs.vbase.com/
|
|
64
|
+
See the [local installation](https://docs.vbase.com/python-sdk/python-quickstart-readme/quickstart-1) and the [cloud notebooks](https://docs.vbase.com/python-sdk/python-quickstart-readme/quickstart) guides to get started using vBase from Python.
|
|
66
65
|
|
|
67
66
|
## Development
|
|
68
67
|
|
|
69
|
-
|
|
70
|
-
hash-checking mode:
|
|
68
|
+
Install the generated development lock and package locally:
|
|
71
69
|
|
|
72
70
|
```bash
|
|
73
|
-
python -m pip install --require-hashes -r requirements
|
|
71
|
+
python -m pip install --require-hashes -r requirements/dev.txt
|
|
74
72
|
python -m pip install --no-deps --no-build-isolation -e .
|
|
75
73
|
```
|
|
76
74
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
75
|
+
See `internal/specs/python-dependency-hashes.md` in this repository for the
|
|
76
|
+
dependency layout, lock policy, package metadata rules, and regeneration
|
|
77
|
+
commands.
|
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
vBase Python Software Development Kit (SDK)
|
|
4
4
|
|
|
5
|
-
- Python 3.
|
|
5
|
+
- Python 3.11+ support
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
## License
|
|
10
10
|
|
|
11
|
-
This project is licensed under the Apache 2.0 License - see the [LICENSE.txt](LICENSE.txt) file for details.
|
|
11
|
+
This project is licensed under the Apache 2.0 License - see the [LICENSE.txt](https://github.com/validityBase/vbase-py/blob/main/LICENSE.txt) file for details.
|
|
12
12
|
|
|
13
13
|
## Introduction
|
|
14
14
|
|
|
@@ -35,18 +35,17 @@ Install the package from PyPI:
|
|
|
35
35
|
pip install vbase
|
|
36
36
|
```
|
|
37
37
|
|
|
38
|
-
See the [local installation](https://docs.vbase.com/
|
|
38
|
+
See the [local installation](https://docs.vbase.com/python-sdk/python-quickstart-readme/quickstart-1) and the [cloud notebooks](https://docs.vbase.com/python-sdk/python-quickstart-readme/quickstart) guides to get started using vBase from Python.
|
|
39
39
|
|
|
40
40
|
## Development
|
|
41
41
|
|
|
42
|
-
|
|
43
|
-
hash-checking mode:
|
|
42
|
+
Install the generated development lock and package locally:
|
|
44
43
|
|
|
45
44
|
```bash
|
|
46
|
-
python -m pip install --require-hashes -r requirements
|
|
45
|
+
python -m pip install --require-hashes -r requirements/dev.txt
|
|
47
46
|
python -m pip install --no-deps --no-build-isolation -e .
|
|
48
47
|
```
|
|
49
48
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
49
|
+
See `internal/specs/python-dependency-hashes.md` in this repository for the
|
|
50
|
+
dependency layout, lock policy, package metadata rules, and regeneration
|
|
51
|
+
commands.
|
|
@@ -7,7 +7,7 @@ name = "vbase"
|
|
|
7
7
|
dynamic = ["version", "dependencies"]
|
|
8
8
|
description = "vBase Python Software Development Kit (SDK)"
|
|
9
9
|
readme = "README.md"
|
|
10
|
-
requires-python = ">=3.
|
|
10
|
+
requires-python = ">=3.11"
|
|
11
11
|
license = "Apache-2.0"
|
|
12
12
|
authors = [
|
|
13
13
|
{ name = "vBase", email = "tech@vbase.com" },
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
A Python library for interacting with the validityBase (vBase) platform
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
|
-
from vbase._version import __version__
|
|
7
6
|
from vbase.core.aggregate_indexing_service import AggregateIndexingService
|
|
8
7
|
from vbase.core.failover_indexing_service import FailoverIndexingService
|
|
9
8
|
from vbase.core.forwarder_commitment_service import ForwarderCommitmentService
|
|
@@ -41,6 +40,7 @@ from vbase.core.vbase_object import (
|
|
|
41
40
|
from vbase.core.web3_http_commitment_service import Web3HTTPCommitmentService
|
|
42
41
|
from vbase.core.web3_http_commitment_service_test import Web3HTTPCommitmentServiceTest
|
|
43
42
|
from vbase.utils.log import get_default_logger
|
|
43
|
+
from ._version import __version__
|
|
44
44
|
|
|
45
45
|
__all__ = [
|
|
46
46
|
"__version__",
|
|
@@ -53,7 +53,6 @@ __all__ = [
|
|
|
53
53
|
"IndexingService",
|
|
54
54
|
"Web3HTTPIndexingService",
|
|
55
55
|
"SQLIndexingService",
|
|
56
|
-
|
|
57
56
|
"ChainSetMatchingService",
|
|
58
57
|
"HeadBasedSetMatchingService",
|
|
59
58
|
"FuzzySetMatchingService",
|
|
@@ -61,7 +60,6 @@ __all__ = [
|
|
|
61
60
|
"SetMatch",
|
|
62
61
|
"SetMatchingCriteria",
|
|
63
62
|
"TimestampedCid",
|
|
64
|
-
|
|
65
63
|
"FailoverIndexingService",
|
|
66
64
|
"AggregateIndexingService",
|
|
67
65
|
"VBaseObject",
|
|
@@ -10,7 +10,7 @@ _LOG = get_default_logger(__name__)
|
|
|
10
10
|
_LOG.setLevel(logging.INFO)
|
|
11
11
|
|
|
12
12
|
|
|
13
|
-
class AggregateIndexingService(IndexingService):
|
|
13
|
+
class AggregateIndexingService(IndexingService): # pylint: disable=abstract-method
|
|
14
14
|
"""This indexing service aggregates the responses from a set of indexing services
|
|
15
15
|
|
|
16
16
|
Each operation executes a corresponding method on all services and aggregates the results.
|
|
@@ -84,8 +84,21 @@ class CommitmentService(ABC):
|
|
|
84
84
|
It does not specify how a hash is built and does not provide
|
|
85
85
|
a schema for hashing complex information.
|
|
86
86
|
|
|
87
|
+
The operation is idempotent. A successful transaction receipt containing
|
|
88
|
+
a matching ``AddSet`` event is authoritative for the submitted write and
|
|
89
|
+
avoids a potentially stale state read. If an idempotent transaction emits
|
|
90
|
+
no event, the service confirms the existing commitment using bounded,
|
|
91
|
+
exponential-backoff retries.
|
|
92
|
+
|
|
93
|
+
Transaction confirmation does not guarantee immediate visibility through
|
|
94
|
+
an indexing service. Consumers that query indexing immediately after a
|
|
95
|
+
write may need read-your-write handling based on the returned transaction
|
|
96
|
+
hash.
|
|
97
|
+
|
|
87
98
|
:param set_cid: The CID identifying the set.
|
|
88
99
|
:return: The commitment log containing commitment receipt info.
|
|
100
|
+
:raises RuntimeError: If a matching event is absent and the commitment
|
|
101
|
+
cannot be confirmed after retrying.
|
|
89
102
|
"""
|
|
90
103
|
|
|
91
104
|
@abstractmethod
|
|
@@ -9,7 +9,7 @@ _LOG = get_default_logger(__name__)
|
|
|
9
9
|
_LOG.setLevel(logging.INFO)
|
|
10
10
|
|
|
11
11
|
|
|
12
|
-
class FailoverIndexingService(IndexingService):
|
|
12
|
+
class FailoverIndexingService(IndexingService): # pylint: disable=abstract-method
|
|
13
13
|
"""This indexing service calls a set of indexing services one after another
|
|
14
14
|
and provides a failover mechanism to ensure that if one service fails,
|
|
15
15
|
another service can be used to retrieve the data.
|
|
@@ -3,10 +3,8 @@
|
|
|
3
3
|
Core classes for set matching services in the validityBase (vBase) platform Python library
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
|
-
from vbase.core.set_matching.chain_set_matching_service import (
|
|
7
|
-
ChainSetMatchingService,
|
|
8
|
-
)
|
|
9
6
|
from vbase.core.set_matching.base_set_matching_service import BaseSetMatchingService
|
|
7
|
+
from vbase.core.set_matching.chain_set_matching_service import ChainSetMatchingService
|
|
10
8
|
from vbase.core.set_matching.fuzzy_set_matching_service import FuzzySetMatchingService
|
|
11
9
|
from vbase.core.set_matching.head_based_set_matching_service import (
|
|
12
10
|
HeadBasedSetMatchingService,
|
|
@@ -11,7 +11,7 @@ from vbase.core.models import EventAddSetObject, LastBatchProcessingTime
|
|
|
11
11
|
from vbase.core.set_matching.types import SetIdentifier, SetMatch, SetMatchingCriteria
|
|
12
12
|
|
|
13
13
|
|
|
14
|
-
class BaseSetMatchingService(ABC):
|
|
14
|
+
class BaseSetMatchingService(ABC): # pylint: disable=too-few-public-methods
|
|
15
15
|
"""
|
|
16
16
|
Abstract base class for set matching strategies.
|
|
17
17
|
|
|
@@ -2,12 +2,13 @@
|
|
|
2
2
|
Aggregate set matching strategies.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
-
|
|
6
5
|
from vbase.core.set_matching.base_set_matching_service import BaseSetMatchingService
|
|
7
6
|
from vbase.core.set_matching.types import SetMatch, SetMatchingCriteria
|
|
8
7
|
|
|
9
8
|
|
|
10
|
-
class ChainSetMatchingService(
|
|
9
|
+
class ChainSetMatchingService(
|
|
10
|
+
BaseSetMatchingService
|
|
11
|
+
): # pylint: disable=too-few-public-methods
|
|
11
12
|
"""
|
|
12
13
|
Aggregate multiple set matching strategies to return first non-empty result.
|
|
13
14
|
|
|
@@ -18,7 +18,9 @@ from vbase.core.set_matching.types import (
|
|
|
18
18
|
)
|
|
19
19
|
|
|
20
20
|
|
|
21
|
-
class FuzzySetMatchingService(
|
|
21
|
+
class FuzzySetMatchingService(
|
|
22
|
+
BaseSetMatchingService
|
|
23
|
+
): # pylint: disable=too-few-public-methods
|
|
22
24
|
"""
|
|
23
25
|
Service for performing fuzzy set matching with tolerance.
|
|
24
26
|
Finds sets whose elements match the criteria within a configurable tolerance.
|
|
@@ -142,7 +144,9 @@ class FuzzySetMatchingService(BaseSetMatchingService):
|
|
|
142
144
|
rank=s.rank,
|
|
143
145
|
set_cid=s.key.set_cid,
|
|
144
146
|
user=s.key.user,
|
|
145
|
-
last_matching_element_timestamp=s.objects[
|
|
147
|
+
last_matching_element_timestamp=s.objects[
|
|
148
|
+
s.projected_last_element_index
|
|
149
|
+
].timestamp,
|
|
146
150
|
data_freshness_timestamp=last_batch,
|
|
147
151
|
is_full_match=(
|
|
148
152
|
s.set_length == len(sorted_criteria.objects)
|
|
@@ -292,8 +296,8 @@ class FuzzySetMatchingService(BaseSetMatchingService):
|
|
|
292
296
|
dp[i][j] = dp[i - 1][j - 1]
|
|
293
297
|
else:
|
|
294
298
|
dp[i][j] = 1 + min(
|
|
295
|
-
dp[i - 1][j],
|
|
296
|
-
dp[i][j - 1],
|
|
299
|
+
dp[i - 1][j], # deletion
|
|
300
|
+
dp[i][j - 1], # insertion
|
|
297
301
|
dp[i - 1][j - 1], # substitution
|
|
298
302
|
)
|
|
299
303
|
|
|
@@ -325,9 +329,7 @@ class FuzzySetMatchingService(BaseSetMatchingService):
|
|
|
325
329
|
if not criteria.objects:
|
|
326
330
|
return []
|
|
327
331
|
|
|
328
|
-
required_matches = max(
|
|
329
|
-
1, math.ceil(len(criteria.objects) * (1.0 - tolerance))
|
|
330
|
-
)
|
|
332
|
+
required_matches = max(1, math.ceil(len(criteria.objects) * (1.0 - tolerance)))
|
|
331
333
|
|
|
332
334
|
# Collect all criteria CIDs
|
|
333
335
|
criteria_cids = [obj.object_cid for obj in criteria.objects]
|
|
@@ -6,10 +6,17 @@ from sqlmodel import Session, create_engine, select
|
|
|
6
6
|
|
|
7
7
|
from vbase.core.models import EventAddSetObject
|
|
8
8
|
from vbase.core.set_matching.base_set_matching_service import BaseSetMatchingService
|
|
9
|
-
from vbase.core.set_matching.types import
|
|
9
|
+
from vbase.core.set_matching.types import (
|
|
10
|
+
ObjectSetData,
|
|
11
|
+
SetIdentifier,
|
|
12
|
+
SetMatch,
|
|
13
|
+
SetMatchingCriteria,
|
|
14
|
+
)
|
|
10
15
|
|
|
11
16
|
|
|
12
|
-
class HeadBasedSetMatchingService(
|
|
17
|
+
class HeadBasedSetMatchingService(
|
|
18
|
+
BaseSetMatchingService
|
|
19
|
+
): # pylint: disable=too-few-public-methods
|
|
13
20
|
"""
|
|
14
21
|
Service for performing head-based set matching.
|
|
15
22
|
Finds sets whose head (first elements) matches the elements specified in the criteria.
|
|
@@ -25,10 +32,7 @@ class HeadBasedSetMatchingService(BaseSetMatchingService):
|
|
|
25
32
|
(distributed sets).
|
|
26
33
|
"""
|
|
27
34
|
|
|
28
|
-
def __init__(
|
|
29
|
-
self,
|
|
30
|
-
db_url: str
|
|
31
|
-
):
|
|
35
|
+
def __init__(self, db_url: str):
|
|
32
36
|
self.db_url = db_url
|
|
33
37
|
self.db_engine = create_engine(db_url)
|
|
34
38
|
|
|
@@ -68,7 +72,6 @@ class HeadBasedSetMatchingService(BaseSetMatchingService):
|
|
|
68
72
|
return []
|
|
69
73
|
event_rows = self._load_candidate_events(session, candidate_keys)
|
|
70
74
|
|
|
71
|
-
|
|
72
75
|
# Build ObjectSetData from event_rows (already ordered by timestamp)
|
|
73
76
|
candidate_sets_dict: dict[SetIdentifier, ObjectSetData] = {}
|
|
74
77
|
for event_row in event_rows:
|
|
@@ -5,6 +5,8 @@ Core types for indexing and matching strategies.
|
|
|
5
5
|
from dataclasses import dataclass, field
|
|
6
6
|
|
|
7
7
|
from vbase.core.models import EventAddSetObject
|
|
8
|
+
|
|
9
|
+
|
|
8
10
|
@dataclass
|
|
9
11
|
class TimestampedCid:
|
|
10
12
|
"""Pair of object_cid and its timestamp criteria."""
|
|
@@ -23,6 +25,7 @@ class SetMatchingCriteria:
|
|
|
23
25
|
|
|
24
26
|
objects: list[TimestampedCid]
|
|
25
27
|
|
|
28
|
+
|
|
26
29
|
@dataclass(frozen=True)
|
|
27
30
|
class SetMatch:
|
|
28
31
|
"""
|
|
@@ -48,6 +51,7 @@ class SetIdentifier:
|
|
|
48
51
|
Unique identifier for a set, based on its set_cid and user.
|
|
49
52
|
Sets can span multiple chains (distributed sets).
|
|
50
53
|
"""
|
|
54
|
+
|
|
51
55
|
set_cid: str
|
|
52
56
|
user: str
|
|
53
57
|
|
|
@@ -19,7 +19,7 @@ from .models import (
|
|
|
19
19
|
INDEXING_STALE_THRESHOLD_SECONDS = 60
|
|
20
20
|
|
|
21
21
|
|
|
22
|
-
class SQLIndexingService(IndexingService):
|
|
22
|
+
class SQLIndexingService(IndexingService): # pylint: disable=abstract-method
|
|
23
23
|
"""
|
|
24
24
|
Indexing service based on chain indexing data from sql db.
|
|
25
25
|
"""
|
|
@@ -106,8 +106,21 @@ class VBaseClient:
|
|
|
106
106
|
It does not specify how a hash is built and does not provide
|
|
107
107
|
a schema for hashing complex information.
|
|
108
108
|
|
|
109
|
+
The operation is idempotent. A successful transaction receipt containing
|
|
110
|
+
a matching ``AddSet`` event is authoritative for the submitted write and
|
|
111
|
+
avoids a potentially stale state read. If an idempotent transaction emits
|
|
112
|
+
no event, the service confirms the existing commitment using bounded,
|
|
113
|
+
exponential-backoff retries.
|
|
114
|
+
|
|
115
|
+
Transaction confirmation does not guarantee immediate visibility through
|
|
116
|
+
an indexing service. Consumers that query indexing immediately after a
|
|
117
|
+
write may need read-your-write handling based on the returned transaction
|
|
118
|
+
hash.
|
|
119
|
+
|
|
109
120
|
:param set_cid: The CID (hash) identifying the set.
|
|
110
121
|
:return: The commitment log containing commitment receipt info.
|
|
122
|
+
:raises RuntimeError: If a matching event is absent and the commitment
|
|
123
|
+
cannot be confirmed after retrying.
|
|
111
124
|
"""
|
|
112
125
|
return self.commitment_service.add_set(set_cid)
|
|
113
126
|
|
|
@@ -14,6 +14,7 @@ from io import TextIOWrapper
|
|
|
14
14
|
from typing import List, Optional, Type, Union
|
|
15
15
|
|
|
16
16
|
import pandas as pd
|
|
17
|
+
from retry.api import retry_call
|
|
17
18
|
from web3 import Web3
|
|
18
19
|
from web3.contract import Contract
|
|
19
20
|
from web3.contract.base_contract import EventLogErrorFlags
|
|
@@ -32,6 +33,10 @@ class Web3CommitmentService(CommitmentService, ABC):
|
|
|
32
33
|
either directly or via a forwarder.
|
|
33
34
|
"""
|
|
34
35
|
|
|
36
|
+
RETRY_TRIES = 3
|
|
37
|
+
RETRY_DELAY = 1
|
|
38
|
+
RETRY_BACKOFF = 2
|
|
39
|
+
|
|
35
40
|
def __init__(
|
|
36
41
|
self, w3: Web3, commitment_service_contract: Union[Type[Contract], Contract]
|
|
37
42
|
):
|
|
@@ -113,6 +118,24 @@ class Web3CommitmentService(CommitmentService, ABC):
|
|
|
113
118
|
_LOG.error(msg)
|
|
114
119
|
raise RuntimeError(msg)
|
|
115
120
|
|
|
121
|
+
def _require_user_set_exists(self, user: str, set_cid: str) -> None:
|
|
122
|
+
"""Raise if a set commitment is not visible for a user."""
|
|
123
|
+
if not self.user_set_exists(user, set_cid):
|
|
124
|
+
raise RuntimeError(
|
|
125
|
+
"AddSet event not found and set commitment does not exist"
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
def _user_set_exists_with_retry(self, user: str, set_cid: str) -> None:
|
|
129
|
+
"""Confirm set visibility with bounded exponential-backoff retries."""
|
|
130
|
+
retry_call(
|
|
131
|
+
self._require_user_set_exists,
|
|
132
|
+
fargs=[user, set_cid],
|
|
133
|
+
tries=self.RETRY_TRIES,
|
|
134
|
+
delay=self.RETRY_DELAY,
|
|
135
|
+
backoff=self.RETRY_BACKOFF,
|
|
136
|
+
logger=_LOG,
|
|
137
|
+
)
|
|
138
|
+
|
|
116
139
|
def _add_set_worker(self, set_cid: str, receipt: TxReceipt) -> dict:
|
|
117
140
|
"""Process results of a addSect transaction.
|
|
118
141
|
|
|
@@ -132,6 +155,12 @@ class Web3CommitmentService(CommitmentService, ABC):
|
|
|
132
155
|
cl = dict(add_set_events[0]["args"])
|
|
133
156
|
# Convert bytestrings to strings to allow serialization for upper layers.
|
|
134
157
|
cl["setCid"] = bytes_to_hex_str(cl["setCid"])
|
|
158
|
+
if str(cl["user"]).lower() != self.get_default_user().lower():
|
|
159
|
+
raise RuntimeError("AddSet event user does not match requested user")
|
|
160
|
+
if cl["setCid"].lower() != set_cid.lower():
|
|
161
|
+
raise RuntimeError(
|
|
162
|
+
"AddSet event set CID does not match requested set CID"
|
|
163
|
+
)
|
|
135
164
|
cl["transactionHash"] = receipt["transactionHash"]
|
|
136
165
|
# Expose committer as userAddress for API consumers.
|
|
137
166
|
self._init_receipt_fields(cl)
|
|
@@ -147,14 +176,10 @@ class Web3CommitmentService(CommitmentService, ABC):
|
|
|
147
176
|
else:
|
|
148
177
|
# No event means addSet was a no-op (set already existed).
|
|
149
178
|
cl = {}
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
# Note that this may be a forwarded transaction.
|
|
155
|
-
# In this case, the receipt["from"] is the forwarder/relayer address
|
|
156
|
-
# and cl["user"] is the user address for the commitment.
|
|
157
|
-
assert self.user_set_exists(self.get_default_user(), set_cid)
|
|
179
|
+
# Confirm that an eventless transaction was the expected idempotent no-op.
|
|
180
|
+
# A matching AddSet event is already authoritative proof of a new
|
|
181
|
+
# commitment and avoids a stale read from a different RPC backend.
|
|
182
|
+
self._user_set_exists_with_retry(self.get_default_user(), set_cid)
|
|
158
183
|
|
|
159
184
|
_LOG.debug("Commitment log:\n%s", pprint.pformat(cl))
|
|
160
185
|
return cl
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: vbase
|
|
3
|
-
Version:
|
|
3
|
+
Version: 2.0.0
|
|
4
4
|
Summary: vBase Python Software Development Kit (SDK)
|
|
5
5
|
Author-email: vBase <tech@vbase.com>
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -10,32 +10,31 @@ Project-URL: Issues, https://github.com/validityBase/vbase-py/issues
|
|
|
10
10
|
Keywords: vbase,blockchain,provenance,web3,sdk
|
|
11
11
|
Classifier: Operating System :: OS Independent
|
|
12
12
|
Classifier: Programming Language :: Python :: 3
|
|
13
|
-
Requires-Python: >=3.
|
|
13
|
+
Requires-Python: >=3.11
|
|
14
14
|
Description-Content-Type: text/markdown
|
|
15
15
|
License-File: LICENSE.txt
|
|
16
16
|
License-File: NOTICE.txt
|
|
17
|
-
Requires-Dist: hexbytes
|
|
18
|
-
Requires-Dist: numpy
|
|
19
|
-
Requires-Dist: pandas
|
|
20
|
-
Requires-Dist: python-dotenv
|
|
21
|
-
Requires-Dist: requests
|
|
22
|
-
Requires-Dist: web3
|
|
23
|
-
Requires-Dist: sqlmodel
|
|
24
|
-
Requires-Dist:
|
|
25
|
-
Requires-Dist: retry>=0.9.2
|
|
17
|
+
Requires-Dist: hexbytes<3,>=1.2.0
|
|
18
|
+
Requires-Dist: numpy<3,>=1.24.0
|
|
19
|
+
Requires-Dist: pandas<4,>=2.0.0
|
|
20
|
+
Requires-Dist: python-dotenv<2,>=1.0.0
|
|
21
|
+
Requires-Dist: requests<3,>=2.31.0
|
|
22
|
+
Requires-Dist: web3<9,>=7.15.0
|
|
23
|
+
Requires-Dist: sqlmodel<0.1,>=0.0.24
|
|
24
|
+
Requires-Dist: retry<1,>=0.9.2
|
|
26
25
|
Dynamic: license-file
|
|
27
26
|
|
|
28
27
|
# vbase-py
|
|
29
28
|
|
|
30
29
|
vBase Python Software Development Kit (SDK)
|
|
31
30
|
|
|
32
|
-
- Python 3.
|
|
31
|
+
- Python 3.11+ support
|
|
33
32
|
|
|
34
33
|
---
|
|
35
34
|
|
|
36
35
|
## License
|
|
37
36
|
|
|
38
|
-
This project is licensed under the Apache 2.0 License - see the [LICENSE.txt](LICENSE.txt) file for details.
|
|
37
|
+
This project is licensed under the Apache 2.0 License - see the [LICENSE.txt](https://github.com/validityBase/vbase-py/blob/main/LICENSE.txt) file for details.
|
|
39
38
|
|
|
40
39
|
## Introduction
|
|
41
40
|
|
|
@@ -62,18 +61,17 @@ Install the package from PyPI:
|
|
|
62
61
|
pip install vbase
|
|
63
62
|
```
|
|
64
63
|
|
|
65
|
-
See the [local installation](https://docs.vbase.com/
|
|
64
|
+
See the [local installation](https://docs.vbase.com/python-sdk/python-quickstart-readme/quickstart-1) and the [cloud notebooks](https://docs.vbase.com/python-sdk/python-quickstart-readme/quickstart) guides to get started using vBase from Python.
|
|
66
65
|
|
|
67
66
|
## Development
|
|
68
67
|
|
|
69
|
-
|
|
70
|
-
hash-checking mode:
|
|
68
|
+
Install the generated development lock and package locally:
|
|
71
69
|
|
|
72
70
|
```bash
|
|
73
|
-
python -m pip install --require-hashes -r requirements
|
|
71
|
+
python -m pip install --require-hashes -r requirements/dev.txt
|
|
74
72
|
python -m pip install --no-deps --no-build-isolation -e .
|
|
75
73
|
```
|
|
76
74
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
75
|
+
See `internal/specs/python-dependency-hashes.md` in this repository for the
|
|
76
|
+
dependency layout, lock policy, package metadata rules, and regeneration
|
|
77
|
+
commands.
|
vbase-1.0.0/requirements.in
DELETED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|