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

IPFS 去中心化网络 + 去中心化好友系统 #622

Draft
wants to merge 7 commits into
base: master
Choose a base branch
from
Draft
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
5 changes: 5 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,11 @@
<artifactId>semver4j</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>com.github.peergos</groupId>
<artifactId>nabu</artifactId>
<version>v0.8.0</version>
</dependency>
<dependency>
<groupId>com.github.oshi</groupId>
<artifactId>oshi-core</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -681,6 +681,7 @@ private void registerModules() {
moduleManager.register(PBHTorrentController.class);
moduleManager.register(PBHPeerController.class);
moduleManager.register(PBHAlertController.class);
moduleManager.register(PBHFriendController.class);
moduleManager.register(PBHLogsController.class);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,10 @@ private void validate() {

@UpdateScript(version = 22)
public void miscChanges() {
conf.set("ipfs.port", 9899);
conf.set("privacy", null);
}


@UpdateScript(version = 21)
public void addPushProvider(YamlConfiguration bundle) {
conf.set("push-notification", bundle.get("push-notification"));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ private void createTables() throws SQLException {
TableUtils.createTableIfNotExists(database.getDataSource(), ProgressCheatBlockerPersistEntity.class);
TableUtils.createTableIfNotExists(database.getDataSource(), TrafficJournalEntity.class);
TableUtils.createTableIfNotExists(database.getDataSource(), AlertEntity.class);
TableUtils.createTableIfNotExists(database.getDataSource(), FriendEntity.class);
TableUtils.createTableIfNotExists(database.getDataSource(), DHTRecordEntity.class);
}

private void performUpgrade() throws SQLException {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
package com.ghostchu.peerbanhelper.database.dao.impl;

import com.ghostchu.peerbanhelper.database.Database;
import com.ghostchu.peerbanhelper.database.dao.AbstractPBHDao;
import com.ghostchu.peerbanhelper.database.table.DHTRecordEntity;
import io.ipfs.multibase.binary.Base32;
import io.ipfs.multihash.Multihash;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.peergos.protocol.dht.RecordStore;
import org.peergos.protocol.ipns.IpnsRecord;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.sql.SQLException;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.Arrays;
import java.util.Deque;
import java.util.Optional;

@Component
@Slf4j
public class DHTRecordDao extends AbstractPBHDao<DHTRecordEntity, String> implements RecordStore {
private final int SIZE_OF_VAL = 10240;
private final int SIZE_OF_PEERID = 100;

public DHTRecordDao(@Autowired Database database) throws SQLException {
super(database.getDataSource(), DHTRecordEntity.class);
}

@Override
public void close() throws Exception {

}

@SneakyThrows
public void batchSave(Deque<PersistTask> tasks) {
callBatchTasks(() -> {
while (!tasks.isEmpty()) {
var task = tasks.pop();
try {
if (task.delete()) {
remove(task.key);
} else {
put(task.key, task.value);
}
} catch (Exception e) {
log.warn("Unable save {} to DHT records database", task);
}
}
return null;
});
}

private String hashToKey(Multihash hash) {
String padded = new Base32().encodeAsString(hash.toBytes());
int padStart = padded.indexOf("=");
return padStart > 0 ? padded.substring(0, padStart) : padded;
}

@Override
public Optional<IpnsRecord> get(Multihash peerId) {
try {
var entity = queryForId(hashToKey(peerId));
if (entity == null) return Optional.empty();
return Optional.of(
new IpnsRecord(
entity.getRaw(),
entity.getSequence(),
entity.getTtlNanos(),
LocalDateTime.ofEpochSecond(entity.getExpiryUTC(), 0, ZoneOffset.UTC),
entity.getVal().getBytes()
)
);
} catch (SQLException e) {
throw new IllegalStateException(e);
}
}

@Override
public void put(Multihash peerId, IpnsRecord record) {
try {
createOrUpdate(new DHTRecordEntity(
hashToKey(peerId),
record.raw,
record.sequence,
record.ttlNanos,
record.expiry.toEpochSecond(ZoneOffset.UTC),
new String(record.value.length > SIZE_OF_VAL ?
Arrays.copyOfRange(record.value, 0, SIZE_OF_VAL) : record.value)
));
} catch (SQLException e) {
throw new IllegalStateException(e);
}
}

@Override
public void remove(Multihash peerId) {
try {
delete(queryForEq("peerId", hashToKey(peerId)));
} catch (SQLException e) {
throw new IllegalStateException(e);
}
}

public record PersistTask(
boolean delete,
Multihash key,
IpnsRecord value
) {
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.ghostchu.peerbanhelper.database.dao.impl;

import com.ghostchu.peerbanhelper.database.Database;
import com.ghostchu.peerbanhelper.database.dao.AbstractPBHDao;
import com.ghostchu.peerbanhelper.database.table.FriendEntity;
import com.ghostchu.peerbanhelper.friend.Friend;
import com.j256.ormlite.table.TableUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.Set;

@Component
@Slf4j
public class FriendDao extends AbstractPBHDao<FriendEntity, String> {
public FriendDao(@Autowired Database database) throws SQLException {
super(database.getDataSource(), FriendEntity.class);
}

public void saveFriendList(Set<Friend> friends) throws SQLException {
callBatchTasks(() -> {
var entities = friends.stream().map(f -> new FriendEntity(
f.getPeerId(),
f.getPubKey(),
new Timestamp(f.getLastAttemptConnectTime()),
new Timestamp(f.getLastCommunicationTime()),
f.getLastRecordedPBHVersion(),
f.getLastRecordedConnectionStatus()
)).toList();
TableUtils.clearTable(getConnectionSource(), FriendEntity.class);
create(entities);
return null;
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.ghostchu.peerbanhelper.database.table;

import com.j256.ormlite.field.DataType;
import com.j256.ormlite.field.DatabaseField;
import com.j256.ormlite.table.DatabaseTable;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@AllArgsConstructor
@NoArgsConstructor
@Data
@DatabaseTable(tableName = "dht_records")
public final class DHTRecordEntity {
@DatabaseField(id = true, index = true, canBeNull = false, columnDefinition = "VARCHAR(100)")
private String peerId;
@DatabaseField(canBeNull = false, dataType = DataType.BYTE_ARRAY)
private byte[] raw;
@DatabaseField(canBeNull = false)
private long sequence;
@DatabaseField(canBeNull = false)
private long ttlNanos;
@DatabaseField(canBeNull = false)
private long expiryUTC;
@DatabaseField(canBeNull = false, columnDefinition = "VARCHAR(10240)")
private String val;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.ghostchu.peerbanhelper.database.table;

import com.j256.ormlite.field.DataType;
import com.j256.ormlite.field.DatabaseField;
import com.j256.ormlite.table.DatabaseTable;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.sql.Timestamp;

@AllArgsConstructor
@NoArgsConstructor
@Data
@DatabaseTable(tableName = "friend")
public final class FriendEntity {
@DatabaseField(id = true, index = true)
private String peerId;
@DatabaseField(dataType = DataType.BYTE_ARRAY)
private byte[] pubKey;
@DatabaseField(canBeNull = false)
private Timestamp lastAttemptConnectTime;
@DatabaseField(canBeNull = false)
private Timestamp lastCommunicationTime;
@DatabaseField(canBeNull = false)
private String lastRecordedPBHVersion;
@DatabaseField(canBeNull = false)
private String lastRecordedConnectionStatus;
}
Loading
Loading