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

Commit

Permalink
Merge pull request #833 from trufflesuite/feat/filecoin-stateminerinfo
Browse files Browse the repository at this point in the history
  • Loading branch information
mikeseese committed Mar 16, 2021
2 parents bbdf647 + 48f10e8 commit 726d327
Show file tree
Hide file tree
Showing 7 changed files with 365 additions and 0 deletions.
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

0 comments on commit 726d327

Please sign in to comment.