Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: stacks #394

Open
wants to merge 23 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
0071194
wip: implement stacks (not working yet)
CyrusVorwald Oct 8, 2024
8548223
wip: stacks get fee
CyrusVorwald Oct 10, 2024
230e073
fix: update stacks expected fee
CyrusVorwald Oct 10, 2024
f6c57fe
fix: get-default-connection uses nid
CyrusVorwald Oct 10, 2024
3435422
wip(stacks): verify protocols
CyrusVorwald Oct 11, 2024
6f365bf
fix: pass nid to verify-protocols
CyrusVorwald Oct 11, 2024
f4468f2
wip: use conn recv instead of handle-call directly
CyrusVorwald Oct 11, 2024
839def2
fix: protocol verification
CyrusVorwald Oct 11, 2024
9a048ca
wip: execute arbitrary call
CyrusVorwald Oct 12, 2024
49b3790
wip: rollback fails on decode-rlp-message
CyrusVorwald Oct 12, 2024
dbd4b51
fix: rollback test passes
CyrusVorwald Oct 12, 2024
1d54b27
chore: remove unused lib files
CyrusVorwald Oct 12, 2024
d86e9fe
Merge branch 'main' into feat/stacks
CyrusVorwald Nov 7, 2024
dd2a88c
fix: rlp, callmessagesent, xcall-impl-trait
CyrusVorwald Nov 19, 2024
874b68f
fix: change rlp to match xcall instead of ethereum
CyrusVorwald Nov 21, 2024
82e1f0c
fix: get-network-address char limit
CyrusVorwald Nov 21, 2024
bad90bd
test: add rlp tests
CyrusVorwald Nov 21, 2024
2074fa7
fix: rlp encode u8 and u32
CyrusVorwald Nov 21, 2024
2138759
refactor: remove duplicate if statement
CyrusVorwald Nov 22, 2024
a50771a
fix: rlp encode call message
CyrusVorwald Nov 23, 2024
60399ed
fix: rlp encodes dynamic length strings
CyrusVorwald Nov 24, 2024
13cfe18
fix: recv-message auth
CyrusVorwald Dec 4, 2024
5f1271e
identical calls to address-string-to-principal
CyrusVorwald Dec 10, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions contracts/stacks/.gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
tests/** linguist-vendored
vitest.config.js linguist-vendored
* text=lf
13 changes: 13 additions & 0 deletions contracts/stacks/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@

**/settings/Mainnet.toml
**/settings/Testnet.toml
.cache/**
history.txt

logs
*.log
npm-debug.log*
coverage
*.info
costs-reports.json
node_modules
69 changes: 69 additions & 0 deletions contracts/stacks/Clarinet.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
[project]
name = 'stacks'
description = ''
authors = []
telemetry = true
cache_dir = './.cache'

[contracts.centralized-connection]
path = 'contracts/connections/centralized-connection.clar'
clarity_version = 2
epoch = 2.5

[contracts.mock-dapp]
path = 'tests/mocks/mock-dapp.clar'
clarity_version = 2
epoch = 2.5

[contracts.rlp-decode]
path = 'lib/rlp/rlp-decode.clar'
clarity_version = 2
epoch = 2.5

[contracts.rlp-encode]
path = 'lib/rlp/rlp-encode.clar'
clarity_version = 2
epoch = 2.5

[contracts.util]
path = 'contracts/util.clar'
clarity_version = 2
epoch = 2.5

[contracts.xcall-common-trait]
path = 'contracts/xcall/xcall-common-trait.clar'
clarity_version = 2
epoch = 2.5

[contracts.xcall-impl]
path = 'contracts/xcall/xcall-impl.clar'
clarity_version = 2
epoch = 2.5

[contracts.xcall-impl-trait]
path = 'contracts/xcall/xcall-impl-trait.clar'
clarity_version = 2
epoch = 2.5

[contracts.xcall-proxy]
path = 'contracts/xcall/xcall-proxy.clar'
clarity_version = 2
epoch = 2.5

[contracts.xcall-proxy-trait]
path = 'contracts/xcall/xcall-proxy-trait.clar'
clarity_version = 2
epoch = 2.5

[contracts.xcall-receiver-trait]
path = 'contracts/xcall/xcall-receiver-trait.clar'
clarity_version = 2
epoch = 2.5
[repl.analysis]
passes = ['check_checker']

[repl.analysis.check_checker]
strict = false
trusted_sender = false
trusted_caller = false
callee_filter = false
98 changes: 98 additions & 0 deletions contracts/stacks/contracts/connections/centralized-connection.clar
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
(use-trait xcall-impl-trait .xcall-impl-trait.xcall-impl-trait)

(define-constant ERR_UNAUTHORIZED (err u100))
(define-constant ERR_INVALID_FEE (err u101))
(define-constant ERR_DUPLICATE_MESSAGE (err u102))
(define-constant ERR_XCALL_NOT_SET (err u103))

(define-data-var xcall (optional principal) none)
(define-data-var admin principal tx-sender)
(define-data-var conn-sn int 0)

(define-map message-fees {network-id: (string-ascii 128)} uint)
(define-map response-fees {network-id: (string-ascii 128)} uint)
(define-map receipts {network-id: (string-ascii 128), conn-sn: int} bool)

(define-read-only (get-xcall)
(ok (var-get xcall)))

(define-read-only (get-admin)
(ok (var-get admin)))

(define-read-only (get-conn-sn)
(ok (var-get conn-sn)))

(define-read-only (get-fee (to (string-ascii 128)) (response bool))
(let
((message-fee (default-to u0 (map-get? message-fees {network-id: to}))))
(if response
(let
((response-fee (default-to u0 (map-get? response-fees {network-id: to}))))
(ok (+ message-fee response-fee)))
(ok message-fee))))

(define-read-only (get-receipt (src-network (string-ascii 128)) (conn-sn-in int))
(ok (default-to false (map-get? receipts {network-id: src-network, conn-sn: conn-sn-in}))))

(define-private (is-admin)
(is-eq tx-sender (var-get admin)))

(define-private (is-xcall)
(match (var-get xcall)
xcall-contract (is-eq tx-sender xcall-contract)
false
))

(define-public (initialize (xcall-contract principal) (admin-address principal))
(begin
(asserts! (is-admin) ERR_UNAUTHORIZED)
(var-set xcall (some xcall-contract))
(var-set admin admin-address)
(ok true)))

(define-public (set-fee (network-id (string-ascii 128)) (message-fee uint) (response-fee uint))
(begin
(asserts! (is-admin) ERR_UNAUTHORIZED)
(map-set message-fees {network-id: network-id} message-fee)
(map-set response-fees {network-id: network-id} response-fee)
(ok true)))

(define-public (claim-fees)
(begin
(asserts! (is-admin) ERR_UNAUTHORIZED)
(as-contract (stx-transfer? (stx-get-balance (as-contract tx-sender)) tx-sender (var-get admin)))))

(define-public (set-admin (new-admin principal))
(begin
(asserts! (is-admin) ERR_UNAUTHORIZED)
(var-set admin new-admin)
(ok true)))

(define-private (emit-message-event (to (string-ascii 128)) (sn int) (msg (buff 2048)))
(print
{
event: "Message",
to: to,
sn: sn,
msg: msg
}
)
)

(define-public (send-message (to (string-ascii 128)) (svc (string-ascii 128)) (sn int) (msg (buff 2048)) (implementation <xcall-impl-trait>))
(begin
(asserts! (is-xcall) ERR_UNAUTHORIZED)
AntonAndell marked this conversation as resolved.
Show resolved Hide resolved
(let
((fee (unwrap! (get-fee to (> sn 0)) ERR_INVALID_FEE)))
(asserts! (>= (stx-get-balance tx-sender) fee) ERR_INVALID_FEE)
(var-set conn-sn (+ (var-get conn-sn) 1))
(as-contract (unwrap-panic (contract-call? .xcall-proxy handle-message to msg implementation)))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was added for testing?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah yeah I think this was when I was initially trying to figure out how to call the proxy

(emit-message-event to (var-get conn-sn) msg)
(ok (var-get conn-sn)))))

(define-public (recv-message (src-network-id (string-ascii 128)) (conn-sn-in int) (msg (buff 2048)) (implementation <xcall-impl-trait>))
(begin
(asserts! (is-eq tx-sender (var-get admin)) ERR_UNAUTHORIZED)
(asserts! (is-none (map-get? receipts {network-id: src-network-id, conn-sn: conn-sn-in})) ERR_DUPLICATE_MESSAGE)
(map-set receipts {network-id: src-network-id, conn-sn: conn-sn-in} true)
(as-contract (contract-call? .xcall-proxy handle-message src-network-id msg implementation))))
72 changes: 72 additions & 0 deletions contracts/stacks/contracts/util.clar
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
(define-constant C32SET "0123456789ABCDEFGHJKMNPQRSTVWXYZ")

(define-constant ERR_INVALID_ADDRESS (err u1000))
(define-constant ERR_INVALID_CONTRACT_NAME (err u1001))

(define-data-var result-var (buff 400) 0x)
(define-data-var addr-var (buff 400) 0x)

(define-public (address-string-to-principal (address (string-ascii 128)))
(let (
(period-index (index-of address "."))
)
(if (is-some period-index)
(let (
(address-part (unwrap-panic (slice? address u0 (unwrap-panic period-index))))
(contract-name-part (unwrap-panic (slice? address u42 (len address))))
)
(begin
(asserts! (is-eq (unwrap-panic period-index) u41) ERR_INVALID_ADDRESS)
(asserts! (is-valid-c32 address-part) ERR_INVALID_ADDRESS)
(ok (unwrap-panic (c32-decode address-part (as-max-len? contract-name-part u40))))
)
)
(begin
(asserts! (is-eq (len address) u41) ERR_INVALID_ADDRESS)
(asserts! (is-valid-c32 address) ERR_INVALID_ADDRESS)
(ok (unwrap-panic (c32-decode address none)))
)
)
)
)

(define-private (c32-decode-aux (input (string-ascii 1)) (res {bit-buff: uint, bits-remaining: uint}))
(let ((index (unwrap-panic (index-of? C32SET input)))
(bit-buff (bit-or (bit-shift-left (get bit-buff res) u5) index))
(bits-remaining (+ (get bits-remaining res) u5)))
(if (>= bits-remaining u8)
(let ((char (to-buff (bit-and (bit-shift-right bit-buff (- bits-remaining u8)) u255)))
(bits-remaining1 (- bits-remaining u8))
(bit-buff1 (bit-and bit-buff (- (bit-shift-left u1 bits-remaining1) u1))))
(set (unwrap-panic (as-max-len? (var-get addr-var) u399)) char)
(tuple (bit-buff bit-buff1) (bits-remaining bits-remaining1)))
(tuple (bit-buff bit-buff) (bits-remaining bits-remaining)))))

(define-private (c32-decode (address (string-ascii 128)) (contract-name (optional (string-ascii 40))))
(begin
(var-set addr-var 0x)
(fold c32-decode-aux (unwrap-panic (slice? address u1 (- (len address) u5))) (tuple (bit-buff u0) (bits-remaining u0)))
(let ((version (to-buff (unwrap-panic (index-of? C32SET (unwrap-panic (element-at? address u1))))))
(pub-key-hash (unwrap-panic (slice? (var-get addr-var) u1 u21))))
(if (is-some contract-name)
(principal-construct? version (unwrap-panic (as-max-len? pub-key-hash u20)) (unwrap-panic contract-name))
(principal-construct? version (unwrap-panic (as-max-len? pub-key-hash u20)))
)
)
)
)

(define-private (set (address (buff 399)) (char (buff 1)))
(var-set addr-var (concat address char)))

(define-private (to-buff (data uint))
(begin
(let ((encoded (unwrap-panic (to-consensus-buff? data))))
(unwrap-panic (element-at? encoded (- (len encoded) u1))))))


(define-private (is-valid-c32 (address (string-ascii 128)))
(fold is-c32-char address true))

(define-private (is-c32-char (char (string-ascii 1)) (valid bool))
(and valid (is-some (index-of C32SET char))))
6 changes: 6 additions & 0 deletions contracts/stacks/contracts/xcall/xcall-common-trait.clar
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
(define-trait xcall-common-trait
(
(get-network-address () (response (string-ascii 128) uint))
(send-call-message ((string-ascii 128) (buff 2048) (optional (buff 1024)) (optional (list 10 (string-ascii 128))) (optional (list 10 (string-ascii 128)))) (response uint uint))
)
)
27 changes: 27 additions & 0 deletions contracts/stacks/contracts/xcall/xcall-impl-trait.clar
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
(use-trait xcall-receiver-trait .xcall-receiver-trait.xcall-receiver-trait)
(use-trait xcall-common-trait .xcall-common-trait.xcall-common-trait)

(define-trait xcall-impl-trait
(
(send-call ((string-ascii 128) (buff 2048)) (response uint uint))

(execute-call (uint (buff 2048) <xcall-receiver-trait> <xcall-common-trait>) (response bool uint))
(execute-rollback (uint <xcall-receiver-trait> <xcall-common-trait>) (response bool uint))

(verify-success (uint) (response bool uint))

(handle-message ((string-ascii 128) (buff 2048)) (response bool uint))
(handle-error (uint) (response bool uint))

(set-admin (principal) (response bool uint))
(set-protocol-fee-handler (principal) (response bool uint))
(set-protocol-fee (uint) (response bool uint))
(set-default-connection ((string-ascii 128) (string-ascii 128)) (response bool uint))
(set-trusted-protocols ((string-ascii 128) (list 10 (string-ascii 128))) (response bool uint))

(get-network-address () (response (string-ascii 257) uint))
(get-network-id () (response (string-ascii 128) uint))
(get-protocol-fee () (response uint uint))
(get-fee ((string-ascii 128) bool (optional (list 10 (string-ascii 128)))) (response uint uint))
)
)
Loading
Loading