Skip to content

Commit e0648f6

Browse files
committed
Merge branch 'dev'
# Conflicts: # README.md
2 parents 82f15fb + 8640d36 commit e0648f6

17 files changed

+432
-21
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ project build.gradle
2424
```groovy
2525
2626
ext {
27-
minterBlockchainSDK = "0.3.0"
27+
minterBlockchainSDK = "0.3.1"
2828
}
2929
3030
dependencies {

RELEASE.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Release notes
22

3+
## 0.3.1
4+
- Added minter check creation support
5+
- Updated core library
6+
37
## 0.3.0
48
- Multiple signatures support
59
- BREAKING CHANGES:

build.gradle

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ buildscript {
3131
mavenLocal()
3232
}
3333
dependencies {
34-
classpath 'com.android.tools.build:gradle:3.2.0'
34+
classpath 'com.android.tools.build:gradle:3.2.1'
3535
classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.4'
3636
}
3737
}
@@ -58,15 +58,45 @@ apply plugin: 'com.jfrog.bintray'
5858

5959

6060
group = 'network.minter.android'
61-
version = '0.3.0'
61+
version = '0.3.1'
6262

6363
ext {
6464
minterMinSdk = 16
6565
minterMaxSdk = 28
66-
minterBuildTools = "28.0.2"
67-
minterLibSupport = "27.1.1"
68-
minterCoreVers = "0.2.0"
66+
minterBuildTools = "28.0.3"
67+
minterLibSupport = "28.0.0"
68+
minterCoreVers = "0.2.1"
69+
70+
71+
buildArtifactName = project.name
72+
buildArtifactVersion = version
73+
buildArtifactGroup = group
74+
75+
pomName = "Minter Core"
76+
pomUrl = "https://github.com/MinterTeam/minter-android-blockchain"
77+
pomScm = {
78+
connection = "scm:git:git://github.com/MinterTeam/minter-android-blockchain.git"
79+
url = pomUrl
80+
}
81+
pomInceptionYear = "2018"
82+
pomContributors = {}
6983
pomDescription = "Minter Android Blockchain API SDK"
84+
pomDevelopers = {
85+
developer {
86+
id = "edwardstock"
87+
name = "Eduard Maximovich"
88+
email = "edwatd.vstock@gmail.com"
89+
roles = ["maintainer"]
90+
timezone = "Europe/Moscow"
91+
}
92+
}
93+
pomLicenses = {
94+
license {
95+
name = "MIT License"
96+
url = "https://opensource.org/licenses/MIT"
97+
distribution = "repo"
98+
}
99+
}
70100
}
71101

72102
def libPath = ""
@@ -156,7 +186,7 @@ dependencies {
156186
compileOnly 'com.google.code.findbugs:jsr305:3.0.2'
157187

158188
// network
159-
implementation 'com.squareup.okhttp3:okhttp:3.10.0'
189+
implementation 'com.squareup.okhttp3:okhttp:3.11.0'
160190
implementation 'com.squareup.okhttp3:logging-interceptor:3.9.0'
161191
implementation 'com.squareup.retrofit2:retrofit:2.4.0'
162192
implementation 'com.squareup.retrofit2:converter-gson:2.4.0'
@@ -174,7 +204,7 @@ dependencies {
174204
androidTestImplementation 'com.android.support.test:runner:1.0.2'
175205
androidTestImplementation 'com.android.support.test:rules:1.0.2'
176206
androidTestImplementation 'com.squareup.retrofit2:converter-gson:2.4.0'
177-
androidTestImplementation 'com.google.code.gson:gson:2.8.2'
207+
androidTestImplementation 'com.google.code.gson:gson:2.8.5'
178208
}
179209

180210
// Coverage

scripts

Lines changed: 235 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,235 @@
1+
/*
2+
* Copyright (C) by MinterTeam. 2018
3+
* @link <a href="https://github.com/MinterTeam">Org Github</a>
4+
* @link <a href="https://github.com/edwardstock">Maintainer Github</a>
5+
*
6+
* The MIT License
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
27+
package network.minter.blockchain.models.operational;
28+
29+
import com.edwardstock.secp256k1.NativeSecp256k1;
30+
31+
import java.math.BigDecimal;
32+
import java.math.BigInteger;
33+
34+
import network.minter.core.MinterSDK;
35+
import network.minter.core.crypto.BytesData;
36+
import network.minter.core.crypto.HashUtil;
37+
import network.minter.core.crypto.MinterAddress;
38+
import network.minter.core.crypto.PrivateKey;
39+
import network.minter.core.util.RLP;
40+
41+
import static network.minter.core.internal.common.Preconditions.checkArgument;
42+
import static network.minter.core.internal.common.Preconditions.checkNotNull;
43+
import static network.minter.core.internal.helpers.StringHelper.strrpad;
44+
45+
/**
46+
* minter-android-blockchain. 2018
47+
* @author Eduard Maximovich [edward.vstock@gmail.com]
48+
*/
49+
public class CheckTransaction {
50+
private String mPassphrase;
51+
private BigInteger mNonce;
52+
private BigInteger mDueBlock;
53+
private String mCoin = MinterSDK.DEFAULT_COIN;
54+
private BigInteger mValue;
55+
private BytesData mLock;
56+
private SignatureSingleData mSignature;
57+
58+
CheckTransaction(BigInteger nonce, String passphrase) {
59+
mNonce = nonce;
60+
mPassphrase = passphrase;
61+
}
62+
63+
/**
64+
* Create check proff
65+
* @param address minter address
66+
* @param passphrase check password
67+
* @return proof bytes data
68+
*/
69+
public static BytesData makeProof(MinterAddress address, String passphrase) {
70+
BytesData key = new BytesData(HashUtil.sha256(passphrase.getBytes()));
71+
BytesData encodedAddress = new BytesData(RLP.encode(new Object[]{address.getData()})).sha3Mutable();
72+
73+
NativeSecp256k1.RecoverableSignature signature;
74+
long ctx = NativeSecp256k1.contextCreate();
75+
try {
76+
signature = NativeSecp256k1.signRecoverableSerialized(ctx, encodedAddress.getData(), key.getData());
77+
} finally {
78+
NativeSecp256k1.contextCleanup(ctx);
79+
}
80+
81+
// carefully, hack detected!
82+
if (signature.v[0] != 1) {
83+
signature.v[0] = 0;
84+
}
85+
86+
return new BytesData(signature.r, signature.s, signature.v);
87+
}
88+
89+
/**
90+
* Use this to decrease object lifetime (especially if you need to create final instance of this object)
91+
*/
92+
public void cleanup() {
93+
mPassphrase = null;
94+
mNonce = null;
95+
mDueBlock = null;
96+
mCoin = null;
97+
mValue = null;
98+
mLock = null;
99+
mSignature = null;
100+
}
101+
102+
public String getCoin() {
103+
return mCoin.replace("\0", "");
104+
}
105+
106+
public BigInteger getNonce() {
107+
return mNonce;
108+
}
109+
110+
public BigInteger getDueBlock() {
111+
return mDueBlock;
112+
}
113+
114+
public String getPassphrase() {
115+
return mPassphrase;
116+
}
117+
118+
public BigInteger getValue() {
119+
return mValue;
120+
}
121+
122+
public SignatureSingleData getSignature() {
123+
return mSignature;
124+
}
125+
126+
public TransactionSign sign(PrivateKey privateKey) {
127+
BytesData hashBytes = new BytesData(encode(true));
128+
BytesData hash = hashBytes.sha3Data();
129+
BytesData pk = new BytesData(mPassphrase.getBytes()).sha256Mutable();
130+
131+
NativeSecp256k1.RecoverableSignature lockSig;
132+
133+
long ctx = NativeSecp256k1.contextCreate();
134+
try {
135+
lockSig = NativeSecp256k1.signRecoverableSerialized(ctx, hash.getData(), pk.getData());
136+
} finally {
137+
NativeSecp256k1.contextCleanup(ctx);
138+
}
139+
140+
141+
// carefully, hack detected!
142+
if (lockSig.v[0] != 1) {
143+
lockSig.v[0] = 0;
144+
}
145+
146+
mLock = new BytesData(lockSig.r, lockSig.s, lockSig.v);
147+
148+
BytesData withLock = new BytesData(encode(false)).sha3Mutable();
149+
150+
NativeSecp256k1.RecoverableSignature rsv;
151+
long ctx2 = NativeSecp256k1.contextCreate();
152+
try {
153+
rsv = NativeSecp256k1.signRecoverableSerialized(ctx2, withLock.getData(), privateKey.getData());
154+
} finally {
155+
NativeSecp256k1.contextCleanup(ctx2);
156+
}
157+
158+
mSignature = new SignatureSingleData();
159+
mSignature.setSign(rsv);
160+
161+
String signedCheck = new BytesData(encode(false)).toHexString(MinterSDK.PREFIX_CHECK);
162+
163+
return new TransactionSign(signedCheck);
164+
}
165+
166+
private byte[] encode(boolean forSigning) {
167+
if (forSigning) {
168+
return RLP.encode(new Object[]{
169+
mNonce,
170+
mDueBlock,
171+
mCoin,
172+
mValue
173+
});
174+
}
175+
176+
final byte[] lock = mLock.getData();
177+
if (mSignature != null && mSignature.getV() != null && mSignature.getR() != null && mSignature.getS() != null) {
178+
return RLP.encode(new Object[]{
179+
mNonce,
180+
mDueBlock,
181+
mCoin,
182+
mValue,
183+
lock,
184+
mSignature.getV(),
185+
mSignature.getR(),
186+
mSignature.getS(),
187+
});
188+
}
189+
190+
return RLP.encode(new Object[]{
191+
mNonce,
192+
mDueBlock,
193+
mCoin,
194+
mValue,
195+
lock
196+
});
197+
}
198+
199+
public static final class Builder {
200+
private CheckTransaction mCheck;
201+
202+
public Builder(BigInteger nonce, String passphrase) {
203+
mCheck = new CheckTransaction(nonce, passphrase);
204+
}
205+
206+
public Builder setCoin(String coin) {
207+
checkArgument(coin != null && coin.length() >= 3 && coin.length() <= 10, String.format("Invalid coin passed: %s", coin));
208+
mCheck.mCoin = strrpad(10, coin);
209+
return this;
210+
}
211+
212+
public Builder setValue(BigDecimal value) {
213+
mCheck.mValue = value.multiply(Transaction.VALUE_MUL_DEC).toBigInteger();
214+
return this;
215+
}
216+
217+
public Builder setValue(double value) {
218+
return setValue(new BigDecimal(value));
219+
}
220+
221+
public Builder setDueBlock(BigInteger dueBlockNum) {
222+
mCheck.mDueBlock = dueBlockNum;
223+
return this;
224+
}
225+
226+
public CheckTransaction build() {
227+
checkNotNull(mCheck.mValue, "Value must be set");
228+
checkNotNull(mCheck.mDueBlock, "Due block must be set");
229+
checkNotNull(mCheck.mNonce, "Nonce required");
230+
checkNotNull(mCheck.mPassphrase, "Passphrase required");
231+
return mCheck;
232+
}
233+
}
234+
235+
}

src/main/java/network/minter/blockchain/models/operational/Transaction.java

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ public Transaction[] newArray(int size) {
8080
private OperationType mType = OperationType.SendCoin;
8181
private Operation mOperationData;
8282

83-
// max - 128 bytes
83+
// max - 1024 bytes (1 kilobyte)
8484
private BytesData mPayload = new BytesData(new byte[0]);
8585
private BytesData mServiceData = new BytesData(new byte[0]);
8686
private SignatureType mSignatureType = Single;
@@ -176,6 +176,21 @@ public static Transaction fromEncoded(@Nonnull String hexEncoded) {
176176
return transaction;
177177
}
178178

179+
/**
180+
* Use this to decrease object lifetime (especially if you need to create final instance of this object)
181+
*/
182+
public void cleanup() {
183+
mNonce = null;
184+
mGasPrice = null;
185+
mGasCoin = null;
186+
mType = null;
187+
mOperationData = null;
188+
mPayload = null;
189+
mServiceData = null;
190+
mSignatureType = null;
191+
mSignatureData = null;
192+
}
193+
179194
/**
180195
* Signature type
181196
* @return {@link SignatureType}
@@ -437,7 +452,7 @@ public Builder setPayload(byte[] data) {
437452
* @return {@link Builder}
438453
*/
439454
public Builder setPayload(BytesData data) {
440-
checkArgument(data.size() <= 1024, "Data size can't be maximum 1024 bytes");
455+
checkArgument(data.size() <= 1024, "Payload maximum size: 1024 bytes");
441456
mTx.mPayload = new BytesData(data, true);
442457
return this;
443458
}
@@ -449,7 +464,7 @@ public Builder setPayload(BytesData data) {
449464
*/
450465
public Builder setPayload(@Nonnull String hexString) {
451466
checkNotNull(hexString, "Hex data string can't be null");
452-
checkArgument(hexString.length() <= 2048, "Hex string length can't have length > 2048 (1024 bytes)");
467+
checkArgument(hexString.length() <= 2048, "Payload maximum size: 1024 bytes (2048 in hex string)");
453468
mTx.mPayload = new BytesData(hexString);
454469
return this;
455470
}

0 commit comments

Comments
 (0)