Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(examples): Voting Realm: A Bitmap and Nonce-based Approach #2225

Closed
wants to merge 57 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
0aa26e2
logic + test cases
linhpn99 May 16, 2024
4122497
add new line
linhpn99 May 16, 2024
3db2ecb
Merge branch 'master' into add-package-nonces
linhpn99 May 17, 2024
48c8623
Merge branch 'master' into add-package-nonces
linhpn99 May 19, 2024
fd63c27
Merge branch 'master' into add-package-nonces
linhpn99 May 22, 2024
276b97f
Merge branch 'master' into add-package-nonces
linhpn99 May 22, 2024
9f4a065
Update examples/gno.land/p/demo/nonces/nonces.gno
linhpn99 May 23, 2024
a808269
Update examples/gno.land/p/demo/nonces/nonces.gno
linhpn99 May 23, 2024
1e120b3
Update examples/gno.land/p/demo/nonces/nonces.gno
linhpn99 May 23, 2024
9c871ce
Update examples/gno.land/p/demo/nonces/gno.mod
linhpn99 May 23, 2024
5aa74b5
Update examples/gno.land/p/demo/nonces/nonces.gno
linhpn99 May 23, 2024
12f5fea
refactored code after reviewing of Moul
linhpn99 May 23, 2024
386f78e
remove new line
linhpn99 May 23, 2024
fe78475
remove ufmt
linhpn99 May 23, 2024
4b1bbaf
remove require
linhpn99 May 23, 2024
944e652
remove require
linhpn99 May 23, 2024
593376b
update
linhpn99 May 23, 2024
8b03000
wrong type
linhpn99 May 23, 2024
13a0f3a
Merge branch 'master' into add-package-nonces
linhpn99 May 23, 2024
84cf5cb
add new line
linhpn99 May 23, 2024
4ad3cec
Merge branch 'add-package-nonces' of https://github.com/linhpn99/gno …
linhpn99 May 23, 2024
1518362
Merge branch 'master' into add-package-nonces
linhpn99 May 23, 2024
f39ba2a
Merge branch 'master' into add-package-nonces
linhpn99 May 24, 2024
a22ae04
Merge branch 'master' into add-package-nonces
linhpn99 May 24, 2024
114f9a8
Merge branch 'master' into add-package-nonces
linhpn99 May 25, 2024
fa1476f
Merge branch 'master' into add-package-nonces
linhpn99 May 26, 2024
47c9663
Merge branch 'master' into add-package-nonces
linhpn99 May 26, 2024
aceb6a2
add new line
linhpn99 May 26, 2024
b9355b5
add import
linhpn99 May 26, 2024
e39e79d
make tidy
linhpn99 May 26, 2024
7a4f936
Merge branch 'master' into add-package-nonces
linhpn99 May 26, 2024
49c623c
Merge branch 'master' into add-package-nonces
linhpn99 May 26, 2024
cf481a4
Merge branch 'master' into add-package-nonces
linhpn99 May 27, 2024
0fd4086
Merge branch 'master' into add-package-nonces
linhpn99 May 27, 2024
2aa527e
Merge branch 'master' into add-package-nonces
linhpn99 May 27, 2024
be82a2f
Merge branch 'master' into add-package-nonces
linhpn99 May 28, 2024
b6a8cf5
draft
linhpn99 May 28, 2024
0874ae3
make tidy
linhpn99 May 28, 2024
6c5fc07
remove useless code
linhpn99 May 28, 2024
28f74c9
undefined packages
linhpn99 May 28, 2024
135d365
add bitmap
linhpn99 May 28, 2024
ddb5a9e
add GetOwner
linhpn99 May 28, 2024
d664990
Merge branch 'master' into demo-new-packages
linhpn99 May 28, 2024
1167b54
Merge branch 'master' into demo-new-packages
linhpn99 May 29, 2024
4095853
Merge branch 'master' into demo-new-packages
linhpn99 May 29, 2024
561d567
Merge branch 'master' into demo-new-packages
linhpn99 May 29, 2024
758c05a
Merge branch 'master' into demo-new-packages
linhpn99 May 30, 2024
e1cac6b
use TestSetRealm instead
linhpn99 May 30, 2024
ba75218
Merge branch 'master' into demo-new-packages
linhpn99 May 31, 2024
c9693b4
Merge branch 'master' into demo-new-packages
linhpn99 Jun 6, 2024
c06a3fe
Merge branch 'master' into demo-new-packages
linhpn99 Jun 6, 2024
5f70b46
Merge branch 'master' into demo-new-packages
linhpn99 Jun 10, 2024
30761b2
Merge branch 'master' into demo-new-packages
linhpn99 Jun 11, 2024
5f4c223
Merge branch 'master' into demo-new-packages
linhpn99 Jun 19, 2024
7aa1bd8
Merge branch 'master' into demo-new-packages
linhpn99 Jun 26, 2024
d7c2d91
Merge branch 'master' into demo-new-packages
linhpn99 Jul 3, 2024
bf02d57
Merge branch 'master' into demo-new-packages
linhpn99 Jul 8, 2024
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
58 changes: 58 additions & 0 deletions examples/gno.land/p/demo/bitmap/bitmap.gno
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package bitmap

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

