Skip to content

Commit

Permalink
Merge branch 'master' into feat/token-hub
Browse files Browse the repository at this point in the history
  • Loading branch information
matijamarjanovic authored Jan 17, 2025
2 parents 48c6cd1 + d2813f8 commit c0ca4a5
Show file tree
Hide file tree
Showing 144 changed files with 6,461 additions and 8,175 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/bot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,12 @@ jobs:
define-prs-matrix:
name: Define PRs matrix
# Skip this workflow if:
# - the bot is not configured on this repo/fork
# - the bot is retriggering itself
# - the event is emitted by codecov
# - the event is a review on a pull request from a fork (see save-pr-number job below)
if: |
vars.GH_BOT_LOGIN != '' &&
github.actor != vars.GH_BOT_LOGIN &&
github.actor != 'codecov[bot]' &&
(github.event_name != 'pull_request_review' || github.event.pull_request.base.repo.full_name == github.event.pull_request.head.repo.full_name)
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/releaser-master.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:
cache: true

- uses: sigstore/[email protected]
- uses: anchore/sbom-action/[email protected].8
- uses: anchore/sbom-action/[email protected].9

- uses: docker/login-action@v3
with:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/releaser-nightly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ jobs:
cache: true

- uses: sigstore/[email protected]
- uses: anchore/sbom-action/[email protected].8
- uses: anchore/sbom-action/[email protected].9

