Skip to content

Commit d800631

Browse files
authored
feat: ConfidentialMPT Support (#919)
## High Level Overview of Change <!-- Please include a summary/list of the changes. If too broad, please consider splitting into multiple PRs. If a relevant Asana task, please link it here. --> Support Confidential Transfers for Multi-Purpose Tokens (XLS-0096) Spec: https://github.com/XRPLF/XRPL-Standards/tree/master/XLS-0096-confidential-mpt Rippled PR: XRPLF/rippled#5860 `mpt-crypto` library: https://github.com/XRPLF/mpt-crypto ### Context of Change <!-- Please include the context of a change. If a bug fix, when was the bug introduced? What was the behavior? If a new feature, why was this architecture chosen? What were the alternatives? If a refactor, how is this better than the previous implementation? If there is a design document for this feature, please link it here. --> All cryptographic related helpers to generate El Gama keypairs and multiple proofs used for this feature will be implemented as C-binder from `mpt-crypto` library. Details can be found in `xrpl/core/confidential/README.md` folder. ### Type of Change <!-- Please check relevant options, delete irrelevant ones. --> - [ ] Bug fix (non-breaking change which fixes an issue) - [x] New feature (non-breaking change which adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) - [ ] Refactor (non-breaking change that only restructures code) - [ ] Tests (You added tests for code that already exists, or your new feature included in this PR) - [ ] Documentation Updates - [ ] Release ### Did you update CHANGELOG.md? - [x] Yes - [ ] No, this change does not impact library users
1 parent e648619 commit d800631

65 files changed

Lines changed: 12442 additions & 3 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.ci-config/xrpld.cfg

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,9 @@ LendingProtocol
209209
PermissionDelegationV1_1
210210
Sponsor
211211

212+
# 3.2.0 Amendments
213+
ConfidentialTransfer
214+
212215
# This section can be used to simulate various FeeSettings scenarios for rippled node in standalone mode
213216
[voting]
214217
reference_fee = 200 # 200 drops

.flake8

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,13 @@ max-line-length = 88
1616
# TODO: remove this rule
1717
allow-init-docstring=True
1818

19+
# The confidential add-on (xrpl/ext/confidential/) is linted under the SAME
20+
# rules as the rest of xrpl-py. Only the CFFI build script (embedded C source
21+
# in a string) and example scripts are excluded.
22+
exclude =
23+
xrpl/ext/confidential/build_mpt_crypto.py,
24+
xrpl/ext/confidential/examples/*
25+
1926
per-file-ignores =
2027
# For tests, disable type annotation and docstring linting.
2128
tests/*: ANN D DOC
Lines changed: 326 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,326 @@
1+
# ──────────────────────────────────────────────────────────────────────────────
2+
# Build mpt-crypto Native Libraries
3+
#
4+
# Builds the mpt-crypto C library as a self-contained shared library for each
5+
# supported platform. Dependencies (secp256k1, OpenSSL) are statically linked
6+
# so the resulting binaries can be loaded directly by JNA at runtime without
7+
# requiring any system-level installs.
8+
#
9+
# The output artifacts follow JNA's platform naming convention:
10+
# darwin-aarch64/libmptcrypto.dylib (macOS ARM64)
11+
# darwin-x86-64/libmptcrypto.dylib (macOS x86_64)
12+
# linux-aarch64/libmptcrypto.so (Linux ARM64)
13+
# linux-x86-64/libmptcrypto.so (Linux x86_64)
14+
# win32-x86-64/mptcrypto.dll (Windows x86_64)
15+
#
16+
# These artifacts are intended to be downloaded and placed into
17+
# xrpl4j-mpt-crypto/src/main/resources/ for JNA to discover at runtime.
18+
# ──────────────────────────────────────────────────────────────────────────────
19+
20+
name: Build mpt-crypto Native Libraries
21+
22+
on:
23+
workflow_dispatch:
24+
inputs:
25+
mpt_crypto_ref:
26+
# Prefer an immutable release tag (e.g. 1.0.4) so published native
27+
# binaries are built from a known, auditable source rather than a moving
28+
# branch like main. Branch/commit refs are still accepted for testing.
29+
description: 'Release tag (preferred), branch, or commit SHA of XRPLF/mpt-crypto to build'
30+
required: true
31+
default: '1.0.4'
32+
33+
jobs:
34+
build:
35+
name: Build ${{ matrix.platform }}
36+
strategy:
37+
fail-fast: false
38+
matrix:
39+
include:
40+
# ── macOS ARM64 (Apple Silicon) ──
41+
- os: macos-14
42+
platform: darwin-aarch64
43+
lib_filename: libmptcrypto.dylib
44+
cmake_lib_filename: libmpt-crypto.dylib
45+
46+
# ── macOS x86_64 (Intel) ──
47+
- os: macos-15-intel
48+
platform: darwin-x86-64
49+
lib_filename: libmptcrypto.dylib
50+
cmake_lib_filename: libmpt-crypto.dylib
51+
52+
# ── Linux ARM64 ──
53+
- os: ubuntu-24.04-arm
54+
platform: linux-aarch64
55+
lib_filename: libmptcrypto.so
56+
cmake_lib_filename: libmpt-crypto.so
57+
58+
# ── Linux x86_64 ──
59+
- os: ubuntu-latest
60+
platform: linux-x86-64
61+
lib_filename: libmptcrypto.so
62+
cmake_lib_filename: libmpt-crypto.so
63+
64+
# ── Windows x86_64 ──
65+
- os: windows-latest
66+
platform: win32-x86-64
67+
lib_filename: mptcrypto.dll
68+
cmake_lib_filename: mpt-crypto.dll
69+
70+
runs-on: ${{ matrix.os }}
71+
72+
steps:
73+
# ── Checkout mpt-crypto source at the requested ref ──
74+
# actions/checkout doesn't support arbitrary commit SHAs for external repos
75+
# (it only matches branches/tags). So we do a full clone + checkout instead.
76+
- name: Clone mpt-crypto
77+
shell: bash
78+
env:
79+
MPT_REF: ${{ inputs.mpt_crypto_ref }}
80+
# Immutable commit the pinned release tag must resolve to. Keep in sync
81+
# with MPT_CRYPTO_VERSION / MPT_CRYPTO_COMMIT in
82+
# packaging/confidential/version.env (the single source of truth for
83+
# the xrpl-py packaging path; this JNA-natives workflow does not check
84+
# out xrpl-py, so the value is mirrored here).
85+
PINNED_VERSION: "1.0.4"
86+
PINNED_COMMIT: "85dbac73d033241b73f0565ae7cce86d07005c70"
87+
run: |
88+
git clone https://github.com/XRPLF/mpt-crypto.git .
89+
git checkout "${MPT_REF}"
90+
echo "==> Checked out mpt-crypto at:"
91+
git log --oneline -1
92+
93+
# Supply-chain: git tags are mutable (force-pushable), so pinning a tag
94+
# is NOT the same as pinning a commit. When building the pinned release
95+
# (the default), verify the resolved commit matches the immutable SHA so
96+
# a moved/tampered tag can't inject code into the built native
97+
# artifacts. Mirrors the check in
98+
# packaging/confidential/scripts/build-mpt-crypto-lib.sh. A custom ref
99+
# is an explicit testing override and is allowed with a warning (a
100+
# 40-char commit SHA is already immutable).
101+
if [ "${MPT_REF}" = "${PINNED_VERSION}" ]; then
102+
ACTUAL_SHA="$(git rev-parse HEAD)"
103+
if [ "${ACTUAL_SHA}" != "${PINNED_COMMIT}" ]; then
104+
echo "ERROR: tag ${MPT_REF} resolved to ${ACTUAL_SHA}," >&2
105+
echo " expected pinned commit ${PINNED_COMMIT}." >&2
106+
echo " The tag may have been moved or tampered with; refusing to build." >&2
107+
exit 1
108+
fi
109+
echo "==> Verified ${MPT_REF} resolves to pinned commit ${PINNED_COMMIT}."
110+
else
111+
echo "==> WARNING: building custom ref '${MPT_REF}' (not the pinned" \
112+
"release ${PINNED_VERSION}); skipping commit-SHA verification."
113+
fi
114+
115+
# ── Set up build tools ──
116+
- name: Set up Python
117+
uses: actions/setup-python@v5
118+
with:
119+
python-version: '3.12'
120+
121+
- name: Install Conan and Ninja
122+
run: pip install "conan>=2.0.0" ninja
123+
124+
# Windows needs the MSVC developer environment for cl.exe, link.exe, etc.
125+
- name: Set up MSVC environment
126+
if: runner.os == 'Windows'
127+
uses: ilammy/msvc-dev-cmd@v1
128+
129+
# ── Configure Conan ──
130+
# Use auto-detected profile so we don't need to hand-craft compiler
131+
# settings for each platform. Then add the XRPLF remote where secp256k1
132+
# packages are hosted.
133+
- name: Configure Conan
134+
shell: bash
135+
run: |
136+
conan profile detect --force
137+
echo "==> Detected Conan profile:"
138+
conan profile show
139+
conan remote add --index 0 xrplf https://conan.ripplex.io || true
140+
141+
# ── Install dependencies via Conan ──
142+
#
143+
# Key flags:
144+
# -o "&:shared=True" → Build mpt-crypto as a SHARED library
145+
# -o "&:tests=False" → Skip building test executables
146+
# -o "secp256k1/*:shared=False" → Static secp256k1, linked INTO the shared lib
147+
# -o "openssl/*:shared=False" → Static OpenSSL, linked INTO the shared lib
148+
# -o "*/fPIC=True" → Position Independent Code for static deps
149+
# (required when linking static libs into a .so/.dylib)
150+
# -b missing → Build deps from source if no pre-built binary
151+
#
152+
# On Windows, fPIC doesn't apply — Conan ignores it for MSVC targets.
153+
- name: Install dependencies (Unix)
154+
if: runner.os != 'Windows'
155+
shell: bash
156+
run: |
157+
conan install . \
158+
-of build \
159+
-b missing \
160+
-s build_type=Release \
161+
-o "&:shared=True" \
162+
-o "&:tests=False" \
163+
-o "secp256k1/*:shared=False" \
164+
-o "secp256k1/*:fPIC=True" \
165+
-o "openssl/*:shared=False" \
166+
-o "openssl/*:fPIC=True"
167+
168+
- name: Install dependencies (Windows)
169+
if: runner.os == 'Windows'
170+
shell: bash
171+
run: |
172+
conan install . \
173+
-of build \
174+
-b missing \
175+
-s build_type=Release \
176+
-o "&:shared=True" \
177+
-o "&:tests=False" \
178+
-o "secp256k1/*:shared=False" \
179+
-o "openssl/*:shared=False"
180+
181+
# ── Configure CMake ──
182+
#
183+
# The Conan toolchain file (conan_toolchain.cmake) configures:
184+
# - CMAKE_BUILD_TYPE=Release (single-config generators)
185+
# - BUILD_SHARED_LIBS=ON (from shared=True)
186+
# - Find-package paths for secp256k1 and OpenSSL
187+
#
188+
# Windows uses the VS generator because Ninja doesn't support
189+
# CMAKE_GENERATOR_PLATFORM which Conan's MSVC toolchain sets.
190+
- name: Configure CMake (Unix)
191+
if: runner.os != 'Windows'
192+
shell: bash
193+
run: |
194+
TOOLCHAIN=$(find build -name "conan_toolchain.cmake" -print -quit)
195+
if [ -z "${TOOLCHAIN}" ]; then
196+
echo "ERROR: Could not find conan_toolchain.cmake under build/"
197+
find build -type f -name "*.cmake" | head -20
198+
exit 1
199+
fi
200+
echo "==> Using toolchain: ${TOOLCHAIN}"
201+
202+
cmake -B build -S . \
203+
-G Ninja \
204+
-DCMAKE_TOOLCHAIN_FILE="${TOOLCHAIN}" \
205+
-DCMAKE_BUILD_TYPE=Release
206+
207+
- name: Configure CMake (Windows)
208+
if: runner.os == 'Windows'
209+
shell: bash
210+
run: |
211+
TOOLCHAIN=$(find build -name "conan_toolchain.cmake" -print -quit)
212+
if [ -z "${TOOLCHAIN}" ]; then
213+
echo "ERROR: Could not find conan_toolchain.cmake under build/"
214+
find build -type f -name "*.cmake" | head -20
215+
exit 1
216+
fi
217+
echo "==> Using toolchain: ${TOOLCHAIN}"
218+
219+
cmake -B build -S . \
220+
-G "Visual Studio 17 2022" \
221+
-DCMAKE_TOOLCHAIN_FILE="${TOOLCHAIN}" \
222+
-DCMAKE_WINDOWS_EXPORT_ALL_SYMBOLS=ON
223+
224+
# ── Build ──
225+
- name: Build shared library
226+
shell: bash
227+
run: cmake --build build --config Release
228+
229+
# ── Package ──
230+
# CMake produces "mpt-crypto" (with hyphen) as the library name.
231+
# We rename to "mptcrypto" (no hyphen) because JNA's Native.load("mptcrypto")
232+
# expects this convention.
233+
- name: Package library
234+
shell: bash
235+
run: |
236+
mkdir -p output/${{ matrix.platform }}
237+
238+
BUILT_LIB=$(find build -maxdepth 2 \( \
239+
-name "${{ matrix.cmake_lib_filename }}" \
240+
\) -print -quit)
241+
242+
if [ -z "${BUILT_LIB}" ]; then
243+
echo "ERROR: Could not find ${{ matrix.cmake_lib_filename }} in build/"
244+
echo "Build directory contents:"
245+
find build -type f \( -name "*.dylib" -o -name "*.so" -o -name "*.dll" \) 2>/dev/null
246+
exit 1
247+
fi
248+
249+
echo "==> Found: ${BUILT_LIB}"
250+
cp "${BUILT_LIB}" "output/${{ matrix.platform }}/${{ matrix.lib_filename }}"
251+
echo "==> Packaged: output/${{ matrix.platform }}/${{ matrix.lib_filename }}"
252+
253+
# ── Verify ──
254+
# Confirm the library is self-contained: linked libraries should only be
255+
# system libs (no secp256k1 or libcrypto as external shared deps).
256+
- name: Verify library (macOS)
257+
if: startsWith(matrix.platform, 'darwin')
258+
run: |
259+
echo "==> Linked libraries (should only show system libs):"
260+
otool -L output/${{ matrix.platform }}/${{ matrix.lib_filename }}
261+
echo ""
262+
echo "==> Architecture:"
263+
file output/${{ matrix.platform }}/${{ matrix.lib_filename }}
264+
265+
- name: Verify library (Linux)
266+
if: startsWith(matrix.platform, 'linux')
267+
run: |
268+
echo "==> Linked libraries (should only show system libs):"
269+
ldd output/${{ matrix.platform }}/${{ matrix.lib_filename }} || true
270+
echo ""
271+
echo "==> Architecture:"
272+
file output/${{ matrix.platform }}/${{ matrix.lib_filename }}
273+
274+
- name: Verify library (Windows)
275+
if: startsWith(matrix.platform, 'win32')
276+
shell: bash
277+
run: |
278+
echo "==> File info:"
279+
file output/${{ matrix.platform }}/${{ matrix.lib_filename }}
280+
281+
# ── Upload per-platform artifact ──
282+
# Upload output/ (not output/<platform>/) so the platform subdirectory
283+
# is preserved inside the artifact. This ensures merge-multiple in the
284+
# bundle job doesn't overwrite files with the same name across platforms.
285+
- name: Upload artifact
286+
uses: actions/upload-artifact@v4
287+
with:
288+
name: mptcrypto-${{ matrix.platform }}
289+
path: output/
290+
if-no-files-found: error
291+
292+
# ──────────────────────────────────────────────────────────────────────────
293+
# Bundle all platform artifacts into a single downloadable archive.
294+
# The structure matches what JNA expects on the classpath:
295+
# darwin-aarch64/libmptcrypto.dylib
296+
# darwin-x86-64/libmptcrypto.dylib
297+
# linux-aarch64/libmptcrypto.so
298+
# linux-x86-64/libmptcrypto.so
299+
# win32-x86-64/mptcrypto.dll
300+
# ──────────────────────────────────────────────────────────────────────────
301+
bundle:
302+
name: Bundle all native libraries
303+
needs: build
304+
runs-on: ubuntu-latest
305+
steps:
306+
- name: Download all platform artifacts
307+
uses: actions/download-artifact@v4
308+
with:
309+
pattern: mptcrypto-*
310+
path: natives/
311+
merge-multiple: true
312+
313+
- name: Display bundled structure
314+
run: |
315+
echo "==> Bundled native libraries:"
316+
find natives/ -type f | sort
317+
echo ""
318+
echo "==> File sizes:"
319+
find natives/ -type f -exec ls -lh {} \;
320+
321+
- name: Upload combined artifact
322+
uses: actions/upload-artifact@v4
323+
with:
324+
name: mptcrypto-all-platforms
325+
path: natives/
326+
if-no-files-found: error

0 commit comments

Comments
 (0)