Skip to content

Commit

Permalink
Merge pull request #117 from orogvany/remove_fee_from_vm
Browse files Browse the repository at this point in the history
VM: Remove fee for VM calls
  • Loading branch information
orogvany authored Jan 29, 2019
2 parents 885dbed + 454f0f9 commit 50ed1a6
Show file tree
Hide file tree
Showing 6 changed files with 55 additions and 59 deletions.
8 changes: 8 additions & 0 deletions src/main/java/org/semux/api/util/TransactionBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,13 @@ public TransactionBuilder withValue(String value) {
return this; // ignore the provided parameter
}

if (type == TransactionType.CREATE) {
if (value != null && !value.isEmpty()) {
throw new IllegalArgumentException("Parameter `value` is not needed for CREATE transaction");
}
return this; // ignore the provided parameter
}

if (value == null) {
throw new IllegalArgumentException("Parameter `value` is required");
}
Expand Down Expand Up @@ -256,6 +263,7 @@ public Transaction buildUnsigned() {
}
if (type == TransactionType.CREATE) {
to = Bytes.EMPTY_ADDRESS;
value = Amount.ZERO;
}

return new Transaction(
Expand Down
15 changes: 7 additions & 8 deletions src/main/java/org/semux/api/v2/SemuxApiImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -744,17 +744,16 @@ public Response transfer(String from, String to, String value, String fee, Strin
}

@Override
public Response create(String from, String value, String data, String gasPrice, String gas, String fee,
String nonce, Boolean validateNonce) {
return doTransaction(TransactionType.CREATE, from, null, value, fee, nonce, validateNonce, data, gasPrice,
public Response create(String from, String data, String gasPrice, String gas, String nonce, Boolean validateNonce) {
return doTransaction(TransactionType.CREATE, from, null, null, "0", nonce, validateNonce, data, gasPrice,
gas);
}

@Override
public Response call(String from, String to, String value, String gasPrice, String gas, String fee,
public Response call(String from, String to, String value, String gasPrice, String gas,
String nonce, Boolean validateNonce, String data, Boolean local) {
if (local) {
Transaction tx = getTransaction(TransactionType.CALL, from, to, value, fee, nonce, validateNonce, data,
Transaction tx = getTransaction(TransactionType.CALL, from, to, value, "0", nonce, validateNonce, data,
gasPrice, gas);

SemuxTransaction transaction = new SemuxTransaction(tx);
Expand All @@ -777,7 +776,7 @@ public Response call(String from, String to, String value, String gasPrice, Stri
return success(resp);
}
} else {
return doTransaction(TransactionType.CALL, from, to, value, fee, nonce, validateNonce, data, gasPrice,
return doTransaction(TransactionType.CALL, from, to, value, "0", nonce, validateNonce, data, gasPrice,
gas);
}
}
Expand Down Expand Up @@ -921,9 +920,10 @@ private Transaction getTransaction(TransactionType type, String from, String to,
.withType(type)
.withFrom(from)
.withTo(to)
.withValue(value)
.withFee(fee, true)
.withValue(value)
.withData(data);

if (type == TransactionType.CREATE || type == TransactionType.CALL) {
transactionBuilder.withGasPrice(gasPrice).withGas(gas);
}
Expand All @@ -943,7 +943,6 @@ private Transaction getTransaction(TransactionType type, String from, String to,
throw new IllegalArgumentException("Invalid transaction nonce.");
}
return tx;

}

/**
Expand Down
4 changes: 4 additions & 0 deletions src/main/java/org/semux/core/Amount.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ public Amount of(long a) {
return new Amount(Math.multiplyExact(a, factor));
}

public Amount ofGas(long gas, long gasPrice) {
return new Amount(Math.multiplyExact(gas, gasPrice));
}

public BigDecimal toDecimal(Amount a, int scale) {
BigDecimal $nano = BigDecimal.valueOf(a.nano);
return $nano.movePointLeft(exp).setScale(scale, FLOOR);
Expand Down
53 changes: 33 additions & 20 deletions src/main/java/org/semux/core/TransactionExecutor.java
Original file line number Diff line number Diff line change
Expand Up @@ -115,10 +115,19 @@ public List<TransactionResult> execute(List<Transaction> txs, AccountState as, D
continue;
}

// check fee
if (fee.lt(config.minTransactionFee())) {
result.setCode(Code.INVALID_FEE);
continue;
boolean isVmCall = type == TransactionType.CREATE || type == TransactionType.CALL;

// check fee (call and create use gas instead)
if (isVmCall) {
if (fee.lt(Amount.ZERO)) {
result.setCode(Code.INVALID_FEE);
continue;
}
} else {
if (fee.lt(config.minTransactionFee())) {
result.setCode(Code.INVALID_FEE);
continue;
}
}

// check data length
Expand Down Expand Up @@ -197,25 +206,29 @@ public List<TransactionResult> execute(List<Transaction> txs, AccountState as, D
case CALL:
case CREATE:
long maxGasFee = tx.getGas() * tx.getGasPrice();

Amount maxCost = sum(sum(value, fee), Unit.NANO_SEM.of(maxGasFee));
if (maxCost.lte(available)) {
// VM calls still use fees
as.adjustAvailable(from, neg(sum(value, fee)));

if (tx.getGas() > config.vmMaxBlockGasLimit()) {
result.setCode(Code.INVALID_GAS);
} else if (block == null) {
// workaround for pending manager so it doesn't execute these
// we charge gas later
as.increaseNonce(from);
result.setCode(Code.SUCCESS);
} else {
executeVmTransaction(result, tx, as, block, gasUsedInBlock);
gasUsedInBlock += result.getGasUsed();
}
} else {
if (available.lt(maxCost)) {
result.setCode(Code.INSUFFICIENT_AVAILABLE);
break;
}

// VM calls can have fees/values set.
as.adjustAvailable(from, neg(sum(value, fee)));

if (tx.getGas() > config.vmMaxBlockGasLimit()) {
result.setCode(Code.INVALID_GAS);
} else if (block == null) {
// workaround for pending manager so it doesn't execute these
// we charge gas later
as.increaseNonce(from);
result.setCode(Code.SUCCESS);
} else {
executeVmTransaction(result, tx, as, block, gasUsedInBlock);
gasUsedInBlock += result.getGasUsed();
}

break;

default:
Expand All @@ -226,7 +239,7 @@ public List<TransactionResult> execute(List<Transaction> txs, AccountState as, D

// increase nonce if success
// creates and calls increase their own nonces internal to VM
if (result.getCode().isAccepted() && type != TransactionType.CREATE && type != TransactionType.CALL) {
if (result.getCode().isAccepted() && !isVmCall) {
as.increaseNonce(from);
}
}
Expand Down
27 changes: 0 additions & 27 deletions src/main/resources/org/semux/api/swagger/v2.2.0.json
Original file line number Diff line number Diff line change
Expand Up @@ -1059,24 +1059,6 @@
"type" : "string",
"pattern" : "^(0x)?[0-9a-fA-F]{40}$"
},
{
"name" : "value",
"in" : "query",
"description" : "Amount of SEM to transfer in nano SEM",
"required" : true,
"type" : "string",
"format" : "int64",
"pattern" : "^\\d+$"
},
{
"name" : "fee",
"in" : "query",
"description" : "Transaction fee in nano SEM, default to minimum fee if omitted",
"required" : false,
"type" : "string",
"format" : "int64",
"pattern" : "^\\d+$"
},
{
"name" : "nonce",
"in" : "query",
Expand Down Expand Up @@ -1173,15 +1155,6 @@
"format" : "int64",
"pattern" : "^\\d+$"
},
{
"name" : "fee",
"in" : "query",
"description" : "Transaction fee in nano SEM, default to minimum fee if omitted",
"required" : false,
"type" : "string",
"format" : "int64",
"pattern" : "^\\d+$"
},
{
"name" : "nonce",
"in" : "query",
Expand Down
7 changes: 3 additions & 4 deletions src/test/java/org/semux/core/VmTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ public void testCall() {
byte[] from = key.toAddress();
byte[] to = Bytes.random(20);
Amount value = NANO_SEM.of(5);
Amount fee = config.minTransactionFee();
long nonce = as.getAccount(from).getNonce();
long timestamp = TimeUtil.currentTimeMillis();

Expand All @@ -84,7 +83,7 @@ public void testCall() {
long gas = 30000;
long gasPrice = 1;

Transaction tx = new Transaction(network, type, to, value, fee, nonce, timestamp, data, gas, gasPrice);
Transaction tx = new Transaction(network, type, to, value, Amount.ZERO, nonce, timestamp, data, gas, gasPrice);
tx.sign(key);
assertTrue(tx.validate(network));

Expand Down Expand Up @@ -117,7 +116,6 @@ public void testCreate() {
byte[] from = key.toAddress();
byte[] to = Bytes.EMPTY_ADDRESS;
Amount value = NANO_SEM.of(0);
Amount fee = config.minTransactionFee();
long nonce = as.getAccount(from).getNonce();
long timestamp = TimeUtil.currentTimeMillis();

Expand All @@ -134,7 +132,8 @@ public void testCreate() {
long gas = 1000000;
long gasPrice = 1;

Transaction tx = new Transaction(network, type, to, value, fee, nonce, timestamp, create, gas, gasPrice);
Transaction tx = new Transaction(network, type, to, value, Amount.ZERO, nonce, timestamp, create, gas,
gasPrice);
tx.sign(key);
assertTrue(tx.validate(network));

Expand Down

0 comments on commit 50ed1a6

Please sign in to comment.