Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 3 additions & 1 deletion extensions/register.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
package extensions

import (
"github.com/trufnetwork/node/extensions/database-size"
database_size "github.com/trufnetwork/node/extensions/database-size"
"github.com/trufnetwork/node/extensions/leaderwatch"
"github.com/trufnetwork/node/extensions/tn_attestation"
"github.com/trufnetwork/node/extensions/tn_cache"
"github.com/trufnetwork/node/extensions/tn_digest"
"github.com/trufnetwork/node/extensions/tn_vacuum"
"github.com/trufnetwork/node/extensions/tn_utils"
)

func init() {
leaderwatch.InitializeExtension()
tn_utils.InitializeExtension()
tn_cache.InitializeExtension()
tn_digest.InitializeExtension()
tn_vacuum.InitializeExtension()
Expand Down
17 changes: 17 additions & 0 deletions extensions/tn_cache/syncschecker/sync_checker.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"encoding/json"
"fmt"
"strings"
"sync"
"time"

Expand All @@ -20,6 +21,20 @@ const (
healthEndpoint = "http://localhost:8484/api/v1/health"
)

// retryableHTTPLogger adapts kwil's logger to work with go-retryablehttp
// It logs HTTP requests at Debug level so they only appear when debug logging is enabled
type retryableHTTPLogger struct {
logger log.Logger
}

// Printf implements the retryablehttp.Logger interface
// We log at Debug level since these are routine health checks
func (l *retryableHTTPLogger) Printf(format string, v ...interface{}) {
// Remove trailing newline if present, as Debugf adds its own
format = strings.TrimSuffix(format, "\n")
l.logger.Debugf(format, v...)
}

// SyncChecker monitors if the node is synced enough to perform cache operations
type SyncChecker struct {
logger log.Logger
Expand Down Expand Up @@ -134,6 +149,8 @@ func (sc *SyncChecker) updateStatus(ctx context.Context) {
client.RetryMax = 3
client.RetryWaitMin = 1 * time.Second
client.RetryWaitMax = 5 * time.Second
// Use kwil logger adapter so HTTP logs respect the configured log level
client.Logger = &retryableHTTPLogger{logger: sc.logger}

req, err := retryablehttp.NewRequest("GET", sc.endpoint, nil)
if err != nil {
Expand Down
52 changes: 52 additions & 0 deletions extensions/tn_utils/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# tn_utils Extension

Reusable precompiles that support attestation and other deterministic workflows.

## Methods

### `call_dispatch(action_name TEXT, args_bytes BYTEA) -> BYTEA`
- Dispatches to another action while preserving the current engine context.
- Returns the canonical, deterministic encoding of the target action's result rows.

### `bytea_join(chunks BYTEA[], delimiter BYTEA) -> BYTEA`
- Concatenates an array of `BYTEA` chunks, inserting the provided delimiter between entries.
- Treats `NULL` or empty chunks as empty segments.

### `bytea_length_prefix(chunk BYTEA) -> BYTEA`
- Returns a 4-byte little-endian length prefix followed by the original chunk (treats `NULL` as zero-length).

### `bytea_length_prefix_many(chunks BYTEA[]) -> BYTEA[]`
- Applies the same length-prefix transformation to each entry, returning a new `BYTEA[]`.

### `encode_uint8(value INT) -> BYTEA`
### `encode_uint16(value INT) -> BYTEA`
### `encode_uint32(value INT) -> BYTEA`
### `encode_uint64(value INT) -> BYTEA`
- Encode unsigned integers to big-endian byte arrays with the specified width.

## Usage

```sql
USE tn_utils AS util;

-- Call another action
$result_bytes := util.call_dispatch('get_record', $args_bytes);

-- Join canonical payload chunks
$payload := util.bytea_join(util.bytea_length_prefix_many(ARRAY[
$version_bytes,
$algo_bytes,
$result_bytes
]), E'');
```

The Go package lives at `github.com/trufnetwork/node/extensions/tn_utils`.
Import it to register the utilities precompile bundle on node startup:

```go
import "github.com/trufnetwork/node/extensions/tn_utils"

func init() {
tn_utils.InitializeExtension()
}
```
24 changes: 24 additions & 0 deletions extensions/tn_utils/extension.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package tn_utils

import (
"context"
"fmt"

"github.com/trufnetwork/kwil-db/common"
"github.com/trufnetwork/kwil-db/extensions/precompiles"
sql "github.com/trufnetwork/kwil-db/node/types/sql"
)

// ExtensionName identifies this utilities precompile bundle.
const ExtensionName = "tn_utils"

// InitializeExtension registers the utilities precompile bundle.
func InitializeExtension() {
if err := precompiles.RegisterInitializer(ExtensionName, initializePrecompile); err != nil {
panic(fmt.Sprintf("failed to register %s initializer: %v", ExtensionName, err))
}
}

func initializePrecompile(ctx context.Context, service *common.Service, db sql.DB, alias string, metadata map[string]any) (precompiles.Precompile, error) {
return buildPrecompile(), nil
}
Loading
Loading