Skip to content

Commit 4ff51ec

Browse files
Merge pull request #19 from HorizenOfficial/st/HZN-2468
Updated Request fields type
2 parents b1adc87 + 3e147a3 commit 4ff51ec

23 files changed

Lines changed: 252 additions & 223 deletions

runtime/wasm-go/app/app.go

Lines changed: 40 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,19 @@ package app
33
import (
44
"encoding/json"
55
"fmt"
6-
"github.com/horizen-pes-nova/payment-app/utils"
6+
"math/big"
77

8+
ethCommon "github.com/ethereum/go-ethereum/common"
89
"github.com/horizen-pes/pkg/common"
910
wasmCommon "github.com/horizen-pes/pkg/wasm/common"
1011
)
1112

1213
// --- High-Level Application Logic ---
1314

14-
func LoadModule(appId string) []byte {
15+
func LoadModule(appId int64) []byte {
1516
initialState := &ApplicationInternalState{
1617
AppID: appId,
17-
Accounts: make(map[string]*AccountState),
18+
Accounts: make(map[ethCommon.Address]*AccountState),
1819
Nonce: 0,
1920
}
2021
stateJSON, err := json.Marshal(initialState)
@@ -24,29 +25,36 @@ func LoadModule(appId string) []byte {
2425
return stateJSON
2526
}
2627

27-
func DepositFunds(sender string, value uint64, stateJSON string) wasmCommon.DepositResult {
28+
func DepositFunds(senderPtr *ethCommon.Address, value *big.Int, stateJSON string) wasmCommon.DepositResult {
29+
if senderPtr == nil {
30+
return wasmCommon.DepositResult{Error: "Sender address is missing"}
31+
}
32+
33+
sender := *senderPtr
34+
//This should never happens but just in case
35+
if value == nil {
36+
return wasmCommon.DepositResult{Error: "value is nil"}
37+
}
38+
2839
var currentState ApplicationInternalState
2940
if err := json.Unmarshal([]byte(stateJSON), &currentState); err != nil {
3041
return wasmCommon.DepositResult{Error: "Failed to parse application state"}
3142
}
32-
if !utils.IsValidAddress(sender) {
33-
return wasmCommon.DepositResult{Error: fmt.Sprintf("sender address is not valid: %s", sender)}
34-
}
3543

3644
var events []common.PlainEvent
3745

3846
// Handle deposit
39-
if value > 0 {
47+
if value.Sign() > 0 {
4048
// Ensure sender account exists
4149
if currentState.Accounts[sender] == nil {
4250
currentState.Accounts[sender] = &AccountState{
4351
Address: sender,
44-
Balance: 0,
52+
Balance: big.NewInt(0),
4553
}
4654
}
4755

4856
// Add deposit to sender's balance
49-
currentState.Accounts[sender].Balance += value
57+
currentState.Accounts[sender].Balance.Add(currentState.Accounts[sender].Balance, value)
5058
currentState.Nonce++
5159

5260
// Create deposit event
@@ -75,15 +83,16 @@ func DepositFunds(sender string, value uint64, stateJSON string) wasmCommon.Depo
7583
return wasmCommon.DepositResult{State: newStateBytes, Events: events}
7684
}
7785

78-
func ProcessRequest(sender, payloadJSON, stateJSON string) wasmCommon.ProcessResult {
86+
func ProcessRequest(senderPtr *ethCommon.Address, payloadJSON, stateJSON string) wasmCommon.ProcessResult {
87+
if senderPtr == nil {
88+
return wasmCommon.ProcessResult{Error: "Sender address is missing"}
89+
}
90+
sender := *senderPtr
7991
// Deserialize current state
8092
var currentState ApplicationInternalState
8193
if err := json.Unmarshal([]byte(stateJSON), &currentState); err != nil {
8294
return wasmCommon.ProcessResult{Error: "Failed to parse application state"}
8395
}
84-
if !utils.IsValidAddress(sender) {
85-
return wasmCommon.ProcessResult{Error: fmt.Sprintf("sender address is not valid: %s", sender)}
86-
}
8796

8897
var events []common.PlainEvent
8998
var withdrawals []common.Withdrawal
@@ -101,29 +110,26 @@ func ProcessRequest(sender, payloadJSON, stateJSON string) wasmCommon.ProcessRes
101110
return wasmCommon.ProcessResult{Error: "Transfer instruction is missing"}
102111
}
103112

104-
if !utils.IsValidAddress(instructions.Transfer.To) {
105-
return wasmCommon.ProcessResult{Error: fmt.Sprintf("Transfer destination address is not valid: %s", instructions.Transfer.To)}
106-
}
107113

108114
// Validate sender account exists and has sufficient balance
109115
if currentState.Accounts[sender] == nil {
110-
return wasmCommon.ProcessResult{Error: fmt.Sprintf("Account does not exist: %s", sender)}
116+
return wasmCommon.ProcessResult{Error: fmt.Sprintf("Account does not exist: %s", sender.Hex())}
111117
}
112-
if currentState.Accounts[sender].Balance < instructions.Transfer.Amount {
118+
if currentState.Accounts[sender].Balance.Cmp( instructions.Transfer.Amount) < 0 {
113119
return wasmCommon.ProcessResult{Error: "Insufficient balance for transfer"}
114120
}
115121

116122
// Ensure recipient account exists
117123
if currentState.Accounts[instructions.Transfer.To] == nil {
118124
currentState.Accounts[instructions.Transfer.To] = &AccountState{
119125
Address: instructions.Transfer.To,
120-
Balance: 0,
126+
Balance: big.NewInt(0),
121127
}
122128
}
123129

124130
// Execute transfer
125-
currentState.Accounts[sender].Balance -= instructions.Transfer.Amount
126-
currentState.Accounts[instructions.Transfer.To].Balance += instructions.Transfer.Amount
131+
currentState.Accounts[sender].Balance.Sub(currentState.Accounts[sender].Balance, instructions.Transfer.Amount)
132+
currentState.Accounts[instructions.Transfer.To].Balance.Add(currentState.Accounts[instructions.Transfer.To].Balance, instructions.Transfer.Amount)
127133
currentState.Nonce++
128134

129135
// Create events for both parties
@@ -171,12 +177,12 @@ func ProcessRequest(sender, payloadJSON, stateJSON string) wasmCommon.ProcessRes
171177
return wasmCommon.ProcessResult{Error: "Account does not exist"}
172178
}
173179

174-
if currentState.Accounts[sender].Balance < instructions.Withdraw.Amount {
180+
if currentState.Accounts[sender].Balance.Cmp(instructions.Withdraw.Amount) < 0 {
175181
return wasmCommon.ProcessResult{Error: "Insufficient balance for withdrawal"}
176182
}
177183

178184
// Execute withdrawal
179-
currentState.Accounts[sender].Balance -= instructions.Withdraw.Amount
185+
currentState.Accounts[sender].Balance.Sub(currentState.Accounts[sender].Balance,instructions.Withdraw.Amount)
180186
currentState.Nonce++
181187

182188
// Create withdrawal
@@ -252,27 +258,27 @@ func GenerateDeanonymizationReport(payloadJSON, stateJSON string) wasmCommon.Dea
252258

253259
// AccountState represents the state of a user account
254260
type AccountState struct {
255-
Address string `json:"address"`
256-
Balance uint64 `json:"balance"`
261+
Address ethCommon.Address `json:"address"`
262+
Balance *big.Int `json:"balance"`
257263
}
258264

259265
// ApplicationInternalState represents the internal state of the application
260266
type ApplicationInternalState struct {
261-
AppID string `json:"appId"`
262-
Accounts map[string]*AccountState `json:"accounts"`
263-
Nonce uint64 `json:"nonce"`
267+
AppID int64 `json:"appId"`
268+
Accounts map[ethCommon.Address]*AccountState `json:"accounts"`
269+
Nonce uint64 `json:"nonce"`
264270
}
265271

266272
// TransferInstruction represents instructions for transferring funds
267273
type TransferInstruction struct {
268-
To string `json:"to"`
269-
Amount uint64 `json:"amount"`
274+
To ethCommon.Address `json:"to"`
275+
Amount *big.Int `json:"amount"`
270276
}
271277

272278
// WithdrawInstruction represents instructions for withdrawing funds
273279
type WithdrawInstruction struct {
274-
To string `json:"to"`
275-
Amount uint64 `json:"amount"`
280+
To ethCommon.Address `json:"to"`
281+
Amount *big.Int `json:"amount"`
276282
}
277283

278284
// PayloadInstructions represents the deserialized payload instructions
@@ -283,7 +289,7 @@ type PayloadInstructions struct {
283289
}
284290

285291
type UnencryptedDeanonymizationReportData struct {
286-
Accounts map[string]*AccountState `json:"accounts"`
292+
Accounts map[ethCommon.Address]*AccountState `json:"accounts"`
287293
Nonce uint64 `json:"nonce"`
288294
}
289295

runtime/wasm-go/go.mod

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,14 @@ go 1.23.0
66
// This prevents "works on my machine" problems that can arise from subtle differences between minor Go versions
77
toolchain go1.24.3
88

9-
replace github.com/horizen-pes => github.com/HorizenOfficial/horizen-pes v0.0.9
9+
replace github.com/horizen-pes => github.com/HorizenOfficial/horizen-pes v0.0.10
1010

1111
// Can be useful for local developments
1212
//replace github.com/horizen-pes => ../../../horizen-pes
1313

1414
require (
15-
github.com/horizen-pes v0.0.9
15+
github.com/ethereum/go-ethereum v1.16.1
16+
github.com/horizen-pes v0.0.10
1617
github.com/stretchr/testify v1.10.0
1718
)
1819

@@ -29,7 +30,6 @@ require (
2930
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect
3031
github.com/elliotchance/orderedmap/v3 v3.1.0 // indirect
3132
github.com/ethereum/c-kzg-4844/v2 v2.1.0 // indirect
32-
github.com/ethereum/go-ethereum v1.16.1 // indirect
3333
github.com/ethereum/go-verkle v0.2.2 // indirect
3434
github.com/fsnotify/fsnotify v1.6.0 // indirect
3535
github.com/go-ole/go-ole v1.3.0 // indirect

runtime/wasm-go/go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
github.com/DataDog/zstd v1.4.5 h1:EndNeuB0l9syBZhut0wns3gV1hL8zX8LIu6ZiVHWLIQ=
22
github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo=
3-
github.com/HorizenOfficial/horizen-pes v0.0.9 h1:ZrprDvqDmgDC70Lt8voXc7pauX5+ER+yPbjnlDwK/Cs=
4-
github.com/HorizenOfficial/horizen-pes v0.0.9/go.mod h1:+RKFCQu8nfhdB7x17KXDyq1UASqKwjJRbJCTgEQABF4=
3+
github.com/HorizenOfficial/horizen-pes v0.0.10 h1:WRnvBktQJ9BWkgybVqpejiTjcMuo62MJGH3RHqkprSE=
4+
github.com/HorizenOfficial/horizen-pes v0.0.10/go.mod h1:+RKFCQu8nfhdB7x17KXDyq1UASqKwjJRbJCTgEQABF4=
55
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
66
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
77
github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA=

runtime/wasm-go/integration_test.go

Lines changed: 26 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,14 @@ import (
44
"context"
55
"encoding/json"
66
"fmt"
7+
"math/big"
78
"os"
89
"os/exec"
910
"testing"
1011

12+
ethCommon "github.com/ethereum/go-ethereum/common"
1113
"github.com/horizen-pes-nova/payment-app/app"
14+
"github.com/horizen-pes/pkg/common"
1215
"github.com/horizen-pes/pkg/wasm"
1316
"github.com/stretchr/testify/assert"
1417
"github.com/stretchr/testify/require"
@@ -37,15 +40,15 @@ func TestIntegration_LoadModule(t *testing.T) {
3740
defer runtime.Close()
3841

3942
ctx := context.Background()
40-
appId := "test-app"
43+
appId := common.NewApplicationId(1)
4144

4245
state, err := runtime.LoadModule(ctx, appId, wasmBytes)
4346
require.NoError(t, err)
4447
require.NotNil(t, state)
4548

4649
var stateData app.ApplicationInternalState
4750
require.NoError(t, json.Unmarshal(state, &stateData))
48-
assert.Equal(t, appId, stateData.AppID)
51+
assert.Equal(t, appId, common.ApplicationIdType(stateData.AppID))
4952
}
5053

5154
func TestIntegration_Deposit(t *testing.T) {
@@ -54,9 +57,9 @@ func TestIntegration_Deposit(t *testing.T) {
5457
defer runtime.Close()
5558

5659
ctx := context.Background()
57-
appId := "test-app"
58-
sender := fmt.Sprintf("0xadd%037x", 1)
59-
value := uint64(1_000_000_000_000_000_000)
60+
appId := common.NewApplicationId(1)
61+
sender := ethCommon.HexToAddress(fmt.Sprintf("0xadd%037x", 1))
62+
value := big.NewInt(1_000_000_000_000_000_000)
6063

6164
state, err := runtime.LoadModule(ctx, appId, wasmBytes)
6265
require.NoError(t, err)
@@ -77,11 +80,11 @@ func TestIntegration_ProcessRequest_Transfer(t *testing.T) {
7780
defer runtime.Close()
7881

7982
ctx := context.Background()
80-
appId := "test-app"
81-
sender := fmt.Sprintf("0xadd%037x", 1)
82-
recipient := fmt.Sprintf("0xadd%037x", 2)
83-
depositValue := uint64(2_000_000_000_000_000_000)
84-
transferValue := uint64(500_000_000_000_000_000)
83+
appId := common.NewApplicationId(1)
84+
sender := ethCommon.HexToAddress(fmt.Sprintf("0xadd%037x", 1))
85+
recipient := ethCommon.HexToAddress(fmt.Sprintf("0xadd%037x", 2))
86+
depositValue := big.NewInt(2_000_000_000_000_000_000)
87+
transferValue := big.NewInt(500_000_000_000_000_000)
8588

8689
state, err := runtime.LoadModule(ctx, appId, wasmBytes)
8790
require.NoError(t, err)
@@ -102,7 +105,8 @@ func TestIntegration_ProcessRequest_Transfer(t *testing.T) {
102105

103106
var stateData app.ApplicationInternalState
104107
require.NoError(t, json.Unmarshal(newState, &stateData))
105-
assert.Equal(t, depositValue-transferValue, stateData.Accounts[sender].Balance)
108+
updatedBalance := new(big.Int).Sub(depositValue, transferValue)
109+
assert.Equal(t, updatedBalance, stateData.Accounts[sender].Balance)
106110
assert.Equal(t, transferValue, stateData.Accounts[recipient].Balance)
107111
}
108112

@@ -112,11 +116,11 @@ func TestIntegration_ProcessRequest_Withdrawal(t *testing.T) {
112116
defer runtime.Close()
113117

114118
ctx := context.Background()
115-
appId := "test-app"
116-
sender := fmt.Sprintf("0xadd%037x", 1)
117-
depositValue := uint64(1_000_000_000_000_000_000)
118-
withdrawValue := uint64(500_000_000_000_000_000)
119-
withdrawAddress := "0x1234567890123456789012345678901234567890"
119+
appId := common.NewApplicationId(1)
120+
sender := ethCommon.HexToAddress(fmt.Sprintf("0xadd%037x", 1))
121+
depositValue := big.NewInt(1_000_000_000_000_000_000)
122+
withdrawValue := big.NewInt(500_000_000_000_000_000)
123+
withdrawAddress := ethCommon.HexToAddress("0x1234567890123456789012345678901234567890")
120124

121125
state, err := runtime.LoadModule(ctx, appId, wasmBytes)
122126
require.NoError(t, err)
@@ -139,7 +143,8 @@ func TestIntegration_ProcessRequest_Withdrawal(t *testing.T) {
139143

140144
var stateData app.ApplicationInternalState
141145
require.NoError(t, json.Unmarshal(newState, &stateData))
142-
assert.Equal(t, depositValue-withdrawValue, stateData.Accounts[sender].Balance)
146+
updatedBalance := new(big.Int).Sub(depositValue, withdrawValue)
147+
assert.Equal(t, updatedBalance, stateData.Accounts[sender].Balance)
143148
}
144149

145150
func TestIntegration_GenerateDeanonymizationReport(t *testing.T) {
@@ -150,14 +155,14 @@ func TestIntegration_GenerateDeanonymizationReport(t *testing.T) {
150155
type reportStruct struct {
151156
ApplicationID string `json:"applicationId"`
152157
RequestID string `json:"requestId"`
153-
Accounts map[string]*app.AccountState `json:"accounts"`
158+
Accounts map[ethCommon.Address]*app.AccountState `json:"accounts"`
154159
Nonce uint64 `json:"nonce"`
155160
}
156161

157162
ctx := context.Background()
158-
appId := "test-app"
159-
sender := fmt.Sprintf("0xadd%037x", 1)
160-
value := uint64(1_000_000_000_000_000_000)
163+
appId := common.NewApplicationId(1)
164+
sender := ethCommon.HexToAddress(fmt.Sprintf("0xadd%037x", 1))
165+
value := big.NewInt(1_000_000_000_000_000_000)
161166

162167
state, err := runtime.LoadModule(ctx, appId, wasmBytes)
163168
require.NoError(t, err)

runtime/wasm-go/main.go

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,33 +10,33 @@ import (
1010
// These functions handle the WASM I/O and call the high-level logic functions.
1111

1212
//export load_module
13-
func load_module(appIdPtr *byte, appIdLen int32) *byte {
14-
appId := utils.PtrToString(appIdPtr, appIdLen)
13+
func load_module(appId int64) *byte {
1514
stateBytes := app.LoadModule(appId)
1615
return utils.StringToPtr(stateBytes)
1716
}
1817

1918
//export deposit
20-
func deposit(appIdPtr *byte, appIdLen int32, senderPtr *byte, senderLen int32, value uint64, statePtr *byte, stateLen int32) *byte {
19+
func deposit(appId int64, senderPtr *byte, senderLen int32, valuePtr *byte, valueLen int32, statePtr *byte, stateLen int32) *byte {
2120
// TODO: in future we must use the appId for adding it to the generated event
22-
_ = utils.PtrToString(appIdPtr, appIdLen)
23-
sender := utils.PtrToString(senderPtr, senderLen)
21+
_ = appId
22+
sender := utils.PtrToAddress(senderPtr, senderLen)
2423
stateJSON := utils.PtrToString(statePtr, stateLen)
24+
value := utils.PtrToNonNegativeBigInt(valuePtr, valueLen)
2525
result := app.DepositFunds(sender, value, stateJSON)
2626
return utils.SerializeAndWriteResult(result)
2727
}
2828

2929
//export process_request
30-
func process_request(appIdPtr *byte, appIdLen int32, senderPtr *byte, senderLen int32, payloadPtr *byte, payloadLen int32, statePtr *byte, stateLen int32) *byte {
31-
// TODO: in future we must use the appId for setting it in the generated event
32-
_ = utils.PtrToString(appIdPtr, appIdLen)
33-
sender := utils.PtrToString(senderPtr, senderLen)
30+
func process_request(appId int64, senderPtr *byte, senderLen int32, payloadPtr *byte, payloadLen int32, statePtr *byte, stateLen int32) *byte {
31+
_ = appId
32+
sender := utils.PtrToAddress(senderPtr, senderLen)
3433
payloadJSON := utils.PtrToString(payloadPtr, payloadLen)
3534
stateJSON := utils.PtrToString(statePtr, stateLen)
3635
result := app.ProcessRequest(sender, payloadJSON, stateJSON)
3736
return utils.SerializeAndWriteResult(result)
3837
}
3938

39+
4040
//export generate_deanonymization_report
4141
func generate_deanonymization_report(payloadPtr *byte, payloadLen int32, statePtr *byte, stateLen int32) *byte {
4242
payloadJSON := utils.PtrToString(payloadPtr, payloadLen)

0 commit comments

Comments
 (0)