diff --git a/examples/erc20/contract/erc20.go b/examples/erc20/contract/erc20.go index 07182b7..95e2778 100644 --- a/examples/erc20/contract/erc20.go +++ b/examples/erc20/contract/erc20.go @@ -80,8 +80,8 @@ type ConstructorReq struct { TotalSupply *big.Int } -func Constructor(req *ConstructorReq) error { - emptyMap, err := adt.MakeEmptyMap(adt.AdtStore(context.Background()), adt.BalanceTableBitwidth) +func Constructor(ctx context.Context, req *ConstructorReq) error { + emptyMap, err := adt.MakeEmptyMap(adt.AdtStore(ctx), adt.BalanceTableBitwidth) if err != nil { return err } @@ -89,7 +89,7 @@ func Constructor(req *ConstructorReq) error { if err != nil { return err } - caller, err := sdk.Caller() + caller, err := sdk.Caller(ctx) if err != nil { return err } @@ -114,8 +114,8 @@ func Constructor(req *ConstructorReq) error { Allowed: emptyRoot, } - logger.Logf("construct token %s issue %s token to %s", req.Name, req.TotalSupply.String(), actorToString(caller)) - _ = sdk.Constructor(state) + logger.Logf(ctx, "construct token %s issue %s token to %s", req.Name, req.TotalSupply.String(), actorToString(caller)) + _ = sdk.Constructor(ctx, state) return nil } @@ -125,13 +125,13 @@ type FakeSetBalance struct { } // FakeSetBalance NOTICE **beacause unable to set init balance in constructor, so just add this function for test contract, and must be remove after fvm support get really caller** -func (t *Erc20Token) FakeSetBalance(req *FakeSetBalance) error { - addrId, err := sdk.ResolveAddress(req.Addr) +func (t *Erc20Token) FakeSetBalance(ctx context.Context, req *FakeSetBalance) error { + addrId, err := sdk.ResolveAddress(ctx, req.Addr) if err != nil { return err } - balanceMap, err := adt.AsMap(adt.AdtStore(context.Background()), t.Balances, adt.BalanceTableBitwidth) + balanceMap, err := adt.AsMap(adt.AdtStore(ctx), t.Balances, adt.BalanceTableBitwidth) if err != nil { return err } @@ -143,7 +143,7 @@ func (t *Erc20Token) FakeSetBalance(req *FakeSetBalance) error { if err != nil { return err } - _ = sdk.SaveState(t) + _ = sdk.SaveState(ctx, t) return nil } @@ -167,19 +167,21 @@ func (t *Erc20Token) GetTotalSupply() *big.Int { return t.TotalSupply } -/*GetBalanceOf sender by ID. +/* +GetBalanceOf sender by ID. -* `args[0]` - the ID of user.*/ -func (t *Erc20Token) GetBalanceOf(addr *address.Address) (*big.Int, error) { - senderId, err := sdk.ResolveAddress(*addr) +* `args[0]` - the ID of user. +*/ +func (t *Erc20Token) GetBalanceOf(ctx context.Context, addr *address.Address) (*big.Int, error) { + senderId, err := sdk.ResolveAddress(ctx, *addr) if err != nil { return nil, err } - return t.getBalanceOf(senderId) + return t.getBalanceOf(ctx, senderId) } -func (t *Erc20Token) getBalanceOf(act abi.ActorID) (*big.Int, error) { - balanceMap, err := adt.AsMap(adt.AdtStore(context.Background()), t.Balances, adt.BalanceTableBitwidth) +func (t *Erc20Token) getBalanceOf(ctx context.Context, act abi.ActorID) (*big.Int, error) { + balanceMap, err := adt.AsMap(adt.AdtStore(ctx), t.Balances, adt.BalanceTableBitwidth) if err != nil { return nil, err } @@ -196,20 +198,21 @@ type TransferReq struct { TransferAmount *big.Int } -/*Transfer token from current caller to a specified address. +/* +Transfer token from current caller to a specified address. * `receiverAddr` - the ID of receiver. * `transferAmount` - the transfer amount. - */ -func (t *Erc20Token) Transfer(transferReq *TransferReq) error { - senderID, err := sdk.Caller() +*/ +func (t *Erc20Token) Transfer(ctx context.Context, transferReq *TransferReq) error { + senderID, err := sdk.Caller(ctx) if err != nil { return err } - receiverID, err := sdk.ResolveAddress(transferReq.ReceiverAddr) + receiverID, err := sdk.ResolveAddress(ctx, transferReq.ReceiverAddr) if err != nil { return err } @@ -218,11 +221,11 @@ func (t *Erc20Token) Transfer(transferReq *TransferReq) error { return errors.New("trasfer value must bigger than zero") } - balanceOfSender, err := t.getBalanceOf(senderID) + balanceOfSender, err := t.getBalanceOf(ctx, senderID) if err != nil { return err } - balanceOfReceiver, err := t.getBalanceOf(receiverID) + balanceOfReceiver, err := t.getBalanceOf(ctx, receiverID) if err != nil { return err } @@ -235,7 +238,7 @@ func (t *Erc20Token) Transfer(transferReq *TransferReq) error { return fmt.Errorf("transfer amount should be less than balance of sender (%v): %v", senderID, err) } - balanceMap, err := adt.AsMap(adt.AdtStore(context.Background()), t.Balances, adt.BalanceTableBitwidth) + balanceMap, err := adt.AsMap(adt.AdtStore(ctx), t.Balances, adt.BalanceTableBitwidth) if err != nil { return err } @@ -251,8 +254,8 @@ func (t *Erc20Token) Transfer(transferReq *TransferReq) error { return err } t.Balances = newBalanceMapRoot - logger.Logf("transfer from %d to %d amount %s", senderID, receiverID, transferReq.TransferAmount.String()) - _ = sdk.SaveState(t) + logger.Logf(ctx, "transfer from %d to %d amount %s", senderID, receiverID, transferReq.TransferAmount.String()) + _ = sdk.SaveState(ctx, t) return nil } @@ -261,27 +264,29 @@ type AllowanceReq struct { SpenderAddr address.Address } -/*GetAllowance checks the amount of tokens that an owner Allowed a spender to transfer in behalf of the owner to another receiver. +/* +GetAllowance checks the amount of tokens that an owner Allowed a spender to transfer in behalf of the owner to another receiver. * `ownerAddr` - the ID of owner. -* `spenderAddr` - the ID of spender*/ -func (t *Erc20Token) Allowance(req *AllowanceReq) (*big.Int, error) { - ownerID, err := sdk.ResolveAddress(req.OwnerAddr) +* `spenderAddr` - the ID of spender +*/ +func (t *Erc20Token) Allowance(ctx context.Context, req *AllowanceReq) (*big.Int, error) { + ownerID, err := sdk.ResolveAddress(ctx, req.OwnerAddr) if err != nil { return nil, err } - spenderId, err := sdk.ResolveAddress(req.SpenderAddr) + spenderId, err := sdk.ResolveAddress(ctx, req.SpenderAddr) if err != nil { return nil, err } - return t.getAllowance(ownerID, spenderId) + return t.getAllowance(ctx, ownerID, spenderId) } -func (t *Erc20Token) getAllowance(ownerID, spenderId abi.ActorID) (*big.Int, error) { - allowBalanceMap, err := adt.AsMap(adt.AdtStore(context.Background()), t.Allowed, adt.BalanceTableBitwidth) +func (t *Erc20Token) getAllowance(ctx context.Context, ownerID, spenderId abi.ActorID) (*big.Int, error) { + allowBalanceMap, err := adt.AsMap(adt.AdtStore(ctx), t.Allowed, adt.BalanceTableBitwidth) if err != nil { return nil, err } @@ -300,21 +305,22 @@ type TransferFromReq struct { TransferAmount *big.Int } -/*TransferFrom transfer tokens from token owner to receiver. +/* +TransferFrom transfer tokens from token owner to receiver. * `ownerAddr` - the ID of token owner. * `receiverAddr` - the ID of receiver. * `transferAmount` - the transfer amount. - */ -func (t *Erc20Token) TransferFrom(req *TransferFromReq) error { - tokenOwnerID, err := sdk.ResolveAddress(req.OwnerAddr) +*/ +func (t *Erc20Token) TransferFrom(ctx context.Context, req *TransferFromReq) error { + tokenOwnerID, err := sdk.ResolveAddress(ctx, req.OwnerAddr) if err != nil { return err } - receiverID, err := sdk.ResolveAddress(req.ReceiverAddr) + receiverID, err := sdk.ResolveAddress(ctx, req.ReceiverAddr) if err != nil { return err } @@ -323,19 +329,19 @@ func (t *Erc20Token) TransferFrom(req *TransferFromReq) error { return errors.New("send value must bigger than zero") } - spenderID, err := sdk.Caller() + spenderID, err := sdk.Caller(ctx) if err != nil { return err } - balanceOfTokenOwner, err := t.getBalanceOf(tokenOwnerID) + balanceOfTokenOwner, err := t.getBalanceOf(ctx,tokenOwnerID) if err != nil { return err } - balanceOfReceiver, err := t.getBalanceOf(receiverID) + balanceOfReceiver, err := t.getBalanceOf(ctx,receiverID) if err != nil { return err } - approvedAmount, err := t.getAllowance(tokenOwnerID, spenderID) + approvedAmount, err := t.getAllowance(ctx,tokenOwnerID, spenderID) if err != nil { return err } @@ -358,7 +364,7 @@ func (t *Erc20Token) TransferFrom(req *TransferFromReq) error { return fmt.Errorf("transfer amount should be less than approved spending amount of %v: %v", spenderID, err) } - store := adt.AdtStore(context.Background()) + store := adt.AdtStore(ctx) balanceMap, err := adt.AsMap(store, t.Balances, adt.BalanceTableBitwidth) if err != nil { return err @@ -387,7 +393,7 @@ func (t *Erc20Token) TransferFrom(req *TransferFromReq) error { if t.Allowed, err = allowBalanceMap.Root(); err != nil { return err } - _ = sdk.SaveState(t) + _ = sdk.SaveState(ctx, t) return nil } @@ -399,8 +405,8 @@ type ApprovalReq struct { /*Approval approves the passed-in identity to spend/burn a maximum amount of tokens on behalf of the function caller. * `spenderAddr` - the ID of approved user. * `newAllowance` - the maximum approved amount.*/ -func (t *Erc20Token) Approval(req *ApprovalReq) error { - spenderID, err := sdk.ResolveAddress(req.SpenderAddr) +func (t *Erc20Token) Approval(ctx context.Context, req *ApprovalReq) error { + spenderID, err := sdk.ResolveAddress(ctx, req.SpenderAddr) if err != nil { return err } @@ -409,17 +415,17 @@ func (t *Erc20Token) Approval(req *ApprovalReq) error { return errors.New("allow value must bigger than zero") } - callerID, err := sdk.Caller() + callerID, err := sdk.Caller(ctx) if err != nil { return err } - allowance, err := t.getAllowance(callerID, spenderID) + allowance, err := t.getAllowance(ctx,callerID, spenderID) if err != nil { return err } - allowBalanceMap, err := adt.AsMap(adt.AdtStore(context.Background()), t.Allowed, adt.BalanceTableBitwidth) + allowBalanceMap, err := adt.AsMap(adt.AdtStore(ctx), t.Allowed, adt.BalanceTableBitwidth) if err != nil { return err } @@ -432,8 +438,8 @@ func (t *Erc20Token) Approval(req *ApprovalReq) error { if err != nil { return err } - _ = sdk.SaveState(t) - logger.Logf("approval %s for %s", getAllowKey(callerID, spenderID), req.NewAllowance.String()) + _ = sdk.SaveState(ctx, t) + logger.Logf(ctx, "approval %s for %s", getAllowKey(callerID, spenderID), req.NewAllowance.String()) return nil } diff --git a/examples/erc20/contract/erc20_test.go b/examples/erc20/contract/erc20_test.go index 10bb4d8..2aae00d 100644 --- a/examples/erc20/contract/erc20_test.go +++ b/examples/erc20/contract/erc20_test.go @@ -1,14 +1,18 @@ +//go:build simulate +// +build simulate + package contract import ( "context" - "github.com/filecoin-project/go-state-types/abi" - "github.com/filecoin-project/go-state-types/builtin/v9/migration" - "github.com/ipfs/go-cid" "math/rand" "reflect" "testing" + "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/go-state-types/builtin/v9/migration" + "github.com/ipfs/go-cid" + "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/big" "github.com/ipfs-force-community/go-fvm-sdk/sdk" @@ -18,21 +22,23 @@ import ( "github.com/stretchr/testify/assert" ) -func makeErc20Token() Erc20Token { - t:= &testing.T{} - map_, err := adt.MakeEmptyMap(adt.AdtStore(context.Background()), adt.BalanceTableBitwidth) +func makeErc20Token(t *testing.T, ctx context.Context) Erc20Token { + empMap, err := adt.MakeEmptyMap(adt.AdtStore(ctx), adt.BalanceTableBitwidth) assert.Nil(t, err) - cidtest, err := map_.Root() + cidtest, err := empMap.Root() assert.Nil(t, err) totalsupplytest := big.NewInt(888888) - return Erc20Token{Name: "name", Symbol: "symbol", Decimals: 8, TotalSupply: &totalsupplytest, Balances: cidtest, Allowed: cidtest} } -func TestErc20TokenFakeSetBalance(t *testing.T) { - simulated.Begin() +func newSimulated() (*simulated.FvmSimulator, context.Context) { + callcontext := &types.InvocationContext{} + return simulated.CreateSimulateEnv(callcontext, big.NewInt(1), big.NewInt(1), big.NewInt(1)) +} - balance := big.NewInt(0) +func TestErc20TokenFakeSetBalance(t *testing.T) { + _, ctx := newSimulated() + balance := big.NewInt(1) addr, err := address.NewIDAddress(uint64(rand.Int())) if err != nil { panic(err) @@ -47,7 +53,7 @@ func TestErc20TokenFakeSetBalance(t *testing.T) { args args wantErr bool }{ - {name: "case1", fields: makeErc20Token(), args: args{req: fakeSetBalance}, wantErr: true}, + {name: "pass", fields: makeErc20Token(t, ctx), args: args{req: fakeSetBalance}, wantErr: true}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -59,22 +65,22 @@ func TestErc20TokenFakeSetBalance(t *testing.T) { Balances: tt.fields.Balances, Allowed: tt.fields.Allowed, } - if err := tr.FakeSetBalance(tt.args.req); (err != nil) != tt.wantErr { + if err := tr.FakeSetBalance(ctx, tt.args.req); (err != nil) != tt.wantErr { t.Errorf("Erc20Token.FakeSetBalance() error = %v, wantErr %v", err, tt.wantErr) } }) } - simulated.End() + } func TestErc20TokenGetName(t *testing.T) { - simulated.Begin() + _, ctx := newSimulated() tests := []struct { name string fields Erc20Token want types.CborString }{ - {name: "pass", fields: makeErc20Token(), want: types.CborString("name")}, + {name: "pass", fields: makeErc20Token(t, ctx), want: types.CborString("name")}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -91,35 +97,35 @@ func TestErc20TokenGetName(t *testing.T) { } }) } - simulated.End() + } func TestErc20TokenSaveState(t *testing.T) { - simulated.Begin() - - erc20 := makeErc20Token() - sdk.SaveState(&erc20) + _, ctx := newSimulated() + erc20 := makeErc20Token(t, ctx) + sdk.SaveState(ctx, &erc20) newSt := new(Erc20Token) - sdk.LoadState(newSt) + sdk.LoadState(ctx, newSt) assert.Equal(t, *newSt, erc20) - simulated.End() + } func TestErc20TokenGetBalanceOf(t1 *testing.T) { - simulated.Begin() - erc20 := makeErc20Token() - balanceMap, _ := adt.AsMap(adt.AdtStore(context.Background()), erc20.Balances, adt.BalanceTableBitwidth) + instance, ctx := newSimulated() + erc20 := makeErc20Token(t1, ctx) + + balanceMap, _ := adt.AsMap(adt.AdtStore(ctx), erc20.Balances, adt.BalanceTableBitwidth) addr, _ := address.NewIDAddress(uint64(rand.Int())) - simulated.SetAccount(8899, addr, migration.Actor{}) + instance.SetAccount(8899, addr, migration.Actor{}) balance := big.NewInt(100) if err := balanceMap.Put(types.ActorKey(8899), &balance); err != nil { panic(err) } newRoot, _ := balanceMap.Root() erc20.Balances = newRoot - sdk.SaveState(&erc20) + sdk.SaveState(ctx, &erc20) type args struct { addr *address.Address @@ -144,7 +150,7 @@ func TestErc20TokenGetBalanceOf(t1 *testing.T) { Balances: tt.fields.Balances, Allowed: tt.fields.Allowed, } - got, err := t.GetBalanceOf(tt.args.addr) + got, err := t.GetBalanceOf(ctx, tt.args.addr) if (err != nil) != tt.wantErr { t1.Errorf("GetBalanceOf() error = %v, wantErr %v", err, tt.wantErr) return @@ -154,21 +160,20 @@ func TestErc20TokenGetBalanceOf(t1 *testing.T) { } }) } - simulated.End() + } func TestErc20TokenTransfer(t *testing.T) { - simulated.Begin() - - erc20 := makeErc20Token() + instance, ctx := newSimulated() + erc20 := makeErc20Token(t, ctx) // set info of caller callactorid := uint32(8899) calladdr, _ := address.NewIDAddress(uint64(rand.Int())) - simulated.SetAccount(callactorid, calladdr, migration.Actor{Code: cid.Undef, Head: cid.Undef, CallSeqNum: 0, Balance: big.NewInt(99)}) + instance.SetAccount(callactorid, calladdr, migration.Actor{Code: cid.Undef, Head: cid.Undef, CallSeqNum: 0, Balance: big.NewInt(99)}) // push balance of caller - balanceMap, _ := adt.AsMap(adt.AdtStore(context.Background()), erc20.Balances, adt.BalanceTableBitwidth) + balanceMap, _ := adt.AsMap(adt.AdtStore(ctx), erc20.Balances, adt.BalanceTableBitwidth) balance := big.NewInt(100000) if err := balanceMap.Put(types.ActorKey(callactorid), &balance); err != nil { panic(err) @@ -176,16 +181,16 @@ func TestErc20TokenTransfer(t *testing.T) { newRoot, _ := balanceMap.Root() erc20.Balances = newRoot - sdk.SaveState(&erc20) + sdk.SaveState(ctx, &erc20) // set info of receiver receiactorid := uint32(7788) receiveaddr, _ := address.NewIDAddress(uint64(rand.Int())) - simulated.SetAccount(receiactorid, receiveaddr, migration.Actor{Code: cid.Undef, Head: cid.Undef, CallSeqNum: 0, Balance: big.NewInt(99)}) + instance.SetAccount(receiactorid, receiveaddr, migration.Actor{Code: cid.Undef, Head: cid.Undef, CallSeqNum: 0, Balance: big.NewInt(99)}) // set info of context callcontext := types.InvocationContext{Caller: abi.ActorID(callactorid)} - simulated.SetCallContext(&callcontext) + instance.SetCallContext(&callcontext) toamount := big.NewInt(9) type args struct { @@ -197,14 +202,14 @@ func TestErc20TokenTransfer(t *testing.T) { args args wantErr bool }{ - {name: "pass", fields: makeErc20Token(), args: args{transferReq: &TransferReq{ReceiverAddr: receiveaddr, TransferAmount: &toamount}}, wantErr: false}, + {name: "pass", fields: makeErc20Token(t, ctx), args: args{transferReq: &TransferReq{ReceiverAddr: receiveaddr, TransferAmount: &toamount}}, wantErr: false}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if err := erc20.Transfer(tt.args.transferReq); (err != nil) != tt.wantErr { + if err := erc20.Transfer(ctx, tt.args.transferReq); (err != nil) != tt.wantErr { t.Errorf("Erc20Token.Transfer() error = %v, wantErr %v", err, tt.wantErr) } }) } - simulated.End() + } diff --git a/examples/erc20/entry.go b/examples/erc20/entry.go index 44a74b7..4463f13 100644 --- a/examples/erc20/entry.go +++ b/examples/erc20/entry.go @@ -3,6 +3,7 @@ package main import ( "bytes" + "context" "fmt" contract "erc20/contract" @@ -33,9 +34,10 @@ func main() {} // //go:export invoke func Invoke(blockId uint32) uint32 { - method, err := sdk.MethodNumber() + ctx := context.Background() + method, err := sdk.MethodNumber(ctx) if err != nil { - sdk.Abort(ferrors.USR_ILLEGAL_STATE, "unable to get method number") + sdk.Abort(ctx, ferrors.USR_ILLEGAL_STATE, "unable to get method number") } var callResult cbor.Marshaler @@ -43,173 +45,173 @@ func Invoke(blockId uint32) uint32 { switch method { case 1: // Constuctor - raw, err = sdk.ParamsRaw(blockId) + raw, err = sdk.ParamsRaw(ctx, blockId) if err != nil { - sdk.Abort(ferrors.USR_ILLEGAL_STATE, "unable to read params raw") + sdk.Abort(ctx, ferrors.USR_ILLEGAL_STATE, "unable to read params raw") } var req contract.ConstructorReq err = req.UnmarshalCBOR(bytes.NewReader(raw.Raw)) if err != nil { - sdk.Abort(ferrors.USR_ILLEGAL_STATE, "unable to unmarshal params raw") + sdk.Abort(ctx, ferrors.USR_ILLEGAL_STATE, "unable to unmarshal params raw") } - err = contract.Constructor(&req) + err = contract.Constructor(ctx, &req) callResult = typegen.CborBool(true) case 2: // no params no error but have return value state := new(contract.Erc20Token) - sdk.LoadState(state) + sdk.LoadState(ctx, state) callResult = state.GetName() case 3: // no params no error but have return value state := new(contract.Erc20Token) - sdk.LoadState(state) + sdk.LoadState(ctx, state) callResult = state.GetSymbol() case 4: // no params no error but have return value state := new(contract.Erc20Token) - sdk.LoadState(state) + sdk.LoadState(ctx, state) callResult = state.GetDecimal() case 5: // no params no error but have return value state := new(contract.Erc20Token) - sdk.LoadState(state) + sdk.LoadState(ctx, state) callResult = state.GetTotalSupply() case 6: - raw, err = sdk.ParamsRaw(blockId) + raw, err = sdk.ParamsRaw(ctx, blockId) if err != nil { - sdk.Abort(ferrors.USR_ILLEGAL_STATE, "unable to read params raw") + sdk.Abort(ctx, ferrors.USR_ILLEGAL_STATE, "unable to read params raw") } var req address.Address err = req.UnmarshalCBOR(bytes.NewReader(raw.Raw)) if err != nil { - sdk.Abort(ferrors.USR_ILLEGAL_STATE, "unable to unmarshal params raw") + sdk.Abort(ctx, ferrors.USR_ILLEGAL_STATE, "unable to unmarshal params raw") } // have params/return/error state := new(contract.Erc20Token) - sdk.LoadState(state) - callResult, err = state.GetBalanceOf(&req) + sdk.LoadState(ctx, state) + callResult, err = state.GetBalanceOf(ctx, &req) case 7: - raw, err = sdk.ParamsRaw(blockId) + raw, err = sdk.ParamsRaw(ctx, blockId) if err != nil { - sdk.Abort(ferrors.USR_ILLEGAL_STATE, "unable to read params raw") + sdk.Abort(ctx, ferrors.USR_ILLEGAL_STATE, "unable to read params raw") } var req contract.TransferReq err = req.UnmarshalCBOR(bytes.NewReader(raw.Raw)) if err != nil { - sdk.Abort(ferrors.USR_ILLEGAL_STATE, "unable to unmarshal params raw") + sdk.Abort(ctx, ferrors.USR_ILLEGAL_STATE, "unable to unmarshal params raw") } // have params/error but no return val state := new(contract.Erc20Token) - sdk.LoadState(state) - if err = state.Transfer(&req); err == nil { + sdk.LoadState(ctx, state) + if err = state.Transfer(ctx, &req); err == nil { callResult = typegen.CborBool(true) } case 8: - raw, err = sdk.ParamsRaw(blockId) + raw, err = sdk.ParamsRaw(ctx, blockId) if err != nil { - sdk.Abort(ferrors.USR_ILLEGAL_STATE, "unable to read params raw") + sdk.Abort(ctx, ferrors.USR_ILLEGAL_STATE, "unable to read params raw") } var req contract.TransferFromReq err = req.UnmarshalCBOR(bytes.NewReader(raw.Raw)) if err != nil { - sdk.Abort(ferrors.USR_ILLEGAL_STATE, "unable to unmarshal params raw") + sdk.Abort(ctx, ferrors.USR_ILLEGAL_STATE, "unable to unmarshal params raw") } // have params/error but no return val state := new(contract.Erc20Token) - sdk.LoadState(state) - if err = state.TransferFrom(&req); err == nil { + sdk.LoadState(ctx, state) + if err = state.TransferFrom(ctx, &req); err == nil { callResult = typegen.CborBool(true) } case 9: - raw, err = sdk.ParamsRaw(blockId) + raw, err = sdk.ParamsRaw(ctx, blockId) if err != nil { - sdk.Abort(ferrors.USR_ILLEGAL_STATE, "unable to read params raw") + sdk.Abort(ctx, ferrors.USR_ILLEGAL_STATE, "unable to read params raw") } var req contract.ApprovalReq err = req.UnmarshalCBOR(bytes.NewReader(raw.Raw)) if err != nil { - sdk.Abort(ferrors.USR_ILLEGAL_STATE, "unable to unmarshal params raw") + sdk.Abort(ctx, ferrors.USR_ILLEGAL_STATE, "unable to unmarshal params raw") } // have params/error but no return val state := new(contract.Erc20Token) - sdk.LoadState(state) - if err = state.Approval(&req); err == nil { + sdk.LoadState(ctx, state) + if err = state.Approval(ctx, &req); err == nil { callResult = typegen.CborBool(true) } case 10: - raw, err = sdk.ParamsRaw(blockId) + raw, err = sdk.ParamsRaw(ctx, blockId) if err != nil { - sdk.Abort(ferrors.USR_ILLEGAL_STATE, "unable to read params raw") + sdk.Abort(ctx, ferrors.USR_ILLEGAL_STATE, "unable to read params raw") } var req contract.AllowanceReq err = req.UnmarshalCBOR(bytes.NewReader(raw.Raw)) if err != nil { - sdk.Abort(ferrors.USR_ILLEGAL_STATE, "unable to unmarshal params raw") + sdk.Abort(ctx, ferrors.USR_ILLEGAL_STATE, "unable to unmarshal params raw") } // have params/return/error state := new(contract.Erc20Token) - sdk.LoadState(state) - callResult, err = state.Allowance(&req) + sdk.LoadState(ctx, state) + callResult, err = state.Allowance(ctx, &req) case 11: - raw, err = sdk.ParamsRaw(blockId) + raw, err = sdk.ParamsRaw(ctx, blockId) if err != nil { - sdk.Abort(ferrors.USR_ILLEGAL_STATE, "unable to read params raw") + sdk.Abort(ctx, ferrors.USR_ILLEGAL_STATE, "unable to read params raw") } var req contract.FakeSetBalance err = req.UnmarshalCBOR(bytes.NewReader(raw.Raw)) if err != nil { - sdk.Abort(ferrors.USR_ILLEGAL_STATE, "unable to unmarshal params raw") + sdk.Abort(ctx, ferrors.USR_ILLEGAL_STATE, "unable to unmarshal params raw") } // have params/error but no return val state := new(contract.Erc20Token) - sdk.LoadState(state) - if err = state.FakeSetBalance(&req); err == nil { + sdk.LoadState(ctx, state) + if err = state.FakeSetBalance(ctx, &req); err == nil { callResult = typegen.CborBool(true) } default: - sdk.Abort(ferrors.USR_ILLEGAL_STATE, "unsupport method") + sdk.Abort(ctx, ferrors.USR_ILLEGAL_STATE, "unsupport method") } if err != nil { - sdk.Abort(ferrors.USR_ILLEGAL_STATE, fmt.Sprintf("call error %s", err)) + sdk.Abort(ctx, ferrors.USR_ILLEGAL_STATE, fmt.Sprintf("call error %s", err)) } if !sdk.IsNil(callResult) { buf := bytes.NewBufferString("") err = callResult.MarshalCBOR(buf) if err != nil { - sdk.Abort(ferrors.USR_ILLEGAL_STATE, fmt.Sprintf("marshal resp fail %s", err)) + sdk.Abort(ctx, ferrors.USR_ILLEGAL_STATE, fmt.Sprintf("marshal resp fail %s", err)) } - id, err := sdk.PutBlock(sdkTypes.DAGCbor, buf.Bytes()) + id, err := sdk.PutBlock(ctx, sdkTypes.DAGCbor, buf.Bytes()) if err != nil { - sdk.Abort(ferrors.USR_ILLEGAL_STATE, fmt.Sprintf("failed to store return value: %v", err)) + sdk.Abort(ctx, ferrors.USR_ILLEGAL_STATE, fmt.Sprintf("failed to store return value: %v", err)) } return id } else { diff --git a/examples/erc20/gen/go.sum b/examples/erc20/gen/go.sum index 3fdfe18..f47d02a 100644 --- a/examples/erc20/gen/go.sum +++ b/examples/erc20/gen/go.sum @@ -1624,6 +1624,8 @@ github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1 github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c/go.mod h1:hzIxponao9Kjc7aWznkXaL4U4TWaDSs8zcsY4Ka08nM= github.com/twitchyliquid64/golang-asm v0.15.0/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= +github.com/twmb/murmur3 v1.1.6 h1:mqrRot1BRxm+Yct+vavLMou2/iJt0tNVTTC0QoIjaZg= +github.com/twmb/murmur3 v1.1.6/go.mod h1:Qq/R7NUyOfr65zD+6Q5IHKsJLwP7exErjN6lyyq3OSQ= github.com/uber/jaeger-client-go v2.15.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= github.com/uber/jaeger-client-go v2.23.1+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= github.com/uber/jaeger-client-go v2.25.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= diff --git a/examples/erc20/go.sum b/examples/erc20/go.sum index 45b3967..386fa68 100644 --- a/examples/erc20/go.sum +++ b/examples/erc20/go.sum @@ -1624,6 +1624,8 @@ github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1 github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c/go.mod h1:hzIxponao9Kjc7aWznkXaL4U4TWaDSs8zcsY4Ka08nM= github.com/twitchyliquid64/golang-asm v0.15.0/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= +github.com/twmb/murmur3 v1.1.6 h1:mqrRot1BRxm+Yct+vavLMou2/iJt0tNVTTC0QoIjaZg= +github.com/twmb/murmur3 v1.1.6/go.mod h1:Qq/R7NUyOfr65zD+6Q5IHKsJLwP7exErjN6lyyq3OSQ= github.com/uber/jaeger-client-go v2.15.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= github.com/uber/jaeger-client-go v2.23.1+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= github.com/uber/jaeger-client-go v2.25.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= diff --git a/examples/hellocontract/contract/helloworld.go b/examples/hellocontract/contract/helloworld.go index b1b8c5a..31aebdc 100644 --- a/examples/hellocontract/contract/helloworld.go +++ b/examples/hellocontract/contract/helloworld.go @@ -1,6 +1,7 @@ package contract import ( + "context" "fmt" "github.com/ipfs-force-community/go-fvm-sdk/sdk/types" @@ -23,17 +24,18 @@ func (e *State) Export() map[int]interface{} { // / // Method num 1. This is part of the Filecoin calling convention. // InitActor#Exec will call the constructor on method_num = 1. -func Constructor() error { +func Constructor(ctx context.Context) error { // This constant should be part of the SDK. // var ActorID = 1; - _ = sdk.Constructor(&State{}) + s := &State{} + _ = sdk.Constructor(ctx, s) return nil } // Method num 2. -func (st *State) SayHello() types.CBORBytes { +func (st *State) SayHello(ctx context.Context) types.CBORBytes { st.Count += 1 ret := fmt.Sprintf("%d", st.Count) - _ = sdk.SaveState(&State{}) + _ = sdk.SaveState(ctx, &State{}) return []byte(ret) } diff --git a/examples/hellocontract/contract/helloworld_test.go b/examples/hellocontract/contract/helloworld_test.go index 2697802..db0919b 100644 --- a/examples/hellocontract/contract/helloworld_test.go +++ b/examples/hellocontract/contract/helloworld_test.go @@ -1,19 +1,33 @@ package contract import ( + "context" + + "github.com/ipfs/go-cid" + + "testing" + + "github.com/filecoin-project/go-state-types/big" "github.com/ipfs-force-community/go-fvm-sdk/sdk/sys/simulated" + "github.com/ipfs-force-community/go-fvm-sdk/sdk/types" "github.com/stretchr/testify/assert" - "testing" + + mh "github.com/multiformats/go-multihash" ) +func newSimulated() (*simulated.FvmSimulator, context.Context) { + callcontext := &types.InvocationContext{} + return simulated.CreateSimulateEnv(callcontext, big.NewInt(1), big.NewInt(1), big.NewInt(1)) +} + func TestSayHello(t *testing.T) { - simulated.Begin() + _, ctx := newSimulated() + testState := State{} - a := testState.SayHello() + a := testState.SayHello(ctx) assert.Equal(t, string(a), "1", "The two words should be the same.") - b := testState.SayHello() + b := testState.SayHello(ctx) assert.Equal(t, string(b), "2", "The two words should be the same.") - simulated.End() } diff --git a/examples/hellocontract/entry.go b/examples/hellocontract/entry.go index e7bb5fa..c4994e9 100644 --- a/examples/hellocontract/entry.go +++ b/examples/hellocontract/entry.go @@ -3,6 +3,7 @@ package main import ( "bytes" + "context" "fmt" cbor "github.com/filecoin-project/go-state-types/cbor" @@ -31,9 +32,10 @@ func main() {} // //go:export invoke func Invoke(blockId uint32) uint32 { - method, err := sdk.MethodNumber() + ctx := context.Background() + method, err := sdk.MethodNumber(ctx) if err != nil { - sdk.Abort(ferrors.USR_ILLEGAL_STATE, "unable to get method number") + sdk.Abort(ctx, ferrors.USR_ILLEGAL_STATE, "unable to get method number") } var callResult cbor.Marshaler @@ -41,33 +43,33 @@ func Invoke(blockId uint32) uint32 { switch method { case 1: // Constuctor - err = contract.Constructor() + err = contract.Constructor(ctx) callResult = typegen.CborBool(true) case 2: // no params no error but have return value state := new(contract.State) - sdk.LoadState(state) - callResult = state.SayHello() + sdk.LoadState(ctx, state) + callResult = state.SayHello(ctx) default: - sdk.Abort(ferrors.USR_ILLEGAL_STATE, "unsupport method") + sdk.Abort(ctx, ferrors.USR_ILLEGAL_STATE, "unsupport method") } if err != nil { - sdk.Abort(ferrors.USR_ILLEGAL_STATE, fmt.Sprintf("call error %s", err)) + sdk.Abort(ctx, ferrors.USR_ILLEGAL_STATE, fmt.Sprintf("call error %s", err)) } if !sdk.IsNil(callResult) { buf := bytes.NewBufferString("") err = callResult.MarshalCBOR(buf) if err != nil { - sdk.Abort(ferrors.USR_ILLEGAL_STATE, fmt.Sprintf("marshal resp fail %s", err)) + sdk.Abort(ctx, ferrors.USR_ILLEGAL_STATE, fmt.Sprintf("marshal resp fail %s", err)) } - id, err := sdk.PutBlock(sdkTypes.DAGCbor, buf.Bytes()) + id, err := sdk.PutBlock(ctx, sdkTypes.DAGCbor, buf.Bytes()) if err != nil { - sdk.Abort(ferrors.USR_ILLEGAL_STATE, fmt.Sprintf("failed to store return value: %v", err)) + sdk.Abort(ctx, ferrors.USR_ILLEGAL_STATE, fmt.Sprintf("failed to store return value: %v", err)) } return id } else { diff --git a/examples/hellocontract/gen/go.sum b/examples/hellocontract/gen/go.sum index 589a28a..36e0f5b 100644 --- a/examples/hellocontract/gen/go.sum +++ b/examples/hellocontract/gen/go.sum @@ -1624,6 +1624,8 @@ github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1 github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c/go.mod h1:hzIxponao9Kjc7aWznkXaL4U4TWaDSs8zcsY4Ka08nM= github.com/twitchyliquid64/golang-asm v0.15.0/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= +github.com/twmb/murmur3 v1.1.6 h1:mqrRot1BRxm+Yct+vavLMou2/iJt0tNVTTC0QoIjaZg= +github.com/twmb/murmur3 v1.1.6/go.mod h1:Qq/R7NUyOfr65zD+6Q5IHKsJLwP7exErjN6lyyq3OSQ= github.com/uber/jaeger-client-go v2.15.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= github.com/uber/jaeger-client-go v2.23.1+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= github.com/uber/jaeger-client-go v2.25.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= diff --git a/examples/hellocontract/go.sum b/examples/hellocontract/go.sum index f77fdd8..aa34dc0 100644 --- a/examples/hellocontract/go.sum +++ b/examples/hellocontract/go.sum @@ -1624,6 +1624,8 @@ github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1 github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c/go.mod h1:hzIxponao9Kjc7aWznkXaL4U4TWaDSs8zcsY4Ka08nM= github.com/twitchyliquid64/golang-asm v0.15.0/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= +github.com/twmb/murmur3 v1.1.6 h1:mqrRot1BRxm+Yct+vavLMou2/iJt0tNVTTC0QoIjaZg= +github.com/twmb/murmur3 v1.1.6/go.mod h1:Qq/R7NUyOfr65zD+6Q5IHKsJLwP7exErjN6lyyq3OSQ= github.com/uber/jaeger-client-go v2.15.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= github.com/uber/jaeger-client-go v2.23.1+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= github.com/uber/jaeger-client-go v2.25.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= diff --git a/gen/entry_gen.go b/gen/entry_gen.go index 95fa08b..f0c626f 100644 --- a/gen/entry_gen.go +++ b/gen/entry_gen.go @@ -84,6 +84,10 @@ func formateAndWriteCode(code []byte, output string) error { return f.Close() } +func isContext(r reflect.Type) bool { + return r.PkgPath() == "context" && r.Name() == "Context" +} + func getEntryPackageMeta(pkg string, stateT reflect.Type) (*entryMeta, error) { if stateT.Kind() == reflect.Ptr { stateT = stateT.Elem() @@ -114,17 +118,36 @@ func getEntryPackageMeta(pkg string, stateT reflect.Type) (*entryMeta, error) { method.MethodNum = sortedFunc.method_num // functionT := function.Type - if functionT.NumIn() > 1 { + if functionT.NumIn() > 0 { + isCtx := isContext(functionT.In(0)) + if isCtx == true { + method.HasContext = true + } + } + if (method.HasContext == false && functionT.NumIn() > 1) || (method.HasContext == true && functionT.NumIn() > 2) { return nil, fmt.Errorf("func %s can not have params more than 1", method.FuncName) } - if functionT.NumIn() == 1 { - if !functionT.In(0).AssignableTo(unMarshallerT) { - return nil, fmt.Errorf("func %s return value at index 1 must be error", method.FuncName) + if (method.HasContext == false && functionT.NumIn() == 1) || (method.HasContext == true && functionT.NumIn() == 2) { + if method.HasContext == true && functionT.NumIn() == 2 { + if !functionT.In(1).AssignableTo(unMarshallerT) { + return nil, fmt.Errorf("func %s return value at index 1 must be error", method.FuncName) + } + method.HasParam = true + method.ParamsType = functionT.In(1) + hasParam = true + typesToImport = append(typesToImport, functionT.In(1)) + + } else { + + if !functionT.In(0).AssignableTo(unMarshallerT) { + return nil, fmt.Errorf("func %s return value at index 1 must be error", method.FuncName) + } + + method.HasParam = true + method.ParamsType = functionT.In(0) + hasParam = true + typesToImport = append(typesToImport, functionT.In(0)) } - method.HasParam = true - method.ParamsType = functionT.In(0) - hasParam = true - typesToImport = append(typesToImport, functionT.In(0)) } if functionT.NumOut() > 2 { @@ -316,14 +339,15 @@ type entryMeta struct { } type methodMap struct { - StateName string - MethodNum int - FuncT reflect.Value - PkgName string - FuncName string - HasError bool - HasParam bool - HasReturn bool + StateName string + MethodNum int + FuncT reflect.Value + PkgName string + FuncName string + HasError bool + HasParam bool + HasReturn bool + HasContext bool ParamsType reflect.Type ParamsTypeName string @@ -357,9 +381,10 @@ func main() {} // //go:export invoke func Invoke(blockId uint32) uint32 { - method, err := sdk.MethodNumber() + ctx:=context.Background() + method, err := sdk.MethodNumber(ctx) if err != nil { - sdk.Abort(ferrors.USR_ILLEGAL_STATE, "unable to get method number") + sdk.Abort(ctx,ferrors.USR_ILLEGAL_STATE, "unable to get method number") } var callResult cbor.Marshaler @@ -367,51 +392,51 @@ func Invoke(blockId uint32) uint32 { switch method { {{range .Methods}}case {{.MethodNum}}: {{if eq .MethodNum 1}} // Constuctor - {{if .HasParam}}raw, err = sdk.ParamsRaw(blockId) + {{if .HasParam}}raw, err = sdk.ParamsRaw(ctx,blockId) if err != nil { - sdk.Abort(ferrors.USR_ILLEGAL_STATE, "unable to read params raw") + sdk.Abort(ctx,ferrors.USR_ILLEGAL_STATE, "unable to read params raw") } var req {{trimPrefix .ParamsTypeName "*"}} err = req.UnmarshalCBOR(bytes.NewReader(raw.Raw)) if err != nil { - sdk.Abort(ferrors.USR_ILLEGAL_STATE, "unable to unmarshal params raw") + sdk.Abort(ctx,ferrors.USR_ILLEGAL_STATE, "unable to unmarshal params raw") } - err = {{.PkgName}}.{{.FuncName}}(&req) + err = {{.PkgName}}.{{.FuncName}}({{if .HasContext}} ctx, {{end}}&req) callResult = typegen.CborBool(true) - {{else}}err = {{.PkgName}}.{{.FuncName}}() + {{else}}err = {{.PkgName}}.{{.FuncName}}({{if .HasContext}} ctx {{end}}) callResult = typegen.CborBool(true) {{end}} {{else}} - {{if .HasParam}}raw, err = sdk.ParamsRaw(blockId) + {{if .HasParam}}raw, err = sdk.ParamsRaw(ctx,blockId) if err != nil { - sdk.Abort(ferrors.USR_ILLEGAL_STATE, "unable to read params raw") + sdk.Abort(ctx,ferrors.USR_ILLEGAL_STATE, "unable to read params raw") } var req {{trimPrefix .ParamsTypeName "*"}} err = req.UnmarshalCBOR(bytes.NewReader(raw.Raw)) if err != nil { - sdk.Abort(ferrors.USR_ILLEGAL_STATE, "unable to unmarshal params raw") + sdk.Abort(ctx,ferrors.USR_ILLEGAL_STATE, "unable to unmarshal params raw") } {{if .HasError}} {{if .HasReturn}} // have params/return/error state := new({{.StateName}}) - sdk.LoadState(state) - callResult, err = state.{{.FuncName}}(&req) + sdk.LoadState(ctx,state) + callResult, err = state.{{.FuncName}}({{if .HasContext}} ctx, {{end}}&req) {{else}} // have params/error but no return val state := new({{.StateName}}) - sdk.LoadState(state) - if err = state.{{.FuncName}}(&req); err == nil { + sdk.LoadState(ctx,state) + if err = state.{{.FuncName}}({{if .HasContext}} ctx, {{end}}&req); err == nil { callResult = typegen.CborBool(true) } {{end}} {{else}} {{if .HasReturn}}// have params/return but no error state := new({{.StateName}}) - sdk.LoadState(state) - callResult = state.{{.FuncName}}(&req) + sdk.LoadState(ctx,state) + callResult = state.{{.FuncName}}({{if .HasContext}} ctx, {{end}}&req) {{else}}//have params but no return value and error state := new({{.StateName}}) - sdk.LoadState(state) - state.{{.FuncName}}(&req) + sdk.LoadState(ctx,state) + state.{{.FuncName}}({{if .HasContext}} ctx, {{end}}&req) callResult = = typegen.CborBool(true) {{end}} {{end}} @@ -419,24 +444,24 @@ func Invoke(blockId uint32) uint32 { {{if .HasError}} {{if .HasReturn}} // no params but return value/error state := new({{.StateName}}) - sdk.LoadState(state) - callResult, err = state.{{.FuncName}}() + sdk.LoadState(ctx,state) + callResult, err = state.{{.FuncName}}({{if .HasContext}} ctx {{end}}) {{else}} // no params/return value but return error state := new({{.StateName}}) - sdk.LoadState(state) - if err = state.{{.FuncName}}(); err == nil { + sdk.LoadState(ctx,state) + if err = state.{{.FuncName}}({{if .HasContext}} ctx {{end}}); err == nil { callResult = = typegen.CborBool(true) } {{end}} {{else}} {{if .HasReturn}} // no params no error but have return value state := new({{.StateName}}) - sdk.LoadState(state) - callResult = state.{{.FuncName}}() + sdk.LoadState(ctx,state) + callResult = state.{{.FuncName}}({{if .HasContext}} ctx {{end}}) {{else}} // no params/return value/error state := new({{.StateName}}) - sdk.LoadState(state) - state.{{.FuncName}}() + sdk.LoadState(ctx,state) + state.{{.FuncName}}({{if .HasContext}} ctx {{end}}) callResult = = typegen.CborBool(true) {{end}} {{end}} @@ -444,22 +469,22 @@ func Invoke(blockId uint32) uint32 { {{end}} {{end}} default: - sdk.Abort(ferrors.USR_ILLEGAL_STATE, "unsupport method") + sdk.Abort(ctx,ferrors.USR_ILLEGAL_STATE, "unsupport method") } if err != nil { - sdk.Abort(ferrors.USR_ILLEGAL_STATE, fmt.Sprintf("call error %s", err)) + sdk.Abort(ctx,ferrors.USR_ILLEGAL_STATE, fmt.Sprintf("call error %s", err)) } if !sdk.IsNil(callResult) { buf := bytes.NewBufferString("") err = callResult.MarshalCBOR(buf) if err != nil { - sdk.Abort(ferrors.USR_ILLEGAL_STATE, fmt.Sprintf("marshal resp fail %s", err)) + sdk.Abort(ctx,ferrors.USR_ILLEGAL_STATE, fmt.Sprintf("marshal resp fail %s", err)) } - id, err := sdk.PutBlock(sdkTypes.DAGCbor, buf.Bytes()) + id, err := sdk.PutBlock(ctx,sdkTypes.DAGCbor, buf.Bytes()) if err != nil { - sdk.Abort(ferrors.USR_ILLEGAL_STATE, fmt.Sprintf("failed to store return value: %v", err)) + sdk.Abort(ctx,ferrors.USR_ILLEGAL_STATE, fmt.Sprintf("failed to store return value: %v", err)) } return id } else { diff --git a/go.mod b/go.mod index 872beb8..c13ff13 100644 --- a/go.mod +++ b/go.mod @@ -9,12 +9,13 @@ require ( github.com/filecoin-project/go-state-types v0.1.12-alpha github.com/filecoin-project/specs-actors/v2 v2.3.5-0.20210114162132-5b58b773f4fb github.com/filecoin-project/specs-actors/v7 v7.0.0 - github.com/google/uuid v1.3.0 + github.com/google/uuid v1.1.1 github.com/ipfs/go-cid v0.2.0 github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 github.com/minio/sha256-simd v1.0.0 github.com/multiformats/go-multihash v0.0.15 github.com/stretchr/testify v1.7.0 + github.com/twmb/murmur3 v1.1.6 github.com/whyrusleeping/cbor-gen v0.0.0-20220323183124-98fa8256a799 golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f ) diff --git a/go.sum b/go.sum index 990b985..e36a755 100644 --- a/go.sum +++ b/go.sum @@ -79,9 +79,8 @@ github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gopherjs/gopherjs v0.0.0-20190430165422-3e4dfb77656c/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gopherjs/gopherjs v0.0.0-20190812055157-5d271430af9f h1:KMlcu9X58lhTA/KrfX8Bi1LQSO4pzoVjTiL3h4Jk+Zk= @@ -304,6 +303,8 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= github.com/tj/go-spin v1.1.0 h1:lhdWZsvImxvZ3q1C5OIB7d72DuOwP4O2NdBg9PyzNds= github.com/tj/go-spin v1.1.0/go.mod h1:Mg1mzmePZm4dva8Qz60H2lHwmJ2loum4VIrLgVnKwh4= +github.com/twmb/murmur3 v1.1.6 h1:mqrRot1BRxm+Yct+vavLMou2/iJt0tNVTTC0QoIjaZg= +github.com/twmb/murmur3 v1.1.6/go.mod h1:Qq/R7NUyOfr65zD+6Q5IHKsJLwP7exErjN6lyyq3OSQ= github.com/warpfork/go-wish v0.0.0-20190328234359-8b3e70f8e830/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw= github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f/go.mod h1:p9UJB6dDgdPgMJZs7UjUOdulKyRr9fqkS+6JKAInPy8= github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1/go.mod h1:8UvriyWtv5Q5EOgjHaSseUEdkQfvwFv1I/In/O2M9gc= diff --git a/sdk/abort.go b/sdk/abort.go index 6b9a181..020201a 100644 --- a/sdk/abort.go +++ b/sdk/abort.go @@ -1,12 +1,14 @@ package sdk import ( + "context" + "github.com/ipfs-force-community/go-fvm-sdk/sdk/ferrors" "github.com/ipfs-force-community/go-fvm-sdk/sdk/sys" ) // Abort abort execution -func Abort(code ferrors.ExitCode, msg string) { - sys.Abort(uint32(code), msg) +func Abort(ctx context.Context, code ferrors.ExitCode, msg string) { + sys.Abort(ctx, uint32(code), msg) } diff --git a/sdk/actor.go b/sdk/actor.go index b5f39b8..0d41f25 100644 --- a/sdk/actor.go +++ b/sdk/actor.go @@ -2,6 +2,8 @@ package sdk import ( + "context" + address "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" "github.com/ipfs-force-community/go-fvm-sdk/sdk/sys" @@ -12,36 +14,36 @@ import ( // ResolveAddress resolves the ID address of an actor. Returns `None` if the address cannot be resolved. // Successfully resolving an address doesn't necessarily mean the actor exists (e.g., if the // addresss was already an actor ID). -func ResolveAddress(addr address.Address) (abi.ActorID, error) { - return sys.ResolveAddress(addr) +func ResolveAddress(ctx context.Context, addr address.Address) (abi.ActorID, error) { + return sys.ResolveAddress(ctx, addr) } // GetActorCodeCid look up the code ID at an actor address. Returns `None` if the actor cannot be found. -func GetActorCodeCid(addr address.Address) (*cid.Cid, error) { - return sys.GetActorCodeCid(addr) +func GetActorCodeCid(ctx context.Context, addr address.Address) (*cid.Cid, error) { + return sys.GetActorCodeCid(ctx, addr) } // NewActorAddress generates a new actor address for an actor deployed // by the calling actor. -func NewActorAddress() (address.Address, error) { - return sys.NewActorAddress() +func NewActorAddress(ctx context.Context) (address.Address, error) { + return sys.NewActorAddress(ctx) } // CreateActor Creates a new actor of the specified type in the state tree, under // the provided address. // TODO this syscall will change to calculate the address internally. -func CreateActor(actorID abi.ActorID, codeCid cid.Cid) error { - return sys.CreateActor(actorID, codeCid) +func CreateActor(ctx context.Context, actorID abi.ActorID, codeCid cid.Cid) error { + return sys.CreateActor(ctx, actorID, codeCid) } // ResolveBuiltinActorType determines whether the supplied CodeCID belongs to a built-in actor type, // and to which. -func ResolveBuiltinActorType(codeCid cid.Cid) (types.ActorType, error) { - return sys.ResolveBuiltinActorType(codeCid) +func ResolveBuiltinActorType(ctx context.Context, codeCid cid.Cid) (types.ActorType, error) { + return sys.ResolveBuiltinActorType(ctx, codeCid) } // GetCodeCidForType Returns the CodeCID for a built-in actor type. Aborts with IllegalArgument // if the supplied type is invalid. -func GetCodeCidForType(actorT types.ActorType) (cid.Cid, error) { - return sys.GetCodeCidForType(actorT) +func GetCodeCidForType(ctx context.Context, actorT types.ActorType) (cid.Cid, error) { + return sys.GetCodeCidForType(ctx, actorT) } diff --git a/sdk/adt/map.go b/sdk/adt/map.go index 7d4d52b..72a5849 100644 --- a/sdk/adt/map.go +++ b/sdk/adt/map.go @@ -6,10 +6,10 @@ import ( "github.com/minio/sha256-simd" - hamt "github.com/filecoin-project/go-hamt-ipld/v3" + "github.com/filecoin-project/go-hamt-ipld/v3" "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/cbor" - cid "github.com/ipfs/go-cid" + "github.com/ipfs/go-cid" cbg "github.com/whyrusleeping/cbor-gen" ) diff --git a/sdk/adt/store.go b/sdk/adt/store.go index 837d046..87146fc 100644 --- a/sdk/adt/store.go +++ b/sdk/adt/store.go @@ -9,7 +9,7 @@ import ( "github.com/filecoin-project/go-state-types/cbor" "github.com/ipfs-force-community/go-fvm-sdk/sdk" - cid "github.com/ipfs/go-cid" + "github.com/ipfs/go-cid" ) // IpldStore wraps a Blockstore and provides an interface for storing and retrieving CBOR encoded data. @@ -45,8 +45,8 @@ var _ Store = &fvmStore{} func (r fvmStore) Context() context.Context { return r.ctx } -func (r fvmStore) Get(_ context.Context, c cid.Cid, out interface{}) error { - data, err := sdk.Get(c) +func (r fvmStore) Get(ctx context.Context, c cid.Cid, out interface{}) error { + data, err := sdk.Get(ctx, c) if err != nil { return err } @@ -57,7 +57,7 @@ func (r fvmStore) Get(_ context.Context, c cid.Cid, out interface{}) error { return unmarshalableObj.UnmarshalCBOR(bytes.NewBuffer(data)) } -func (r fvmStore) Put(_ context.Context, in interface{}) (cid.Cid, error) { +func (r fvmStore) Put(ctx context.Context, in interface{}) (cid.Cid, error) { marshalableObj, ok := in.(cbor.Marshaler) if !ok { return cid.Undef, fmt.Errorf("ipld store put method must be marshalable") @@ -67,5 +67,5 @@ func (r fvmStore) Put(_ context.Context, in interface{}) (cid.Cid, error) { if err != nil { return cid.Undef, fmt.Errorf("marshal object fail") } - return sdk.Put(types.BLAKE2B256, types.BLAKE2BLEN, types.DAGCbor, buf.Bytes()) + return sdk.Put(ctx, types.BLAKE2B256, types.BLAKE2BLEN, types.DAGCbor, buf.Bytes()) } diff --git a/sdk/cases/abort.go b/sdk/cases/abort.go index 70b67ba..526ceac 100644 --- a/sdk/cases/abort.go +++ b/sdk/cases/abort.go @@ -1,6 +1,8 @@ package main import ( + "context" + "github.com/ipfs-force-community/go-fvm-sdk/sdk" "github.com/ipfs-force-community/go-fvm-sdk/sdk/ferrors" ) @@ -9,15 +11,16 @@ func main() {} //nolint //go:export invoke func Invoke(_ uint32) uint32 { //nolint - method_num, err := sdk.MethodNumber() + ctx := context.Background() + method_num, err := sdk.MethodNumber(ctx) if err != nil { - sdk.Abort(ferrors.USR_ILLEGAL_STATE, "unable to get method number") + sdk.Abort(ctx, ferrors.USR_ILLEGAL_STATE, "unable to get method number") } switch method_num { case 1: - sdk.Abort(ferrors.USR_ILLEGAL_ARGUMENT, "test_abort USR_ILLEGAL_ARGUMENT") + sdk.Abort(ctx, ferrors.USR_ILLEGAL_ARGUMENT, "test_abort USR_ILLEGAL_ARGUMENT") case 2: - sdk.Abort(ferrors.SYS_SENDER_STATE_INVALID, "test_abort SYS_SENDER_STATE_INVALID") + sdk.Abort(ctx, ferrors.SYS_SENDER_STATE_INVALID, "test_abort SYS_SENDER_STATE_INVALID") } return 0 } diff --git a/sdk/cases/debug.go b/sdk/cases/debug.go index 99b1e21..6c09dad 100644 --- a/sdk/cases/debug.go +++ b/sdk/cases/debug.go @@ -1,6 +1,8 @@ package main import ( + "context" + "github.com/ipfs-force-community/go-fvm-sdk/sdk" "github.com/ipfs-force-community/go-fvm-sdk/sdk/testing" "github.com/stretchr/testify/assert" @@ -13,13 +15,14 @@ func Invoke(_ uint32) uint32 { //nolint t := testing.NewTestingT() defer t.CheckResult() + ctx := context.Background() logger, err := sdk.NewLogger() assert.Nil(t, err, "create debug logger %v", err) - enabled := logger.Enabled() + enabled := logger.Enabled(ctx) assert.Equal(t, true, enabled) - err = logger.Log("") + err = logger.Log(ctx, "") assert.Nil(t, err) return 0 diff --git a/sdk/cases/gas.go b/sdk/cases/gas.go index 5100990..5fc498d 100644 --- a/sdk/cases/gas.go +++ b/sdk/cases/gas.go @@ -1,6 +1,8 @@ package main import ( + "context" + "github.com/ipfs-force-community/go-fvm-sdk/sdk" "github.com/ipfs-force-community/go-fvm-sdk/sdk/testing" "github.com/stretchr/testify/assert" @@ -12,8 +14,8 @@ func main() {} //nolint func Invoke(_ uint32) uint32 { //nolint t := testing.NewTestingT() defer t.CheckResult() - - err := sdk.Charge("OnChainMessage", 38863) + ctx := context.Background() + err := sdk.Charge(ctx, "OnChainMessage", 38863) assert.Nil(t, err, "charge gas %v", err) return 0 diff --git a/sdk/cases/ipld.go b/sdk/cases/ipld.go index fb12249..812a2dd 100644 --- a/sdk/cases/ipld.go +++ b/sdk/cases/ipld.go @@ -1,6 +1,8 @@ package main import ( + "context" + "github.com/ipfs-force-community/go-fvm-sdk/sdk" "github.com/ipfs-force-community/go-fvm-sdk/sdk/sys" @@ -17,21 +19,22 @@ func Invoke(_ uint32) uint32 { //nolint t := testing.NewTestingT() defer t.CheckResult() + ctx := context.Background() data := []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12} //create - stCid, err := sdk.Put(types.BLAKE2B256, types.BLAKE2BLEN, types.DAGCbor, data) + stCid, err := sdk.Put(ctx, types.BLAKE2B256, types.BLAKE2BLEN, types.DAGCbor, data) assert.Nil(t, err, "unable to put block %v", err) //cid assert assert.Equal(t, stCid.String(), "bafy2bzacedpfdhph46exiifylwgpd5dwukzg763u5burfjpcesqhblyt4k5wg") //open - block, err := sdk.Get(stCid) + block, err := sdk.Get(ctx, stCid) assert.Nil(t, err, "unable to get block %v", err) //state - blockId, err := sdk.PutBlock(types.DAGCbor, data) + blockId, err := sdk.PutBlock(ctx, types.DAGCbor, data) assert.Nil(t, err, "unable to putblock %v", err) - state, err := sys.Stat(blockId) + state, err := sys.Stat(ctx, blockId) assert.Nil(t, err, "unable to inspect state for block %d reason %v", blockId, err) assert.Equal(t, state.Size, uint32(len(data))) assert.Equal(t, state.Codec, types.DAGCbor) diff --git a/sdk/cases/message.go b/sdk/cases/message.go index e4c7eeb..8f2f363 100644 --- a/sdk/cases/message.go +++ b/sdk/cases/message.go @@ -1,6 +1,8 @@ package main import ( + "context" + "github.com/ipfs-force-community/go-fvm-sdk/sdk" "github.com/ipfs-force-community/go-fvm-sdk/sdk/testing" "github.com/stretchr/testify/assert" @@ -12,20 +14,20 @@ func main() {} //nolint func Invoke(_ uint32) uint32 { //nolint t := testing.NewTestingT() defer t.CheckResult() - - _, err := sdk.Caller() + ctx := context.Background() + _, err := sdk.Caller(ctx) assert.Nil(t, err) // assert.Equal(t, caller, 1) todo unable to verify caller, its random value in tester - receiver, err := sdk.Receiver() + receiver, err := sdk.Receiver(ctx) assert.Nil(t, err) assert.Equal(t, 10000, int(receiver)) - method_num, err := sdk.MethodNumber() + method_num, err := sdk.MethodNumber(ctx) assert.Nil(t, err) assert.Equal(t, 1, int(method_num)) - valueRecieved, err := sdk.ValueReceived() + valueRecieved, err := sdk.ValueReceived(ctx) assert.Nil(t, err) assert.Equal(t, "10", valueRecieved.Big().String()) return 0 diff --git a/sdk/cases/network.go b/sdk/cases/network.go index c2981d9..9e391af 100644 --- a/sdk/cases/network.go +++ b/sdk/cases/network.go @@ -2,6 +2,8 @@ package main import ( + "context" + "github.com/ipfs-force-community/go-fvm-sdk/sdk" "github.com/ipfs-force-community/go-fvm-sdk/sdk/testing" "github.com/stretchr/testify/assert" @@ -13,20 +15,20 @@ func main() {} //nolint func Invoke(_ uint32) uint32 { //nolint t := testing.NewTestingT() defer t.CheckResult() - - epoch, err := sdk.CurrEpoch() + ctx := context.Background() + epoch, err := sdk.CurrEpoch(ctx) assert.Nil(t, err) assert.Equal(t, 0, int(epoch)) - ver, err := sdk.Version() + ver, err := sdk.Version(ctx) assert.Nil(t, err) assert.Equal(t, 15, int(ver)) - fee, err := sdk.BaseFee() + fee, err := sdk.BaseFee(ctx) assert.Nil(t, err) assert.Equal(t, "100", fee.Big().String()) - value, err := sdk.TotalFilCircSupply() + value, err := sdk.TotalFilCircSupply(ctx) assert.Nil(t, err) assert.Equal(t, "2000000000000000000000000000", value.Big().String()) return 0 diff --git a/sdk/cases/rand.go b/sdk/cases/rand.go index 6ac1dd0..f19d0d5 100644 --- a/sdk/cases/rand.go +++ b/sdk/cases/rand.go @@ -1,6 +1,8 @@ package main import ( + "context" + "github.com/filecoin-project/go-state-types/crypto" "github.com/ipfs-force-community/go-fvm-sdk/sdk" "github.com/ipfs-force-community/go-fvm-sdk/sdk/testing" @@ -14,12 +16,14 @@ func Invoke(_ uint32) uint32 { //nolint t := testing.NewTestingT() defer t.CheckResult() - randValue, err := sdk.GetChainRandomness(crypto.DomainSeparationTag_TicketProduction, 0, []byte{}) + ctx := context.Background() + + randValue, err := sdk.GetChainRandomness(ctx, crypto.DomainSeparationTag_TicketProduction, 0, []byte{}) assert.Nil(t, err, "get chain randomness %v", err) t.Infof("got chain randomness %v", randValue) assert.NotEmpty(t, randValue) - randValue, err = sdk.GetBeaconRandomness(crypto.DomainSeparationTag_SealRandomness, 0, []byte{}) + randValue, err = sdk.GetBeaconRandomness(ctx, crypto.DomainSeparationTag_SealRandomness, 0, []byte{}) assert.Nil(t, err, "get beacon randomness %v", err) t.Infof("got beacon randomness %v", randValue) assert.NotEmpty(t, randValue) diff --git a/sdk/cases/send.go b/sdk/cases/send.go index d7c1938..ab965d5 100644 --- a/sdk/cases/send.go +++ b/sdk/cases/send.go @@ -1,6 +1,8 @@ package main import ( + "context" + "github.com/filecoin-project/go-address" "github.com/ipfs-force-community/go-fvm-sdk/sdk" "github.com/ipfs-force-community/go-fvm-sdk/sdk/ferrors" @@ -16,20 +18,22 @@ func Invoke(_ uint32) uint32 { //nolint t := testing.NewTestingT() defer t.CheckResult() - methodsNum, err := sdk.MethodNumber() + ctx := context.Background() + + methodsNum, err := sdk.MethodNumber(ctx) if err != nil { - sdk.Abort(ferrors.USR_ILLEGAL_STATE, "unable to get method number") + sdk.Abort(ctx, ferrors.USR_ILLEGAL_STATE, "unable to get method number") } switch methodsNum { case 1: // actor does not exist: 128788 (6: resource not found) addr, _ := address.NewFromString("f0128788") - ret, err := sdk.Send(addr, 0, []byte{}, types.From64(1000)) + ret, err := sdk.Send(ctx, addr, 0, []byte{}, types.From64(1000)) assert.Nil(t, err, "send %v", err) assert.Equal(t, 0, int(ret.ExitCode)) case 2: addr, _ := address.NewFromString("f010000") - ret, err := sdk.Send(addr, 0, []byte{}, types.From64(1)) + ret, err := sdk.Send(ctx, addr, 0, []byte{}, types.From64(1)) assert.Nil(t, err, "send %v", err) assert.Equal(t, 0, int(ret.ExitCode)) assert.Equal(t, 0, int(ret.GasUsed)) @@ -37,7 +41,7 @@ func Invoke(_ uint32) uint32 { //nolint case 3: // sender does not have funds to transfer (balance 10, transfer 5000) (5: insufficient funds) addr, _ := address.NewFromString("f010000") - ret, err := sdk.Send(addr, 0, []byte{}, types.From64(5000)) + ret, err := sdk.Send(ctx, addr, 0, []byte{}, types.From64(5000)) assert.Nil(t, err, "send %v", err) assert.Equal(t, 0, int(ret.ExitCode)) } diff --git a/sdk/cases/sself.go b/sdk/cases/sself.go index 59be4d4..6f2c1a8 100644 --- a/sdk/cases/sself.go +++ b/sdk/cases/sself.go @@ -1,6 +1,8 @@ package main import ( + "context" + "github.com/filecoin-project/go-address" "github.com/ipfs-force-community/go-fvm-sdk/sdk" "github.com/stretchr/testify/assert" @@ -18,36 +20,37 @@ func Invoke(_ uint32) uint32 { //nolint t := testing.NewTestingT() defer t.CheckResult() + ctx := context.Background() originData := []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12} //set data - stCid, err := sdk.Put(0xb220, 32, types.DAGCbor, originData) + stCid, err := sdk.Put(ctx, 0xb220, 32, types.DAGCbor, originData) assert.Nil(t, err) //set root - err = sdk.SetRoot(stCid) + err = sdk.SetRoot(ctx, stCid) assert.Nil(t, err) //get root - root, err := sdk.Root() + root, err := sdk.Root(ctx) assert.Nil(t, err) //get data - data, err := sdk.Get(root) + data, err := sdk.Get(ctx, root) assert.Nil(t, err) assert.Equal(t, originData, data) //check balance - actorBalance := sdk.CurrentBalance() + actorBalance := sdk.CurrentBalance(ctx) assert.Nil(t, err) assert.Equal(t, "20", actorBalance.Big().String()) //destruct toAddr, err := address.NewFromString("f1dwyrbh74hr5nwqv2gjedjyvgphxxkffxug4rkkq") assert.Nil(t, err) - err = sdk.SelfDestruct(toAddr) + err = sdk.SelfDestruct(ctx, toAddr) assert.Nil(t, err) - _, err = sdk.Root() + _, err = sdk.Root(ctx) assert.NotNil(t, err) assert.Contains(t, err.Error(), "unable to create ipld") return 0 diff --git a/sdk/cases/test.json b/sdk/cases/test.json index 129db30..c2770ce 100644 --- a/sdk/cases/test.json +++ b/sdk/cases/test.json @@ -17,9 +17,38 @@ } ], "cases":[ - { - "name": "message_test", + "name": "abort_USR_ILLEGAL_ARGUMENT", + "binary": "abort.wasm", + "actor_balance": 0, + "send_value": 0, + "method_num": 1, + "params":"", + "expect_code": 16, + "expect_message": "test_abort USR_ILLEGAL_ARGUMENT" + }, + { + "name": "abort_SYS_SENDER_STATE_INVALID ", + "binary": "abort.wasm", + "actor_balance": 0, + "send_value": 0, + "params":"", + "method_num": 2, + "expect_code": 2, + "expect_message": "test_abort SYS_SENDER_STATE_INVALID" + }, + { + "name": "ipld_test ", + "binary": "ipld.wasm", + "actor_balance": 0, + "send_value": 0, + "params":"", + "method_num": 1, + "expect_code": 0, + "expect_message": "" + }, + { + "name": "message_test ", "binary": "message.wasm", "actor_balance": 0, "send_value": 10, @@ -27,6 +56,94 @@ "method_num": 1, "expect_code": 0, "expect_message": "" + }, + { + "name": "sself_test ", + "binary": "sself.wasm", + "actor_balance": 20, + "send_value": 0, + "params":"", + "method_num": 1, + "expect_code": 0, + "expect_message": "" + }, + { + "name": "network_test", + "binary": "network.wasm", + "actor_balance": 0, + "send_value": 0, + "params":"", + "method_num": 1, + "expect_code": 0, + "expect_message": "" + }, + { + "name": "gas_test", + "binary": "gas.wasm", + "actor_balance": 0, + "send_value": 0, + "params":"", + "method_num": 1, + "expect_code": 0, + "expect_message": "" + }, + { + "name": "debug_log_test", + "binary": "debug.wasm", + "actor_balance": 0, + "send_value": 0, + "params":"", + "method_num": 1, + "expect_code": 0, + "expect_message": "" + }, + { + "name": "send_test_SYS_ILLEGAL_INSTRUCTION(resource not found)", + "binary": "send.wasm", + "actor_balance": 10, + "send_value": 0, + "params":"", + "method_num": 1, + "expect_code": 4, + "expect_message": "wasm `unreachable` instruction executed" + }, + { + "name": "send_test", + "binary": "send.wasm", + "actor_balance": 10, + "send_value": 0, + "params":"", + "method_num": 2, + "expect_code": 0, + "expect_message": "" + }, + { + "name": "send_test_SYS_ILLEGAL_INSTRUCTION(insufficient funds)", + "binary": "send.wasm", + "actor_balance": 10, + "send_value": 0, + "params":"", + "method_num": 3, + "expect_code": 4, + "expect_message": "wasm `unreachable` instruction executed" + }, + { + "name": "adt_test", + "binary": "adt.wasm", + "actor_balance": 0, + "send_value": 0, + "method_num": 1, + "params":"", + "expect_code": 0 + }, + { + "name": "rand_test", + "binary": "rand.wasm", + "actor_balance": 0, + "send_value": 0, + "method_num": 1, + "params":"", + "expect_code": 0 } ] -} +} \ No newline at end of file diff --git a/sdk/crypto.go b/sdk/crypto.go index 4676d32..3e35ea2 100644 --- a/sdk/crypto.go +++ b/sdk/crypto.go @@ -1,6 +1,8 @@ package sdk import ( + "context" + address "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/crypto" @@ -13,34 +15,36 @@ import ( // VerifySignature verifies that a signature is valid for an address and plaintext. func VerifySignature( + ctx context.Context, signature *crypto.Signature, signer *address.Address, plainText []byte, ) (bool, error) { - return sys.VerifySignature(signature, signer, plainText) + return sys.VerifySignature(ctx, signature, signer, plainText) } // HashBlake2b hashes input data using blake2b with 256 bit output. -func HashBlake2b(data []byte) ([32]byte, error) { - return sys.HashBlake2b(data) +func HashBlake2b(ctx context.Context, data []byte) ([32]byte, error) { + return sys.HashBlake2b(ctx, data) } // ComputeUnsealedSectorCid computes an unsealed sector CID (CommD) from its constituent piece CIDs (CommPs) and sizes. func ComputeUnsealedSectorCid( + ctx context.Context, proofType abi.RegisteredSealProof, pieces []abi.PieceInfo, ) (cid.Cid, error) { - return sys.ComputeUnsealedSectorCid(proofType, pieces) + return sys.ComputeUnsealedSectorCid(ctx, proofType, pieces) } // VerifySeal verifies a sector seal proof. -func VerifySeal(info *proof.SealVerifyInfo) (bool, error) { - return sys.VerifySeal(info) +func VerifySeal(ctx context.Context, info *proof.SealVerifyInfo) (bool, error) { + return sys.VerifySeal(ctx, info) } // VerifyPost verifies a sector seal proof. -func VerifyPost(info *proof.WindowPoStVerifyInfo) (bool, error) { - return sys.VerifyPost(info) +func VerifyPost(ctx context.Context, info *proof.WindowPoStVerifyInfo) (bool, error) { + return sys.VerifyPost(ctx, info) } // VerifyConsensusFault verifies that two block headers provide proof of a consensus fault: @@ -54,24 +58,25 @@ func VerifyPost(info *proof.WindowPoStVerifyInfo) (bool, error) { // blocks in the parent of h2 (i.e. h2's grandparent). // Returns None and an error if the headers don't prove a fault. func VerifyConsensusFault( + ctx context.Context, h1 []byte, h2 []byte, extra []byte, ) (*runtime.ConsensusFault, error) { - return sys.VerifyConsensusFault(h1, h2, extra) + return sys.VerifyConsensusFault(ctx, h1, h2, extra) } // VerifyAggregateSeals verifies aggregate proof of replication of sectors -func VerifyAggregateSeals(info *types.AggregateSealVerifyProofAndInfos) (bool, error) { - return sys.VerifyAggregateSeals(info) +func VerifyAggregateSeals(ctx context.Context, info *types.AggregateSealVerifyProofAndInfos) (bool, error) { + return sys.VerifyAggregateSeals(ctx, info) } // VerifyReplicaUpdate verifies sector replica update -func VerifyReplicaUpdate(info *types.ReplicaUpdateInfo) (bool, error) { - return sys.VerifyReplicaUpdate(info) +func VerifyReplicaUpdate(ctx context.Context, info *types.ReplicaUpdateInfo) (bool, error) { + return sys.VerifyReplicaUpdate(ctx, info) } // BatchVerifySeals batch verifies seals -func BatchVerifySeals(sealVerifyInfos []proof.SealVerifyInfo) ([]bool, error) { - return sys.BatchVerifySeals(sealVerifyInfos) +func BatchVerifySeals(ctx context.Context, sealVerifyInfos []proof.SealVerifyInfo) ([]bool, error) { + return sys.BatchVerifySeals(ctx, sealVerifyInfos) } diff --git a/sdk/debug.go b/sdk/debug.go index 8e41dac..1a5bc5b 100644 --- a/sdk/debug.go +++ b/sdk/debug.go @@ -1,6 +1,7 @@ package sdk import ( + "context" "fmt" "github.com/ipfs-force-community/go-fvm-sdk/sdk/sys" @@ -8,42 +9,42 @@ import ( // Logger is a debug-only logger that uses the FVM syscalls. type Logger interface { - Enabled() bool - Log(...interface{}) error - Logf(format string, a ...interface{}) error + Enabled(ctx context.Context) bool + Log(ctx context.Context, args ...interface{}) error + Logf(ctx context.Context, format string, a ...interface{}) error } var _ Logger = (*logger)(nil) // NewLogger create a logging if debugging is enabled. func NewLogger() (Logger, error) { - debugEnabled, err := sys.Enabled() - if err != nil { - return nil, err - } - return &logger{ - enable: debugEnabled, - }, nil + return &logger{}, nil } type logger struct { - enable bool + enable *bool } -func (l *logger) Enabled() bool { - return l.enable +// inline +func (l *logger) Enabled(ctx context.Context) bool { + if l.enable != nil { + return *l.enable + } + logEnable, _ := sys.Enabled(ctx) + l.enable = &logEnable + return logEnable } -func (l *logger) Log(a ...interface{}) error { - if l.enable { - return sys.Log(fmt.Sprint(a...)) +func (l *logger) Log(ctx context.Context, a ...interface{}) error { + if l.Enabled(ctx) { + return sys.Log(ctx, fmt.Sprint(a...)) } return nil } -func (l *logger) Logf(format string, a ...interface{}) error { - if l.enable { - return sys.Log(fmt.Sprintf(format, a...)) +func (l *logger) Logf(ctx context.Context, format string, a ...interface{}) error { + if l.Enabled(ctx) { + return sys.Log(ctx, fmt.Sprintf(format, a...)) } return nil } diff --git a/sdk/gas.go b/sdk/gas.go index 04fe1d1..6d0f126 100644 --- a/sdk/gas.go +++ b/sdk/gas.go @@ -1,8 +1,12 @@ package sdk -import "github.com/ipfs-force-community/go-fvm-sdk/sdk/sys" +import ( + "context" + + "github.com/ipfs-force-community/go-fvm-sdk/sdk/sys" +) // Charge charges the gas -func Charge(name string, compute uint64) error { - return sys.Charge(name, compute) +func Charge(ctx context.Context, name string, compute uint64) error { + return sys.Charge(ctx, name, compute) } diff --git a/sdk/ipld.go b/sdk/ipld.go index e143cbb..de58c5b 100644 --- a/sdk/ipld.go +++ b/sdk/ipld.go @@ -1,6 +1,8 @@ package sdk import ( + "context" + "github.com/ipfs-force-community/go-fvm-sdk/sdk/sys" "github.com/ipfs-force-community/go-fvm-sdk/sdk/types" "github.com/ipfs/go-cid" @@ -8,15 +10,15 @@ import ( // Put store a block. The block will only be persisted in the state-tree if the CID is "linked in" to // the actor's state-tree before the end of the current invocation. -func Put(mhCode uint64, mhSize uint32, codec uint64, data []byte) (cid.Cid, error) { - id, err := sys.Create(codec, data) +func Put(ctx context.Context, mhCode uint64, mhSize uint32, codec uint64, data []byte) (cid.Cid, error) { + id, err := sys.Create(ctx, codec, data) if err != nil { return cid.Undef, err } // I really hate this CID interface. Why can't I just have bytes? buf := [types.MaxCidLen]byte{} - return sys.BlockLink(id, mhCode, mhSize, buf[:]) + return sys.BlockLink(ctx, id, mhCode, mhSize, buf[:]) } // Get get a block. It's valid to call this on: @@ -26,19 +28,19 @@ func Put(mhCode uint64, mhSize uint32, codec uint64, data []byte) (cid.Cid, erro // 3. Any children of a blocks returned by prior calls to `get`... // // ...during the current invocation. -func Get(cid cid.Cid) ([]byte, error) { +func Get(ctx context.Context, cid cid.Cid) ([]byte, error) { // TODO: Check length of cid? - result, err := sys.Open(cid) + result, err := sys.Open(ctx, cid) if err != nil { return nil, err } - return GetBlock(result.ID, &result.Size) + return GetBlock(ctx, result.ID, &result.Size) } // GetBlock gets the data of the block referenced by BlockId. If the caller knows the size, this function // will read the block in a single syscall. Otherwise, any block over 1KiB will take two syscalls. -func GetBlock(id types.BlockID, size *uint32) ([]byte, error) { +func GetBlock(ctx context.Context, id types.BlockID, size *uint32) ([]byte, error) { if id == types.UNIT { return []byte{}, nil } @@ -51,13 +53,13 @@ func GetBlock(id types.BlockID, size *uint32) ([]byte, error) { } // block := make([]byte, size1) - block, remaining, err := sys.Read(id, 0, size1) //only set len and slice + block, remaining, err := sys.Read(ctx, id, 0, size1) //only set len and slice if err != nil { return nil, err } if remaining > 0 { //more than 1KiB - sencondPart, remaining, err := sys.Read(id, uint32(len(block)), remaining) //only set len and slice + sencondPart, remaining, err := sys.Read(ctx, id, uint32(len(block)), remaining) //only set len and slice if err != nil { return nil, err } @@ -70,6 +72,6 @@ func GetBlock(id types.BlockID, size *uint32) ([]byte, error) { } // PutBlock writes the supplied block and returns the BlockId. -func PutBlock(codec types.Codec, data []byte) (types.BlockID, error) { - return sys.Create(codec, data) +func PutBlock(ctx context.Context, codec types.Codec, data []byte) (types.BlockID, error) { + return sys.Create(ctx, codec, data) } diff --git a/sdk/message.go b/sdk/message.go index 8de28de..628e491 100644 --- a/sdk/message.go +++ b/sdk/message.go @@ -1,6 +1,8 @@ package sdk import ( + "context" + "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/network" "github.com/ipfs-force-community/go-fvm-sdk/sdk/types" @@ -12,10 +14,10 @@ import ( var InvocationCtx *types.InvocationContext // Caller get caller, from address of message -func Caller() (abi.ActorID, error) { +func Caller(ctx context.Context) (abi.ActorID, error) { if InvocationCtx == nil { var err error - InvocationCtx, err = sys.VMContext() + InvocationCtx, err = sys.VMContext(ctx) if err != nil { return 0, err } @@ -24,10 +26,10 @@ func Caller() (abi.ActorID, error) { } // Receiver get recevier, to address of message -func Receiver() (abi.ActorID, error) { +func Receiver(ctx context.Context) (abi.ActorID, error) { if InvocationCtx == nil { var err error - InvocationCtx, err = sys.VMContext() + InvocationCtx, err = sys.VMContext(ctx) if err != nil { return 0, err } @@ -36,10 +38,10 @@ func Receiver() (abi.ActorID, error) { } // MethodNumber method number -func MethodNumber() (abi.MethodNum, error) { +func MethodNumber(ctx context.Context) (abi.MethodNum, error) { if InvocationCtx == nil { var err error - InvocationCtx, err = sys.VMContext() + InvocationCtx, err = sys.VMContext(ctx) if err != nil { return 0, err } @@ -48,10 +50,10 @@ func MethodNumber() (abi.MethodNum, error) { } // ValueReceived the amount was transferred in message -func ValueReceived() (*types.TokenAmount, error) { +func ValueReceived(ctx context.Context) (*types.TokenAmount, error) { if InvocationCtx == nil { var err error - InvocationCtx, err = sys.VMContext() + InvocationCtx, err = sys.VMContext(ctx) if err != nil { return nil, err } @@ -64,16 +66,16 @@ func ValueReceived() (*types.TokenAmount, error) { } // ParamsRaw returns the message codec and parameters. -func ParamsRaw(id types.BlockID) (*types.ParamsRaw, error) { +func ParamsRaw(ctx context.Context, id types.BlockID) (*types.ParamsRaw, error) { if id == types.NoDataBlockID { return &types.ParamsRaw{}, nil } - state, err := sys.Stat(id) + state, err := sys.Stat(ctx, id) if err != nil { return nil, err } - block, err := GetBlock(id, &state.Size) + block, err := GetBlock(ctx, id, &state.Size) if err != nil { return nil, err } @@ -84,10 +86,10 @@ func ParamsRaw(id types.BlockID) (*types.ParamsRaw, error) { } // CurrEpoch get network current epoch -func CurrEpoch() (abi.ChainEpoch, error) { +func CurrEpoch(ctx context.Context) (abi.ChainEpoch, error) { if InvocationCtx == nil { var err error - InvocationCtx, err = sys.VMContext() + InvocationCtx, err = sys.VMContext(ctx) if err != nil { return 0, err } @@ -96,10 +98,10 @@ func CurrEpoch() (abi.ChainEpoch, error) { } // Version network version -func Version() (network.Version, error) { +func Version(ctx context.Context) (network.Version, error) { if InvocationCtx == nil { var err error - InvocationCtx, err = sys.VMContext() + InvocationCtx, err = sys.VMContext(ctx) if err != nil { return 0, err } diff --git a/sdk/network.go b/sdk/network.go index b1e3836..6f714eb 100644 --- a/sdk/network.go +++ b/sdk/network.go @@ -1,16 +1,18 @@ package sdk import ( + "context" + "github.com/ipfs-force-community/go-fvm-sdk/sdk/sys" "github.com/ipfs-force-community/go-fvm-sdk/sdk/types" ) // BaseFee gets the base fee for the current epoch. -func BaseFee() (*types.TokenAmount, error) { - return sys.BaseFee() +func BaseFee(ctx context.Context) (*types.TokenAmount, error) { + return sys.BaseFee(ctx) } // TotalFilCircSupply gets the circulating supply. -func TotalFilCircSupply() (*types.TokenAmount, error) { - return sys.TotalFilCircSupply() +func TotalFilCircSupply(ctx context.Context) (*types.TokenAmount, error) { + return sys.TotalFilCircSupply(ctx) } diff --git a/sdk/rand.go b/sdk/rand.go index 17398a3..1608a20 100644 --- a/sdk/rand.go +++ b/sdk/rand.go @@ -1,6 +1,8 @@ package sdk import ( + "context" + "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/crypto" "github.com/ipfs-force-community/go-fvm-sdk/sdk/sys" @@ -10,14 +12,14 @@ import ( // The supplied output buffer must have at least 32 bytes of capacity. // If this syscall succeeds, exactly 32 bytes will be written starting at the // supplied offset. -func GetChainRandomness(dst crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte) (abi.Randomness, error) { - return sys.GetChainRandomness(int64(dst), int64(round), entropy) +func GetChainRandomness(ctx context.Context, dst crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte) (abi.Randomness, error) { + return sys.GetChainRandomness(ctx, int64(dst), int64(round), entropy) } // GetBeaconRandomness gets 32 bytes of randomness from the beacon system (currently Drand). // The supplied output buffer must have at least 32 bytes of capacity. // If this syscall succeeds, exactly 32 bytes will be written starting at the // supplied offset. -func GetBeaconRandomness(dst crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte) (abi.Randomness, error) { - return sys.GetBeaconRandomness(int64(dst), int64(round), entropy) +func GetBeaconRandomness(ctx context.Context, dst crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte) (abi.Randomness, error) { + return sys.GetBeaconRandomness(ctx, int64(dst), int64(round), entropy) } diff --git a/sdk/send.go b/sdk/send.go index f06b07d..256cbc5 100644 --- a/sdk/send.go +++ b/sdk/send.go @@ -1,6 +1,7 @@ package sdk import ( + "context" "fmt" "github.com/ipfs-force-community/go-fvm-sdk/sdk/ferrors" @@ -12,13 +13,13 @@ import ( ) // Send sends a message to another actor. -func Send(to address.Address, method abi.MethodNum, params types.RawBytes, value types.TokenAmount) (*types.Receipt, error) { +func Send(ctx context.Context, to address.Address, method abi.MethodNum, params types.RawBytes, value types.TokenAmount) (*types.Receipt, error) { var ( paramsID uint32 err error ) if len(params) > 0 { - paramsID, err = sys.Create(types.DAGCbor, params) + paramsID, err = sys.Create(ctx, types.DAGCbor, params) if err != nil { return nil, fmt.Errorf("invalid params: %w", err) } @@ -26,7 +27,7 @@ func Send(to address.Address, method abi.MethodNum, params types.RawBytes, value paramsID = types.NoDataBlockID } - send, err := sys.Send(to, uint64(method), paramsID, value) + send, err := sys.Send(ctx, to, uint64(method), paramsID, value) if err != nil { return nil, err } @@ -34,14 +35,14 @@ func Send(to address.Address, method abi.MethodNum, params types.RawBytes, value var returnData types.RawBytes var exitCode = ferrors.ExitCode(send.ExitCode) if exitCode == ferrors.OK && send.ReturnID != types.NoDataBlockID { - ipldStat, err := sys.Stat(send.ReturnID) + ipldStat, err := sys.Stat(ctx, send.ReturnID) if err != nil { return nil, fmt.Errorf("return id ipld-stat: %w", err) } // Now read the return data. - readBuf, read, err := sys.Read(send.ReturnID, 0, ipldStat.Size) + readBuf, read, err := sys.Read(ctx, send.ReturnID, 0, ipldStat.Size) if err != nil { return nil, fmt.Errorf("read return_data: %w", err) } diff --git a/sdk/sself.go b/sdk/sself.go index 54a075d..259a855 100644 --- a/sdk/sself.go +++ b/sdk/sself.go @@ -1,6 +1,8 @@ package sdk import ( + "context" + addr "github.com/filecoin-project/go-address" "github.com/ipfs-force-community/go-fvm-sdk/sdk/sys" "github.com/ipfs-force-community/go-fvm-sdk/sdk/types" @@ -9,8 +11,8 @@ import ( // Root Get the IPLD root CID. Fails if the actor doesn't have state (before the first call to // `set_root` and after actor deletion). -func Root() (cid.Cid, error) { - return sys.SelfRoot() +func Root(ctx context.Context) (cid.Cid, error) { + return sys.SelfRoot(ctx) } // SetRoot set the actor's state-tree root. @@ -19,13 +21,13 @@ func Root() (cid.Cid, error) { // // - The new root is not in the actor's "reachable" set. // - Fails if the actor has been deleted. -func SetRoot(c cid.Cid) error { - return sys.SelfSetRoot(c) +func SetRoot(ctx context.Context, c cid.Cid) error { + return sys.SelfSetRoot(ctx, c) } // CurrentBalance gets the current balance for the calling actor. -func CurrentBalance() *types.TokenAmount { - tok, err := sys.SelfCurrentBalance() +func CurrentBalance(ctx context.Context) *types.TokenAmount { + tok, err := sys.SelfCurrentBalance(ctx) if err != nil { panic(err.Error()) } @@ -36,6 +38,6 @@ func CurrentBalance() *types.TokenAmount { // to the supplied address, which cannot be itself. // // Fails if the beneficiary doesn't exist or is the actor being deleted. -func SelfDestruct(addr addr.Address) error { - return sys.SelfDestruct(addr) +func SelfDestruct(ctx context.Context, addr addr.Address) error { + return sys.SelfDestruct(ctx, addr) } diff --git a/sdk/sys/abort.go b/sdk/sys/abort.go index 00200f1..a8e673d 100644 --- a/sdk/sys/abort.go +++ b/sdk/sys/abort.go @@ -1,9 +1,12 @@ -//go:build !simulated -// +build !simulated +//go:build !simulate +// +build !simulate +// Package sys ... package sys -func Abort(code uint32, msg string) { +import "context" + +func Abort(ctx context.Context, code uint32, msg string) { strPtr, strLen := GetStringPointerAndLen(msg) _ = vmAbort(code, strPtr, strLen) } diff --git a/sdk/sys/abort_simulated.go b/sdk/sys/abort_simulated.go index 70fb74e..d6d00ad 100644 --- a/sdk/sys/abort_simulated.go +++ b/sdk/sys/abort_simulated.go @@ -1,12 +1,16 @@ -//go:build simulated -// +build simulated +//go:build simulate +// +build simulate package sys import ( - "github.com/ipfs-force-community/go-fvm-sdk/sdk/sys/simulated" + "context" ) -func Abort(code uint32, msg string) { - simulated.DefaultFsm.Abort(code, msg) +func Abort(ctx context.Context, code uint32, msg string) { + if env, ok := tryGetSimulator(ctx); ok { + env.Abort(code, msg) + return + } + panic(ErrorEnvValid) } diff --git a/sdk/sys/actor.go b/sdk/sys/actor.go index 1f9c36f..650f78d 100644 --- a/sdk/sys/actor.go +++ b/sdk/sys/actor.go @@ -1,10 +1,10 @@ -//go:build !simulated -// +build !simulated +//go:build !simulate +// +build !simulate -// Package sys : a go-fvm-sdk system calls package sys import ( + "context" "fmt" "unsafe" @@ -15,7 +15,7 @@ import ( "github.com/ipfs/go-cid" ) -func ResolveAddress(addr address.Address) (abi.ActorID, error) { +func ResolveAddress(ctx context.Context, addr address.Address) (abi.ActorID, error) { if addr.Protocol() == address.ID { actid, err := address.IDFromAddress(addr) return abi.ActorID(actid), err @@ -29,7 +29,7 @@ func ResolveAddress(addr address.Address) (abi.ActorID, error) { return result, nil } -func GetActorCodeCid(addr address.Address) (*cid.Cid, error) { +func GetActorCodeCid(ctx context.Context, addr address.Address) (*cid.Cid, error) { addrBufPtr, addrBufLen := GetSlicePointerAndLen(addr.Bytes()) buf := make([]byte, types.MaxCidLen) bufPtr, bufLen := GetSlicePointerAndLen(buf) @@ -50,7 +50,7 @@ func GetActorCodeCid(addr address.Address) (*cid.Cid, error) { } } -func ResolveBuiltinActorType(codeCid cid.Cid) (types.ActorType, error) { +func ResolveBuiltinActorType(ctx context.Context, codeCid cid.Cid) (types.ActorType, error) { addrBufPtr, _ := GetSlicePointerAndLen(codeCid.Bytes()) var result types.ActorType code := actorResolveBuiltinActorType(uintptr(unsafe.Pointer(&result)), addrBufPtr) @@ -60,7 +60,7 @@ func ResolveBuiltinActorType(codeCid cid.Cid) (types.ActorType, error) { return result, nil } -func GetCodeCidForType(actorT types.ActorType) (cid.Cid, error) { +func GetCodeCidForType(ctx context.Context, actorT types.ActorType) (cid.Cid, error) { buf := make([]byte, types.MaxCidLen) bufPtr, bufLen := GetSlicePointerAndLen(buf) @@ -76,7 +76,7 @@ func GetCodeCidForType(actorT types.ActorType) (cid.Cid, error) { return result, nil } -func NewActorAddress() (address.Address, error) { +func NewActorAddress(ctx context.Context) (address.Address, error) { buf := make([]byte, types.MaxActorAddrLen) bufPtr, bufLen := GetSlicePointerAndLen(buf) @@ -88,7 +88,7 @@ func NewActorAddress() (address.Address, error) { return address.NewFromBytes(buf[:addrLen]) } -func CreateActor(actorID abi.ActorID, codeCid cid.Cid) error { +func CreateActor(ctx context.Context, actorID abi.ActorID, codeCid cid.Cid) error { addrBufPtr, _ := GetSlicePointerAndLen(codeCid.Bytes()) code := actorCreateActor(uint64(actorID), addrBufPtr) if code != 0 { diff --git a/sdk/sys/actor_simulated.go b/sdk/sys/actor_simulated.go index 43a7300..316861c 100644 --- a/sdk/sys/actor_simulated.go +++ b/sdk/sys/actor_simulated.go @@ -1,36 +1,55 @@ -//go:build simulated -// +build simulated +//go:build simulate +// +build simulate package sys import ( + "context" + address "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" - "github.com/ipfs-force-community/go-fvm-sdk/sdk/sys/simulated" "github.com/ipfs-force-community/go-fvm-sdk/sdk/types" "github.com/ipfs/go-cid" ) -func ResolveAddress(addr address.Address) (abi.ActorID, error) { - return simulated.DefaultFsm.ResolveAddress(addr) +func ResolveAddress(ctx context.Context, addr address.Address) (abi.ActorID, error) { + if env, ok := tryGetSimulator(ctx); ok { + return env.ResolveAddress(addr) + } + panic(ErrorEnvValid) } -func GetActorCodeCid(addr address.Address) (*cid.Cid, error) { - return simulated.DefaultFsm.GetActorCodeCid(addr) +func GetActorCodeCid(ctx context.Context, addr address.Address) (*cid.Cid, error) { + if env, ok := tryGetSimulator(ctx); ok { + return env.GetActorCodeCid(addr) + } + panic(ErrorEnvValid) } -func ResolveBuiltinActorType(codeCid cid.Cid) (types.ActorType, error) { - return simulated.DefaultFsm.ResolveBuiltinActorType(codeCid) +func ResolveBuiltinActorType(ctx context.Context, codeCid cid.Cid) (types.ActorType, error) { + if env, ok := tryGetSimulator(ctx); ok { + return env.ResolveBuiltinActorType(codeCid) + } + panic(ErrorEnvValid) } -func GetCodeCidForType(actorT types.ActorType) (cid.Cid, error) { - return simulated.DefaultFsm.GetCodeCidForType(actorT) +func GetCodeCidForType(ctx context.Context, actorT types.ActorType) (cid.Cid, error) { + if env, ok := tryGetSimulator(ctx); ok { + return env.GetCodeCidForType(actorT) + } + panic(ErrorEnvValid) } -func NewActorAddress() (address.Address, error) { - return simulated.DefaultFsm.NewActorAddress() +func NewActorAddress(ctx context.Context) (address.Address, error) { + if env, ok := tryGetSimulator(ctx); ok { + return env.NewActorAddress() + } + panic(ErrorEnvValid) } -func CreateActor(actorID abi.ActorID, codeCid cid.Cid) error { - return simulated.DefaultFsm.CreateActor(actorID, codeCid) +func CreateActor(ctx context.Context, actorID abi.ActorID, codeCid cid.Cid) error { + if env, ok := tryGetSimulator(ctx); ok { + return env.CreateActor(actorID, codeCid) + } + panic(ErrorEnvValid) } diff --git a/sdk/sys/context.go b/sdk/sys/context.go index 6b863c2..19f42b3 100644 --- a/sdk/sys/context.go +++ b/sdk/sys/context.go @@ -1,16 +1,17 @@ -//go:build !simulated -// +build !simulated +//go:build !simulate +// +build !simulate package sys import ( + "context" "unsafe" "github.com/ipfs-force-community/go-fvm-sdk/sdk/ferrors" "github.com/ipfs-force-community/go-fvm-sdk/sdk/types" ) -func VMContext() (*types.InvocationContext, error) { +func VMContext(ctx context.Context) (*types.InvocationContext, error) { var result types.InvocationContext code := vmContext(uintptr(unsafe.Pointer(&result))) if code != 0 { diff --git a/sdk/sys/context_simulated.go b/sdk/sys/context_simulated.go index 954a521..b3d0e76 100644 --- a/sdk/sys/context_simulated.go +++ b/sdk/sys/context_simulated.go @@ -1,13 +1,17 @@ -//go:build simulated -// +build simulated +//go:build simulate +// +build simulate package sys import ( - "github.com/ipfs-force-community/go-fvm-sdk/sdk/sys/simulated" + "context" + "github.com/ipfs-force-community/go-fvm-sdk/sdk/types" ) -func VMContext() (*types.InvocationContext, error) { - return simulated.DefaultFsm.VMContext() +func VMContext(ctx context.Context) (*types.InvocationContext, error) { + if env, ok := tryGetSimulator(ctx); ok { + return env.VMContext() + } + panic(ErrorEnvValid) } diff --git a/sdk/sys/crypto.go b/sdk/sys/crypto.go index 187db70..d31db26 100644 --- a/sdk/sys/crypto.go +++ b/sdk/sys/crypto.go @@ -1,14 +1,15 @@ -//go:build !simulated -// +build !simulated +//go:build !simulate +// +build !simulate package sys import ( "bytes" + "context" "fmt" "unsafe" - address "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/crypto" "github.com/filecoin-project/specs-actors/v7/actors/runtime" @@ -20,6 +21,7 @@ import ( ) func VerifySignature( + ctx context.Context, signature *crypto.Signature, signer *address.Address, plaintext []byte, @@ -41,7 +43,7 @@ func VerifySignature( return result == 0, nil } -func HashBlake2b(data []byte) ([32]byte, error) { +func HashBlake2b(ctx context.Context, data []byte) ([32]byte, error) { dataPtr, dataLen := GetSlicePointerAndLen(data) result := [32]byte{} resultPtr, _ := GetSlicePointerAndLen(result[:]) @@ -53,10 +55,10 @@ func HashBlake2b(data []byte) ([32]byte, error) { } func ComputeUnsealedSectorCid( + ctx context.Context, proofType abi.RegisteredSealProof, pieces []abi.PieceInfo, ) (cid.Cid, error) { - //todo need to be test buf := bytes.NewBuffer([]byte{}) cw := cbg.NewCborWriter(buf) @@ -85,7 +87,7 @@ func ComputeUnsealedSectorCid( } // VerifySeal Verifies a sector seal proof. -func VerifySeal(info *proof.SealVerifyInfo) (bool, error) { +func VerifySeal(ctx context.Context, info *proof.SealVerifyInfo) (bool, error) { verifyBuf := bytes.NewBuffer([]byte{}) err := info.MarshalCBOR(verifyBuf) if err != nil { @@ -101,7 +103,7 @@ func VerifySeal(info *proof.SealVerifyInfo) (bool, error) { } // VerifyPost Verifies a sector seal proof. -func VerifyPost(info *proof.WindowPoStVerifyInfo) (bool, error) { +func VerifyPost(ctx context.Context, info *proof.WindowPoStVerifyInfo) (bool, error) { verifyBuf := bytes.NewBuffer([]byte{}) err := info.MarshalCBOR(verifyBuf) if err != nil { @@ -117,11 +119,11 @@ func VerifyPost(info *proof.WindowPoStVerifyInfo) (bool, error) { } func VerifyConsensusFault( + ctx context.Context, h1 []byte, h2 []byte, extra []byte, ) (*runtime.ConsensusFault, error) { - h1Ptr, h1Len := GetSlicePointerAndLen(h1) h2Ptr, h2Len := GetSlicePointerAndLen(h2) extraPtr, extraLen := GetSlicePointerAndLen(extra) @@ -149,7 +151,11 @@ func VerifyConsensusFault( }, nil } -func VerifyAggregateSeals(info *types.AggregateSealVerifyProofAndInfos) (bool, error) { +func VerifyAggregateSeals(ctx context.Context, info *types.AggregateSealVerifyProofAndInfos) (bool, error) { + if env, ok := tryGetSimulator(ctx); ok { + return env.VerifyAggregateSeals(info) + } + aggregateSealBuf := bytes.NewBuffer([]byte{}) err := info.MarshalCBOR(aggregateSealBuf) if err != nil { @@ -164,7 +170,7 @@ func VerifyAggregateSeals(info *types.AggregateSealVerifyProofAndInfos) (bool, e return result == 0, nil } -func VerifyReplicaUpdate(info *types.ReplicaUpdateInfo) (bool, error) { +func VerifyReplicaUpdate(ctx context.Context, info *types.ReplicaUpdateInfo) (bool, error) { replicaUpdateInfoBuf := bytes.NewBuffer([]byte{}) err := info.MarshalCBOR(replicaUpdateInfoBuf) if err != nil { @@ -179,7 +185,7 @@ func VerifyReplicaUpdate(info *types.ReplicaUpdateInfo) (bool, error) { return result == 0, nil } -func BatchVerifySeals(sealVerifyInfos []proof.SealVerifyInfo) ([]bool, error) { +func BatchVerifySeals(ctx context.Context, sealVerifyInfos []proof.SealVerifyInfo) ([]bool, error) { //todo need to be test buf := bytes.NewBuffer([]byte{}) cw := cbg.NewCborWriter(buf) diff --git a/sdk/sys/crypto_simulated.go b/sdk/sys/crypto_simulated.go index df8a8f2..a438ea9 100644 --- a/sdk/sys/crypto_simulated.go +++ b/sdk/sys/crypto_simulated.go @@ -1,66 +1,95 @@ -//go:build simulated -// +build simulated +//go:build simulate +// +build simulate package sys import ( + "context" + address "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/crypto" "github.com/filecoin-project/specs-actors/v7/actors/runtime" "github.com/filecoin-project/specs-actors/v7/actors/runtime/proof" - "github.com/ipfs-force-community/go-fvm-sdk/sdk/sys/simulated" "github.com/ipfs-force-community/go-fvm-sdk/sdk/types" "github.com/ipfs/go-cid" ) func VerifySignature( + ctx context.Context, signature *crypto.Signature, signer *address.Address, plaintext []byte, ) (bool, error) { - return simulated.DefaultFsm.VerifySignature(signature, signer, plaintext) + if env, ok := tryGetSimulator(ctx); ok { + return env.VerifySignature(signature, signer, plaintext) + } + panic(ErrorEnvValid) } -func HashBlake2b(data []byte) ([32]byte, error) { - return simulated.DefaultFsm.HashBlake2b(data) +func HashBlake2b(ctx context.Context, data []byte) ([32]byte, error) { + if env, ok := tryGetSimulator(ctx); ok { + return env.HashBlake2b(data) + } + panic(ErrorEnvValid) } func ComputeUnsealedSectorCid( + ctx context.Context, proofType abi.RegisteredSealProof, pieces []abi.PieceInfo, ) (cid.Cid, error) { - - return simulated.DefaultFsm.ComputeUnsealedSectorCid(proofType, pieces) + if env, ok := tryGetSimulator(ctx); ok { + return env.ComputeUnsealedSectorCid(proofType, pieces) + } + panic(ErrorEnvValid) } // VerifySeal Verifies a sector seal proof. -func VerifySeal(info *proof.SealVerifyInfo) (bool, error) { - return simulated.DefaultFsm.VerifySeal(info) +func VerifySeal(ctx context.Context, info *proof.SealVerifyInfo) (bool, error) { + if env, ok := tryGetSimulator(ctx); ok { + return env.VerifySeal(info) + } + return false, nil } // VerifyPost Verifies a sector seal proof. -func VerifyPost(info *proof.WindowPoStVerifyInfo) (bool, error) { - return simulated.DefaultFsm.VerifyPost(info) +func VerifyPost(ctx context.Context, info *proof.WindowPoStVerifyInfo) (bool, error) { + if env, ok := tryGetSimulator(ctx); ok { + return env.VerifyPost(info) + } + panic(ErrorEnvValid) } func VerifyConsensusFault( + ctx context.Context, h1 []byte, h2 []byte, extra []byte, ) (*runtime.ConsensusFault, error) { - - return simulated.DefaultFsm.VerifyConsensusFault(h1, h2, extra) + if env, ok := tryGetSimulator(ctx); ok { + return env.VerifyConsensusFault(h1, h2, extra) + } + panic(ErrorEnvValid) } -func VerifyAggregateSeals(info *types.AggregateSealVerifyProofAndInfos) (bool, error) { - return simulated.DefaultFsm.VerifyAggregateSeals(info) +func VerifyAggregateSeals(ctx context.Context, info *types.AggregateSealVerifyProofAndInfos) (bool, error) { + if env, ok := tryGetSimulator(ctx); ok { + return env.VerifyAggregateSeals(info) + } + panic(ErrorEnvValid) } -func VerifyReplicaUpdate(info *types.ReplicaUpdateInfo) (bool, error) { - return simulated.DefaultFsm.VerifyReplicaUpdate(info) +func VerifyReplicaUpdate(ctx context.Context, info *types.ReplicaUpdateInfo) (bool, error) { + if env, ok := tryGetSimulator(ctx); ok { + return env.VerifyReplicaUpdate(info) + } + panic(ErrorEnvValid) } -func BatchVerifySeals(sealVerifyInfos []proof.SealVerifyInfo) ([]bool, error) { - return simulated.DefaultFsm.BatchVerifySeals(sealVerifyInfos) +func BatchVerifySeals(ctx context.Context, sealVerifyInfos []proof.SealVerifyInfo) ([]bool, error) { + if env, ok := tryGetSimulator(ctx); ok { + return env.BatchVerifySeals(sealVerifyInfos) + } + panic(ErrorEnvValid) } diff --git a/sdk/sys/debug.go b/sdk/sys/debug.go index e2d54ce..9fc4b39 100644 --- a/sdk/sys/debug.go +++ b/sdk/sys/debug.go @@ -1,15 +1,16 @@ -//go:build !simulated -// +build !simulated +//go:build !simulate +// +build !simulate package sys import ( + "context" "unsafe" "github.com/ipfs-force-community/go-fvm-sdk/sdk/ferrors" ) -func Enabled() (bool, error) { +func Enabled(ctx context.Context) (bool, error) { var result int32 code := debugEnabled(uintptr(unsafe.Pointer(&result))) if code != 0 { @@ -19,7 +20,7 @@ func Enabled() (bool, error) { return result == 0, nil } -func Log(msg string) error { +func Log(ctx context.Context, msg string) error { msgBufPtr, msgBufLen := GetStringPointerAndLen(msg) code := debugLog(msgBufPtr, msgBufLen) if code != 0 { diff --git a/sdk/sys/debug_simulated.go b/sdk/sys/debug_simulated.go index d62bbc2..b2d0dca 100644 --- a/sdk/sys/debug_simulated.go +++ b/sdk/sys/debug_simulated.go @@ -1,16 +1,22 @@ -//go:build simulated -// +build simulated +//go:build simulate +// +build simulate package sys import ( - "github.com/ipfs-force-community/go-fvm-sdk/sdk/sys/simulated" + "context" ) -func Enabled() (bool, error) { - return simulated.DefaultFsm.Enabled() +func Enabled(ctx context.Context) (bool, error) { + if env, ok := tryGetSimulator(ctx); ok { + return env.Enabled() + } + panic(ErrorEnvValid) } -func Log(msg string) error { - return simulated.DefaultFsm.Log(msg) +func Log(ctx context.Context, msg string) error { + if env, ok := tryGetSimulator(ctx); ok { + return env.Log(msg) + } + panic(ErrorEnvValid) } diff --git a/sdk/sys/env.go b/sdk/sys/env.go new file mode 100644 index 0000000..a2a7aab --- /dev/null +++ b/sdk/sys/env.go @@ -0,0 +1,18 @@ +package sys + +import ( + "context" + "errors" + + "github.com/ipfs-force-community/go-fvm-sdk/sdk/sys/simulated" + "github.com/ipfs-force-community/go-fvm-sdk/sdk/types" +) + +var ( + ErrorEnvValid = errors.New("env is valid") +) + +func tryGetSimulator(ctx context.Context) (*simulated.FvmSimulator, bool) { + env, ok := ctx.Value(types.SimulatedEnvkey).(*simulated.FvmSimulator) //nolint:govet + return env, ok //nolint:govet +} diff --git a/sdk/sys/gas.go b/sdk/sys/gas.go index ef78bc0..b5cb5d0 100644 --- a/sdk/sys/gas.go +++ b/sdk/sys/gas.go @@ -1,16 +1,17 @@ -//go:build !simulated -// +build !simulated +//go:build !simulate +// +build !simulate package sys import ( + "context" "fmt" "github.com/ipfs-force-community/go-fvm-sdk/sdk/ferrors" ) // Charge charge gas for the operation identified by name. -func Charge(name string, compute uint64) error { +func Charge(ctx context.Context, name string, compute uint64) error { nameBufPtr, nameBufLen := GetStringPointerAndLen(name) code := gasCharge(nameBufPtr, nameBufLen, compute) if code != 0 { diff --git a/sdk/sys/gas_simulated.go b/sdk/sys/gas_simulated.go index 9939843..8ea8f5e 100644 --- a/sdk/sys/gas_simulated.go +++ b/sdk/sys/gas_simulated.go @@ -1,13 +1,16 @@ -//go:build simulated -// +build simulated +//go:build simulate +// +build simulate package sys import ( - "github.com/ipfs-force-community/go-fvm-sdk/sdk/sys/simulated" + "context" ) // Charge charge gas for the operation identified by name. -func Charge(name string, compute uint64) error { - return simulated.DefaultFsm.Charge(name, compute) +func Charge(ctx context.Context, name string, compute uint64) error { + if env, ok := tryGetSimulator(ctx); ok { + return env.Charge(name, compute) + } + panic(ErrorEnvValid) } diff --git a/sdk/sys/ipld.go b/sdk/sys/ipld.go index e2ec92f..311e125 100644 --- a/sdk/sys/ipld.go +++ b/sdk/sys/ipld.go @@ -1,9 +1,10 @@ -//go:build !simulated -// +build !simulated +//go:build !simulate +// +build !simulate package sys import ( + "context" "fmt" "unsafe" @@ -12,7 +13,7 @@ import ( "github.com/ipfs/go-cid" ) -func Open(id cid.Cid) (*types.IpldOpen, error) { +func Open(ctx context.Context, id cid.Cid) (*types.IpldOpen, error) { cidBuf := make([]byte, types.MaxCidLen) copy(cidBuf, id.Bytes()) cidBufPtr, _ := GetSlicePointerAndLen(cidBuf) @@ -25,7 +26,7 @@ func Open(id cid.Cid) (*types.IpldOpen, error) { return result, nil } -func Create(codec uint64, data []byte) (uint32, error) { +func Create(ctx context.Context, codec uint64, data []byte) (uint32, error) { result := uint32(0) dataPtr, dataLen := GetSlicePointerAndLen(data) code := ipldCreate(uintptr(unsafe.Pointer(&result)), codec, dataPtr, dataLen) @@ -35,7 +36,7 @@ func Create(codec uint64, data []byte) (uint32, error) { return result, nil } -func Read(id uint32, offset, size uint32) ([]byte, uint32, error) { +func Read(ctx context.Context, id uint32, offset, size uint32) ([]byte, uint32, error) { result := uint32(0) buf := make([]byte, size) bufPtr, bufLen := GetSlicePointerAndLen(buf) @@ -46,7 +47,7 @@ func Read(id uint32, offset, size uint32) ([]byte, uint32, error) { return buf, result, nil } -func Stat(id uint32) (*types.IpldStat, error) { +func Stat(ctx context.Context, id uint32) (*types.IpldStat, error) { result := new(types.IpldStat) code := ipldStat(uintptr(unsafe.Pointer(result)), id) if code != 0 { @@ -55,7 +56,7 @@ func Stat(id uint32) (*types.IpldStat, error) { return result, nil } -func BlockLink(id uint32, hashFun uint64, hashLen uint32, cidBuf []byte) (cid.Cid, error) { +func BlockLink(ctx context.Context, id uint32, hashFun uint64, hashLen uint32, cidBuf []byte) (cid.Cid, error) { result := uint32(0) cidBufPtr, cidBufLen := GetSlicePointerAndLen(cidBuf) code := ipldLink(uintptr(unsafe.Pointer(&result)), id, hashFun, hashLen, cidBufPtr, cidBufLen) diff --git a/sdk/sys/ipld_simulated.go b/sdk/sys/ipld_simulated.go index b0094f6..07f256b 100644 --- a/sdk/sys/ipld_simulated.go +++ b/sdk/sys/ipld_simulated.go @@ -1,30 +1,47 @@ -//go:build simulated -// +build simulated +//go:build simulate +// +build simulate package sys import ( - "github.com/ipfs-force-community/go-fvm-sdk/sdk/sys/simulated" + "context" + "github.com/ipfs-force-community/go-fvm-sdk/sdk/types" "github.com/ipfs/go-cid" ) -func Open(id cid.Cid) (*types.IpldOpen, error) { - return simulated.DefaultFsm.Open(id) +func Open(ctx context.Context, id cid.Cid) (*types.IpldOpen, error) { + if env, ok := tryGetSimulator(ctx); ok { + return env.Open(id) + } + panic(ErrorEnvValid) } -func Create(codec uint64, data []byte) (uint32, error) { - return simulated.DefaultFsm.Create(codec, data) +func Create(ctx context.Context, codec uint64, data []byte) (uint32, error) { + if env, ok := tryGetSimulator(ctx); ok { + a, v := env.Create(codec, data) + return a, v + } + panic(ErrorEnvValid) } -func Read(id uint32, offset, size uint32) ([]byte, uint32, error) { - return simulated.DefaultFsm.Read(id, offset, size) +func Read(ctx context.Context, id uint32, offset, size uint32) ([]byte, uint32, error) { + if env, ok := tryGetSimulator(ctx); ok { + return env.Read(id, offset, size) + } + panic(ErrorEnvValid) } -func Stat(id uint32) (*types.IpldStat, error) { - return simulated.DefaultFsm.Stat(id) +func Stat(ctx context.Context, id uint32) (*types.IpldStat, error) { + if env, ok := tryGetSimulator(ctx); ok { + return env.Stat(id) + } + panic(ErrorEnvValid) } -func BlockLink(id uint32, hashFun uint64, hashLen uint32, cidBuf []byte) (cided cid.Cid, err error) { - return simulated.DefaultFsm.BlockLink(id, hashFun, hashLen, cidBuf) +func BlockLink(ctx context.Context, id uint32, hashFun uint64, hashLen uint32, cidBuf []byte) (cid.Cid, error) { + if env, ok := tryGetSimulator(ctx); ok { + return env.BlockLink(id, hashFun, hashLen, cidBuf) + } + panic(ErrorEnvValid) } diff --git a/sdk/sys/network.go b/sdk/sys/network.go index 392fb39..3b689f2 100644 --- a/sdk/sys/network.go +++ b/sdk/sys/network.go @@ -1,9 +1,10 @@ -//go:build !simulated -// +build !simulated +//go:build !simulate +// +build !simulate package sys import ( + "context" "unsafe" "github.com/ipfs-force-community/go-fvm-sdk/sdk/ferrors" @@ -11,7 +12,7 @@ import ( ) // BaseFee gets the base fee for the current epoch. -func BaseFee() (*types.TokenAmount, error) { +func BaseFee(ctx context.Context) (*types.TokenAmount, error) { result := new(types.TokenAmount) code := networkBaseFee(uintptr(unsafe.Pointer(result))) if code != 0 { @@ -22,7 +23,7 @@ func BaseFee() (*types.TokenAmount, error) { } // TotalFilCircSupply gets the circulating supply. -func TotalFilCircSupply() (*types.TokenAmount, error) { +func TotalFilCircSupply(ctx context.Context) (*types.TokenAmount, error) { result := new(types.TokenAmount) code := networkTotalFilCircSupply(uintptr(unsafe.Pointer(result))) if code != 0 { diff --git a/sdk/sys/network_simulated.go b/sdk/sys/network_simulated.go index 9a88b2e..c6e9563 100644 --- a/sdk/sys/network_simulated.go +++ b/sdk/sys/network_simulated.go @@ -1,17 +1,26 @@ -//go:build simulated -// +build simulated +//go:build simulate +// +build simulate package sys import ( + "context" + "github.com/ipfs-force-community/go-fvm-sdk/sdk/types" - "github.com/ipfs-force-community/go-fvm-sdk/sdk/sys/simulated" ) -func BaseFee() (*types.TokenAmount, error) { - return simulated.DefaultFsm.BaseFee() +// BaseFee gets the base fee for the current epoch. +func BaseFee(ctx context.Context) (*types.TokenAmount, error) { + if env, ok := tryGetSimulator(ctx); ok { + return env.BaseFee() + } + panic(ErrorEnvValid) } -func TotalFilCircSupply() (*types.TokenAmount, error) { - return simulated.DefaultFsm.TotalFilCircSupply() +// TotalFilCircSupply gets the circulating supply. +func TotalFilCircSupply(ctx context.Context) (*types.TokenAmount, error) { + if env, ok := tryGetSimulator(ctx); ok { + return env.TotalFilCircSupply() + } + panic(ErrorEnvValid) } diff --git a/sdk/sys/rand.go b/sdk/sys/rand.go index ea74f0a..d32bb26 100644 --- a/sdk/sys/rand.go +++ b/sdk/sys/rand.go @@ -1,14 +1,16 @@ -//go:build !simulated -// +build !simulated +//go:build !simulate +// +build !simulate package sys import ( + "context" + "github.com/filecoin-project/go-state-types/abi" "github.com/ipfs-force-community/go-fvm-sdk/sdk/ferrors" ) -func GetChainRandomness(dst int64, round int64, entropy []byte) (abi.Randomness, error) { +func GetChainRandomness(ctx context.Context, dst int64, round int64, entropy []byte) (abi.Randomness, error) { result := [abi.RandomnessLength]byte{} resultPtr, _ := GetSlicePointerAndLen(result[:]) @@ -21,7 +23,7 @@ func GetChainRandomness(dst int64, round int64, entropy []byte) (abi.Randomness, return result[:], nil } -func GetBeaconRandomness(dst int64, round int64, entropy []byte) (abi.Randomness, error) { +func GetBeaconRandomness(ctx context.Context, dst int64, round int64, entropy []byte) (abi.Randomness, error) { result := [abi.RandomnessLength]byte{} resultPtr, _ := GetSlicePointerAndLen(result[:]) diff --git a/sdk/sys/rand_simulated.go b/sdk/sys/rand_simulated.go index 52ce94b..c872875 100644 --- a/sdk/sys/rand_simulated.go +++ b/sdk/sys/rand_simulated.go @@ -1,17 +1,24 @@ -//go:build simulated -// +build simulated +//go:build simulate +// +build simulate package sys import ( + "context" + "github.com/filecoin-project/go-state-types/abi" - "github.com/ipfs-force-community/go-fvm-sdk/sdk/sys/simulated" ) -func GetChainRandomness(dst int64, round int64, entropy []byte) (abi.Randomness, error) { - return simulated.DefaultFsm.GetChainRandomness(dst, round, entropy) +func GetChainRandomness(ctx context.Context, dst int64, round int64, entropy []byte) (abi.Randomness, error) { + if env, ok := tryGetSimulator(ctx); ok { + return env.GetChainRandomness(dst, round, entropy) + } + panic(ErrorEnvValid) } -func GetBeaconRandomness(dst int64, round int64, entropy []byte) (abi.Randomness, error) { - return simulated.DefaultFsm.GetBeaconRandomness(dst, round, entropy) +func GetBeaconRandomness(ctx context.Context, dst int64, round int64, entropy []byte) (abi.Randomness, error) { + if env, ok := tryGetSimulator(ctx); ok { + return env.GetBeaconRandomness(dst, round, entropy) + } + panic(ErrorEnvValid) } diff --git a/sdk/sys/send.go b/sdk/sys/send.go index de31fdb..ea54065 100644 --- a/sdk/sys/send.go +++ b/sdk/sys/send.go @@ -1,9 +1,10 @@ -//go:build !simulated -// +build !simulated +//go:build !simulate +// +build !simulate package sys import ( + "context" "unsafe" "github.com/filecoin-project/go-address" @@ -12,7 +13,7 @@ import ( "github.com/ipfs-force-community/go-fvm-sdk/sdk/types" ) -func Send(to address.Address, method uint64, params uint32, value types.TokenAmount) (*types.Send, error) { +func Send(ctx context.Context, to address.Address, method uint64, params uint32, value types.TokenAmount) (*types.Send, error) { send := new(types.Send) addrBufPtr, addrBufLen := GetSlicePointerAndLen(to.Bytes()) code := sysSend(uintptr(unsafe.Pointer(send)), addrBufPtr, addrBufLen, method, params, value.Hi, value.Lo) diff --git a/sdk/sys/send_simulate.go b/sdk/sys/send_simulate.go index 42e9f1a..9730d44 100644 --- a/sdk/sys/send_simulate.go +++ b/sdk/sys/send_simulate.go @@ -1,15 +1,18 @@ -//go:build simulated -// +build simulated +//go:build simulate +// +build simulate package sys import ( - "github.com/filecoin-project/go-address" + "context" - "github.com/ipfs-force-community/go-fvm-sdk/sdk/sys/simulated" + "github.com/filecoin-project/go-address" "github.com/ipfs-force-community/go-fvm-sdk/sdk/types" ) -func Send(to address.Address, method uint64, params uint32, value types.TokenAmount) (*types.Send, error) { - return simulated.DefaultFsm.Send(to, method, params, value) +func Send(ctx context.Context, to address.Address, method uint64, params uint32, value types.TokenAmount) (*types.Send, error) { + if env, ok := tryGetSimulator(ctx); ok { + return env.Send(to, method, params, value) + } + panic(ErrorEnvValid) } diff --git a/sdk/sys/simulated/opration.go b/sdk/sys/simulated/opration.go index 3919de2..c8e32d9 100644 --- a/sdk/sys/simulated/opration.go +++ b/sdk/sys/simulated/opration.go @@ -2,8 +2,7 @@ package simulated import ( "fmt" - - "github.com/google/uuid" + "time" "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" @@ -15,25 +14,25 @@ import ( "github.com/ipfs/go-cid" ) -func (s *Fsm) Open(id cid.Cid) (*types.IpldOpen, error) { +func (s *FvmSimulator) Open(id cid.Cid) (*types.IpldOpen, error) { blockid, blockstat := s.blockOpen(id) return &types.IpldOpen{ID: blockid, Size: blockstat.size, Codec: blockstat.codec}, nil } -func (s *Fsm) SelfRoot() (cid.Cid, error) { +func (s *FvmSimulator) SelfRoot() (cid.Cid, error) { return s.rootCid, nil } -func (s *Fsm) SelfSetRoot(id cid.Cid) error { +func (s *FvmSimulator) SelfSetRoot(id cid.Cid) error { s.rootCid = id return nil } -func (s *Fsm) SelfCurrentBalance() (*types.TokenAmount, error) { - return s.baseFee, nil +func (s *FvmSimulator) SelfCurrentBalance() (*types.TokenAmount, error) { + return &s.baseFee, nil } -func (s *Fsm) SelfDestruct(addr address.Address) error { +func (s *FvmSimulator) SelfDestruct(addr address.Address) error { s.actorMutex.Lock() defer s.actorMutex.Unlock() @@ -46,26 +45,25 @@ func (s *Fsm) SelfDestruct(addr address.Address) error { } // nolint -func (s *Fsm) Create(codec uint64, data []byte) (uint32, error) { +func (s *FvmSimulator) Create(codec uint64, data []byte) (uint32, error) { index := s.blockCreate(codec, data) return uint32(index), nil } -func (s *Fsm) Read(id uint32, offset, size uint32) ([]byte, uint32, error) { +func (s *FvmSimulator) Read(id uint32, offset, size uint32) ([]byte, uint32, error) { data, err := s.blockRead(id, offset) return data, 0, err } -func (s *Fsm) Stat(id uint32) (*types.IpldStat, error) { +func (s *FvmSimulator) Stat(id uint32) (*types.IpldStat, error) { return s.blockStat(id) } -func (s *Fsm) BlockLink(id uint32, hashFun uint64, hashLen uint32, cidBuf []byte) (cided cid.Cid, err error) { +func (s *FvmSimulator) BlockLink(id uint32, hashFun uint64, hashLen uint32, cidBuf []byte) (cided cid.Cid, err error) { return s.blockLink(id, hashFun, hashLen) } -func (s *Fsm) ResolveAddress(addr address.Address) (abi.ActorID, error) { - +func (s *FvmSimulator) ResolveAddress(addr address.Address) (abi.ActorID, error) { id, ok := s.addressMap.Load(addr) if !ok { return 0, ErrorNotFound @@ -77,12 +75,12 @@ func (s *Fsm) ResolveAddress(addr address.Address) (abi.ActorID, error) { return abi.ActorID(idu32), nil } -func (s *Fsm) NewActorAddress() (address.Address, error) { - uuid := uuid.New() - return address.NewActorAddress(uuid[:]) +func (s *FvmSimulator) NewActorAddress() (address.Address, error) { + seed := time.Now().String() + return address.NewActorAddress([]byte(seed)) } -func (s *Fsm) GetActorCodeCid(addr address.Address) (*cid.Cid, error) { +func (s *FvmSimulator) GetActorCodeCid(addr address.Address) (*cid.Cid, error) { acstat, err := s.getActorWithAddress(addr) if err != nil { return nil, err @@ -90,7 +88,7 @@ func (s *Fsm) GetActorCodeCid(addr address.Address) (*cid.Cid, error) { return &acstat.Code, nil } -func (s *Fsm) ResolveBuiltinActorType(codeCid cid.Cid) (types.ActorType, error) { +func (s *FvmSimulator) ResolveBuiltinActorType(codeCid cid.Cid) (types.ActorType, error) { for k, v := range EmbeddedBuiltinActors { if v == codeCid { av, err := stringToactorType(k) @@ -100,7 +98,7 @@ func (s *Fsm) ResolveBuiltinActorType(codeCid cid.Cid) (types.ActorType, error) return types.ActorType(0), ErrorNotFound } -func (s *Fsm) GetCodeCidForType(actorT types.ActorType) (cid.Cid, error) { +func (s *FvmSimulator) GetCodeCidForType(actorT types.ActorType) (cid.Cid, error) { actstr, err := actorTypeTostring(actorT) if err != nil { return cid.Undef, err @@ -108,17 +106,17 @@ func (s *Fsm) GetCodeCidForType(actorT types.ActorType) (cid.Cid, error) { return EmbeddedBuiltinActors[actstr], nil } -func (s *Fsm) CreateActor(actorID abi.ActorID, codeCid cid.Cid) error { - SetActorAndAddress(uint32(actorID), migration.Actor{Code: codeCid}, address.Address{}) +func (s *FvmSimulator) CreateActor(actorID abi.ActorID, codeCid cid.Cid) error { + s.SetActorAndAddress(uint32(actorID), migration.Actor{Code: codeCid}, address.Address{}) return nil } // nolint -func (s *Fsm) Abort(code uint32, msg string) { +func (s *FvmSimulator) Abort(code uint32, msg string) { panic(fmt.Sprintf("%d:%s", code, msg)) } -func (s *Fsm) VerifySignature( +func (s *FvmSimulator) VerifySignature( signature *crypto.Signature, signer *address.Address, plaintext []byte, @@ -126,29 +124,29 @@ func (s *Fsm) VerifySignature( panic("This is not implement") } -func (s *Fsm) HashBlake2b(data []byte) ([32]byte, error) { +func (s *FvmSimulator) HashBlake2b(data []byte) ([32]byte, error) { result := blakehash(data) var temp [32]byte copy(temp[:], result[:32]) return temp, nil } -func (s *Fsm) ComputeUnsealedSectorCid( +func (s *FvmSimulator) ComputeUnsealedSectorCid( proofType abi.RegisteredSealProof, pieces []abi.PieceInfo, ) (cid.Cid, error) { panic("This is not implement") } -func (s *Fsm) VerifySeal(info *proof.SealVerifyInfo) (bool, error) { +func (s *FvmSimulator) VerifySeal(info *proof.SealVerifyInfo) (bool, error) { panic("This is not implement") } -func (s *Fsm) VerifyPost(info *proof.WindowPoStVerifyInfo) (bool, error) { +func (s *FvmSimulator) VerifyPost(info *proof.WindowPoStVerifyInfo) (bool, error) { panic("This is not implement") } -func (s *Fsm) VerifyConsensusFault( +func (s *FvmSimulator) VerifyConsensusFault( h1 []byte, h2 []byte, extra []byte, @@ -156,31 +154,31 @@ func (s *Fsm) VerifyConsensusFault( panic("This is not implement") } -func (s *Fsm) VerifyAggregateSeals(info *types.AggregateSealVerifyProofAndInfos) (bool, error) { +func (s *FvmSimulator) VerifyAggregateSeals(info *types.AggregateSealVerifyProofAndInfos) (bool, error) { panic("This is not implement") } -func (s *Fsm) VerifyReplicaUpdate(info *types.ReplicaUpdateInfo) (bool, error) { +func (s *FvmSimulator) VerifyReplicaUpdate(info *types.ReplicaUpdateInfo) (bool, error) { panic("This is not implement") } -func (s *Fsm) BatchVerifySeals(sealVerifyInfos []proof.SealVerifyInfo) ([]bool, error) { +func (s *FvmSimulator) BatchVerifySeals(sealVerifyInfos []proof.SealVerifyInfo) ([]bool, error) { panic("This is not implement") } -func (s *Fsm) VMContext() (*types.InvocationContext, error) { +func (s *FvmSimulator) VMContext() (*types.InvocationContext, error) { return s.callContext, nil } -func (s *Fsm) Enabled() (bool, error) { +func (s *FvmSimulator) Enabled() (bool, error) { return true, nil } -func (s *Fsm) Log(msg string) error { +func (s *FvmSimulator) Log(msg string) error { fmt.Println(msg) return nil } -func (s *Fsm) Send(to address.Address, method uint64, params uint32, value types.TokenAmount) (*types.Send, error) { +func (s *FvmSimulator) Send(to address.Address, method uint64, params uint32, value types.TokenAmount) (*types.Send, error) { send, ok := s.sendMatch(to, method, params, *value.Big()) if ok { return send, nil @@ -188,24 +186,24 @@ func (s *Fsm) Send(to address.Address, method uint64, params uint32, value types return nil, ErrorKeyMatchFail } -func (s *Fsm) GetChainRandomness(dst int64, round int64, entropy []byte) (abi.Randomness, error) { +func (s *FvmSimulator) GetChainRandomness(dst int64, round int64, entropy []byte) (abi.Randomness, error) { h := makeRandomness(dst, round, entropy) return abi.Randomness(h), nil } -func (s *Fsm) GetBeaconRandomness(dst int64, round int64, entropy []byte) (abi.Randomness, error) { +func (s *FvmSimulator) GetBeaconRandomness(dst int64, round int64, entropy []byte) (abi.Randomness, error) { h := makeRandomness(dst, round, entropy) return abi.Randomness(h), nil } -func (s *Fsm) BaseFee() (*types.TokenAmount, error) { - return s.baseFee, nil +func (s *FvmSimulator) BaseFee() (*types.TokenAmount, error) { + return &s.baseFee, nil } -func (s *Fsm) TotalFilCircSupply() (*types.TokenAmount, error) { - return s.totalFilCircSupply, nil +func (s *FvmSimulator) TotalFilCircSupply() (*types.TokenAmount, error) { + return &s.totalFilCircSupply, nil } -func (s *Fsm) Charge(name string, compute uint64) error { +func (s *FvmSimulator) Charge(name string, compute uint64) error { return nil } diff --git a/sdk/sys/simulated/options.go b/sdk/sys/simulated/options.go index e7cd5c3..eece5e0 100644 --- a/sdk/sys/simulated/options.go +++ b/sdk/sys/simulated/options.go @@ -8,11 +8,11 @@ import ( "github.com/ipfs-force-community/go-fvm-sdk/sdk/types" ) -func SetActorAndAddress(actorID uint32, actorState migration.Actor, addr address.Address) { - DefaultFsm.actorMutex.Lock() - defer DefaultFsm.actorMutex.Unlock() - DefaultFsm.actorsMap.Store(actorID, actorState) - DefaultFsm.addressMap.Store(addr, actorID) +func (s *FvmSimulator) SetActorAndAddress(actorID uint32, actorState migration.Actor, addr address.Address) { + s.actorMutex.Lock() + defer s.actorMutex.Unlock() + s.actorsMap.Store(actorID, actorState) + s.addressMap.Store(addr, actorID) } type SendMock struct { @@ -23,41 +23,41 @@ type SendMock struct { out types.Send } -func SetSend(mock ...SendMock) { +func (s *FvmSimulator) SetSend(mock ...SendMock) { temp := make([]SendMock, 0) for _, v := range mock { - _, ok := DefaultFsm.sendMatch(v.to, v.method, v.params, v.value) + _, ok := s.sendMatch(v.to, v.method, v.params, v.value) if !ok { temp = append(temp, v) } } - DefaultFsm.SendList = append(DefaultFsm.SendList, temp...) + s.sendList = append(s.sendList, temp...) } -func SetAccount(actorID uint32, addr address.Address, actor migration.Actor) { - DefaultFsm.actorMutex.Lock() - defer DefaultFsm.actorMutex.Unlock() +func (s *FvmSimulator) SetAccount(actorID uint32, addr address.Address, actor migration.Actor) { + s.actorMutex.Lock() + defer s.actorMutex.Unlock() - DefaultFsm.actorsMap.Store(actorID, actor) - DefaultFsm.addressMap.Store(addr, actorID) + s.actorsMap.Store(actorID, actor) + s.addressMap.Store(addr, actorID) } -func SetBaseFee(ta big.Int) { +func (s *FvmSimulator) SetBaseFee(ta big.Int) { amount, _ := types.FromString(ta.String()) - DefaultFsm.baseFee = &amount + s.baseFee = amount } -func SetTotalFilCircSupply(ta big.Int) { +func (s *FvmSimulator) SetTotalFilCircSupply(ta big.Int) { amount, _ := types.FromString(ta.String()) - DefaultFsm.totalFilCircSupply = &amount + s.totalFilCircSupply = amount } -func SetCurrentBalance(ta big.Int) { +func (s *FvmSimulator) SetCurrentBalance(ta big.Int) { amount, _ := types.FromString(ta.String()) - DefaultFsm.currentBalance = &amount + s.currentBalance = amount } -func SetCallContext(callcontext *types.InvocationContext) { - DefaultFsm.callContext = callcontext +func (s *FvmSimulator) SetCallContext(callcontext *types.InvocationContext) { + s.callContext = callcontext } diff --git a/sdk/sys/simulated/options_test.go b/sdk/sys/simulated/options_test.go index f422540..c6e03c9 100644 --- a/sdk/sys/simulated/options_test.go +++ b/sdk/sys/simulated/options_test.go @@ -9,10 +9,11 @@ import ( ) func TestSetSend(t *testing.T) { - sendMockCase := make([]SendMock, 0) - sendMockCase = append(sendMockCase, SendMock{address.Undef, 1, 1, big.NewInt(1), types.Send{}}) - SetSend(sendMockCase...) - _, ok := DefaultFsm.sendMatch(address.Undef, 1, 1, big.NewInt(1)) + sendmockcase := make([]SendMock, 0) + sendmockcase = append(sendmockcase, SendMock{address.Undef, 1, 1, big.NewInt(1), types.Send{}}) + defaultfsm := FvmSimulator{} + defaultfsm.SetSend(sendmockcase...) + _, ok := defaultfsm.sendMatch(address.Undef, 1, 1, big.NewInt(1)) if ok != true { t.Errorf("match is failed") } diff --git a/sdk/sys/simulated/state.go b/sdk/sys/simulated/state.go index 67c3684..64b9b56 100644 --- a/sdk/sys/simulated/state.go +++ b/sdk/sys/simulated/state.go @@ -2,6 +2,7 @@ package simulated import ( + "context" "sync" "github.com/filecoin-project/go-address" @@ -12,7 +13,7 @@ import ( mh "github.com/multiformats/go-multihash" ) -//nolint +// nolint type IpldOpen struct { codec uint64 id uint32 @@ -34,25 +35,20 @@ func (s *block) stat() BlockStat { type blocks []block -var DefaultFsm *Fsm - -func init() { - Begin() +// CreateSimulateEnv new context of simulated +func CreateSimulateEnv(callContext *types.InvocationContext, baseFee big.Int, totalFilCircSupply big.Int, currentBalance big.Int) (*FvmSimulator, context.Context) { + fsm := &FvmSimulator{blockid: 1, ipld: sync.Map{}, callContext: callContext, rootCid: cid.Undef, baseFee: types.FromBig(&baseFee), totalFilCircSupply: types.FromBig(&totalFilCircSupply), currentBalance: types.FromBig(¤tBalance)} + fsm.Context = context.WithValue(context.Background(), types.SimulatedEnvkey, fsm) + return fsm, fsm.Context } -func Begin() { - DefaultFsm = newSate() -} -func End() { - DefaultFsm = newSate() -} - -type Fsm struct { +type FvmSimulator struct { + Context context.Context blocksMutex sync.Mutex - blocks - blockid uint32 - Ipld sync.Map - actorMutex sync.Mutex + blocks blocks + blockid uint32 + ipld sync.Map + actorMutex sync.Mutex // actorid->ActorState actorsMap sync.Map // address->actorid @@ -60,14 +56,14 @@ type Fsm struct { callContext *types.InvocationContext rootCid cid.Cid - baseFee *types.TokenAmount - totalFilCircSupply *types.TokenAmount - currentBalance *types.TokenAmount - SendList []SendMock + baseFee types.TokenAmount + totalFilCircSupply types.TokenAmount + currentBalance types.TokenAmount + sendList []SendMock } -func (a *Fsm) sendMatch(to address.Address, method uint64, params uint32, value big.Int) (*types.Send, bool) { - for i, v := range a.SendList { +func (a *FvmSimulator) sendMatch(to address.Address, method uint64, params uint32, value big.Int) (*types.Send, bool) { + for i, v := range a.sendList { if to != v.to { continue } @@ -80,10 +76,10 @@ func (a *Fsm) sendMatch(to address.Address, method uint64, params uint32, value if !value.Equals(v.value) { continue } - if i == len(a.SendList)-1 { - a.SendList = a.SendList[0 : i-1] + if i == len(a.sendList)-1 { + a.sendList = a.sendList[0 : i-1] } else { - a.SendList = append(a.SendList[:i], a.SendList[i+1:]...) + a.sendList = append(a.sendList[:i], a.sendList[i+1:]...) } return &v.out, true @@ -91,27 +87,25 @@ func (a *Fsm) sendMatch(to address.Address, method uint64, params uint32, value return nil, false } -func newSate() *Fsm { - return &Fsm{blockid: 1, Ipld: sync.Map{}} -} - -func (s *Fsm) blockLink(blockid uint32, hashfun uint64, hashlen uint32) (cided cid.Cid, err error) { +func (s *FvmSimulator) blockLink(blockid uint32, hashfun uint64, hashlen uint32) (blkCid cid.Cid, err error) { block, err := s.getBlock(blockid) if err != nil { return cid.Undef, err } + Mult, _ := mh.Sum(block.data, hashfun, int(hashlen)) - cided = cid.NewCidV1(block.codec, Mult) - s.putData(cided, block.data) + + blkCid = cid.NewCidV1(block.codec, Mult) + s.putData(blkCid, block.data) return } -func (s *Fsm) blockCreate(codec uint64, data []byte) uint32 { +func (s *FvmSimulator) blockCreate(codec uint64, data []byte) uint32 { s.putBlock(block{codec: codec, data: data}) return uint32(len(s.blocks) - 1) } -func (s *Fsm) blockOpen(id cid.Cid) (blockID uint32, blockStat BlockStat) { +func (s *FvmSimulator) blockOpen(id cid.Cid) (blockID uint32, blockStat BlockStat) { data, _ := s.getData(id) block := block{data: data, codec: id.Prefix().GetCodec()} @@ -121,7 +115,7 @@ func (s *Fsm) blockOpen(id cid.Cid) (blockID uint32, blockStat BlockStat) { } -func (s *Fsm) blockRead(id uint32, offset uint32) ([]byte, error) { +func (s *FvmSimulator) blockRead(id uint32, offset uint32) ([]byte, error) { block, err := s.getBlock(id) if err != nil { return nil, err @@ -134,7 +128,7 @@ func (s *Fsm) blockRead(id uint32, offset uint32) ([]byte, error) { return data[offset:], nil } -func (s *Fsm) blockStat(blockID uint32) (*types.IpldStat, error) { +func (s *FvmSimulator) blockStat(blockID uint32) (*types.IpldStat, error) { b, err := s.getBlock(blockID) if err != nil { return nil, ErrorNotFound @@ -142,28 +136,28 @@ func (s *Fsm) blockStat(blockID uint32) (*types.IpldStat, error) { return &types.IpldStat{Size: b.stat().size, Codec: b.codec}, ErrorNotFound } -func (s *Fsm) putData(key cid.Cid, value []byte) { - - s.Ipld.Store(key, value) +func (s *FvmSimulator) putData(key cid.Cid, value []byte) { + s.ipld.Store(key, value) } -func (s *Fsm) getData(key cid.Cid) ([]byte, error) { - value, ok := s.Ipld.Load(key) +func (s *FvmSimulator) getData(key cid.Cid) ([]byte, error) { + value, ok := s.ipld.Load(key) if ok { return value.([]byte), nil } return nil, ErrorNotFound } -func (s *Fsm) putBlock(block block) uint32 { +func (s *FvmSimulator) putBlock(block block) uint32 { s.blocksMutex.Lock() defer s.blocksMutex.Unlock() s.blocks = append(s.blocks, block) + return uint32(len(s.blocks) - 1) } -func (s *Fsm) getBlock(blockID uint32) (block, error) { +func (s *FvmSimulator) getBlock(blockID uint32) (block, error) { s.blocksMutex.Lock() defer s.blocksMutex.Unlock() @@ -173,18 +167,18 @@ func (s *Fsm) getBlock(blockID uint32) (block, error) { return s.blocks[blockID], nil } -//nolint -func (s *Fsm) putActor(actorID uint64, actor migration.Actor) error { +// nolint +func (s *FvmSimulator) putActor(actorID uint64, actor migration.Actor) error { _, err := s.getActorWithActorid(uint32(actorID)) if err == nil { return ErrorKeyExists } - s.Ipld.Store(actorID, actor) + s.ipld.Store(actorID, actor) return nil } -//nolint -func (s *Fsm) getActorWithActorid(actorID uint32) (migration.Actor, error) { +// nolint +func (s *FvmSimulator) getActorWithActorid(actorID uint32) (migration.Actor, error) { actor, ok := s.actorsMap.Load(actorID) if ok { return actor.(migration.Actor), nil @@ -192,8 +186,8 @@ func (s *Fsm) getActorWithActorid(actorID uint32) (migration.Actor, error) { return migration.Actor{}, ErrorNotFound } -//nolint -func (s *Fsm) getActorWithAddress(addr address.Address) (migration.Actor, error) { +// nolint +func (s *FvmSimulator) getActorWithAddress(addr address.Address) (migration.Actor, error) { s.actorMutex.Lock() defer s.actorMutex.Unlock() diff --git a/sdk/sys/simulated/utils.go b/sdk/sys/simulated/utils.go index 7af2a7e..6b8e448 100644 --- a/sdk/sys/simulated/utils.go +++ b/sdk/sys/simulated/utils.go @@ -2,7 +2,6 @@ package simulated import ( - "crypto/sha256" "encoding/binary" "reflect" "unsafe" @@ -41,10 +40,7 @@ func makeRandomness(dst int64, round int64, entropy []byte) []byte { binary.BigEndian.PutUint64(roundbyte[0:8], abs(round)) entropy = append(entropy, dstbyte[:]...) entropy = append(entropy, roundbyte[:]...) - h := sha256.New() - h.Write(entropy) - result := h.Sum(nil) - return result + return blakehash(entropy) } func abs(i int64) uint64 { diff --git a/sdk/sys/sself.go b/sdk/sys/sself.go index e7236d4..27db7bb 100644 --- a/sdk/sys/sself.go +++ b/sdk/sys/sself.go @@ -1,9 +1,10 @@ -//go:build !simulated -// +build !simulated +//go:build !simulate +// +build !simulate package sys import ( + "context" "fmt" "unsafe" @@ -13,7 +14,7 @@ import ( "github.com/ipfs/go-cid" ) -func SelfRoot() (cid.Cid, error) { +func SelfRoot(ctx context.Context) (cid.Cid, error) { // I really hate this CID interface. Why can't I just have bytes? result := uint32(0) cidBuf := make([]byte, types.MaxCidLen) @@ -30,7 +31,7 @@ func SelfRoot() (cid.Cid, error) { return cid, err } -func SelfSetRoot(id cid.Cid) error { +func SelfSetRoot(ctx context.Context, id cid.Cid) error { buf := make([]byte, types.MaxCidLen) copy(buf, id.Bytes()) cidBufPtr, _ := GetSlicePointerAndLen(buf) @@ -42,7 +43,7 @@ func SelfSetRoot(id cid.Cid) error { } -func SelfCurrentBalance() (*types.TokenAmount, error) { +func SelfCurrentBalance(ctx context.Context) (*types.TokenAmount, error) { result := new(types.TokenAmount) code := selfCurrentBalance(uintptr(unsafe.Pointer(result))) if code != 0 { @@ -51,7 +52,7 @@ func SelfCurrentBalance() (*types.TokenAmount, error) { return result, nil } -func SelfDestruct(addr addr.Address) error { +func SelfDestruct(ctx context.Context, addr addr.Address) error { addrPtr, addrLen := GetSlicePointerAndLen(addr.Bytes()) code := selfDestruct(addrPtr, addrLen) if code != 0 { diff --git a/sdk/sys/sself_simulated.go b/sdk/sys/sself_simulated.go index 4676c31..587e7e7 100644 --- a/sdk/sys/sself_simulated.go +++ b/sdk/sys/sself_simulated.go @@ -1,27 +1,40 @@ -//go:build simulated -// +build simulated +//go:build simulate +// +build simulate package sys import ( + "context" + addr "github.com/filecoin-project/go-address" - "github.com/ipfs-force-community/go-fvm-sdk/sdk/sys/simulated" "github.com/ipfs-force-community/go-fvm-sdk/sdk/types" "github.com/ipfs/go-cid" ) -func SelfRoot() (cid.Cid, error) { - return simulated.DefaultFsm.SelfRoot() +func SelfRoot(ctx context.Context) (cid.Cid, error) { + if env, ok := tryGetSimulator(ctx); ok { + return env.SelfRoot() + } + panic(ErrorEnvValid) } -func SelfSetRoot(id cid.Cid) error { - return simulated.DefaultFsm.SelfSetRoot(id) +func SelfSetRoot(ctx context.Context, id cid.Cid) error { + if env, ok := tryGetSimulator(ctx); ok { + return env.SelfSetRoot(id) + } + panic(ErrorEnvValid) } -func SelfCurrentBalance() (*types.TokenAmount, error) { - return simulated.DefaultFsm.SelfCurrentBalance() +func SelfCurrentBalance(ctx context.Context) (*types.TokenAmount, error) { + if env, ok := tryGetSimulator(ctx); ok { + return env.SelfCurrentBalance() + } + panic(ErrorEnvValid) } -func SelfDestruct(addr addr.Address) error { - return simulated.DefaultFsm.SelfDestruct(addr) +func SelfDestruct(ctx context.Context, addr addr.Address) error { + if env, ok := tryGetSimulator(ctx); ok { + return env.SelfDestruct(addr) + } + panic(ErrorEnvValid) } diff --git a/sdk/testing/testingT.go b/sdk/testing/testingT.go index f2c6da7..27286e5 100644 --- a/sdk/testing/testingT.go +++ b/sdk/testing/testingT.go @@ -2,6 +2,7 @@ package testing import ( "bytes" + "context" "fmt" "github.com/ipfs-force-community/go-fvm-sdk/sdk" @@ -33,21 +34,21 @@ func (t *TestingT) Error(args ...interface{}) { } func (t *TestingT) Infof(format string, args ...interface{}) { - t.logger.Logf(format, args...) + t.logger.Logf(context.Background(), format, args...) } func (t *TestingT) Info(args ...interface{}) { - t.logger.Log(args...) + t.logger.Log(context.Background(), args...) } func (t *TestingT) FailNow() { t.failed = true - sdk.Abort(ferrors.SYS_ASSERTION_FAILED, t.errBuf.String()) + sdk.Abort(context.Background(), ferrors.SYS_ASSERTION_FAILED, t.errBuf.String()) } func (t *TestingT) CheckResult() { if t.failed { - sdk.Abort(ferrors.SYS_ASSERTION_FAILED, fmt.Sprintf("assert fail:\n"+t.errBuf.String())) + sdk.Abort(context.Background(), ferrors.SYS_ASSERTION_FAILED, fmt.Sprintf("assert fail:\n"+t.errBuf.String())) } } diff --git a/sdk/types/key.go b/sdk/types/key.go index 1e53364..21c7ff0 100644 --- a/sdk/types/key.go +++ b/sdk/types/key.go @@ -19,3 +19,7 @@ type StringKey string func (k StringKey) Key() string { return string(k) } + +type emptyKeyType struct{} + +var SimulatedEnvkey emptyKeyType diff --git a/sdk/utils.go b/sdk/utils.go index 8564984..bb94241 100644 --- a/sdk/utils.go +++ b/sdk/utils.go @@ -2,6 +2,7 @@ package sdk import ( "bytes" + "context" "fmt" "unsafe" @@ -13,65 +14,65 @@ import ( ) // SaveState save actor state -func SaveState(state cbor.Marshaler) cid.Cid { +func SaveState(ctx context.Context, state cbor.Marshaler) cid.Cid { buf := bytes.NewBuffer([]byte{}) err := state.MarshalCBOR(buf) if err != nil { - Abort(ferrors.USR_ILLEGAL_STATE, fmt.Sprintf("failed to get root: %v", err)) + Abort(ctx, ferrors.USR_ILLEGAL_STATE, fmt.Sprintf("failed to get root: %v", err)) } stBytes := buf.Bytes() - stCid, err := Put(0xb220, 32, types.DAGCbor, stBytes) + stCid, err := Put(ctx, 0xb220, 32, types.DAGCbor, stBytes) if err != nil { - Abort(ferrors.USR_ILLEGAL_STATE, fmt.Sprintf("failed to get root: %v", err)) + Abort(ctx, ferrors.USR_ILLEGAL_STATE, fmt.Sprintf("failed to get root: %v", err)) } - err = SetRoot(stCid) + err = SetRoot(ctx, stCid) if err != nil { - Abort(ferrors.USR_ILLEGAL_STATE, fmt.Sprintf("failed to get root: %v", err)) + Abort(ctx, ferrors.USR_ILLEGAL_STATE, fmt.Sprintf("failed to get root: %v", err)) } return stCid } // Constructor construct a acor with initialize state -func Constructor(state cbor.Marshaler) error { - caller, err := Caller() +func Constructor(ctx context.Context, state cbor.Marshaler) error { + caller, err := Caller(ctx) if err != nil { - Abort(ferrors.USR_ILLEGAL_STATE, "unable to get caller") + Abort(ctx, ferrors.USR_ILLEGAL_STATE, "unable to get caller") } if caller != 1 { - Abort(ferrors.USR_ILLEGAL_STATE, "constructor invoked by non-init actor") + Abort(ctx, ferrors.USR_ILLEGAL_STATE, "constructor invoked by non-init actor") } - _ = SaveState(state) + _ = SaveState(ctx, state) return nil } // LoadState loads actors current state -func LoadState(state cbor.Unmarshaler) { - root, err := Root() +func LoadState(ctx context.Context, state cbor.Unmarshaler) { + root, err := Root(ctx) if err != nil { - Abort(ferrors.USR_ILLEGAL_STATE, fmt.Sprintf("failed to get root: %v", err)) + Abort(ctx, ferrors.USR_ILLEGAL_STATE, fmt.Sprintf("failed to get root: %v", err)) } - data, err := Get(root) + data, err := Get(ctx, root) if err != nil { - Abort(ferrors.USR_ILLEGAL_STATE, fmt.Sprintf("failed to get data: %v", err)) + Abort(ctx, ferrors.USR_ILLEGAL_STATE, fmt.Sprintf("failed to get data: %v", err)) } err = state.UnmarshalCBOR(bytes.NewReader(data)) if err != nil { - Abort(ferrors.USR_ILLEGAL_STATE, fmt.Sprintf("failed to get data: %v", err)) + Abort(ctx, ferrors.USR_ILLEGAL_STATE, fmt.Sprintf("failed to get data: %v", err)) } } -func LoadStateFromCid(cid cid.Cid, state cbor.Unmarshaler) { // nolint - data, err := Get(cid) +func LoadStateFromCid(ctx context.Context, cid cid.Cid, state cbor.Unmarshaler) { // nolint + data, err := Get(ctx, cid) if err != nil { - Abort(ferrors.USR_ILLEGAL_STATE, fmt.Sprintf("failed to get data: %v", err)) + Abort(ctx, ferrors.USR_ILLEGAL_STATE, fmt.Sprintf("failed to get data: %v", err)) } err = state.UnmarshalCBOR(bytes.NewReader(data)) if err != nil { - Abort(ferrors.USR_ILLEGAL_STATE, fmt.Sprintf("failed to get data: %v", err)) + Abort(ctx, ferrors.USR_ILLEGAL_STATE, fmt.Sprintf("failed to get data: %v", err)) } } diff --git a/tools/sdk_tool/src/wasmprocess.rs b/tools/sdk_tool/src/wasmprocess.rs index 76b3faa..6b76ac8 100644 --- a/tools/sdk_tool/src/wasmprocess.rs +++ b/tools/sdk_tool/src/wasmprocess.rs @@ -346,7 +346,7 @@ impl<'a> GoFvmBinProcessor<'a> { Instruction::I32Load(2, 0), //why -1 Instruction::GetLocal(1), Instruction::I32Load(2, 4), - Instruction::Call(new_insert_debug_index as u32), + Instruction::Call(new_insert_debug_index), ]), ); codes.push(fd_write_code);