- uses: docker/login-action@v3
with:
Expand Down
2 changes: 1 addition & 1 deletion contribs/gnodev/pkg/dev/node_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -438,7 +438,7 @@ func testingCallRealm(t *testing.T, node *Node, msgs ...vm.MsgCall) (*core_types

txcfg := gnoclient.BaseTxCfg{
GasFee: ugnot.ValueString(1000000), // Gas fee
GasWanted: 2_000_000, // Gas wanted
GasWanted: 3_000_000, // Gas wanted
}

// Set Caller in the msgs
Expand Down
16 changes: 16 additions & 0 deletions examples/gno.land/p/demo/avl/list/list.gno
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,22 @@ import (
"gno.land/p/demo/seqid"
)

// IList defines the interface for list operations
type IList interface {
Len() int
Append(values ...interface{})
Get(index int) interface{}
Set(index int, value interface{}) bool
Delete(index int) (interface{}, bool)
Slice(startIndex, endIndex int) []interface{}
ForEach(fn func(index int, value interface{}) bool)
Clone() *List
DeleteRange(startIndex, endIndex int) int
}

// Verify List implements IList interface
var _ IList = (*List)(nil)

// List represents an ordered sequence of items backed by an AVL tree
type List struct {
tree avl.Tree
Expand Down
64 changes: 64 additions & 0 deletions examples/gno.land/p/demo/avl/list/list_test.gno
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package list

import (
"testing"

"gno.land/p/demo/ufmt"
)

func TestList_Basic(t *testing.T) {
Expand Down Expand Up @@ -395,6 +397,68 @@ func TestList_IndexConsistency(t *testing.T) {
}
}

func TestList_RecursiveSafety(t *testing.T) {
// Create a new list
l := &List{}

// Add some initial values
l.Append("id1")
l.Append("id2")
l.Append("id3")

// Test deep list traversal
found := false
l.ForEach(func(i int, v interface{}) bool {
if str, ok := v.(string); ok {
if str == "id2" {
found = true
return true // stop iteration
}
}
return false // continue iteration
})

if !found {
t.Error("Failed to find expected value in list")
}

short := testing.Short()

// Test recursive safety by performing multiple operations
for i := 0; i < 1000; i++ {
// Add new value
l.Append(ufmt.Sprintf("id%d", i+4))

if !short {
// Search for a value
var lastFound bool
l.ForEach(func(j int, v interface{}) bool {
if str, ok := v.(string); ok {
if str == ufmt.Sprintf("id%d", i+3) {
lastFound = true
return true
}
}
return false
})

if !lastFound {
t.Errorf("Failed to find value id%d after insertion", i+3)
}
}
}

// Verify final length
expectedLen := 1003 // 3 initial + 1000 added
if l.Len() != expectedLen {
t.Errorf("Expected length %d, got %d", expectedLen, l.Len())
}

if short {
t.Skip("skipping extended recursive safety test in short mode")
}
}

// Helper function to compare slices
func sliceEqual(a, b []interface{}) bool {
if len(a) != len(b) {
Expand Down
1 change: 1 addition & 0 deletions examples/gno.land/p/demo/avl/rolist/gno.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module gno.land/p/demo/avl/rolist
119 changes: 119 additions & 0 deletions examples/gno.land/p/demo/avl/rolist/rolist.gno
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
// Package rolist provides a read-only wrapper for list.List with safe value transformation.
//
// It is useful when you want to expose a read-only view of a list while ensuring that
// the sensitive data cannot be modified.
//
// Example:
//
// // Define a user structure with sensitive data
// type User struct {
// Name string
// Balance int
// Internal string // sensitive field
// }
//
// // Create and populate the original list
// privateList := list.New()
// privateList.Append(&User{
// Name: "Alice",
// Balance: 100,
// Internal: "sensitive",
// })
//
// // Create a safe transformation function that copies the struct
// // while excluding sensitive data
// makeEntrySafeFn := func(v interface{}) interface{} {
// u := v.(*User)
// return &User{
// Name: u.Name,
// Balance: u.Balance,
// Internal: "", // omit sensitive data
// }
// }
//
// // Create a read-only view of the list
// publicList := rolist.Wrap(list, makeEntrySafeFn)
//
// // Safely access the data
// value := publicList.Get(0)
// user := value.(*User)
// // user.Name == "Alice"
// // user.Balance == 100
// // user.Internal == "" (sensitive data is filtered)
package rolist

import (
"gno.land/p/demo/avl/list"
)

// IReadOnlyList defines the read-only operations available on a list.
type IReadOnlyList interface {
Len() int
Get(index int) interface{}
Slice(startIndex, endIndex int) []interface{}
ForEach(fn func(index int, value interface{}) bool)
}

// ReadOnlyList wraps a list.List and provides read-only access.
type ReadOnlyList struct {
list *list.List
makeEntrySafeFn func(interface{}) interface{}
}

// Verify interface implementations
var _ IReadOnlyList = (*ReadOnlyList)(nil)
var _ IReadOnlyList = (interface{ list.IList })(nil) // is subset of list.IList

// Wrap creates a new ReadOnlyList from an existing list.List and a safety transformation function.
// If makeEntrySafeFn is nil, values will be returned as-is without transformation.
func Wrap(list *list.List, makeEntrySafeFn func(interface{}) interface{}) *ReadOnlyList {
return &ReadOnlyList{
list: list,
makeEntrySafeFn: makeEntrySafeFn,
}
}

// getSafeValue applies the makeEntrySafeFn if it exists, otherwise returns the original value
func (rol *ReadOnlyList) getSafeValue(value interface{}) interface{} {
if rol.makeEntrySafeFn == nil {
return value
}
return rol.makeEntrySafeFn(value)
}

// Len returns the number of elements in the list.
func (rol *ReadOnlyList) Len() int {
return rol.list.Len()
}

// Get returns the value at the specified index, converted to a safe format.
// Returns nil if index is out of bounds.
func (rol *ReadOnlyList) Get(index int) interface{} {
value := rol.list.Get(index)
if value == nil {
return nil
}
return rol.getSafeValue(value)
}

// Slice returns a slice of values from startIndex (inclusive) to endIndex (exclusive),
// with all values converted to a safe format.
func (rol *ReadOnlyList) Slice(startIndex, endIndex int) []interface{} {
values := rol.list.Slice(startIndex, endIndex)
if values == nil {
return nil
}

result := make([]interface{}, len(values))
for i, v := range values {
result[i] = rol.getSafeValue(v)
}
return result
}

// ForEach iterates through all elements in the list, providing safe versions of the values.
func (rol *ReadOnlyList) ForEach(fn func(index int, value interface{}) bool) {
rol.list.ForEach(func(index int, value interface{}) bool {
return fn(index, rol.getSafeValue(value))
})
}
Loading

0 comments on commit c0ca4a5

Please sign in to comment.