Skip to content

Commit

Permalink
Merge pull request #2840 from jorgemmsilva/feat/nft-mint
Browse files Browse the repository at this point in the history
feat: nft mint
  • Loading branch information
jorgemmsilva authored Sep 8, 2023
2 parents bf363f6 + 0e57a3e commit 6c1b772
Show file tree
Hide file tree
Showing 42 changed files with 752 additions and 168 deletions.
2 changes: 0 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -657,8 +657,6 @@ github.com/samber/lo v1.38.1/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXn
github.com/sasha-s/go-deadlock v0.3.1 h1:sqv7fDNShgjcaxkO0JNcOAlr8B9+cV5Ey/OB71efZx0=
github.com/sasha-s/go-deadlock v0.3.1/go.mod h1:F73l+cr82YSh10GxyRI6qZiCgK64VaZjwesgfQ1/iLM=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
github.com/second-state/WasmEdge-go v0.13.3 h1:ZUPMQKJH0FHVGvBiobuEkNOKMfIL20fP0H5aaqG1JtY=
github.com/second-state/WasmEdge-go v0.13.3/go.mod h1:HyBf9hVj1sRAjklsjc1Yvs9b5RcmthPG9z99dY78TKg=
github.com/second-state/WasmEdge-go v0.13.4 h1:NHfJC+aayUW93ydAzlcX7Jx1WDRpI24KvY5SAbeTyvY=
github.com/second-state/WasmEdge-go v0.13.4/go.mod h1:HyBf9hVj1sRAjklsjc1Yvs9b5RcmthPG9z99dY78TKg=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
Expand Down
4 changes: 4 additions & 0 deletions packages/chain/mempool/mempool.go
Original file line number Diff line number Diff line change
Expand Up @@ -649,6 +649,10 @@ func (mpi *mempoolImpl) handleReceiveOnLedgerRequest(request isc.OnLedgerRequest
mpi.log.Warnf("dropping request, because it has ReturnAmount, ID=%v", requestID)
return
}
if request.SenderAccount() == nil {
// do not process requests without the sender feature
return
}
//
// Check, maybe mempool already has it.
if mpi.onLedgerPool.Has(requestRef) || mpi.timePool.Has(requestRef) {
Expand Down
2 changes: 1 addition & 1 deletion packages/chain/mempool/mempool_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -779,7 +779,7 @@ func getRequestsOnLedger(t *testing.T, chainAddress iotago.Address, amount int,
}
output := transaction.BasicOutputFromPostData(
tpkg.RandEd25519Address(),
isc.Hn("dummySenderContract"),
0,
requestParams,
)
outputID := tpkg.RandOutputID(uint16(i))
Expand Down
3 changes: 1 addition & 2 deletions packages/isc/sandbox_interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,6 @@ type Sandbox interface {
EstimateRequiredStorageDeposit(r RequestParameters) uint64
// StateAnchor properties of the anchor output
StateAnchor() *StateAnchor
// MintNFT mints an NFT
// MintNFT(metadata []byte) // TODO returns a temporary ID

// EVMTracer returns a non-nil tracer if an EVM tx is being traced
// (e.g. with the debug_traceTransaction JSONRPC method).
Expand All @@ -138,6 +136,7 @@ type Privileged interface {
CreateNewFoundry(scheme iotago.TokenScheme, metadata []byte) (uint32, uint64)
DestroyFoundry(uint32) uint64
ModifyFoundrySupply(serNum uint32, delta *big.Int) int64
MintNFT(addr iotago.Address, immutableMetadata []byte, issuer iotago.Address) (uint16, *iotago.NFTOutput)
GasBurnEnable(enable bool)
MustMoveBetweenAccounts(fromAgentID, toAgentID AgentID, assets *Assets)
DebitFromAccount(AgentID, *Assets)
Expand Down
2 changes: 2 additions & 0 deletions packages/kv/codec/encodego.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ func Encode(v interface{}) []byte {
return EncodeRequestID(*vt)
case isc.Hname:
return vt.Bytes()
case iotago.NFTID:
return EncodeNFTID(vt)
case isc.VMErrorCode:
return vt.Bytes()
case time.Time:
Expand Down
14 changes: 7 additions & 7 deletions packages/solo/ledgerl1l2.go
Original file line number Diff line number Diff line change
Expand Up @@ -358,13 +358,13 @@ func (ch *Chain) MustDepositNFT(nft *isc.NFT, to isc.AgentID, owner *cryptolib.K

// Withdraw sends assets from the L2 account to L1
func (ch *Chain) Withdraw(assets *isc.Assets, user *cryptolib.KeyPair) error {
_, err := ch.PostRequestSync(
NewCallParams(accounts.Contract.Name, accounts.FuncWithdraw.Name).
AddAllowance(assets).
AddAllowance(isc.NewAssetsBaseTokens(1*isc.Million)). // for storage deposit
WithGasBudget(math.MaxUint64),
user,
)
req := NewCallParams(accounts.Contract.Name, accounts.FuncWithdraw.Name).
AddAllowance(assets).
WithGasBudget(math.MaxUint64)
if assets.BaseTokens == 0 {
req.AddAllowance(isc.NewAssetsBaseTokens(1 * isc.Million)) // for storage deposit
}
_, err := ch.PostRequestOffLedger(req, user)
return err
}

Expand Down
16 changes: 15 additions & 1 deletion packages/solo/mempool.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ package solo

import (
"fmt"
"sync"
"time"

"github.com/iotaledger/wasp/packages/isc"
Expand All @@ -30,18 +31,27 @@ type mempoolImpl struct {
requests map[isc.RequestID]isc.Request
info MempoolInfo
currentTime func() time.Time
chainID isc.ChainID
mu sync.Mutex
}

func newMempool(currentTime func() time.Time) Mempool {
func newMempool(currentTime func() time.Time, chainID isc.ChainID) Mempool {
return &mempoolImpl{
requests: map[isc.RequestID]isc.Request{},
info: MempoolInfo{},
currentTime: currentTime,
chainID: chainID,
mu: sync.Mutex{},
}
}

func (mi *mempoolImpl) ReceiveRequests(reqs ...isc.Request) {
mi.mu.Lock()
defer mi.mu.Unlock()
for _, req := range reqs {
if req.SenderAccount() == nil {
continue // ignore requests without a sender
}
if _, ok := mi.requests[req.ID()]; !ok {
mi.info.TotalPool++
mi.info.InPoolCounter++
Expand All @@ -51,6 +61,8 @@ func (mi *mempoolImpl) ReceiveRequests(reqs ...isc.Request) {
}

func (mi *mempoolImpl) RequestBatchProposal() []isc.Request {
mi.mu.Lock()
defer mi.mu.Unlock()
now := mi.currentTime()
batch := []isc.Request{}
for rid, request := range mi.requests {
Expand Down Expand Up @@ -78,6 +90,8 @@ func (mi *mempoolImpl) RequestBatchProposal() []isc.Request {
}

func (mi *mempoolImpl) RemoveRequest(rID isc.RequestID) {
mi.mu.Lock()
defer mi.mu.Unlock()
if _, ok := mi.requests[rID]; ok {
mi.info.OutPoolCounter++
mi.info.TotalPool--
Expand Down
6 changes: 3 additions & 3 deletions packages/solo/req.go
Original file line number Diff line number Diff line change
Expand Up @@ -454,16 +454,16 @@ func (ch *Chain) CallView(scName, funName string, params ...interface{}) (dict.D

func (ch *Chain) CallViewAtState(chainState state.State, scName, funName string, params ...interface{}) (dict.Dict, error) {
ch.Log().Debugf("callView: %s::%s", scName, funName)
return ch.CallViewByHnameAtState(chainState, isc.Hn(scName), isc.Hn(funName), params...)
return ch.callViewByHnameAtState(chainState, isc.Hn(scName), isc.Hn(funName), params...)
}

func (ch *Chain) CallViewByHname(hContract, hFunction isc.Hname, params ...interface{}) (dict.Dict, error) {
latestState, err := ch.store.LatestState()
require.NoError(ch.Env.T, err)
return ch.CallViewByHnameAtState(latestState, hContract, hFunction, params...)
return ch.callViewByHnameAtState(latestState, hContract, hFunction, params...)
}

func (ch *Chain) CallViewByHnameAtState(chainState state.State, hContract, hFunction isc.Hname, params ...interface{}) (dict.Dict, error) {
func (ch *Chain) callViewByHnameAtState(chainState state.State, hContract, hFunction isc.Hname, params ...interface{}) (dict.Dict, error) {
ch.Log().Debugf("callView: %s::%s", hContract.String(), hFunction.String())

p := parseParams(params)
Expand Down
7 changes: 2 additions & 5 deletions packages/solo/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,6 @@ func (ch *Chain) RunOffLedgerRequests(reqs []isc.Request) []*vm.RequestResult {
func (ch *Chain) RunRequestsSync(reqs []isc.Request, trace string) (results []*vm.RequestResult) {
ch.runVMMutex.Lock()
defer ch.runVMMutex.Unlock()

ch.mempool.ReceiveRequests(reqs...)

return ch.runRequestsNolock(reqs, trace)
}

Expand Down Expand Up @@ -128,6 +125,8 @@ func (ch *Chain) runRequestsNolock(reqs []isc.Request, trace string) (results []
l1C := ch.GetL1Commitment()
require.Equal(ch.Env.T, rootC, l1C.TrieRoot())

ch.Env.EnqueueRequests(tx)

return res.RequestResults
}

Expand Down Expand Up @@ -155,8 +154,6 @@ func (ch *Chain) settleStateTransition(stateTx *iotago.Transaction, stateDraft s
}
ch.Log().Infof("state transition --> #%d. Requests in the block: %d. Outputs: %d",
stateDraft.BlockIndex(), len(blockReceipts), len(stateTx.Essence.Outputs))

go ch.Env.EnqueueRequests(stateTx)
}

func (ch *Chain) logRequestLastBlock() {
Expand Down
10 changes: 6 additions & 4 deletions packages/solo/snapshot.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package solo
import (
"encoding/json"
"os"
"sync"

"github.com/stretchr/testify/require"

Expand All @@ -29,8 +30,8 @@ type soloChainSnapshot struct {

// SaveSnapshot generates a snapshot of the Solo environment
func (env *Solo) SaveSnapshot(fname string) {
env.glbMutex.Lock()
defer env.glbMutex.Unlock()
env.chainsMutex.Lock()
defer env.chainsMutex.Unlock()

snapshot := soloSnapshot{
UtxoDB: env.utxoDB.State(),
Expand Down Expand Up @@ -62,8 +63,8 @@ func (env *Solo) SaveSnapshot(fname string) {

// LoadSnapshot restores the Solo environment from the given snapshot
func (env *Solo) LoadSnapshot(fname string) {
env.glbMutex.Lock()
defer env.glbMutex.Unlock()
env.chainsMutex.Lock()
defer env.chainsMutex.Unlock()

b, err := os.ReadFile(fname)
require.NoError(env.T, err)
Expand Down Expand Up @@ -99,6 +100,7 @@ func (env *Solo) LoadSnapshot(fname string) {
OriginatorPrivateKey: okp,
ValidatorFeeTarget: val,
db: db,
writeMutex: &sync.Mutex{},
}
env.addChain(chainData)
}
Expand Down
31 changes: 12 additions & 19 deletions packages/solo/solo.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import (
"github.com/iotaledger/wasp/packages/vm/core/coreprocessors"
"github.com/iotaledger/wasp/packages/vm/core/governance"
"github.com/iotaledger/wasp/packages/vm/core/migrations"
"github.com/iotaledger/wasp/packages/vm/core/migrations/allmigrations"
"github.com/iotaledger/wasp/packages/vm/processors"
_ "github.com/iotaledger/wasp/packages/vm/sandbox"
"github.com/iotaledger/wasp/packages/vm/vmtypes"
Expand All @@ -59,7 +60,7 @@ type Solo struct {
logger *logger.Logger
chainStateDatabaseManager *database.ChainStateDatabaseManager
utxoDB *utxodb.UtxoDB
glbMutex sync.RWMutex
chainsMutex sync.RWMutex
ledgerMutex sync.RWMutex
chains map[isc.ChainID]*Chain
processorConfig *processors.Config
Expand Down Expand Up @@ -212,8 +213,8 @@ func (env *Solo) Publisher() *publisher.Publisher {
}

func (env *Solo) GetChainByName(name string) *Chain {
env.glbMutex.Lock()
defer env.glbMutex.Unlock()
env.chainsMutex.Lock()
defer env.chainsMutex.Unlock()
for _, ch := range env.chains {
if ch.Name == name {
return ch
Expand Down Expand Up @@ -343,8 +344,8 @@ func (env *Solo) NewChainExt(
) (*Chain, *iotago.Transaction) {
chData, originTx := env.deployChain(chainOriginator, initBaseTokens, name, originParams...)

env.glbMutex.Lock()
defer env.glbMutex.Unlock()
env.chainsMutex.Lock()
defer env.chainsMutex.Unlock()
ch := env.addChain(chData)

ch.log.Infof("chain '%s' deployed. Chain ID: %s", ch.Name, ch.ChainID.String())
Expand All @@ -362,7 +363,8 @@ func (env *Solo) addChain(chData chainData) *Chain {
proc: processors.MustNew(env.processorConfig),
log: env.logger.Named(chData.Name),
metrics: metrics.NewChainMetricsProvider().GetChainMetrics(chData.ChainID),
mempool: newMempool(env.utxoDB.GlobalTime),
mempool: newMempool(env.utxoDB.GlobalTime, chData.ChainID),
migrationScheme: allmigrations.DefaultScheme,
}
env.chains[chData.ChainID] = ch
go ch.batchLoop()
Expand All @@ -377,8 +379,8 @@ func (env *Solo) AddToLedger(tx *iotago.Transaction) error {

// RequestsForChain parses the transaction and returns all requests contained in it which have chainID as the target
func (env *Solo) RequestsForChain(tx *iotago.Transaction, chainID isc.ChainID) ([]isc.Request, error) {
env.glbMutex.RLock()
defer env.glbMutex.RUnlock()
env.chainsMutex.RLock()
defer env.chainsMutex.RUnlock()

m := env.requestsByChain(tx)
ret, ok := m[chainID]
Expand All @@ -397,18 +399,13 @@ func (env *Solo) requestsByChain(tx *iotago.Transaction) map[isc.ChainID][]isc.R

// AddRequestsToMempool adds all the requests to the chain mempool,
func (env *Solo) AddRequestsToMempool(ch *Chain, reqs []isc.Request) {
env.glbMutex.RLock()
defer env.glbMutex.RUnlock()
ch.runVMMutex.Lock()
defer ch.runVMMutex.Unlock()

ch.mempool.ReceiveRequests(reqs...)
}

// EnqueueRequests adds requests contained in the transaction to mempools of respective target chains
func (env *Solo) EnqueueRequests(tx *iotago.Transaction) {
env.glbMutex.RLock()
defer env.glbMutex.RUnlock()
env.chainsMutex.RLock()
defer env.chainsMutex.RUnlock()

requests := env.requestsByChain(tx)

Expand All @@ -418,11 +415,7 @@ func (env *Solo) EnqueueRequests(tx *iotago.Transaction) {
env.logger.Infof("dispatching requests. Unknown chain: %s", chainID.String())
continue
}
ch.runVMMutex.Lock()

ch.mempool.ReceiveRequests(reqs...)

ch.runVMMutex.Unlock()
}
}

Expand Down
2 changes: 1 addition & 1 deletion packages/testutil/testdbhash/TestStorageContract.hex
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0x24e3aae46e4ed7ce22ac6eb6baf81fbca6c3777fdaaee73b2dae77a0267d96b1
0x067c2015d0e63eb81b311fcddc20693668c18b575752786aa0288ce59c820391
2 changes: 1 addition & 1 deletion packages/vm/core/accounts/foundries.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ func allFoundriesMapR(state kv.KVStoreReader) *collections.ImmutableMap {
}

// SaveFoundryOutput stores foundry output into the map of all foundry outputs (compressed form)
func SaveFoundryOutput(state kv.KVStore, f *iotago.FoundryOutput, blockIndex uint32, outputIndex uint16) {
func SaveFoundryOutput(state kv.KVStore, f *iotago.FoundryOutput, outputIndex uint16) {
foundryRec := foundryOutputRec{
// TransactionID is unknown yet, will be filled next block
OutputID: iotago.OutputIDFromTransactionIDAndIndex(iotago.TransactionID{}, outputIndex),
Expand Down
2 changes: 2 additions & 0 deletions packages/vm/core/accounts/impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ var Processor = Contract.Processor(nil,
FuncFoundryCreateNew.WithHandler(foundryCreateNew),
FuncFoundryDestroy.WithHandler(foundryDestroy),
FuncFoundryModifySupply.WithHandler(foundryModifySupply),
FuncMintNFT.WithHandler(mintNFT),
FuncTransferAccountToChain.WithHandler(transferAccountToChain),
FuncTransferAllowanceTo.WithHandler(transferAllowanceTo),
FuncWithdraw.WithHandler(withdraw),
Expand All @@ -35,6 +36,7 @@ var Processor = Contract.Processor(nil,
ViewAccountNFTAmount.WithHandler(viewAccountNFTAmount),
ViewAccountNFTsInCollection.WithHandler(viewAccountNFTsInCollection),
ViewAccountNFTAmountInCollection.WithHandler(viewAccountNFTAmountInCollection),
ViewNFTIDbyMintID.WithHandler(viewNFTIDbyMintID),
ViewAccountFoundries.WithHandler(viewAccountFoundries),
ViewAccounts.WithHandler(viewAccounts),
ViewBalance.WithHandler(viewBalance),
Expand Down
7 changes: 5 additions & 2 deletions packages/vm/core/accounts/impl_views.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ func viewAccountNFTs(ctx isc.SandboxView) dict.Dict {
func viewAccountNFTAmount(ctx isc.SandboxView) dict.Dict {
aid := ctx.Params().MustGetAgentID(ParamAgentID, ctx.Caller())
return dict.Dict{
ParamNFTAmount: codec.EncodeUint32(nftsMapR(ctx.StateR(), aid).Len()),
ParamNFTAmount: codec.EncodeUint32(accountToNFTsMapR(ctx.StateR(), aid).Len()),
}
}

Expand Down Expand Up @@ -155,7 +155,10 @@ func viewAccountNFTAmountInCollection(ctx isc.SandboxView) dict.Dict {
func viewNFTData(ctx isc.SandboxView) dict.Dict {
ctx.Log().Debugf("accounts.viewNFTData")
nftID := ctx.Params().MustGetNFTID(ParamNFTID)
data := MustGetNFTData(ctx.StateR(), nftID)
data := GetNFTData(ctx.StateR(), nftID)
if data == nil {
panic("NFTID not found")
}
return dict.Dict{
ParamNFTData: data.Bytes(),
}
Expand Down
5 changes: 5 additions & 0 deletions packages/vm/core/accounts/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ var (
FuncFoundryCreateNew = coreutil.Func("foundryCreateNew")
FuncFoundryDestroy = coreutil.Func("foundryDestroy")
FuncFoundryModifySupply = coreutil.Func("foundryModifySupply")
FuncMintNFT = coreutil.Func("mintNFT")
FuncTransferAccountToChain = coreutil.Func("transferAccountToChain")
FuncTransferAllowanceTo = coreutil.Func("transferAllowanceTo")
FuncWithdraw = coreutil.Func("withdraw")
Expand All @@ -24,6 +25,7 @@ var (
ViewAccountNFTAmountInCollection = coreutil.ViewFunc("accountNFTAmountInCollection")
ViewAccountNFTs = coreutil.ViewFunc("accountNFTs")
ViewAccountNFTsInCollection = coreutil.ViewFunc("accountNFTsInCollection")
ViewNFTIDbyMintID = coreutil.ViewFunc("NFTIDbyMintID")
ViewAccounts = coreutil.ViewFunc("accounts")
ViewBalance = coreutil.ViewFunc("balance")
ViewBalanceBaseToken = coreutil.ViewFunc("balanceBaseToken")
Expand All @@ -50,6 +52,9 @@ const (
ParamNFTData = "e"
ParamNFTID = "z"
ParamNFTIDs = "i"
ParamNFTImmutableData = "I"
ParamNFTWithdrawOnMint = "w"
ParamMintID = "D"
ParamNativeTokenID = "N"
ParamSupplyDeltaAbs = "d"
ParamTokenScheme = "t"
Expand Down
Loading

0 comments on commit 6c1b772

Please sign in to comment.