Skip to content

Commit 6c90f0b

Browse files
authored
Implement submit tx api endpoint (#2124)
Resolves #2107 Implementation and tests are added. --- <!-- Consider each and tick it off one way or the other --> * [x] CHANGELOG updated or not needed * [x] Documentation updated or not needed * [x] Haddocks updated or not needed * [x] No new TODOs introduced or explained herafter
2 parents 593cade + b423ec7 commit 6c90f0b

18 files changed

+536
-34
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ changes.
1818

1919
- Hydra node now rejects requests for incremental commits if provided UTxO is below the limit.
2020

21+
- Add API endpoint `POST /transaction` to submit transaction to the head.
22+
2123
## [0.22.2] - 2025.06.30
2224

2325
* Fix wrong hydra-script-tx-ids in networks.json

docs/docs/dev/architecture/hydra-components.svg

Lines changed: 1 addition & 1 deletion
Loading

docs/docs/tutorial/index.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -639,6 +639,23 @@ Submit the transaction through the already open WebSocket connection. Generate t
639639
cat tx-signed.json | jq -c '{tag: "NewTx", transaction: .}'
640640
```
641641

642+
<details>
643+
<summary>Alternative: use the HTTP API endpoint</summary>
644+
645+
Alternatively, you can submit the transaction using the HTTP API endpoint:
646+
647+
```shell
648+
curl -X POST 127.0.0.1:4001/transaction \
649+
--data @tx-signed.json
650+
```
651+
652+
The HTTP endpoint provides a synchronous response with different status codes:
653+
- **200 OK**: Transaction was included in a confirmed snapshot (includes `snapshotNumber`)
654+
- **202 Accepted**: Transaction was accepted but not yet confirmed
655+
- **400 Bad Request**: Transaction was rejected due to validation errors (includes `validationError`)
656+
657+
</details>
658+
642659
The transaction will be validated by both `hydra-node`s and either result in a
643660
`TxInvalid` message with a reason, or a `TxValid` message and a
644661
`SnapshotConfirmed` with the new UTXO available in the head shortly after.

hydra-cluster/src/HydraNode.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,7 @@ prepareHydraNode chainConfig workDir hydraNodeId hydraSKey hydraVKeys allNodeIds
413413
CardanoLedgerConfig
414414
{ cardanoLedgerProtocolParametersFile
415415
}
416+
, apiTransactionTimeout = 100000
416417
}
417418
where
418419
port = fromIntegral $ 5_000 + hydraNodeId

hydra-node/golden/ReasonablySized (SubmitL2TxRequest (Tx ConwayEra)).json

Lines changed: 35 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"samples": [
3+
{
4+
"tag": "SubmitTxSubmitted"
5+
},
6+
{
7+
"tag": "SubmitTxInvalid",
8+
"validationError": ""
9+
},
10+
{
11+
"tag": "SubmitTxInvalid",
12+
"validationError": "\u0001)e"
13+
},
14+
{
15+
"tag": "SubmitTxInvalid",
16+
"validationError": "=\u000e􂨤p"
17+
},
18+
{
19+
"tag": "SubmitTxSubmitted"
20+
}
21+
],
22+
"seed": -1369626537
23+
}

hydra-node/golden/RunOptions.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
"tag": "IPv4"
1111
},
1212
"apiPort": 18036,
13+
"apiTransactionTimeout": 0,
1314
"chainConfig": {
1415
"cardanoSigningKey": "a/c/b/c.sk",
1516
"cardanoVerificationKeys": [
@@ -85,6 +86,7 @@
8586
"tag": "IPv4"
8687
},
8788
"apiPort": 32191,
89+
"apiTransactionTimeout": 27,
8890
"chainConfig": {
8991
"initialUTxOFile": "b/b/c/a.json",
9092
"ledgerGenesisFile": null,
@@ -143,6 +145,7 @@
143145
"tag": "IPv4"
144146
},
145147
"apiPort": 20019,
148+
"apiTransactionTimeout": 26,
146149
"chainConfig": {
147150
"cardanoSigningKey": "c/b/a/b/c/b.sk",
148151
"cardanoVerificationKeys": [
@@ -223,6 +226,7 @@
223226
"tag": "IPv4"
224227
},
225228
"apiPort": 9965,
229+
"apiTransactionTimeout": 17,
226230
"chainConfig": {
227231
"initialUTxOFile": "b/c/b/a/a/c.json",
228232
"ledgerGenesisFile": "b/c/a.json",
@@ -263,6 +267,7 @@
263267
"tag": "IPv4"
264268
},
265269
"apiPort": 8054,
270+
"apiTransactionTimeout": 23,
266271
"chainConfig": {
267272
"cardanoSigningKey": "a/c/a.sk",
268273
"cardanoVerificationKeys": [

hydra-node/hydra-node.cabal

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ library
9090
Hydra.Network.Message
9191
Hydra.NetworkVersions
9292
Hydra.Node
93+
Hydra.Node.ApiTransactionTimeout
9394
Hydra.Node.DepositPeriod
9495
Hydra.Node.EmbedTH
9596
Hydra.Node.Environment
@@ -395,6 +396,7 @@ test-suite tests
395396
, req
396397
, resourcet
397398
, silently
399+
, stm
398400
, temporary
399401
, text
400402
, time

hydra-node/json-schemas/api.yaml

Lines changed: 100 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -367,7 +367,7 @@ channels:
367367
$ref: "api.yaml#/components/schemas/Transaction"
368368
bindings:
369369
http:
370-
type: response
370+
type: request
371371
method: POST
372372
bindingVersion: '0.1.0'
373373
subscribe:
@@ -388,11 +388,73 @@ channels:
388388
summary: 400 Bad Request
389389
payload:
390390
$ref: "api.yaml#/components/schemas/PostTxError"
391+
bindings:
392+
http:
393+
type: response
394+
method: POST
395+
bindingVersion: '0.1.0'
396+
397+
/transaction:
398+
servers:
399+
- localhost-http
400+
publish:
401+
operationId: submitL2TxRequest
402+
message:
403+
summary: |
404+
A transaction to be submitted to the head.
405+
Accepts transactions encoded as Base16 CBOR string, TextEnvelope type or JSON.
406+
payload:
407+
$ref: "api.yaml#/components/schemas/Transaction"
391408
bindings:
392409
http:
393410
type: request
394411
method: POST
395412
bindingVersion: '0.1.0'
413+
subscribe:
414+
operationId: submitL2TxResponse
415+
message:
416+
oneOf:
417+
- name: SubmitTxConfirmed
418+
summary: 200 OK
419+
description: Transaction was included in a confirmed snapshot.
420+
payload:
421+
type: object
422+
additionalProperties: false
423+
properties:
424+
tag:
425+
type: string
426+
enum: ["SubmitTxConfirmed"]
427+
snapshotNumber:
428+
type: integer
429+
minimum: 0
430+
- name: SubmitTxInvalid
431+
summary: 400 Bad Request
432+
description: Transaction was rejected due to validation errors.
433+
payload:
434+
type: object
435+
additionalProperties: false
436+
properties:
437+
tag:
438+
type: string
439+
enum: ["SubmitTxInvalid"]
440+
validationError:
441+
type: string
442+
- name: SubmitTxSubmitted
443+
summary: 202 Accepted
444+
description: Transaction was accepted but not yet confirmed.
445+
payload:
446+
type: object
447+
additionalProperties: false
448+
properties:
449+
tag:
450+
type: string
451+
enum: ["SubmitTxSubmitted"]
452+
bindings:
453+
http:
454+
type: response
455+
method: POST
456+
bindingVersion: '0.1.0'
457+
396458
components:
397459
messages:
398460

@@ -3262,6 +3324,43 @@ components:
32623324
status:
32633325
$ref: "api.yaml#/components/schemas/DepositStatus"
32643326

3327+
SubmitL2TxResponse:
3328+
oneOf:
3329+
- title: SubmitTxConfirmed
3330+
type: object
3331+
additionalProperties: false
3332+
required:
3333+
- tag
3334+
- snapshotNumber
3335+
properties:
3336+
tag:
3337+
type: string
3338+
enum: ["SubmitTxConfirmed"]
3339+
snapshotNumber:
3340+
type: integer
3341+
minimum: 0
3342+
- title: SubmitTxInvalid
3343+
type: object
3344+
additionalProperties: false
3345+
required:
3346+
- tag
3347+
- validationError
3348+
properties:
3349+
tag:
3350+
type: string
3351+
enum: ["SubmitTxInvalid"]
3352+
validationError:
3353+
type: string
3354+
- title: SubmitTxSubmitted
3355+
type: object
3356+
additionalProperties: false
3357+
required:
3358+
- tag
3359+
properties:
3360+
tag:
3361+
type: string
3362+
enum: ["SubmitTxSubmitted"]
3363+
32653364
DepositStatus:
32663365
oneOf:
32673366
- title: Unknown

hydra-node/src/Hydra/API/APIServerLog.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ data APIServerLog
1616
{ method :: Method
1717
, path :: PathInfo
1818
}
19+
| APITransactionSubmitted {submittedTxId :: String}
1920
deriving stock (Eq, Show, Generic)
2021
deriving anyclass (ToJSON)
2122

0 commit comments

Comments
 (0)