diff --git a/test/api_test.go b/test/api_test.go index cb305e8e9..877465f5b 100644 --- a/test/api_test.go +++ b/test/api_test.go @@ -18,6 +18,7 @@ import ( "go.vocdoni.io/dvote/util" "go.vocdoni.io/dvote/vochain" "go.vocdoni.io/dvote/vochain/state" + "go.vocdoni.io/dvote/vochain/state/electionprice" "go.vocdoni.io/proto/build/go/models" "google.golang.org/protobuf/proto" ) @@ -254,6 +255,123 @@ func TestAPIaccount(t *testing.T) { qt.Assert(t, code, qt.Equals, 200, qt.Commentf("response: %s", resp)) } +func TestAPIElectionCost(t *testing.T) { + server := testcommon.APIserver{} + server.Start(t, + api.ChainHandler, + api.CensusHandler, + api.VoteHandler, + api.AccountHandler, + api.ElectionHandler, + api.WalletHandler, + ) + + // Advance a few blocks, once there was a bug with election cost vs block heigh + for i := 0; i < 100; i++ { + server.VochainAPP.AdvanceTestBlock() + } + + token1 := uuid.New() + c := testutil.NewTestHTTPclient(t, server.ListenAddr, &token1) + + // create a new census + resp, code := c.Request("POST", nil, "censuses", "weighted") + qt.Assert(t, code, qt.Equals, 200) + censusData := &api.Census{} + qt.Assert(t, json.Unmarshal(resp, censusData), qt.IsNil) + + id1 := censusData.CensusID.String() + resp, code = c.Request("POST", nil, "censuses", id1, "publish") + qt.Assert(t, code, qt.Equals, 200) + qt.Assert(t, json.Unmarshal(resp, censusData), qt.IsNil) + qt.Assert(t, censusData.CensusID, qt.IsNotNil) + root := censusData.CensusID + + metadataBytes, err := json.Marshal( + &api.ElectionMetadata{ + Title: map[string]string{"default": "test election"}, + Description: map[string]string{"default": "test election description"}, + Version: "1.0", + }) + + qt.Assert(t, err, qt.IsNil) + metadataURI := ipfs.CalculateCIDv1json(metadataBytes) + + params := electionprice.ElectionParameters{ + MaxCensusSize: 500, + ElectionDuration: 1000, + EncryptedVotes: true, + AnonymousVotes: true, + MaxVoteOverwrite: 1, + } + + predicted := struct { + Price uint64 `json:"price"` + }{} + + server.VochainAPP.State.SetTxBaseCost(models.TxType_NEW_PROCESS, 2) + server.VochainAPP.State.ElectionPriceCalc.SetBasePrice(2) + server.VochainAPP.State.ElectionPriceCalc.SetCapacity(1000) + + resp, code = c.Request("POST", params, "elections", "price") + qt.Assert(t, code, qt.Equals, 200) + err = json.Unmarshal(resp, &predicted) + qt.Assert(t, err, qt.IsNil) + + qt.Assert(t, predicted.Price, qt.Equals, uint64(16)) // given the hardcoded params + + // TODO: check balance before creating election and then after creating, + // and confirm the balance decreased exactly the expected amount + + tx := models.Tx{ + Payload: &models.Tx_NewProcess{ + NewProcess: &models.NewProcessTx{ + Txtype: models.TxType_NEW_PROCESS, + Nonce: 0, + Process: &models.Process{ + StartBlock: 0, + BlockCount: params.ElectionDuration, + Status: models.ProcessStatus_READY, + CensusRoot: root, + CensusOrigin: models.CensusOrigin_OFF_CHAIN_TREE_WEIGHTED, + Mode: &models.ProcessMode{AutoStart: true, Interruptible: true}, + VoteOptions: &models.ProcessVoteOptions{ + MaxCount: 1, + MaxValue: 1, + MaxVoteOverwrites: params.MaxVoteOverwrite, + }, + EnvelopeType: &models.EnvelopeType{ + EncryptedVotes: params.EncryptedVotes, + Anonymous: params.AnonymousVotes, + }, + Metadata: &metadataURI, + MaxCensusSize: params.MaxCensusSize, + }, + }, + }, + } + txb, err := proto.Marshal(&tx) + qt.Assert(t, err, qt.IsNil) + signedTxb, err := server.Account.SignVocdoniTx(txb, server.VochainAPP.ChainID()) + qt.Assert(t, err, qt.IsNil) + stx := models.SignedTx{Tx: txb, Signature: signedTxb} + stxb, err := proto.Marshal(&stx) + qt.Assert(t, err, qt.IsNil) + + election := api.ElectionCreate{ + TxPayload: stxb, + Metadata: metadataBytes, + } + resp, code = c.Request("POST", election, "elections") + qt.Assert(t, code, qt.Equals, 200) + err = json.Unmarshal(resp, &election) + qt.Assert(t, err, qt.IsNil) + + // Block 2 + server.VochainAPP.AdvanceTestBlock() + waitUntilHeight(t, c, 2) +} + func waitUntilHeight(t testing.TB, c *testutil.TestHTTPclient, h uint32) { for { resp, code := c.Request("GET", nil, "chain", "info")