linksplatform / linksplatform/data-rs

LinksConstants::external() overlaps the external range with the `continue` constant

Open Beginner friendly
#18 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Rust
Stars
1
Forks
0
PR merge metrics
No merged PRs in 30d

Description

## Summary

`LinksConstants::external()` builds an external-reference range that starts on the `continue` constant, so `is_external(constants.r#continue)` is `true`. The C# `LinksConstants` this type mirrors starts the external range one address later and answers `False` for the same query.

## Where it comes from

`full_new` reserves six service values at the top of the internal range and then takes the external range verbatim ([`src/constants.rs`](https://github.com/linksplatform/data-rs/blob/main/src/constants.rs)):

```rust
r#continue: *internal.end(),
r#break: *internal.end() - T::from_byte(1),
// ...
internal_range: *internal.start()..=*internal.end() - T::from_byte(6),
external_range: external,
```

and the defaults for `external()` are

```rust
fn default_internal(external: bool) -> RangeInclusive {
if external { T::from_byte(1)..=Hybrid::half() } else { ... }
}

fn default_external(external: bool) -> Option> {
if external { Some(Hybrid::half()..=T::MAX) } else { None }
}
```

`internal.end()` is `Hybrid::half()`, so `r#continue == Hybrid::half()` — which is also `*external_range.start()`. The two ranges overlap by exactly one address.

## Reproduction

`LinksConstants::::external()`, platform-data 2.0.0 via doublets 0.5.0:

```
continue = 2147483647
break = 2147483646
skip = 2147483645
any = 2147483644
itself = 2147483643
error = 2147483642
internal = 1..=2147483641
external = Some(2147483647..=4294967295)

is_external(continue) = true
```

`new LinksConstants(enableExternalReferencesSupport: true)`, Platform.Data.Doublets 0.18.1:

```
continue = 2147483647
break = 2147483646
skip = 2147483645
any = 2147483644
itself = 2147483643
error = 2147483642
internal = [1..2147483641]
external = [2147483648..4294967295]

IsExternalReference(continue) = False
```

Both programs, one per language, are runnable:

- Rust — [`external-range/rust`](https://github.com/link-foundation/link-cli/tree/3d53362125be47de595b0cad7a24fe4c3aeefd3d/docs/case-studies/issue-100/evidence/external-range/rust) (`./run.sh`; exits 0 while the overlap reproduces, non-zero once it is fixed)
- C# — [`external-range/csharp`](https://github.com/link-foundation/link-cli/tree/3d53362125be47de595b0cad7a24fe4c3aeefd3d/docs/case-studies/issue-100/evidence/external-range/csharp) (`./run.sh`)

## Why it matters

`doublets::data::LinksExtensions::exist` branches on `is_external` first:

```rust
let constants = self.constants();
if constants.is_external(link) {
true
} else {
constants.is_internal(link) && self.count_by([link]) != T::from_byte(0)
}
```

so on a store built with `LinksConstants::external()`, `exist(constants.r#continue)` reports `true` for an address that is a control marker rather than a link. Any code that funnels a `Flow`-style constant through an existence check — or that hands out `0 - value` external references and reasons about which addresses are reachable — sees one address classified the wrong way. C# does not.

## Suggested fix

Start the default external range one past the half:

```rust
fn default_external(external: bool) -> Option> {
if external {
Some(Hybrid::half() + T::from_byte(1)..=T::MAX)
} else {
None
}
}
```

`full_new` could also assert that the two ranges are disjoint, so a caller-supplied pair cannot reintroduce the overlap.

Found while updating [link-foundation/link-cli](https://github.com/link-foundation/link-cli) to doublets 0.5.0 (link-foundation/link-cli#100).

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in src/constants.rs with default_external and compare its range boundary with the C# behavior described in the issue. Run docs/case-studies/issue-100/evidence/external-range/rust/run.sh; done means the external range starts one address after Hybrid::half() and is_external(constants.r#continue) no longer reports true.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
databases
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
82/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.