Skip to content
This repository has been archived by the owner on Feb 26, 2024. It is now read-only.

add StateMinerInfo method #833

Merged
merged 7 commits into from
Mar 16, 2021
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
16 changes: 16 additions & 0 deletions src/chains/filecoin/filecoin/src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { SubscriptionMethod, SubscriptionId } from "./types/subscriptions";
import { FileRef, SerializedFileRef } from "./things/file-ref";
import { MinerPower, SerializedMinerPower } from "./things/miner-power";
import { PowerClaim } from "./things/power-claim";
import { MinerInfo, SerializedMinerInfo } from "./things/miner-info";

export default class FilecoinApi implements types.Api {
readonly [index: string]: (...args: any) => Promise<any>;
Expand Down Expand Up @@ -179,6 +180,21 @@ export default class FilecoinApi implements types.Api {
}
}

// This function technically takes an additional TipSetKey
// argument, but since the miner info won't change in Ganache,
// it will go unused, and therefore not provided.
async "Filecoin.StateMinerInfo"(
minerAddress: string
): Promise<SerializedMinerInfo> {
if (minerAddress === this.#blockchain.miner) {
// The defaults are set up to correspond to the current
// miner address t01000, which is not configurable currently
return new MinerInfo().serialize();
} else {
throw new Error("Failed to load miner actor: actor not found");
}
}

async "Filecoin.WalletDefaultAddress"(): Promise<SerializedAddress> {
return this.#blockchain.address.serialize();
}
Expand Down
199 changes: 199 additions & 0 deletions src/chains/filecoin/filecoin/src/things/miner-info.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
import {
SerializableObject,
SerializedObject,
DeserializedObject,
Definitions
} from "./serializable-object";
import { RegisteredSealProof } from "../types/registered-seal-proof";

// https://pkg.go.dev/github.com/filecoin-project/lotus@v1.4.0/chain/actors/builtin/miner#MinerInfo

type MinerInfoConfig = {
properties: {
owner: {
type: string;
serializedType: string;
serializedName: "Owner";
};
worker: {
type: string;
serializedType: string;
serializedName: "Worker";
};
newWorker: {
type: string;
serializedType: string;
serializedName: "NewWorker";
};
controlAddresses: {
type: string[];
serializedType: string[];
serializedName: "ControlAddresses";
};
workerChangeEpoch: {
type: number;
serializedType: number;
serializedName: "WorkerChangeEpoch";
};
peerId: {
type: string;
serializedType: string;
serializedName: "PeerId";
};
multiaddrs: {
type: Uint8Array[];
serializedType: Uint8Array[];
serializedName: "Multiaddrs";
};
sealProofType: {
type: number;
serializedType: number;
serializedName: "SealProofType";
};
sectorSize: {
type: number;
serializedType: number;
serializedName: "SectorSize";
};
windowPoStPartitionSectors: {
type: number;
serializedType: number;
serializedName: "WindowPoStPartitionSectors";
};
consensusFaultElapsed: {
type: number;
serializedType: number;
serializedName: "ConsensusFaultElapsed";
};
};
};

