Abit/app/src/main/java/ch/dissem/apps/abit/repository/AndroidProofOfWorkRepository.java

173 lines
6.4 KiB
Java
Raw Normal View History

/*
* Copyright 2016 Christian Basler
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
2015-12-21 15:31:48 +01:00
package ch.dissem.apps.abit.repository;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteConstraintException;
import android.database.sqlite.SQLiteDatabase;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.ByteArrayInputStream;
import java.util.LinkedList;
import java.util.List;
2016-08-13 23:24:42 +02:00
import ch.dissem.bitmessage.InternalContext;
2015-12-21 15:31:48 +01:00
import ch.dissem.bitmessage.entity.ObjectMessage;
import ch.dissem.bitmessage.factory.Factory;
import ch.dissem.bitmessage.ports.ProofOfWorkRepository;
import ch.dissem.bitmessage.utils.Encode;
import static ch.dissem.bitmessage.utils.Singleton.cryptography;
2016-09-12 11:00:00 +02:00
import static ch.dissem.bitmessage.utils.Strings.hex;
2015-12-21 15:31:48 +01:00
/**
* @author Christian Basler
*/
2016-08-13 23:24:42 +02:00
public class AndroidProofOfWorkRepository implements ProofOfWorkRepository, InternalContext
2016-09-12 11:00:00 +02:00
.ContextHolder {
2015-12-21 15:31:48 +01:00
private static final Logger LOG = LoggerFactory.getLogger(AndroidProofOfWorkRepository.class);
private static final String TABLE_NAME = "POW";
private static final String COLUMN_INITIAL_HASH = "initial_hash";
private static final String COLUMN_DATA = "data";
private static final String COLUMN_VERSION = "version";
private static final String COLUMN_NONCE_TRIALS_PER_BYTE = "nonce_trials_per_byte";
private static final String COLUMN_EXTRA_BYTES = "extra_bytes";
private static final String COLUMN_EXPIRATION_TIME = "expiration_time";
private static final String COLUMN_MESSAGE_ID = "message_id";
2015-12-21 15:31:48 +01:00
private final SqlHelper sql;
2016-08-13 23:24:42 +02:00
private InternalContext bmc;
2015-12-21 15:31:48 +01:00
public AndroidProofOfWorkRepository(SqlHelper sql) {
this.sql = sql;
}
2016-08-13 23:24:42 +02:00
@Override
public void setContext(InternalContext internalContext) {
this.bmc = internalContext;
}
2015-12-21 15:31:48 +01:00
@Override
public Item getItem(byte[] initialHash) {
// Define a projection that specifies which columns from the database
// you will actually use after this query.
String[] projection = {
2016-09-12 11:00:00 +02:00
COLUMN_DATA,
COLUMN_VERSION,
COLUMN_NONCE_TRIALS_PER_BYTE,
COLUMN_EXTRA_BYTES,
COLUMN_EXPIRATION_TIME,
COLUMN_MESSAGE_ID
2015-12-21 15:31:48 +01:00
};
SQLiteDatabase db = sql.getReadableDatabase();
try (Cursor c = db.query(
2016-09-12 11:00:00 +02:00
TABLE_NAME, projection,
"initial_hash=X'" + hex(initialHash) + "'",
null, null, null, null
)) {
2016-09-12 11:00:00 +02:00
if (c.moveToFirst()) {
2015-12-21 15:31:48 +01:00
int version = c.getInt(c.getColumnIndex(COLUMN_VERSION));
byte[] blob = c.getBlob(c.getColumnIndex(COLUMN_DATA));
2016-08-13 23:24:42 +02:00
if (c.isNull(c.getColumnIndex(COLUMN_MESSAGE_ID))) {
return new Item(
2016-09-12 11:00:00 +02:00
Factory.getObjectMessage(version, new ByteArrayInputStream(blob), blob
.length),
c.getLong(c.getColumnIndex(COLUMN_NONCE_TRIALS_PER_BYTE)),
c.getLong(c.getColumnIndex(COLUMN_EXTRA_BYTES))
2016-08-13 23:24:42 +02:00
);
} else {
return new Item(
2016-09-12 11:00:00 +02:00
Factory.getObjectMessage(version, new ByteArrayInputStream(blob), blob
.length),
c.getLong(c.getColumnIndex(COLUMN_NONCE_TRIALS_PER_BYTE)),
c.getLong(c.getColumnIndex(COLUMN_EXTRA_BYTES)),
c.getLong(c.getColumnIndex(COLUMN_EXPIRATION_TIME)),
bmc.getMessageRepository().getMessage(
c.getLong(c.getColumnIndex(COLUMN_MESSAGE_ID)))
2016-08-13 23:24:42 +02:00
);
}
2015-12-21 15:31:48 +01:00
}
}
throw new RuntimeException("Object requested that we don't have. Initial hash: " +
2016-09-12 11:00:00 +02:00
hex(initialHash));
2015-12-21 15:31:48 +01:00
}
@Override
public List<byte[]> getItems() {
// Define a projection that specifies which columns from the database
// you will actually use after this query.
String[] projection = {
2016-09-12 11:00:00 +02:00
COLUMN_INITIAL_HASH
2015-12-21 15:31:48 +01:00
};
SQLiteDatabase db = sql.getReadableDatabase();
List<byte[]> result = new LinkedList<>();
try (Cursor c = db.query(
2016-09-12 11:00:00 +02:00
TABLE_NAME, projection,
null, null, null, null, null
)) {
2016-09-12 11:00:00 +02:00
while (c.moveToNext()) {
2015-12-21 15:31:48 +01:00
byte[] initialHash = c.getBlob(c.getColumnIndex(COLUMN_INITIAL_HASH));
result.add(initialHash);
}
}
return result;
}
@Override
public void putObject(Item item) {
2015-12-21 15:31:48 +01:00
try {
SQLiteDatabase db = sql.getWritableDatabase();
// Create a new map of values, where column names are the keys
ContentValues values = new ContentValues();
values.put(COLUMN_INITIAL_HASH, cryptography().getInitialHash(item.object));
values.put(COLUMN_DATA, Encode.bytes(item.object));
values.put(COLUMN_VERSION, item.object.getVersion());
values.put(COLUMN_NONCE_TRIALS_PER_BYTE, item.nonceTrialsPerByte);
values.put(COLUMN_EXTRA_BYTES, item.extraBytes);
if (item.message != null) {
values.put(COLUMN_EXPIRATION_TIME, item.expirationTime);
values.put(COLUMN_MESSAGE_ID, (Long) item.message.getId());
}
2015-12-21 15:31:48 +01:00
db.insertOrThrow(TABLE_NAME, null, values);
} catch (SQLiteConstraintException e) {
LOG.trace(e.getMessage(), e);
}
}
@Override
public void putObject(ObjectMessage object, long nonceTrialsPerByte, long extraBytes) {
putObject(new Item(object, nonceTrialsPerByte, extraBytes));
}
2015-12-21 15:31:48 +01:00
@Override
public void removeObject(byte[] initialHash) {
SQLiteDatabase db = sql.getWritableDatabase();
2016-09-12 11:00:00 +02:00
db.delete(
TABLE_NAME,
"initial_hash=X'" + hex(initialHash) + "'",
null
);
2015-12-21 15:31:48 +01:00
}
}