Skip to content

Bound incoming request and add postgres service#76

Open
enigbe wants to merge 3 commits intolightningdevkit:mainfrom
enigbe:2025-12-bound-incoming-request-and-postgres-service
Open

Bound incoming request and add postgres service#76
enigbe wants to merge 3 commits intolightningdevkit:mainfrom
enigbe:2025-12-bound-incoming-request-and-postgres-service

Conversation

@enigbe
Copy link
Contributor

@enigbe enigbe commented Dec 14, 2025

What this PR does

  • Adds a PostgreSQL Docker service for the Rust server, removing the need for a local PostgreSQL installation
  • Introduces a configurable maximum size limit for incoming request bodies, addressing a previously noted TODO
    • Operators can optionally set maximum_request_body_size in [server_config] or via environment variable
    • Defaults to 1 GB if not specified

@ldk-reviews-bot
Copy link

ldk-reviews-bot commented Dec 14, 2025

👋 Thanks for assigning @tankyleo as a reviewer!
I'll wait for their review and will help manage the review process.
Once they submit their review, I'll check if a second reviewer would be helpful.

@enigbe enigbe force-pushed the 2025-12-bound-incoming-request-and-postgres-service branch from 4bfb403 to a163ae7 Compare December 14, 2025 22:45
use std::pin::Pin;
use std::sync::Arc;

const MAXIMUM_REQUEST_BODY_SIZE: u16 = 65_535;
Copy link
Contributor

Choose a reason for hiding this comment

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

