Skip to content

Commit

Permalink
Dosable addr (#165)
Browse files Browse the repository at this point in the history
fixes #79 
refs #164 

- added a nonce field to TxCreateDeployment and TxCreateProvider
- check txs with
  - tenant/owner is a singer
  - nonce is valid
- generate the address on the node in deliverTx
- increment account nonce only after successful deliverTx
  • Loading branch information
aastein authored Mar 30, 2018
1 parent 4fe3100 commit 939d951
Show file tree
Hide file tree
Showing 14 changed files with 571 additions and 217 deletions.
57 changes: 36 additions & 21 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,12 +152,28 @@ func (app *app) Query(req tmtypes.RequestQuery) tmtypes.ResponseQuery {
return tmtypes.ResponseQuery{Code: code.UNKNOWN_QUERY, Log: "unknown query"}
}

func (app *app) checkNonce(address []byte, nonce uint64) apptypes.Error {
signer, err_ := app.state.Account().Get(address)
if err_ != nil {
return apptypes.NewError(code.INVALID_TRANSACTION, err_.Error())
}
err := apptypes.NewError(code.INVALID_TRANSACTION, "invalid nonce")
if signer != nil && signer.Nonce >= nonce {
return err
}
return nil
}

func (app *app) CheckTx(buf []byte) tmtypes.ResponseCheckTx {
ctx, app_, tx, err := app.appForTx(buf)
if err != nil {
return tmtypes.ResponseCheckTx{Code: err.Code(), Log: err.Error()}
}
app.traceTx("CheckTx", tx)
err = app.checkNonce(ctx.Signer().Address().Bytes(), tx.Payload.Nonce)
if err != nil {
return tmtypes.ResponseCheckTx{Code: err.Code(), Log: err.Error()}
}
return app_.CheckTx(ctx, tx.Payload.Payload)
}

Expand All @@ -166,45 +182,44 @@ func (app *app) DeliverTx(buf []byte) tmtypes.ResponseDeliverTx {
if err != nil {
return tmtypes.ResponseDeliverTx{Code: err.Code(), Log: err.Error()}
}

app.traceTx("DeliverTx", tx)
err = app.checkNonce(ctx.Signer().Address().Bytes(), tx.Payload.Nonce)
if err != nil {
return tmtypes.ResponseDeliverTx{Code: err.Code(), Log: err.Error()}
}
signer, err_ := app.state.Account().Get(ctx.Signer().Address().Bytes())
if err_ != nil {
return tmtypes.ResponseDeliverTx{
Code: code.INVALID_TRANSACTION,
Log: err_.Error(),
}
return tmtypes.ResponseDeliverTx{Code: code.INVALID_TRANSACTION, Log: err_.Error()}
}

// XXX: Accouts should be implicity created when tokens are sent to it
if signer == nil {
// return tmtypes.ResponseDeliverTx{
// Code: code.INVALID_TRANSACTION,
// Log: "unknown signer account",
// }
signer = &types.Account{
Address: ctx.Signer().Address().Bytes(),
Balance: 0,
Nonce: 0,
}
}

if signer.Nonce >= tx.Payload.Nonce {
return tmtypes.ResponseDeliverTx{
Code: code.INVALID_TRANSACTION,
Log: "invalid nonce",
}
if err_ := app.state.Account().Save(signer); err_ != nil {
return tmtypes.ResponseDeliverTx{Code: code.INVALID_TRANSACTION, Log: err_.Error()}
}

signer.Nonce = tx.Payload.Nonce
resp := app_.DeliverTx(ctx, tx.Payload.Payload)

if err_ := app.state.Account().Save(signer); err_ != nil {
return tmtypes.ResponseDeliverTx{
Code: code.INVALID_TRANSACTION,
Log: err_.Error(),
// set new account nonce
if resp.IsOK() {
signer, err_ = app.state.Account().Get(ctx.Signer().Address().Bytes())
if err_ != nil {
return tmtypes.ResponseDeliverTx{Code: code.INVALID_TRANSACTION, Log: err_.Error()}
}
signer.Nonce = tx.Payload.Nonce
if err_ := app.state.Account().Save(signer); err_ != nil {
return tmtypes.ResponseDeliverTx{Code: code.INVALID_TRANSACTION, Log: err_.Error()}
}
}

app.traceTx("DeliverTx", tx)
return app_.DeliverTx(ctx, tx.Payload.Payload)
return resp
}

func (app *app) BeginBlock(req tmtypes.RequestBeginBlock) tmtypes.ResponseBeginBlock {
Expand Down
2 changes: 1 addition & 1 deletion app/app_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ func TestApp(t *testing.T) {
}

{
nonce := uint64(2)
nonce := uint64(3)
tx, err := txutil.BuildTx(signer, nonce, &types.TxSend{
From: addrfrom,
To: addrto,
Expand Down
34 changes: 26 additions & 8 deletions app/deployment/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,21 +200,21 @@ func (a *app) doDeploymentGroupQuery(key base.Bytes) tmtypes.ResponseQuery {

func (a *app) doCheckCreateTx(ctx apptypes.Context, tx *types.TxCreateDeployment) tmtypes.ResponseCheckTx {

if !bytes.Equal(ctx.Signer().Address(), tx.Deployment.Tenant) {
if !bytes.Equal(ctx.Signer().Address(), tx.Tenant) {
return tmtypes.ResponseCheckTx{
Code: code.INVALID_TRANSACTION,
Log: "Not signed by sending address",
}
}

if len(tx.Groups.GetItems()) == 0 {
if len(tx.Groups) == 0 {
return tmtypes.ResponseCheckTx{
Code: code.INVALID_TRANSACTION,
Log: "No groups in deployment",
}
}

acct, err := a.State().Account().Get(tx.Deployment.Tenant)
acct, err := a.State().Account().Get(tx.Tenant)
if err != nil {
return tmtypes.ResponseCheckTx{
Code: code.INVALID_TRANSACTION,
Expand All @@ -228,6 +228,13 @@ func (a *app) doCheckCreateTx(ctx apptypes.Context, tx *types.TxCreateDeployment
}
}

if acct.Nonce >= tx.Nonce {
return tmtypes.ResponseCheckTx{
Code: code.INVALID_TRANSACTION,
Log: "invalid nonce",
}
}

return tmtypes.ResponseCheckTx{}
}

Expand Down Expand Up @@ -372,16 +379,26 @@ func (a *app) doDeliverCreateTx(ctx apptypes.Context, tx *types.TxCreateDeployme
}
}

deployment := tx.Deployment
deployment := &types.Deployment{
Address: state.DeploymentAddress(tx.Tenant, tx.Nonce),
Tenant: tx.Tenant,
State: types.Deployment_ACTIVE,
}

seq := a.State().Deployment().SequenceFor(deployment.Address)

groups := tx.Groups.GetItems()
groups := tx.Groups

for _, group := range groups {
group.Deployment = deployment.Address
group.Seq = seq.Advance()
a.State().DeploymentGroup().Save(group)
g := &types.DeploymentGroup{
Deployment: deployment.Address,
Seq: seq.Advance(),
State: types.DeploymentGroup_OPEN,
Requirements: group.Requirements,
Resources: group.Resources,
OrderTTL: tx.OrderTTL,
}
a.State().DeploymentGroup().Save(g)
}

if err := a.State().Deployment().Save(deployment); err != nil {
Expand All @@ -393,6 +410,7 @@ func (a *app) doDeliverCreateTx(ctx apptypes.Context, tx *types.TxCreateDeployme

return tmtypes.ResponseDeliverTx{
Tags: apptypes.NewTags(a.Name(), apptypes.TxTypeCreateDeployment),
Data: deployment.Address,
}
}

Expand Down
2 changes: 1 addition & 1 deletion app/fulfillment/app_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ func TestValidTx(t *testing.T) {
papp, err := papp.NewApp(state, testutil.Logger())
require.NoError(t, err)
paccount, pkey := testutil.CreateAccount(t, state)
pnonce := uint64(0)
pnonce := uint64(1)
provider := testutil.CreateProvider(t, papp, paccount, &pkey, pnonce)

// create tenant
Expand Down
4 changes: 2 additions & 2 deletions app/lease/app_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ func TestValidTx(t *testing.T) {
papp, err := papp.NewApp(state, testutil.Logger())
require.NoError(t, err)
paccount, pkey := testutil.CreateAccount(t, state)
pnonce := uint64(0)
pnonce := uint64(1)
provider := testutil.CreateProvider(t, papp, paccount, &pkey, pnonce)

// create tenant
Expand Down Expand Up @@ -116,7 +116,7 @@ func TestBilling(t *testing.T) {
papp, err := papp.NewApp(state, testutil.Logger())
require.NoError(t, err)
paccount, pkey := testutil.CreateAccount(t, state)
pnonce := uint64(0)
pnonce := uint64(1)
provider := testutil.CreateProvider(t, papp, paccount, &pkey, pnonce)

// create tenant
Expand Down
39 changes: 22 additions & 17 deletions app/provider/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,14 +149,28 @@ func (a *app) doRangeQuery(key base.Bytes) tmtypes.ResponseQuery {
}
}

// todo: break each type of check out into a named global exported funtion for all trasaction types to utilize
func (a *app) doCheckTx(ctx apptypes.Context, tx *types.TxCreateProvider) tmtypes.ResponseCheckTx {
if !bytes.Equal(ctx.Signer().Address(), tx.Provider.Owner) {
if !bytes.Equal(ctx.Signer().Address(), tx.Owner) {
return tmtypes.ResponseCheckTx{
Code: code.INVALID_TRANSACTION,
Log: "Not signed by owner",
}
}

signer, err_ := a.State().Account().Get(tx.Owner)
if err_ != nil {
return tmtypes.ResponseCheckTx{
Code: code.INVALID_TRANSACTION,
Log: "unknown source account",
}
}

if signer == nil && tx.Nonce != 1 {
return tmtypes.ResponseCheckTx{Code: code.INVALID_TRANSACTION, Log: "invalid nonce"}
} else if signer != nil && signer.Nonce >= tx.Nonce {
return tmtypes.ResponseCheckTx{Code: code.INVALID_TRANSACTION, Log: "invalid nonce"}
}

return tmtypes.ResponseCheckTx{}
}

Expand All @@ -170,23 +184,13 @@ func (a *app) doDeliverTx(ctx apptypes.Context, tx *types.TxCreateProvider) tmty
}
}

acct, err := a.State().Account().Get(tx.Provider.Owner)
if err != nil {
return tmtypes.ResponseDeliverTx{
Code: code.INVALID_TRANSACTION,
Log: err.Error(),
}
}
if acct == nil {
return tmtypes.ResponseDeliverTx{
Code: code.INVALID_TRANSACTION,
Log: "unknown source account",
}
provider := &types.Provider{
Address: state.ProviderAddress(tx.Owner, tx.Nonce),
Owner: tx.Owner,
Attributes: tx.Attributes,
}

provider := tx.Provider

if err := a.State().Provider().Save(&provider); err != nil {
if err := a.State().Provider().Save(provider); err != nil {
return tmtypes.ResponseDeliverTx{
Code: code.INVALID_TRANSACTION,
Log: err.Error(),
Expand All @@ -195,5 +199,6 @@ func (a *app) doDeliverTx(ctx apptypes.Context, tx *types.TxCreateProvider) tmty

return tmtypes.ResponseDeliverTx{
Tags: apptypes.NewTags(a.Name(), apptypes.TxTypeProviderCreate),
Data: provider.Address,
}
}
46 changes: 31 additions & 15 deletions cmd/akash/deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,15 +49,27 @@ func createDeploymentCommand() *cobra.Command {
return cmd
}

func parseDeployment(file string, tenant []byte, nonce uint64) (*types.Deployment, *types.DeploymentGroups, error) {
func parseDeployment(file string, nonce uint64) ([]*types.GroupSpec, int64, error) {
// todo: read and parse deployment yaml file

specs := []*types.GroupSpec{}

/* begin stub data */
deployment := testutil.Deployment(tenant, nonce)
groups := testutil.DeploymentGroups(deployment.Address, nonce)
groups := testutil.DeploymentGroups(*new(base.Bytes), nonce)

for _, group := range groups.GetItems() {
s := &types.GroupSpec{
Resources: group.Resources,
Requirements: group.Requirements,
}
specs = append(specs, s)
}

ttl := int64(5)

/* end stub data */

return deployment, groups, nil
return specs, ttl, nil
}

func createDeployment(ctx context.Context, cmd *cobra.Command, args []string) error {
Expand All @@ -71,14 +83,16 @@ func createDeployment(ctx context.Context, cmd *cobra.Command, args []string) er
return err
}

deployment, groups, err := parseDeployment(args[0], key.Address(), nonce)
groups, ttl, err := parseDeployment(args[0], nonce)
if err != nil {
return err
}

tx, err := txutil.BuildTx(signer, nonce, &types.TxCreateDeployment{
Deployment: deployment,
Groups: groups,
Tenant: key.Address(),
Nonce: nonce,
OrderTTL: ttl,
Groups: groups,
})
if err != nil {
return err
Expand All @@ -98,24 +112,26 @@ func createDeployment(ctx context.Context, cmd *cobra.Command, args []string) er
return errors.New(res.DeliverTx.GetLog())
}

fmt.Println(X(deployment.Address))
address := res.DeliverTx.Data

fmt.Println(X(address))

if ctx.Wait() {
fmt.Printf("Waiting...\n")
expected := len(groups.GetItems())
expected := len(groups)
handler := marketplace.NewBuilder().
OnTxCreateFulfillment(func(tx *types.TxCreateFulfillment) {
if bytes.Equal(tx.Fulfillment.Deployment, deployment.Address) {
if bytes.Equal(tx.Fulfillment.Deployment, address) {
f := tx.Fulfillment
fmt.Printf("Group %v/%v Fulfillment: %X\n", f.Group, len(groups.GetItems()),
state.FulfillmentID(f.Deployment, f.Group, f.Order, f.Provider))
fmt.Printf("Group %v/%v Fulfillment: %v\n", f.Group, len(groups),
X(state.FulfillmentID(f.Deployment, f.Group, f.Order, f.Provider)))
}
}).
OnTxCreateLease(func(tx *types.TxCreateLease) {
if bytes.Equal(tx.Lease.Deployment, deployment.Address) {
if bytes.Equal(tx.Lease.Deployment, address) {
l := tx.Lease
fmt.Printf("Group %v/%v Lease: %X\n", l.Group, len(groups.GetItems()),
state.FulfillmentID(l.Deployment, l.Group, l.Order, l.Provider))
fmt.Printf("Group %v/%v Lease: %v\n", l.Group, len(groups),
X(state.FulfillmentID(l.Deployment, l.Group, l.Order, l.Provider)))
expected--
}
if expected == 0 {
Expand Down
5 changes: 3 additions & 2 deletions cmd/akash/marketplace.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"github.com/ovrclk/akash/cmd/akash/context"
"github.com/ovrclk/akash/cmd/common"
"github.com/ovrclk/akash/marketplace"
"github.com/ovrclk/akash/state"
"github.com/ovrclk/akash/types"
"github.com/spf13/cobra"

Expand Down Expand Up @@ -37,10 +38,10 @@ func marketplaceMonitorHandler() marketplace.Handler {
fmt.Printf("TRANSFER\t%v tokens from %v to %v\n", tx.GetAmount(), X(tx.From), X(tx.To))
}).
OnTxCreateProvider(func(tx *types.TxCreateProvider) {
fmt.Printf("DATACENTER CREATED\t%v created by %v\n", X(tx.Provider.Address), X(tx.Provider.Owner))
fmt.Printf("DATACENTER CREATED\t%v created by %v\n", X(state.ProviderAddress(tx.Owner, tx.Nonce)), X(tx.Owner))
}).
OnTxCreateDeployment(func(tx *types.TxCreateDeployment) {
fmt.Printf("DEPLOYMENT CREATED\t%v created by %v\n", X(tx.Deployment.Address), X(tx.Deployment.Tenant))
fmt.Printf("DEPLOYMENT CREATED\t%v created by %v\n", X(state.DeploymentAddress(tx.Tenant, tx.Nonce)), X(tx.Tenant))
}).
OnTxCreateOrder(func(tx *types.TxCreateOrder) {
fmt.Printf("ORDER CREATED\t%v/%v/%v\n",
Expand Down
Loading

0 comments on commit 939d951

Please sign in to comment.