Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

VM: Remove fee for VM calls #117

Merged
merged 5 commits into from
Jan 29, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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