This seems very conservative, given that monitors could get quite large. Given that the VSS service is actually a storage service, it also might make sense to make this configurable (in contrast to lightningdevkit/ldk-server#80, but even there we set the limit to 10MB).

Copy link
Contributor

Choose a reason for hiding this comment

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

As mentioned elsewhere: I guess a static upper bound is a good first step, but if we're really concerned about DoS we might need some dynamic rate limiting on a per-IP basis. Although then the question becomes how much of that should be considered the concern of the VSS service itself, and how much we'd just expect users to slap a load balancer/Cloudflare in front of the service to handle that for them

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've made the configuration changes suggested here, capping at 20 MB for the maximum size.

Copy link
Contributor

Choose a reason for hiding this comment

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

No, as mentioned elsewhere, individual values might be quite a bit larger than 10 or 20MB. I think something along the lines of 100MB would be a more reasonable maximum, though per request it raises the question of how much a DoS protection this actually is.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've updated the max to 1GB per Matt's recommendation. We get basic protection with this but I could spent some time on this and propose a coherent strategy.

@enigbe enigbe force-pushed the 2025-12-bound-incoming-request-and-postgres-service branch from 5d391cc to fbdd957 Compare December 16, 2025 08:36
@ldk-reviews-bot
Copy link

🔔 1st Reminder

Hey @tankyleo! This PR has been waiting for your review.
Please take a look when you have a chance. If you're unable to review, please let us know so we can find another reviewer.

@ldk-reviews-bot
Copy link

🔔 2nd Reminder

Hey @tankyleo! This PR has been waiting for your review.
Please take a look when you have a chance. If you're unable to review, please let us know so we can find another reviewer.

@ldk-reviews-bot
Copy link

🔔 3rd Reminder

Hey @tankyleo! This PR has been waiting for your review.
Please take a look when you have a chance. If you're unable to review, please let us know so we can find another reviewer.

@ldk-reviews-bot
Copy link

🔔 4th Reminder

Hey @tankyleo! This PR has been waiting for your review.
Please take a look when you have a chance. If you're unable to review, please let us know so we can find another reviewer.

@ldk-reviews-bot
Copy link

🔔 5th Reminder

Hey @tankyleo! This PR has been waiting for your review.
Please take a look when you have a chance. If you're unable to review, please let us know so we can find another reviewer.

@ldk-reviews-bot
Copy link

🔔 6th Reminder

Hey @tankyleo! This PR has been waiting for your review.
Please take a look when you have a chance. If you're unable to review, please let us know so we can find another reviewer.

@ldk-reviews-bot
Copy link

🔔 7th Reminder

Hey @tankyleo! This PR has been waiting for your review.
Please take a look when you have a chance. If you're unable to review, please let us know so we can find another reviewer.

@ldk-reviews-bot
Copy link

🔔 8th Reminder

Hey @tankyleo! This PR has been waiting for your review.
Please take a look when you have a chance. If you're unable to review, please let us know so we can find another reviewer.

@ldk-reviews-bot
Copy link

🔔 9th Reminder

Hey @tankyleo! This PR has been waiting for your review.
Please take a look when you have a chance. If you're unable to review, please let us know so we can find another reviewer.

Copy link
Contributor

@tnull tnull left a comment

Choose a reason for hiding this comment

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

Can we also add some test coverage to ensure the database / backends actually support the configured maximum values, i.e., that we're not otherwise limited somehow?

use std::pin::Pin;
use std::sync::Arc;

const MAXIMUM_REQUEST_BODY_SIZE: u16 = 65_535;
Copy link
Contributor

Choose a reason for hiding this comment

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

No, as mentioned elsewhere, individual values might be quite a bit larger than 10 or 20MB. I think something along the lines of 100MB would be a more reasonable maximum, though per request it raises the question of how much a DoS protection this actually is.

@ldk-reviews-bot
Copy link

🔔 10th Reminder

Hey @tankyleo! This PR has been waiting for your review.
Please take a look when you have a chance. If you're unable to review, please let us know so we can find another reviewer.

@ldk-reviews-bot
Copy link

🔔 11th Reminder

Hey @tankyleo! This PR has been waiting for your review.
Please take a look when you have a chance. If you're unable to review, please let us know so we can find another reviewer.

@enigbe enigbe force-pushed the 2025-12-bound-incoming-request-and-postgres-service branch 2 times, most recently from 97b6b25 to 93faf38 Compare January 10, 2026 19:14
@enigbe
Copy link
Contributor Author

enigbe commented Jan 10, 2026

Thanks for the review @tnull and @TheBlueMatt. I have updated the maximum request body size and added a test to check that our backend(s) support the configured value. It's ready for another look when you have the time.

@ldk-reviews-bot
Copy link

🔔 12th Reminder

Hey @tankyleo! This PR has been waiting for your review.
Please take a look when you have a chance. If you're unable to review, please let us know so we can find another reviewer.

@tnull tnull self-requested a review January 12, 2026 14:37
Copy link
Contributor

@tnull tnull left a comment

Choose a reason for hiding this comment

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

Generally looks good, mod some comments.

As noted above already, I do wonder how much we're gaining at all we we're limiting to 1GB per request. In any case, probably better than nothing. So generally concept ACK from my side, but I'll leave it to @tankyleo to decide.

@TheBlueMatt
Copy link
Contributor

I mean at least it avoids someone being able to OOM us by just sending us trash 🤷‍♂️ Of course VSS exposed directly would probably still be OOM'able with a few parallel requests, but hopefully a decent frontend proxy can limit the impact by buffering the requests first.

@enigbe enigbe force-pushed the 2025-12-bound-incoming-request-and-postgres-service branch 2 times, most recently from 15417ec to 7121dcc Compare January 13, 2026 23:21
@ldk-reviews-bot
Copy link

🔔 13th Reminder

Hey @tankyleo! This PR has been waiting for your review.
Please take a look when you have a chance. If you're unable to review, please let us know so we can find another reviewer.

Copy link
Contributor

@tankyleo tankyleo left a comment

Choose a reason for hiding this comment

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

Thank your for the PR sorry for the delay on my part, a few bits, looking good !

@enigbe enigbe force-pushed the 2025-12-bound-incoming-request-and-postgres-service branch from 7121dcc to f061dc1 Compare January 15, 2026 22:58
@enigbe enigbe force-pushed the 2025-12-bound-incoming-request-and-postgres-service branch from f061dc1 to 8a49df9 Compare January 15, 2026 23:13
@enigbe
Copy link
Contributor Author

enigbe commented Jan 16, 2026

Hi @tankyleo
Thanks for the review. I've addressed concerns raised and rebased. This is good for another look.

@tankyleo tankyleo self-requested a review January 17, 2026 03:11
@enigbe enigbe force-pushed the 2025-12-bound-incoming-request-and-postgres-service branch 2 times, most recently from 564f34a to 5d0d841 Compare January 23, 2026 09:06
Copy link
Contributor

@tankyleo tankyleo left a comment

Choose a reason for hiding this comment

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

Thanks a few more nits below, feel free to squash the fixups

@enigbe enigbe force-pushed the 2025-12-bound-incoming-request-and-postgres-service branch from 5d0d841 to 04a9213 Compare January 27, 2026 10:29
@enigbe
Copy link
Contributor Author

enigbe commented Jan 27, 2026

Hi @tankyleo,
I've rebased, squashed the fixups, and addressed the remaining comments. It's ready for another look.

Copy link
Contributor

@tankyleo tankyleo left a comment

Choose a reason for hiding this comment

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

LGTM two nits, good to consolidate everything into two commits, one for the docker file, and one for the max_request_body_size feature.

As with the other PR, please remove the prefixes, and capitalize the first word of the commit message.

@enigbe enigbe force-pushed the 2025-12-bound-incoming-request-and-postgres-service branch from 04a9213 to e0ae2f9 Compare January 30, 2026 05:31
Copy link
Contributor Author

@enigbe enigbe left a comment

Choose a reason for hiding this comment

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

I've addressed the last nits. When you approve I'll squash the remaining fixup commit.

@tankyleo
Copy link
Contributor

tankyleo commented Feb 2, 2026

I've addressed the last nits. When you approve I'll squash the remaining fixup commit.

LGTM thank you ! Would you mind consolidating the max request body size feature in a single commit ? I would prefer one commit for the docker service, and one for the max request body size thanks.

@enigbe enigbe force-pushed the 2025-12-bound-incoming-request-and-postgres-service branch from e0ae2f9 to c16f96c Compare February 6, 2026 18:32
@enigbe
Copy link
Contributor Author

enigbe commented Feb 6, 2026

Would you mind consolidating the max request body size feature in a single commit ? I would prefer one commit for the docker service, and one for the max request body size thanks.

I've consolidated the commits as requested.
Thank you for reviewing!

Add VssServiceConfig to make the maximum request body size configurable
through the server configuration file, with a hard limit of 1GB.

Additionally, add test coverage for 1GB maximum supported
value size and verifies that storage backends can
handle the configured maximum value size.
@enigbe enigbe force-pushed the 2025-12-bound-incoming-request-and-postgres-service branch from c16f96c to 2963c8d Compare February 23, 2026 18:38
@enigbe enigbe changed the title feat: bound incoming request and add postgres service Bound incoming request and add postgres service Feb 25, 2026
@enigbe enigbe requested a review from tankyleo February 25, 2026 12:35
Copy link
Contributor

@tankyleo tankyleo left a comment

Choose a reason for hiding this comment

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

Thank you for the ping, appreciate your patience I am now back to focusing on VSS. A quick comment for now, will do a more comprehensive review tomorrow

Comment on lines +102 to +115
let bind_address_env = read_env(BIND_ADDR_VAR)?;
let (bind_address_config, max_request_body_size_config) = match server_config {
Some(c) => (c.bind_address, c.max_request_body_size),
None => (None, None),
};

let bind_address_env = read_env(BIND_ADDR_VAR)?
.map(|addr| {
addr.parse().map_err(|e| {
format!("Unable to parse the bind address environment variable: {}", e)
})
})
.transpose()?;
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you double check this section ? Looks like the rebase reverted some code to how it was before. We don't need to parse BIND_ADDR_VAR into an Option<String>, we can use the original let bind_address_env = read_env(BIND_ADDR_VAR)?; thank you

Copy link
Contributor

@tankyleo tankyleo left a comment

Choose a reason for hiding this comment

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

Made another pass, overall it's nearly ready, just a few more nits that just popped up thank you for continuing the work on this PR. Please amend all the fixes into the top commit.


// Construct entry that's for a field that's the maximum size of a non-"large_object" object
let large_value = vec![0u8; MAXIMUM_SUPPORTED_VALUE_SIZE - PROTOCOL_OVERHEAD_MARGIN];
let kv = KeyValue { key: "k1".into(), version: 0, value: Bytes::from(large_value) };
Copy link
Contributor

Choose a reason for hiding this comment

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

We'll need to clone large_value here

resp_kv.value.len(),
MAXIMUM_SUPPORTED_VALUE_SIZE - PROTOCOL_OVERHEAD_MARGIN
);
assert!(resp_kv.value.iter().all(|&b| b == 0));
Copy link
Contributor