class MinerInfo
extends SerializableObject<MinerInfoConfig>
implements DeserializedObject<MinerInfoConfig> {
get config(): Definitions<MinerInfoConfig> {
return {
owner: {
deserializedName: "owner",
serializedName: "Owner",
defaultValue: "t01000"
},
worker: {
deserializedName: "worker",
serializedName: "Worker",
defaultValue: "t01000"
},
newWorker: {
deserializedName: "newWorker",
serializedName: "NewWorker",
defaultValue: "<empty>" // This is how lotus-devnet responds to StateMinerInfo
},
controlAddresses: {
deserializedName: "controlAddresses",
serializedName: "ControlAddresses",
defaultValue: []
},
workerChangeEpoch: {
deserializedName: "workerChangeEpoch",
serializedName: "WorkerChangeEpoch",
defaultValue: config => (typeof config !== "undefined" ? config : -1)
},
peerId: {
deserializedName: "peerId",
serializedName: "PeerId",
defaultValue: "0" // defaulting this to 0 as we don't have any p2p technology in Ganache
},
multiaddrs: {
deserializedName: "multiaddrs",
serializedName: "Multiaddrs",
defaultValue: []
},
sealProofType: {
deserializedName: "sealProofType",
serializedName: "SealProofType",
defaultValue: config =>
typeof config !== "undefined"
? config
: RegisteredSealProof.StackedDrg2KiBV1_1
},
sectorSize: {
deserializedName: "sectorSize",
serializedName: "SectorSize",
defaultValue: 2048 // sectors/sector sizes don't really matter in Ganache; defaulting to 2 KiB (lotus-devnet default)
},
windowPoStPartitionSectors: {
deserializedName: "windowPoStPartitionSectors",
serializedName: "WindowPoStPartitionSectors",
defaultValue: config => (typeof config !== "undefined" ? config : 0)
},
consensusFaultElapsed: {
deserializedName: "consensusFaultElapsed",
serializedName: "ConsensusFaultElapsed",
defaultValue: config => (typeof config !== "undefined" ? config : -1)
}
};
}

constructor(
options?:
| Partial<SerializedObject<MinerInfoConfig>>
| Partial<DeserializedObject<MinerInfoConfig>>
) {
super();

this.owner = super.initializeValue(this.config.owner, options);
this.worker = super.initializeValue(this.config.worker, options);
this.newWorker = super.initializeValue(this.config.newWorker, options);
this.controlAddresses = super.initializeValue(
this.config.controlAddresses,
options
);
this.workerChangeEpoch = super.initializeValue(
this.config.workerChangeEpoch,
options
);
this.peerId = super.initializeValue(this.config.peerId, options);
this.multiaddrs = super.initializeValue(this.config.multiaddrs, options);
this.sealProofType = super.initializeValue(
this.config.sealProofType,
options
);
this.sectorSize = super.initializeValue(this.config.sectorSize, options);
this.windowPoStPartitionSectors = super.initializeValue(
this.config.windowPoStPartitionSectors,
options
);
this.consensusFaultElapsed = super.initializeValue(
this.config.consensusFaultElapsed,
options
);
}

/**
* The owner address corresponds to a Lotus node address provided during the miner initialization.
*/
owner: string;
/**
* The worker address is used to send and pay for day-to-day operations performed by the miner.
*/
worker: string;
newWorker: string;
/**
* Control addresses are used to submit WindowPoSts proofs to the chain (unused by Ganache).
*/
controlAddresses: string[];
/**
* The epoch time that `worker` becomes `newWorker`. A value of -1 indicates no change.
*/
workerChangeEpoch: number;
peerId: string;
multiaddrs: Uint8Array[];
sealProofType: number;
sectorSize: number;
windowPoStPartitionSectors: number;
consensusFaultElapsed: number;
}

type SerializedMinerInfo = SerializedObject<MinerInfoConfig>;

export { MinerInfo, SerializedMinerInfo };
13 changes: 13 additions & 0 deletions src/chains/filecoin/filecoin/src/types/registered-seal-proof.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Reference implementation: https://git.io/JtnP0
export enum RegisteredSealProof {
StackedDrg2KiBV1 = 0,
StackedDrg8MiBV1 = 1,
StackedDrg512MiBV1 = 2,
StackedDrg32GiBV1 = 3,
StackedDrg64GiBV1 = 4,
StackedDrg2KiBV1_1 = 5,
StackedDrg8MiBV1_1 = 6,
StackedDrg512MiBV1_1 = 7,
StackedDrg32GiBV1_1 = 8,
StackedDrg64GiBV1_1 = 9
}
23 changes: 23 additions & 0 deletions src/chains/filecoin/filecoin/tests/api/filecoin/miners.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,5 +51,28 @@ describe("api", () => {
assert.strictEqual(minerPower.HasMinPower, false);
});
});

describe("Filecoin.StateMinerInfo", () => {
it("should return the miner info for the default miner", async () => {
const minerInfo = await client.stateMinerInfo("t01000");

assert.strictEqual(minerInfo.Owner, "t01000");
assert.strictEqual(minerInfo.Worker, "t01000");
assert.strictEqual(minerInfo.WorkerChangeEpoch, -1);
assert.strictEqual(minerInfo.SectorSize, 2048);
assert.strictEqual(minerInfo.ConsensusFaultElapsed, -1);
});

it("should fail to retrieve miner info for other miners", async () => {
try {
const minerInfo = await client.stateMinerInfo("t01001");
assert.fail(
`Should not have retrieved a miner info for miner t01001, but receive: ${minerInfo}`
);
} catch (e) {
return;
}
});
});
});
});
2 changes: 2 additions & 0 deletions src/chains/filecoin/types/src/api.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { SerializedQueryOffer } from "./things/query-offer";
import { SubscriptionMethod, SubscriptionId } from "./types/subscriptions";
import { SerializedFileRef } from "./things/file-ref";
import { SerializedMinerPower } from "./things/miner-power";
import { SerializedMinerInfo } from "./things/miner-info";
export default class FilecoinApi implements types.Api {
#private;
readonly [index: string]: (...args: any) => Promise<any>;
Expand All @@ -25,6 +26,7 @@ export default class FilecoinApi implements types.Api {
"Filecoin.StateMinerPower"(
minerAddress: string
): Promise<SerializedMinerPower>;
"Filecoin.StateMinerInfo"(minerAddress: string): Promise<SerializedMinerInfo>;
"Filecoin.WalletDefaultAddress"(): Promise<SerializedAddress>;
"Filecoin.WalletBalance"(address: string): Promise<string>;
"Filecoin.ClientStartDeal"(
Expand Down
100 changes: 100 additions & 0 deletions src/chains/filecoin/types/src/things/miner-info.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import {
SerializableObject,
SerializedObject,
DeserializedObject,
Definitions
} from "./serializable-object";
declare type MinerInfoConfig = {
properties: {
owner: {
type: string;
serializedType: string;
serializedName: "Owner";
};
worker: {
type: string;
serializedType: string;
serializedName: "Worker";
};
newWorker: {
type: string;
serializedType: string;
serializedName: "NewWorker";
};
controlAddresses: {
type: string[];
serializedType: string[];
serializedName: "ControlAddresses";
};
workerChangeEpoch: {
type: number;
serializedType: number;
serializedName: "WorkerChangeEpoch";
};
peerId: {
type: string;
serializedType: string;
serializedName: "PeerId";
};
multiaddrs: {
type: Uint8Array[];
serializedType: Uint8Array[];
serializedName: "Multiaddrs";
};
sealProofType: {
type: number;
serializedType: number;
serializedName: "SealProofType";
};
sectorSize: {
type: number;
serializedType: number;
serializedName: "SectorSize";
};
windowPoStPartitionSectors: {
type: number;
serializedType: number;
serializedName: "WindowPoStPartitionSectors";
};
consensusFaultElapsed: {
type: number;
serializedType: number;
serializedName: "ConsensusFaultElapsed";
};
};
};
declare class MinerInfo
extends SerializableObject<MinerInfoConfig>
implements DeserializedObject<MinerInfoConfig> {
get config(): Definitions<MinerInfoConfig>;
constructor(
options?:
| Partial<SerializedObject<MinerInfoConfig>>
| Partial<DeserializedObject<MinerInfoConfig>>
);
/**
* The owner address corresponds to a Lotus node address provided during the miner initialization.
*/
owner: string;
/**
* The worker address is used to send and pay for day-to-day operations performed by the miner.
*/
worker: string;
newWorker: string;
/**
* Control addresses are used to submit WindowPoSts proofs to the chain (unused by Ganache).
*/
controlAddresses: string[];
/**
* The epoch time that `worker` becomes `newWorker`. A value of -1 indicates no change.
*/
workerChangeEpoch: number;
peerId: string;
multiaddrs: Uint8Array[];
sealProofType: number;
sectorSize: number;
windowPoStPartitionSectors: number;
consensusFaultElapsed: number;
}
declare type SerializedMinerInfo = SerializedObject<MinerInfoConfig>;
export { MinerInfo, SerializedMinerInfo };
Loading