// A simple implementation of Bitmap

// Bitmap represents a bitmap using a slice of bytes
type Bitmap struct {
data []byte
}

// NewBitmap creates a new Bitmap with a specific size (in bits)
func New(size uint64) *Bitmap {
byteSize := (size + 7) / 8 // Calculate the number of bytes needed
return &Bitmap{
data: make([]byte, byteSize),
}
}

// MustSet sets the bit at the given index (0-based) and returns an error if out of bounds
func (b *Bitmap) Set(index uint64) error {
if index >= uint64(len(b.data))*8 {
return ufmt.Errorf("Index out of bounds")
}

byteIndex := index / 8
bitIndex := index % 8

b.data[byteIndex] |= 1 << uint(bitIndex) // Set the corresponding bit using bitwise OR

return nil
}

// Set sets the bit at the given index (0-based)
func (b *Bitmap) MustSet(index uint64) {
if index >= uint64(len(b.data))*8 {
panic("Index out of bounds")
}

byteIndex := index / 8
bitIndex := index % 8

b.data[byteIndex] |= 1 << uint(bitIndex) // Set the corresponding bit using bitwise OR
}

// Get checks if the bit at the given index is set
func (b *Bitmap) Get(index uint64) bool {
if index >= uint64(len(b.data))*8 {
panic("Index out of bounds")
}

byteIndex := index / 8
bitIndex := index % 8

return b.data[byteIndex]&(1<<uint(bitIndex)) > 0 // Check if the corresponding bit is set using bitwise AND
}
96 changes: 96 additions & 0 deletions examples/gno.land/p/demo/bitmap/bitmap_test.gno
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package bitmap

import (
"testing"
)

func TestBitmap_New(t *testing.T) {
size := uint64(16)
bm := New(size)

if len(bm.data)*8 != int(size) {
t.Errorf("Expected bitmap size: %d, got: %d", size, len(bm.data)*8)
}
}

func TestBitmap_SetAndGet(t *testing.T) {
bm := New(16)

// Test setting and getting bits within bounds
err := bm.Set(2)
if err != nil {
t.Errorf("Expected no error, got: %v", err)
}

if !bm.Get(2) {
t.Errorf("Expected bit at index 2 to be set")
}

err = bm.Set(15)
if err != nil {
t.Errorf("Expected no error, got: %v", err)
}

if !bm.Get(15) {
t.Errorf("Expected bit at index 15 to be set")
}

// Test setting and getting bits out of bounds
err = bm.Set(16)
if err == nil {
t.Errorf("Expected error, got: nil")
}
}

func TestBitmap_MustSet(t *testing.T) {
bm := New(16)

// Test setting bits within bounds
defer func() {
if r := recover(); r != nil {
t.Errorf("Expected no panic, but got panic: %v", r)
}
}()

bm.MustSet(2)
if !bm.Get(2) {
t.Errorf("Expected bit at index 2 to be set")
}

bm.MustSet(15)
if !bm.Get(15) {
t.Errorf("Expected bit at index 15 to be set")
}

// Test setting bits out of bounds
defer func() {
if r := recover(); r == nil {
t.Errorf("Expected panic, but no panic occurred")
}
}()

bm.MustSet(16 * 8)
}

func TestBitmap_Get(t *testing.T) {
bm := New(16)

// Test getting bits within bounds
bm.MustSet(2)
if !bm.Get(2) {
t.Errorf("Expected bit at index 2 to be set")
}

if bm.Get(3) {
t.Errorf("Expected bit at index 3 to be unset")
}

// Test getting bits out of bounds
defer func() {
if r := recover(); r == nil {
t.Errorf("Expected panic, but no panic occurred")
}
}()

bm.Get(16 * 8)
}
3 changes: 3 additions & 0 deletions examples/gno.land/p/demo/bitmap/gno.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module gno.land/p/demo/bitmap

require gno.land/p/demo/ufmt v0.0.0-latest
6 changes: 6 additions & 0 deletions examples/gno.land/p/demo/nonce/gno.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module gno.land/p/demo/nonce

require (
gno.land/p/demo/avl v0.0.0-latest
gno.land/p/demo/testutils v0.0.0-latest
)
45 changes: 45 additions & 0 deletions examples/gno.land/p/demo/nonce/nonce.gno
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package nonce

import (
"std"

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

type Manager struct {
nonces *avl.Tree
}

// New creates a new instance of Manager
func New() *Manager {
return &Manager{
nonces: avl.NewTree(),
}
}

// GetNonce returns the next unused nonce for an address
func (m *Manager) GetNonce(addr std.Address) uint64 {
key := addr.String()

nonce, found := m.nonces.Get(key)
if !found {
m.nonces.Set(key, uint64(0))
return 0
}

return nonce.(uint64)
}

// UseNonce consumes a nonce and returns the current value, then increments the nonce
func (m *Manager) UseNonce(addr std.Address) {
key := addr.String()

var currentNonce uint64 = 0

val, found := m.nonces.Get(key)
if found {
currentNonce = val.(uint64)
}

m.nonces.Set(key, currentNonce+1)
}
73 changes: 73 additions & 0 deletions examples/gno.land/p/demo/nonce/nonce_test.gno
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package nonce

import (
"testing"

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

// TestNonceManager tests the Manager functions
func TestNonceManager(t *testing.T) {
nm := New()

// Use a dummy address for testing
address := testutils.TestAddress("dummy")

// Test GetNonce method
if nonce := nm.GetNonce(address); nonce != 0 {
t.Errorf("expected nonce to be 0, got %d", nonce)
}

// Test UseNonce method
nm.UseNonce(address)
if newNonce := nm.GetNonce(address); newNonce != 1 {
t.Errorf("expected new nonce to be 1, got %d", newNonce)
}

nm.UseNonce(address)
if finalNonce := nm.GetNonce(address); finalNonce != 2 {
t.Errorf("expected final nonce to be 2, got %d", finalNonce)
}
}

func TestMultipleAddresses(t *testing.T) {
nm := New()

// Use dummy addresses for testing
address1 := testutils.TestAddress("bob")
address2 := testutils.TestAddress("alice")

// Test UseNonce with multiple addresses

if nonce := nm.GetNonce(address1); nonce != 0 {
t.Errorf("expected final nonce to be 0, got %d", nonce)
}

if nonce := nm.GetNonce(address2); nonce != 0 {
t.Errorf("expected final nonce to be 0, got %d", nonce)
}

nm.UseNonce(address1)
if nonce := nm.GetNonce(address1); nonce != 1 {
t.Errorf("expected used nonce to be 1 for address1, got %d", nonce)
}

nm.UseNonce(address2)
if nonce := nm.GetNonce(address2); nonce != 1 {
t.Errorf("expected used nonce to be 1 for address2, got %d", nonce)
}
}

func TestConcurrentUse(t *testing.T) {
nm := New()
address := testutils.TestAddress("dummy")

for i := 0; i < 10; i++ {
t.Parallel()

nm.UseNonce(address)
if nonce := nm.GetNonce(address); nonce != uint64(i+1) {
t.Errorf("expected used nonce to be %d, got %d", i+1, nonce)
}
}
}
9 changes: 9 additions & 0 deletions examples/gno.land/r/demo/voting/gno.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
module gno.land/r/demo/voting

require (
gno.land/p/demo/avl v0.0.0-latest
gno.land/p/demo/bitmap v0.0.0-latest
gno.land/p/demo/nonce v0.0.0-latest
gno.land/p/demo/seqid v0.0.0-latest
gno.land/p/demo/testutils v0.0.0-latest
)
Loading
Loading