Choose a reason for hiding this comment

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

Let's do this here: assert_eq!(resp_kv.value, large_value);

Comment on lines +45 to +46
let vss_service_config = match &config.max_request_body_size {
Some(size) => match VssServiceConfig::new(*size) {
Copy link
Contributor

Choose a reason for hiding this comment

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

usize is Copy, so we can do match config.max_request_body_size and VssServiceConfig::new(size)

Comment on lines +151 to +159
let max_request_body_size_env = read_env(MAX_REQUEST_BODY_SIZE_VAR)?
.map(|mrbs| {
mrbs.parse::<usize>().map_err(|e| {
format!("Unable to parse the maximum request body size environment variable: {}", e)
})
})
.transpose()?;
let max_request_body_size = max_request_body_size_env.or(max_request_body_size_config);

Copy link
Contributor

Choose a reason for hiding this comment

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

nit: This is a little out of place here, let's put this after the let bind_address statement further above, thank you appreciate it

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This has been moved up.

return Ok(Response::builder()
.status(StatusCode::PAYLOAD_TOO_LARGE)
.body(Full::new(Bytes::from("Request body too large")))
.unwrap());
Copy link
Contributor

Choose a reason for hiding this comment

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

For consistency, let's also add // unwrap safety: body only errors when previous chained calls failed. right above this line, like we do for the other body calls below.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've added the comment here.

Addresses the following:
- read bind address correctly,
- add appropriate unwrap documentation,
- drop ref to mrbs because usize impls clone,
- clone large object, and
- assert_eq(Byte, Vec<u8>): because Bytes impls PartialEq
  with Vec<u8>, we can compare them directly.
@enigbe enigbe force-pushed the 2025-12-bound-incoming-request-and-postgres-service branch from 7943877 to 5cef3b6 Compare March 3, 2026 20:53
@enigbe
Copy link
Contributor Author

enigbe commented Mar 3, 2026

Thanks again for the review @tankyleo
I've addressed the latest comments in 5cef3b6.
Once you approve, I'll squash the commit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants